globs.nim 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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
  7. when defined(windows):
  8. from std/strutils import replace
  9. when defined(nimPreviewSlimSystem):
  10. import std/[assertions, objectdollar]
  11. when defined(nimHasEffectsOf):
  12. {.experimental: "strictEffects".}
  13. else:
  14. {.pragma: effectsOf.}
  15. type
  16. PathEntry* = object
  17. kind*: PathComponent
  18. path*: string
  19. iterator walkDirRecFilter*(dir: string, follow: proc(entry: PathEntry): bool = nil,
  20. relative = false, checkDir = true): PathEntry {.tags: [ReadDirEffect], effectsOf: follow.} =
  21. ## Improved `os.walkDirRec`.
  22. #[
  23. note: a yieldFilter isn't needed because caller can filter at call site, without
  24. loss of generality, unlike `follow`.
  25. Future work:
  26. * need to document
  27. * add a `sort` option, which can be implemented efficiently only here, not at call site.
  28. * provide a way to do error reporting, which is tricky because iteration cannot be resumed
  29. ]#
  30. var stack = @["."]
  31. var checkDir = checkDir
  32. var entry: PathEntry
  33. while stack.len > 0:
  34. let d = stack.pop()
  35. for k, p in walkDir(dir / d, relative = true, checkDir = checkDir):
  36. let rel = d / p
  37. entry.kind = k
  38. if relative: entry.path = rel
  39. else: entry.path = dir / rel
  40. if k in {pcDir, pcLinkToDir}:
  41. if follow == nil or follow(entry): stack.add rel
  42. yield entry
  43. checkDir = false
  44. # We only check top-level dir, otherwise if a subdir is invalid (eg. wrong
  45. # permissions), it'll abort iteration and there would be no way to
  46. # continue iteration.
  47. proc nativeToUnixPath*(path: string): string =
  48. # pending https://github.com/nim-lang/Nim/pull/13265
  49. result = path
  50. when defined(windows):
  51. if path.len >= 2 and path[0] in {'a'..'z', 'A'..'Z'} and path[1] == ':':
  52. result[0] = '/'
  53. result[1] = path[0]
  54. if path.len > 2 and path[2] != '\\':
  55. raiseAssert "paths like `C:foo` are currently unsupported, path: " & path
  56. when DirSep == '\\':
  57. result = replace(result, '\\', '/')
  58. when isMainModule:
  59. import std/sugar
  60. for a in walkDirRecFilter(".", follow = a=>a.path.lastPathPart notin ["nimcache", ".git", "csources_v1", "csources", "bin"]):
  61. echo a