globs.nim 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. ##[
  2. unstable API, internal use only for now.
  3. this can eventually be moved to std/os and `walkDirRec` can be implemented in terms of this
  4. to avoid duplication
  5. ]##
  6. import std/[os,strutils]
  7. type
  8. PathEntry* = object
  9. kind*: PathComponent
  10. path*: string
  11. iterator walkDirRecFilter*(dir: string, follow: proc(entry: PathEntry): bool = nil,
  12. relative = false, checkDir = true): PathEntry {.tags: [ReadDirEffect].} =
  13. ## Improved `os.walkDirRec`.
  14. #[
  15. note: a yieldFilter isn't needed because caller can filter at call site, without
  16. loss of generality, unlike `follow`.
  17. Future work:
  18. * need to document
  19. * add a `sort` option, which can be implemented efficiently only here, not at call site.
  20. * provide a way to do error reporting, which is tricky because iteration cannot be resumed
  21. ]#
  22. var stack = @["."]
  23. var checkDir = checkDir
  24. var entry: PathEntry
  25. while stack.len > 0:
  26. let d = stack.pop()
  27. for k, p in walkDir(dir / d, relative = true, checkDir = checkDir):
  28. let rel = d / p
  29. entry.kind = k
  30. if relative: entry.path = rel
  31. else: entry.path = dir / rel
  32. if k in {pcDir, pcLinkToDir}:
  33. if follow == nil or follow(entry): stack.add rel
  34. yield entry
  35. checkDir = false
  36. # We only check top-level dir, otherwise if a subdir is invalid (eg. wrong
  37. # permissions), it'll abort iteration and there would be no way to
  38. # continue iteration.
  39. proc nativeToUnixPath*(path: string): string =
  40. # pending https://github.com/nim-lang/Nim/pull/13265
  41. doAssert not path.isAbsolute # not implemented here; absolute files need more care for the drive
  42. when DirSep == '\\':
  43. result = replace(path, '\\', '/')
  44. else: result = path
  45. when isMainModule:
  46. import sugar
  47. for a in walkDirRecFilter(".", follow = a=>a.path.lastPathPart notin ["nimcache", ".git", ".csources", "bin"]):
  48. echo a