diff options
-rw-r--r-- | lib/pure/os.nim | 56 | ||||
-rw-r--r-- | tests/stdlib/tos.nim | 92 | ||||
-rw-r--r-- | tools/niminst/niminst.nim | 2 | ||||
-rw-r--r-- | web/news/version_0_15_released.rst | 5 |
4 files changed, 136 insertions, 19 deletions
diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 668793c20..52ba110a9 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -778,12 +778,26 @@ iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} yield (TaintedString(substr(environment[i], 0, p-1)), TaintedString(substr(environment[i], p+1))) -iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = - ## Iterate over all the files that match the `pattern`. On POSIX this uses - ## the `glob`:idx: call. - ## - ## `pattern` is OS dependent, but at least the "\*.ext" - ## notation is supported. +# Templates for filtering directories and files +when defined(windows): + template isDir(f: WIN32_FIND_DATA): bool = + (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32 + template isFile(f: WIN32_FIND_DATA): bool = + not isDir(f) +else: + template isDir(f: string): bool = + dirExists(f) + template isFile(f: string): bool = + fileExists(f) + +template defaultWalkFilter(item): bool = + ## Walk filter used to return true on both + ## files and directories + true + +template walkCommon(pattern: string, filter) = + ## Common code for getting the files and directories with the + ## specified `pattern` when defined(windows): var f: WIN32_FIND_DATA @@ -792,8 +806,7 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = if res != -1: defer: findClose(res) while true: - if not skipFindData(f) and - (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) == 0'i32: + if not skipFindData(f) and filter(f): # Windows bug/gotcha: 't*.nim' matches 'tfoo.nims' -.- so we check # that the file extensions have the same length ... let ff = getFilename(f) @@ -816,10 +829,33 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = for i in 0.. f.gl_pathc - 1: assert(f.gl_pathv[i] != nil) let path = $f.gl_pathv[i] - # Make sure it's a file and not a directory - if fileExists(path): + if filter(path): yield path +iterator walkPattern*(pattern: string): string {.tags: [ReadDirEffect].} = + ## Iterate over all the files and directories that match the `pattern`. + ## On POSIX this uses the `glob`:idx: call. + ## + ## `pattern` is OS dependent, but at least the "\*.ext" + ## notation is supported. + walkCommon(pattern, defaultWalkFilter) + +iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = + ## Iterate over all the files that match the `pattern`. On POSIX this uses + ## the `glob`:idx: call. + ## + ## `pattern` is OS dependent, but at least the "\*.ext" + ## notation is supported. + walkCommon(pattern, isFile) + +iterator walkDirs*(pattern: string): string {.tags: [ReadDirEffect].} = + ## Iterate over all the directories that match the `pattern`. + ## On POSIX this uses the `glob`:idx: call. + ## + ## `pattern` is OS dependent, but at least the "\*.ext" + ## notation is supported. + walkCommon(pattern, isDir) + type PathComponent* = enum ## Enumeration specifying a path component. pcFile, ## path refers to a file diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim index cae388792..1ddaacfcb 100644 --- a/tests/stdlib/tos.nim +++ b/tests/stdlib/tos.nim @@ -1,12 +1,88 @@ -# test some things of the os module +discard """ + output: '''true +true +true +true +true +true +true +true +true +All: +__really_obscure_dir_name/are.x +__really_obscure_dir_name/created +__really_obscure_dir_name/dirs +__really_obscure_dir_name/files.q +__really_obscure_dir_name/some +__really_obscure_dir_name/test +__really_obscure_dir_name/testing.r +__really_obscure_dir_name/these.txt +Files: +__really_obscure_dir_name/are.x +__really_obscure_dir_name/files.q +__really_obscure_dir_name/testing.r +__really_obscure_dir_name/these.txt +Dirs: +__really_obscure_dir_name/created +__really_obscure_dir_name/dirs +__really_obscure_dir_name/some +__really_obscure_dir_name/test +false +false +false +false +false +false +false +false +false +''' +""" +# test os path creation, iteration, and deletion import os -proc walkDirTree(root: string) = - for k, f in walkDir(root): - case k - of pcFile, pcLinkToFile: echo(f) - of pcDir: walkDirTree(f) - of pcLinkToDir: discard +let files = @["these.txt", "are.x", "testing.r", "files.q"] +let dirs = @["some", "created", "test", "dirs"] -walkDirTree(".") +let dname = "__really_obscure_dir_name" + +createDir(dname) +echo dirExists(dname) + +# Test creating files and dirs +for dir in dirs: + createDir(dname/dir) + echo dirExists(dname/dir) + +for file in files: + let fh = open(dname/file, fmReadWrite) + fh.close() + echo fileExists(dname/file) + +echo "All:" + +for path in walkPattern(dname/"*"): + echo path + +echo "Files:" + +for path in walkFiles(dname/"*"): + echo path + +echo "Dirs:" + +for path in walkDirs(dname/"*"): + echo path + +# Test removal of files dirs +for dir in dirs: + removeDir(dname/dir) + echo dirExists(dname/dir) + +for file in files: + removeFile(dname/file) + echo fileExists(dname/file) + +removeDir(dname) +echo dirExists(dname) diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index 79e552bde..b4f9c3687 100644 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -253,7 +253,7 @@ proc addFiles(s: var seq[string], patterns: seq[string]) = walkDirRecursively(s, p, p, false) else: var i = 0 - for f in walkFiles(p): + for f in walkPattern(p): if existsDir(f): walkDirRecursively(s, f, p, false) elif not ignoreFile(f, p, false): diff --git a/web/news/version_0_15_released.rst b/web/news/version_0_15_released.rst index 76d78ce71..ecda59fcd 100644 --- a/web/news/version_0_15_released.rst +++ b/web/news/version_0_15_released.rst @@ -30,6 +30,11 @@ Library Additions operations. Currently contains ``partition``, ``rpartition`` and ``expandTabs``. +- Split out ``walkFiles`` in ``os.nim`` to three separate procs in order + to make a clear distinction of functionality. ``walkPattern`` iterates + over both files and directories, while ``walkFiles`` now only iterates + over files and ``walkDirs`` only iterates over directories. + Compiler Additions ------------------ |