From f34daf9ff4f2aec8ef3948c75795d00f8e795cc6 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sun, 24 Oct 2021 19:12:14 +0300 Subject: [PATCH] os: add os.walk_with_context/3 and a test for it --- vlib/os/os.v | 42 ++++++++++++++++++++++++++++++++++++------ vlib/os/os_test.v | 28 +++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/vlib/os/os.v b/vlib/os/os.v index a8e885b947..82692ed255 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -473,9 +473,13 @@ fn impl_walk_ext(path string, ext string, mut out []string) { } } -// walk recursively traverses the given directory `path`. -// When a file is encountred it will call the callback function with current file as argument. +// walk traverses the given directory `path`. +// When a file is encountred it will call the +// callback function `f` with current file as argument. pub fn walk(path string, f fn (string)) { + if path.len == 0 { + return + } if !is_dir(path) { return } @@ -495,13 +499,39 @@ pub fn walk(path string, f fn (string)) { return } +// FnWalkContextCB is used to define the callback functions, passed to os.walk_context +pub type FnWalkContextCB = fn (voidptr, string) + +// walk_with_context traverses the given directory `path`. +// For each encountred file, it will call your `fcb` callback, +// passing it the arbitrary `context` in its first parameter, +// and the path to the file in its second parameter. +pub fn walk_with_context(path string, context voidptr, fcb FnWalkContextCB) { + if path.len == 0 { + return + } + if !is_dir(path) { + return + } + mut files := ls(path) or { return } + mut local_path_separator := path_separator + if path.ends_with(path_separator) { + local_path_separator = '' + } + for file in files { + p := path + local_path_separator + file + if is_dir(p) && !is_link(p) { + walk_with_context(p, context, fcb) + } else { + fcb(context, p) + } + } + return +} + // log will print "os.log: "+`s` ... pub fn log(s string) { - //$if macos { - // Use NSLog() on macos - //} $else { println('os.log: ' + s) - //} } // mkdir_all will create a valid full path of all directories given in `path`. diff --git a/vlib/os/os_test.v b/vlib/os/os_test.v index 58067006b2..7cdca800c9 100644 --- a/vlib/os/os_test.v +++ b/vlib/os/os_test.v @@ -193,13 +193,12 @@ fn test_ls() { } if x := os.ls('.') { assert x.len > 0 - dump(x) } else { assert false } } -fn test_walk_ext() ? { +fn create_tree() ? { os.mkdir_all('myfolder/f1/f2/f3') ? os.mkdir_all('myfolder/a1/a2/a3') ? create_file('myfolder/f1/f2/f3/a.txt') ? @@ -213,6 +212,17 @@ fn test_walk_ext() ? { create_file('myfolder/a1/a2/a3/z.txt') ? create_file('myfolder/a1/1.txt') ? create_file('myfolder/xyz.ini') ? +} + +fn remove_tree() { + os.rmdir_all('myfolder') or {} +} + +fn test_walk_ext() ? { + create_tree() ? + defer { + remove_tree() + } all := os.walk_ext('.', '') assert all.len > 10 mut top := os.walk_ext('myfolder', '.txt') @@ -237,7 +247,19 @@ fn test_walk_ext() ? { mut mds := os.walk_ext('myfolder', '.md') mds.sort() assert mds == ['myfolder/another.md', 'myfolder/f1/f2/f3/d.md'] - os.rmdir_all('myfolder') ? +} + +fn test_walk_with_context() ? { + create_tree() ? + defer { + remove_tree() + } + mut res := []string{} + os.walk_with_context('myfolder', &res, fn (mut res []string, fpath string) { + res << fpath + }) + assert 'myfolder/f1/f2/f3/b.txt' in res + assert 'myfolder/another.md' in res } fn test_create_and_delete_folder() {