Add file globbing
This commit is contained in:
parent
e3c1dd2df5
commit
7cd67dd7f3
@ -288,6 +288,53 @@ A list of file paths.
|
||||
|
||||
---
|
||||
|
||||
### `glob`
|
||||
|
||||
**Description:**
|
||||
Perform a globbing operation and return an array of matching paths. Some glob
|
||||
specific details:
|
||||
|
||||
- The paths "." and ".." are *not* included in any globbing results.
|
||||
- Files or directories that begin with "." will not match `*`, but will match `.*`.
|
||||
- Globs do support `{a,b}` syntax for matching files that match any of several
|
||||
choices of patterns.
|
||||
- The shell-style syntax `**` for matching subdirectories is not supported.
|
||||
|
||||
**Signature:**
|
||||
```tomo
|
||||
func glob(path: Path -> [Path])
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `path`: The path of the directory which may contain special globbing characters
|
||||
like `*`, `?`, or `{...}`
|
||||
|
||||
**Returns:**
|
||||
A list of file paths that match the glob.
|
||||
|
||||
**Example:**
|
||||
```tomo
|
||||
# Current directory includes: foo.txt, baz.txt, qux.jpg, .hidden
|
||||
>> (./*):glob()
|
||||
= [(./foo.txt), (./baz.txt), (./qux.jpg)]
|
||||
|
||||
>> (./*.txt):glob()
|
||||
= [(./foo.txt), (./baz.txt)]
|
||||
|
||||
>> (./*.{txt,jpg}):glob()
|
||||
= [(./foo.txt), (./baz.txt), (./qux.jpg)]
|
||||
|
||||
>> (./.*):glob()
|
||||
= [(./.hidden)]
|
||||
|
||||
# Globs with no matches return an empty array:
|
||||
>> (./*.xxx):glob()
|
||||
= []
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `is_directory`
|
||||
|
||||
**Description:**
|
||||
|
@ -302,6 +302,7 @@ env_t *new_compilation_unit(CORD libname)
|
||||
{"exists", "Path$exists", "func(path:Path -> Bool)"},
|
||||
{"extension", "Path$extension", "func(path:Path, full=yes -> Text)"},
|
||||
{"files", "Path$children", "func(path:Path, include_hidden=no -> [Path])"},
|
||||
{"glob", "Path$glob", "func(path:Path -> [Path])"},
|
||||
{"is_directory", "Path$is_directory", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
||||
{"is_file", "Path$is_file", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
||||
{"is_pipe", "Path$is_pipe", "func(path:Path, follow_symlinks=yes -> Bool)"},
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <gc.h>
|
||||
#include <glob.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@ -535,6 +536,24 @@ public OptionalClosure_t Path$by_line(Path_t path)
|
||||
return (Closure_t){.fn=(void*)_next_line, .userdata=wrapper};
|
||||
}
|
||||
|
||||
public Array_t Path$glob(Path_t path)
|
||||
{
|
||||
glob_t glob_result;
|
||||
int status = glob(Text$as_c_string(path), GLOB_BRACE | GLOB_TILDE | GLOB_TILDE_CHECK, NULL, &glob_result);
|
||||
if (status != 0 && status != GLOB_NOMATCH)
|
||||
fail("Failed to perform globbing");
|
||||
|
||||
Array_t glob_files = {};
|
||||
for (size_t i = 0; i < glob_result.gl_pathc; i++) {
|
||||
size_t len = strlen(glob_result.gl_pathv[i]);
|
||||
if ((len >= 2 && glob_result.gl_pathv[i][len-1] == '.' && glob_result.gl_pathv[i][len-2] == '/')
|
||||
|| (len >= 2 && glob_result.gl_pathv[i][len-1] == '.' && glob_result.gl_pathv[i][len-2] == '.' && glob_result.gl_pathv[i][len-3] == '/'))
|
||||
continue;
|
||||
Array$insert(&glob_files, (Text_t[1]){Text$from_str(glob_result.gl_pathv[i])}, I(0), sizeof(Text_t));
|
||||
}
|
||||
return glob_files;
|
||||
}
|
||||
|
||||
public const TypeInfo_t Path$info = {
|
||||
.size=sizeof(Path_t),
|
||||
.align=__alignof__(Path_t),
|
||||
@ -542,5 +561,4 @@ public const TypeInfo_t Path$info = {
|
||||
.TextInfo={.lang="Path"},
|
||||
};
|
||||
|
||||
|
||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||
|
@ -47,6 +47,7 @@ Path_t Path$parent(Path_t path);
|
||||
Text_t Path$base_name(Path_t path);
|
||||
Text_t Path$extension(Path_t path, bool full);
|
||||
Closure_t Path$by_line(Path_t path);
|
||||
Array_t Path$glob(Path_t path);
|
||||
|
||||
#define Path$hash Text$hash
|
||||
#define Path$compare Text$compare
|
||||
|
@ -133,3 +133,5 @@ func main():
|
||||
>> (/foo/bar/baz) ++ (./.././qux/./../quux)
|
||||
= (/foo/bar/quux)
|
||||
|
||||
!! Globbing:
|
||||
>> (./*.tm):glob()
|
||||
|
Loading…
Reference in New Issue
Block a user