summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/os.nim56
-rw-r--r--tests/stdlib/tos.nim92
-rw-r--r--tools/niminst/niminst.nim2
-rw-r--r--web/news/version_0_15_released.rst5
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
 ------------------