@@ -23,7 +23,7 @@ func FilePathInDirs(fPath string, dirs ...string) string {
2323 }
2424
2525 for _ , dirPath := range dirs {
26- fPath : = JoinSubPaths (dirPath , fPath )
26+ fPath = JoinSubPaths (dirPath , fPath )
2727 if FileExists (fPath ) {
2828 return fPath
2929 }
@@ -67,6 +67,103 @@ func MatchFirst(paths []string, matcher PathMatchFunc, defaultPath string) strin
6767 return defaultPath
6868}
6969
70+ // FindParentOption options
71+ type FindParentOption struct {
72+ MaxLevel int // default: 10
73+ // NeedDir true: find dirs; false(default): find files
74+ NeedDir bool
75+ OnlyOne bool // only find one, default: true
76+ // Collector func
77+ Collector func (fullPath string )
78+ // MatchFunc custom matcher func. return false to stop find.
79+ MatchFunc func (currentDir string ) bool
80+ }
81+
82+ // FindParentOptFn find parent option func
83+ type FindParentOptFn func (opt * FindParentOption )
84+
85+ // FindAllInParentDirs looks for all match file(default)/dir in the current directory and parent directories
86+ func FindAllInParentDirs (dirPath , name string , optFns ... FindParentOptFn ) []string {
87+ var foundPaths []string
88+ optFns = append (optFns , func (opt * FindParentOption ) {
89+ opt .OnlyOne = false
90+ })
91+
92+ FindNameInParentDirs (dirPath , name , func (fullPath string ) {
93+ foundPaths = append (foundPaths , fullPath )
94+ }, optFns ... )
95+ return foundPaths
96+ }
97+
98+ // FindOneInParentDirs looks for a file(default)/dir in the current directory and parent directories
99+ func FindOneInParentDirs (dirPath , name string , optFns ... FindParentOptFn ) string {
100+ var foundPath string
101+ FindNameInParentDirs (dirPath , name , func (fullPath string ) {
102+ foundPath = fullPath
103+ }, optFns ... )
104+ return foundPath
105+ }
106+
107+ // FindNameInParentDirs looks for file(default)/dir in the current directory and parent directories
108+ func FindNameInParentDirs (dirPath , name string , collectFn func (fullPath string ), optFns ... FindParentOptFn ) {
109+ opts := & FindParentOption {
110+ MaxLevel : 10 ,
111+ OnlyOne : true ,
112+ Collector : collectFn ,
113+ }
114+ for _ , fn := range optFns {
115+ fn (opts )
116+ }
117+
118+ FindInParentDirs (dirPath , func (currentDir string ) bool {
119+ filePath := filepath .Join (currentDir , name )
120+ if fi , err := os .Stat (filePath ); err == nil {
121+ found := false
122+ if fi .IsDir () {
123+ found = opts .NeedDir
124+ } else {
125+ found = ! opts .NeedDir
126+ }
127+
128+ if found {
129+ opts .Collector (filePath )
130+ return ! opts .OnlyOne
131+ }
132+ }
133+ return true
134+ }, opts .MaxLevel )
135+ }
136+
137+ // FindInParentDirs looks for file/dir in the current directory and parent directories
138+ // - MatchFunc custom matcher func. return false to stop find.
139+ func FindInParentDirs (dirPath string , matchFunc func (dir string ) bool , maxLevel int ) {
140+ currentLv := 1
141+ currentDir := ToAbsPath (dirPath )
142+
143+ for {
144+ // Check if the file exists in the current directory
145+ if ! matchFunc (currentDir ) {
146+ return
147+ }
148+
149+ // check find level
150+ if maxLevel > 0 && currentLv > maxLevel {
151+ break
152+ }
153+
154+ // Get parent directory
155+ parentDir := filepath .Dir (currentDir )
156+ if parentDir == currentDir {
157+ // Reached the root, file not found
158+ return
159+ }
160+
161+ // Move to parent directory
162+ currentLv ++
163+ currentDir = parentDir
164+ }
165+ }
166+
70167// SearchNameUp find file/dir name in dirPath or parent dirs,
71168// return the name of directory path
72169//
@@ -158,14 +255,10 @@ type (
158255)
159256
160257// OnlyFindDir on find
161- func OnlyFindDir (_ string , ent fs.DirEntry ) bool {
162- return ent .IsDir ()
163- }
258+ func OnlyFindDir (_ string , ent fs.DirEntry ) bool { return ent .IsDir () }
164259
165260// OnlyFindFile on find
166- func OnlyFindFile (_ string , ent fs.DirEntry ) bool {
167- return ! ent .IsDir ()
168- }
261+ func OnlyFindFile (_ string , ent fs.DirEntry ) bool { return ! ent .IsDir () }
169262
170263// ExcludeNames on find
171264func ExcludeNames (names ... string ) FilterFunc {
@@ -182,9 +275,7 @@ func IncludeSuffix(ss ...string) FilterFunc {
182275}
183276
184277// ExcludeDotFile on find
185- func ExcludeDotFile (_ string , ent fs.DirEntry ) bool {
186- return ent .Name ()[0 ] != '.'
187- }
278+ func ExcludeDotFile (_ string , ent fs.DirEntry ) bool { return ent .Name ()[0 ] != '.' }
188279
189280// ExcludeSuffix on find
190281func ExcludeSuffix (ss ... string ) FilterFunc {
@@ -205,7 +296,7 @@ func ApplyFilters(fPath string, ent fs.DirEntry, filters []FilterFunc) bool {
205296
206297// FindInDir code refer the go pkg: path/filepath.glob()
207298//
208- // - TIP: will be not found in sub-dir.
299+ // - TIP: default will be not found in sub-dir.
209300//
210301// filters: return false will skip the file.
211302func FindInDir (dir string , handleFn HandleFunc , filters ... FilterFunc ) (e error ) {
0 commit comments