From fd12be996688cea675e39b2ba99ce4b2baea4993 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Fri, 10 Aug 2018 16:38:48 +0100 Subject: [PATCH] file: list now takes optional pattern for filtering (#2452) Thanks to @TerryE for many useful suggestions --- app/modules/file.c | 55 +++++++++++++++++++++++++++++++++-------- docs/en/modules/file.md | 8 ++++-- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/app/modules/file.c b/app/modules/file.c index 26a91d94..8ccb4924 100644 --- a/app/modules/file.c +++ b/app/modules/file.c @@ -214,18 +214,53 @@ static int file_open( lua_State* L ) static int file_list( lua_State* L ) { vfs_dir *dir; + const char *pattern; + struct vfs_stat stat; + int pcres; - if (dir = vfs_opendir("")) { - lua_newtable( L ); - struct vfs_stat stat; - while (vfs_readdir(dir, &stat) == VFS_RES_OK) { - lua_pushinteger(L, stat.size); - lua_setfield(L, -2, stat.name); - } - vfs_closedir(dir); - return 1; + lua_settop(L, 1); + pattern = luaL_optstring(L, 1, NULL); /* Pattern (arg) or nil (not) at 1 */ + + dir = vfs_opendir(""); + if (dir == NULL) { + return 0; } - return 0; + + lua_newtable( L ); /* Table at 2 */ + + if (pattern) { + /* + * We know that pattern is a string, and so the "match" method will always + * exist. No need to check return value here + */ + luaL_getmetafield( L, 1, "match" ); /* Function at 3 */ + } + + while (vfs_readdir(dir, &stat) == VFS_RES_OK) { + if (pattern) { + lua_settop( L, 3 ); /* Ensure nothing else on stack */ + + /* Construct and pcall(string.match,name,pattern) */ + lua_pushvalue( L, 3 ); + lua_pushstring( L, stat.name ); + lua_pushvalue( L, 1 ); + pcres = lua_pcall( L, 2, 1, 0 ); + if (pcres != 0) { + vfs_closedir(dir); + lua_error( L ); + } + if (lua_isnil( L, -1 )) { + continue; + } + } + lua_pushinteger( L, stat.size ); + lua_setfield( L, 2, stat.name ); + } + + /* Shed everything back to Table */ + lua_settop( L, 2 ); + vfs_closedir(dir); + return 1; } static int get_file_obj( lua_State *L, int *argpos ) diff --git a/docs/en/modules/file.md b/docs/en/modules/file.md index 7f144b76..966e5963 100644 --- a/docs/en/modules/file.md +++ b/docs/en/modules/file.md @@ -144,13 +144,17 @@ print("\nFile system info:\nTotal : "..total.." (k)Bytes\nUsed : "..used.." (k)B Lists all files in the file system. #### Syntax -`file.list()` +`file.list([pattern])` #### Parameters none #### Returns -a Lua table which contains the {file name: file size} pairs +a Lua table which contains all {file name: file size} pairs, if no pattern +given. If a pattern is given, only those file names matching the pattern +(interpreted as a traditional [Lua pattern](https://www.lua.org/pil/20.2.html), +not, say, a UNIX shell glob) will be included in the resulting table. +`file.list` will throw any errors encountered during pattern matching. #### Example ```lua