aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-11-15 18:13:44 -0500
committerBruce Hill <bruce@bruce-hill.com>2025-11-15 18:14:09 -0500
commit290c72732f21f1cddb3a0f8ec3213e4ec321da14 (patch)
tree7c6c939a8d563edda5afddefcc2810d550ede0f3 /src
parenta1884f7a85cbee5a67cf48c9e7b088fdea8b8b38 (diff)
Add Path.lines()
Diffstat (limited to 'src')
-rw-r--r--src/environment.c1
-rw-r--r--src/stdlib/paths.c22
-rw-r--r--src/stdlib/paths.h1
3 files changed, 24 insertions, 0 deletions
diff --git a/src/environment.c b/src/environment.c
index 96595ac7..8f49f86e 100644
--- a/src/environment.c
+++ b/src/environment.c
@@ -325,6 +325,7 @@ env_t *global_env(bool source_mapping) {
{"is_pipe", "Path$is_pipe", "func(path:Path, follow_symlinks=yes -> Bool)"}, //
{"is_socket", "Path$is_socket", "func(path:Path, follow_symlinks=yes -> Bool)"}, //
{"is_symlink", "Path$is_symlink", "func(path:Path -> Bool)"}, //
+ {"lines", "Path$lines", "func(path:Path -> [Text]?)"}, //
{"modified", "Path$modified", "func(path:Path, follow_symlinks=yes -> Int64?)"}, //
{"owner", "Path$owner", "func(path:Path, follow_symlinks=yes -> Text?)"}, //
{"parent", "Path$parent", "func(path:Path -> Path)"}, //
diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c
index 810f98b1..704421c2 100644
--- a/src/stdlib/paths.c
+++ b/src/stdlib/paths.c
@@ -704,6 +704,28 @@ OptionalClosure_t Path$by_line(Path_t path) {
}
public
+OptionalList_t Path$lines(Path_t path) {
+ const char *path_str = Path$as_c_string(path);
+ FILE *f = fopen(path_str, "r");
+ if (f == NULL) {
+ if (errno == EMFILE || errno == ENFILE) {
+ // If we hit file handle limits, run GC collection to try to clean up any lingering file handles that will
+ // be closed by GC finalizers.
+ GC_gcollect();
+ f = fopen(path_str, "r");
+ }
+ }
+
+ if (f == NULL) return NONE_LIST;
+
+ List_t lines = {};
+ for (OptionalText_t line; (line = _next_line(&f)).tag != TEXT_NONE;) {
+ List$insert(&lines, &line, I(0), sizeof(line));
+ }
+ return lines;
+}
+
+public
List_t Path$glob(Path_t path) {
glob_t glob_result;
int status = glob(Path$as_c_string(path), GLOB_BRACE | GLOB_TILDE, NULL, &glob_result);
diff --git a/src/stdlib/paths.h b/src/stdlib/paths.h
index ce6de1c8..3b1f3ce6 100644
--- a/src/stdlib/paths.h
+++ b/src/stdlib/paths.h
@@ -57,6 +57,7 @@ Path_t Path$sibling(Path_t path, Text_t name);
Path_t Path$with_extension(Path_t path, Text_t extension, bool replace);
Path_t Path$current_dir(void);
Closure_t Path$by_line(Path_t path);
+OptionalList_t Path$lines(Path_t path);
List_t Path$glob(Path_t path);
uint64_t Path$hash(const void *obj, const TypeInfo_t *);