{- Copyright (C) 2006 John Goerzen <jgoerzen@complete.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}{- |
Module : System.Path.Glob
Copyright : Copyright (C) 2006 John Goerzen
License : GNU GPL, version 2 or above
Maintainer : John Goerzen <jgoerzen@complete.org>
Stability : provisional
Portability: portable
Functions for expanding wildcards, filenames, and pathnames.
For information on the metacharacters recognized, please see the notes
in "System.Path.WildMatch".
-}moduleSystem.Path.Glob(glob,vGlob)whereimportData.List.Utils(hasAny)importSystem.IO.HVFSimportSystem.FilePath(splitFileName)importControl.Exception(tryJust,ioErrors)importSystem.Path.WildMatch(wildCheckCase)importData.List(isSuffixOf)hasWild::String->BoolhasWild=hasAny"*?["{- | Takes a pattern. Returns a list of names that match that pattern.
The pattern is evaluated by "System.Path.WildMatch". This function
does not perform tilde or environment variable expansion.
Filenames that begin with a dot are not included in the result set unless
that component of the pattern also begins with a dot.
In MissingH, this function is defined as:
>glob = vGlob SystemFS
-}glob::FilePath->IO[FilePath]glob=vGlobSystemFS{- | Like 'glob', but works on both the system ("real") and HVFS virtual
filesystems. -}vGlob::HVFSa=>a->FilePath->IO[FilePath]vGlobfsfn=ifnot(hasWildfn)-- Don't try globbing if there are no wildsthendode<-vDoesExistfsfnifdethenreturn[fn]elsereturn[]elseexpandGlobfsfn-- It's thereexpandGlob::HVFSa=>a->FilePath->IO[FilePath]expandGlobfsfn=casedirnameof"."->runGlobfs"."basename_->dodirlist<-ifhasWilddirnamethenexpandGlobfsdirnameelsereturn[dirname]ifhasWildbasenamethendor<-mapMexpandWildBasedirlistreturn$concatrelsedor<-mapMexpandNormalBasedirlistreturn$concatrwhere(dirnameslash,basename)=splitFileNamefndirname=casedirnameslashof"/"->"/"x->ifisSuffixOf"/"xthentake(lengthx-1)xelsexexpandWildBase::FilePath->IO[FilePath]expandWildBasedname=dodirglobs<-runGlobfsdnamebasenamereturn$map(\globfn->dname++"/"++globfn)dirglobsexpandNormalBase::FilePath->IO[FilePath]expandNormalBasedname=doisdir<-vDoesDirectoryExistfsdnameletnewname=dname++"/"++basenameisexists<-vDoesExistfsnewnameifisexists&&((basename/="."&&basename/="")||isdir)thenreturn[dname++"/"++basename]elsereturn[]runGlob::HVFSa=>a->FilePath->FilePath->IO[FilePath]runGlobfs""patt=runGlobfs"."pattrunGlobfsdirnamepatt=dor<-tryJustioErrors(vGetDirectoryContentsfsdirname)caserofLeft_->return[]Rightnames->letmatches=filter(wildCheckCasepatt)$namesinifheadpatt=='.'thenreturnmatcheselsereturn$filter(\x->headx/='.')matches