Skip to content

Commit c20d02a

Browse files
committed
file: list now takes optional pattern for filtering
1 parent 5d7a46a commit c20d02a

File tree

2 files changed

+69
-11
lines changed

2 files changed

+69
-11
lines changed

app/modules/file.c

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -214,18 +214,71 @@ static int file_open( lua_State* L )
214214
static int file_list( lua_State* L )
215215
{
216216
vfs_dir *dir;
217+
const char *pattern;
218+
static const char *emptystr = "";
219+
struct vfs_stat stat;
220+
int pcres;
221+
int res = 1;
222+
223+
pattern = luaL_optlstring(L, 1, emptystr, NULL);
224+
225+
dir = vfs_opendir("");
226+
if (dir == NULL) {
227+
return 0;
228+
}
229+
230+
/* Allocate result table T */
231+
lua_newtable( L );
232+
233+
/* If we're doing a match, push the Pattern and Function */
234+
if (pattern != emptystr) {
235+
lua_pushstring( L, pattern );
236+
/*
237+
* We know that pattern is a string, and so the "match" method will always
238+
* exist. No need to check return value here
239+
*/
240+
luaL_getmetafield( L, -1, "match" );
241+
}
242+
243+
while (vfs_readdir(dir, &stat) == VFS_RES_OK) {
244+
if (pattern != emptystr) {
245+
/* Stack: T P F . Duplicate F, push Name, duplicate P */
246+
lua_pushvalue( L, -1 );
247+
lua_pushstring( L, stat.name );
248+
lua_pushvalue( L, -4 );
249+
/* Call transforms stack from T P F F N P to T P F Result */
250+
pcres = lua_pcall( L, 2, 1, 0 );
251+
if (pcres != 0) {
252+
/* Abort! Stack is T P F Error; clear out and push nil under Error */
253+
lua_pushnil( L );
254+
lua_replace( L, -5 );
255+
lua_remove( L, -2 );
256+
lua_remove( L, -2 );
257+
res = 2;
258+
goto out;
259+
}
217260

218-
if (dir = vfs_opendir("")) {
219-
lua_newtable( L );
220-
struct vfs_stat stat;
221-
while (vfs_readdir(dir, &stat) == VFS_RES_OK) {
222-
lua_pushinteger(L, stat.size);
223-
lua_setfield(L, -2, stat.name);
261+
/* Check and pop Result, restoring stack to T P F */
262+
if (!lua_isnil( L, -1 )) {
263+
lua_pushinteger( L, stat.size );
264+
lua_setfield( L, -5, stat.name );
265+
}
266+
lua_pop( L, 1 );
267+
} else {
268+
/* Stack just holds result table at the top; add result */
269+
lua_pushinteger( L, stat.size );
270+
lua_setfield( L, -2, stat.name );
224271
}
225-
vfs_closedir(dir);
226-
return 1;
227272
}
228-
return 0;
273+
274+
/* Pop the Pattern and Function we pushed above */
275+
if (pattern != emptystr) {
276+
lua_pop( L, 2 );
277+
}
278+
279+
out:
280+
vfs_closedir(dir);
281+
return res;
229282
}
230283

231284
static int get_file_obj( lua_State *L, int *argpos )

docs/en/modules/file.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,18 @@ print("\nFile system info:\nTotal : "..total.." (k)Bytes\nUsed : "..used.." (k)B
144144
Lists all files in the file system.
145145

146146
#### Syntax
147-
`file.list()`
147+
`file.list([pattern])`
148148

149149
#### Parameters
150150
none
151151

152152
#### Returns
153-
a Lua table which contains the {file name: file size} pairs
153+
a Lua table which contains all {file name: file size} pairs, if no pattern
154+
given. If a pattern is given, only those file names matching the pattern
155+
(interpreted as a traditional [Lua pattern](https://www.lua.org/pil/20.2.html),
156+
not, say, a UNIX shell glob) will be included in the resulting table. If there
157+
is an error during this pattern matching, `file.list` will return `nil` and the
158+
error.
154159

155160
#### Example
156161
```lua

0 commit comments

Comments
 (0)