From a23c315905c126667f13091989ca2879b5337582 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Sun, 4 Aug 2024 17:19:08 -0400 Subject: Hello lua --- compile_commands.json | 56 ++++++++++++++++++++++++++++---------------------- configure.ac | 3 +++ src/Makefile.am | 4 ++-- src/read_cfg.c | 21 +++++++++++++++++++ src/unix/read_cfg.c | 6 +++--- src/windows/read_cfg.c | 4 ++-- 6 files changed, 63 insertions(+), 31 deletions(-) diff --git a/compile_commands.json b/compile_commands.json index cfbbf2d..cdb203b 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -7,6 +7,7 @@ "-I..", "-D_DEFAULT_SOURCE", "-D_XOPEN_SOURCE=600", + "-I/usr/include/lua5.1", "-g", "-O2", "-c", @@ -14,9 +15,9 @@ "terminal_media_launcher-cache.o", "cache.c" ], - "directory": "/home/louie/Documents/code/terminal-media-launcher/source/src", - "file": "/home/louie/Documents/code/terminal-media-launcher/source/src/cache.c", - "output": "/home/louie/Documents/code/terminal-media-launcher/source/src/terminal_media_launcher-cache.o" + "directory": "/home/louie/Documents/code/terminal-media-launcher/src", + "file": "/home/louie/Documents/code/terminal-media-launcher/src/cache.c", + "output": "/home/louie/Documents/code/terminal-media-launcher/src/terminal_media_launcher-cache.o" }, { "arguments": [ @@ -26,6 +27,7 @@ "-I..", "-D_DEFAULT_SOURCE", "-D_XOPEN_SOURCE=600", + "-I/usr/include/lua5.1", "-g", "-O2", "-c", @@ -33,9 +35,9 @@ "terminal_media_launcher-draw.o", "draw.c" ], - "directory": "/home/louie/Documents/code/terminal-media-launcher/source/src", - "file": "/home/louie/Documents/code/terminal-media-launcher/source/src/draw.c", - "output": "/home/louie/Documents/code/terminal-media-launcher/source/src/terminal_media_launcher-draw.o" + "directory": "/home/louie/Documents/code/terminal-media-launcher/src", + "file": "/home/louie/Documents/code/terminal-media-launcher/src/draw.c", + "output": "/home/louie/Documents/code/terminal-media-launcher/src/terminal_media_launcher-draw.o" }, { "arguments": [ @@ -45,6 +47,7 @@ "-I..", "-D_DEFAULT_SOURCE", "-D_XOPEN_SOURCE=600", + "-I/usr/include/lua5.1", "-g", "-O2", "-c", @@ -52,9 +55,9 @@ "terminal_media_launcher-read_cfg.o", "read_cfg.c" ], - "directory": "/home/louie/Documents/code/terminal-media-launcher/source/src", - "file": "/home/louie/Documents/code/terminal-media-launcher/source/src/read_cfg.c", - "output": "/home/louie/Documents/code/terminal-media-launcher/source/src/terminal_media_launcher-read_cfg.o" + "directory": "/home/louie/Documents/code/terminal-media-launcher/src", + "file": "/home/louie/Documents/code/terminal-media-launcher/src/read_cfg.c", + "output": "/home/louie/Documents/code/terminal-media-launcher/src/terminal_media_launcher-read_cfg.o" }, { "arguments": [ @@ -64,6 +67,7 @@ "-I..", "-D_DEFAULT_SOURCE", "-D_XOPEN_SOURCE=600", + "-I/usr/include/lua5.1", "-g", "-O2", "-c", @@ -71,9 +75,9 @@ "terminal_media_launcher-group.o", "group.c" ], - "directory": "/home/louie/Documents/code/terminal-media-launcher/source/src", - "file": "/home/louie/Documents/code/terminal-media-launcher/source/src/group.c", - "output": "/home/louie/Documents/code/terminal-media-launcher/source/src/terminal_media_launcher-group.o" + "directory": "/home/louie/Documents/code/terminal-media-launcher/src", + "file": "/home/louie/Documents/code/terminal-media-launcher/src/group.c", + "output": "/home/louie/Documents/code/terminal-media-launcher/src/terminal_media_launcher-group.o" }, { "arguments": [ @@ -83,6 +87,7 @@ "-I..", "-D_DEFAULT_SOURCE", "-D_XOPEN_SOURCE=600", + "-I/usr/include/lua5.1", "-g", "-O2", "-c", @@ -90,9 +95,9 @@ "terminal_media_launcher-entry.o", "entry.c" ], - "directory": "/home/louie/Documents/code/terminal-media-launcher/source/src", - "file": "/home/louie/Documents/code/terminal-media-launcher/source/src/entry.c", - "output": "/home/louie/Documents/code/terminal-media-launcher/source/src/terminal_media_launcher-entry.o" + "directory": "/home/louie/Documents/code/terminal-media-launcher/src", + "file": "/home/louie/Documents/code/terminal-media-launcher/src/entry.c", + "output": "/home/louie/Documents/code/terminal-media-launcher/src/terminal_media_launcher-entry.o" }, { "arguments": [ @@ -102,6 +107,7 @@ "-I..", "-D_DEFAULT_SOURCE", "-D_XOPEN_SOURCE=600", + "-I/usr/include/lua5.1", "-g", "-O2", "-c", @@ -109,9 +115,9 @@ "unix/terminal_media_launcher-cache.o", "unix/cache.c" ], - "directory": "/home/louie/Documents/code/terminal-media-launcher/source/src", - "file": "/home/louie/Documents/code/terminal-media-launcher/source/src/unix/cache.c", - "output": "/home/louie/Documents/code/terminal-media-launcher/source/src/unix/terminal_media_launcher-cache.o" + "directory": "/home/louie/Documents/code/terminal-media-launcher/src", + "file": "/home/louie/Documents/code/terminal-media-launcher/src/unix/cache.c", + "output": "/home/louie/Documents/code/terminal-media-launcher/src/unix/terminal_media_launcher-cache.o" }, { "arguments": [ @@ -121,6 +127,7 @@ "-I..", "-D_DEFAULT_SOURCE", "-D_XOPEN_SOURCE=600", + "-I/usr/include/lua5.1", "-g", "-O2", "-c", @@ -128,9 +135,9 @@ "unix/terminal_media_launcher-draw.o", "unix/draw.c" ], - "directory": "/home/louie/Documents/code/terminal-media-launcher/source/src", - "file": "/home/louie/Documents/code/terminal-media-launcher/source/src/unix/draw.c", - "output": "/home/louie/Documents/code/terminal-media-launcher/source/src/unix/terminal_media_launcher-draw.o" + "directory": "/home/louie/Documents/code/terminal-media-launcher/src", + "file": "/home/louie/Documents/code/terminal-media-launcher/src/unix/draw.c", + "output": "/home/louie/Documents/code/terminal-media-launcher/src/unix/terminal_media_launcher-draw.o" }, { "arguments": [ @@ -140,6 +147,7 @@ "-I..", "-D_DEFAULT_SOURCE", "-D_XOPEN_SOURCE=600", + "-I/usr/include/lua5.1", "-g", "-O2", "-c", @@ -147,8 +155,8 @@ "unix/terminal_media_launcher-read_cfg.o", "unix/read_cfg.c" ], - "directory": "/home/louie/Documents/code/terminal-media-launcher/source/src", - "file": "/home/louie/Documents/code/terminal-media-launcher/source/src/unix/read_cfg.c", - "output": "/home/louie/Documents/code/terminal-media-launcher/source/src/unix/terminal_media_launcher-read_cfg.o" + "directory": "/home/louie/Documents/code/terminal-media-launcher/src", + "file": "/home/louie/Documents/code/terminal-media-launcher/src/unix/read_cfg.c", + "output": "/home/louie/Documents/code/terminal-media-launcher/src/unix/terminal_media_launcher-read_cfg.o" } ] diff --git a/configure.ac b/configure.ac index 81b0c42..f922ecf 100644 --- a/configure.ac +++ b/configure.ac @@ -7,12 +7,15 @@ AM_INIT_AUTOMAKE([foreign]) # Checks for programs. AC_PROG_CC +AX_PROG_LUA(,,,[AC_MSG_ERROR([requires lua])]) # Checks for libraries. AC_CHECK_LIB([ncurses], [initscr]) +AX_LUA_LIBS # Checks for header files. AC_CHECK_HEADERS([stdlib.h string.h unistd.h]) +AX_LUA_HEADERS # Checks for typedefs, structures, and compiler characteristics. AC_CHECK_HEADER_STDBOOL diff --git a/src/Makefile.am b/src/Makefile.am index 80a550c..7fbb284 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,8 +3,8 @@ EXTRA_DIST = include unix windows bin_PROGRAMS = terminal-media-launcher terminal_media_launcher_SOURCES = cache.c draw.c read_cfg.c group.c entry.c $(PLATFORM)/cache.c $(PLATFORM)/draw.c $(PLATFORM)/read_cfg.c -terminal_media_launcher_LDADD = @CURSES_LIBS@ -terminal_media_launcher_CPPFLAGS = @CURSES_CFLAGS@ +terminal_media_launcher_LDADD = @CURSES_LIBS@ @LUA_LIB@ +terminal_media_launcher_CPPFLAGS = @CURSES_CFLAGS@ @LUA_INCLUDE@ if WINDOWS PLATFORM=windows diff --git a/src/read_cfg.c b/src/read_cfg.c index f757d6b..fa8a424 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -43,12 +45,31 @@ bool cfg_interp(char *path){ int i=0; int j; + // check if file path exists fp = fopen(path, "r"); if(fp == NULL){ printf("Error: Invalid Configuration Path \"%s\"\n", path); return false; } + fclose(fp); + + // load lua configuration + lua_State *L = luaL_newstate(); + int config_load_status = luaL_dofile(L, path); + if(config_load_status != 0) { + printf("Error: could not load configuration \"%s\"\nis there a syntax error?\n", path); + return false; + } + + // demo + lua_getglobal(L, "Message"); + const char *message = lua_tostring(L, -1); + printf("message: %s\n", message); + + lua_close(L); + return true; + /* --- Old code --- */ //build the options array char **options = malloc(sizeof(char *) * OPTION_CNT); options[0] = "add"; diff --git a/src/unix/read_cfg.c b/src/unix/read_cfg.c index b40dd48..4e58863 100644 --- a/src/unix/read_cfg.c +++ b/src/unix/read_cfg.c @@ -20,8 +20,8 @@ char *find_config(){ int check_count = 2; int i; - sprintf(choices[0], "%s%c.config%cterminal-media-launcher%cconfig", home, sep, sep, sep); - sprintf(choices[1], "%s%c.terminal-media-launcher%cconfig", home, sep, sep); + sprintf(choices[0], "%s%c.config%cterminal-media-launcher%cconfig.lua", home, sep, sep, sep); + sprintf(choices[1], "%s%c.terminal-media-launcher%cconfig.lua", home, sep, sep); for(i = 0; i < check_count; i++){ strcpy(path, choices[i]); @@ -69,7 +69,7 @@ void mkconfig_wizard(char *path){ sprintf(path, "%s%c.config%cterminal-media-launcher%c", home, sep, sep, sep); mkdir(path, 0755); - sprintf(path, "%s%c.config%cterminal-media-launcher%cconfig", home, sep, sep, sep); + sprintf(path, "%s%c.config%cterminal-media-launcher%cconfig.lua", home, sep, sep, sep); //open file for writing, make sure non-NULL fp = fopen(path, "w"); diff --git a/src/windows/read_cfg.c b/src/windows/read_cfg.c index f973759..9fa721b 100644 --- a/src/windows/read_cfg.c +++ b/src/windows/read_cfg.c @@ -20,7 +20,7 @@ char *find_config(){ char choices[check_count][BUF_LEN]; int i; - sprintf(choices[0], "%s%cterminal-media-launcher%cconfig", appdata, sep, sep); + sprintf(choices[0], "%s%cterminal-media-launcher%cconfig.lua", appdata, sep, sep); for(i = 0; i < check_count; i++){ strcpy(path, choices[i]); @@ -72,7 +72,7 @@ void mkconfig_wizard(char *path){ sprintf(path, "%s%cterminal-media-launcher%c", appdata, sep, sep); mkdir(path); - sprintf(path, "%s%cterminal-media-launcher%cconfig", appdata, sep, sep); + sprintf(path, "%s%cterminal-media-launcher%cconfig.lua", appdata, sep, sep); //open file for writing, make sure non-NULL fp = fopen(path, "w"); -- cgit From a18a8b783d71859e01c550b0acf6e0cefbef0d9f Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Wed, 7 Aug 2024 22:34:44 -0400 Subject: Working demo for loading groups and entries from lua config --- .gitignore | 3 +++ src/include/read_cfg.h | 2 ++ src/read_cfg.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..540814b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.cache +*~ +*.tar.gz diff --git a/src/include/read_cfg.h b/src/include/read_cfg.h index df3e5bd..a76e55e 100644 --- a/src/include/read_cfg.h +++ b/src/include/read_cfg.h @@ -1,6 +1,8 @@ #ifndef READ_CFG_H #define READ_CFG_H +#include + #define BUF_LEN 1024 bool cfg_interp(char *path); diff --git a/src/read_cfg.c b/src/read_cfg.c index fa8a424..940630b 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -55,16 +55,51 @@ bool cfg_interp(char *path){ // load lua configuration lua_State *L = luaL_newstate(); - int config_load_status = luaL_dofile(L, path); + int config_load_status = luaL_loadfile(L, path); if(config_load_status != 0) { printf("Error: could not load configuration \"%s\"\nis there a syntax error?\n", path); return false; } + // set up base configuration variables + // TODO set helper variables and functions (e.g., so that Groups table doesn't need to be manually created in the user's config) + //lua_newtable(L); + //lua_setglobal(L, "Groups"); + lua_pcall(L, 0, 0, 0); + // demo - lua_getglobal(L, "Message"); - const char *message = lua_tostring(L, -1); - printf("message: %s\n", message); + lua_getglobal(L, "Groups"); + i = lua_gettop(L); + // add each group + const char *group_name; + lua_pushnil(L); + while(lua_next(L, i)) { + // the key is index -2, value is -1 + if(lua_type(L, -2) != LUA_TSTRING) continue; // skip if invalid key + group_name = lua_tostring(L, -2); + group_add(group_name, NULL); + // add each entry + if(lua_type(L, -1) != LUA_TTABLE) continue; // skip if invalid value + lua_pushstring(L, "Entries"); + lua_gettable(L, -2); + j = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, j)) { + if(lua_type(L, -1) != LUA_TSTRING) continue; // skip if invalid value + handle_fname(lua_tostring(L, -1), group_name, false, true, NULL, -1); + lua_pop(L, 1); + } + lua_pop(L, 2); + } + + //lua_getfield(L, -1, "Pictures"); + //lua_getfield(L, -1, "Entries"); + //lua_rawgeti(L, -1, 1); + //printf("message: %d\n", (int)lua_tonumber(L, -1)); + //lua_rawgeti(L, -2, 2); + //printf("message: %d\n", (int)lua_tonumber(L, -1)); + //lua_rawgeti(L, -3, 3); + //printf("message: %d\n", (int)lua_tonumber(L, -1)); lua_close(L); return true; @@ -89,6 +124,7 @@ bool cfg_interp(char *path){ //Read each line of "config" while(fgets(buffer, BUF_LEN, fp)){ + printf("%d\n", i); i++; check_line(buffer, options, i); } -- cgit From 9e999c82f830f48ebabc72338ef721154acd116a Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Wed, 7 Aug 2024 22:59:45 -0400 Subject: Small improvement towards setting launchers, but the current group class makes this a headache --- src/read_cfg.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/read_cfg.c b/src/read_cfg.c index 940630b..549393b 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -78,8 +78,16 @@ bool cfg_interp(char *path){ if(lua_type(L, -2) != LUA_TSTRING) continue; // skip if invalid key group_name = lua_tostring(L, -2); group_add(group_name, NULL); - // add each entry + // check for a launcher if(lua_type(L, -1) != LUA_TTABLE) continue; // skip if invalid value + lua_pushstring(L, "Launcher"); + lua_gettable(L, -2); + if(lua_type(L, -1) == LUA_TSTRING) { + // FIXME the groups '''API''' I built might need some improvements in order for this to not be a headache + //set_gprog(GROUP *g, lua_tostring(L, -1)) + } + lua_pop(L, 1); + // add each entry lua_pushstring(L, "Entries"); lua_gettable(L, -2); j = lua_gettop(L); -- cgit From 459a55528f8d2de726e75d8fc6119fcc3b4681b7 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Thu, 8 Aug 2024 20:52:18 -0400 Subject: Update .gitignore --- .gitignore | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/.gitignore b/.gitignore index 540814b..2093e21 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,64 @@ +# http://www.gnu.org/software/automake + +Makefile.in +/ar-lib +/mdate-sh +/py-compile +/test-driver +/ylwrap +.deps/ +.dirstamp + +# http://www.gnu.org/software/autoconf + +autom4te.cache +/autoscan.log +/autoscan-*.log +/aclocal.m4 +/compile +/config.cache +/config.guess +/config.h.in +/config.log +/config.status +/config.sub +/configure +/configure.scan +/depcomp +/install-sh +/missing +/stamp-h1 + +# https://www.gnu.org/software/libtool/ + +/ltmain.sh + +# http://www.gnu.org/software/texinfo + +/texinfo.tex + +# http://www.gnu.org/software/m4/ + +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 + +# Generated Makefile +# (meta build system like autotools, +# can automatically generate from config.status script +# (which is called by configure script)) +Makefile + +# Additional ignores .cache *~ *.tar.gz +config.h +nsis/installer.nsi +spec/terminal-media-launcher.spec +src/terminal-media-launcher +src/*.o +src/unix/*.o +src/windows/*.o -- cgit From 85596300cc45d73bd3335d8c802b7c590fb1e1d2 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Thu, 8 Aug 2024 21:24:54 -0400 Subject: Allow standard library in config --- src/read_cfg.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/read_cfg.c b/src/read_cfg.c index 549393b..a931a11 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -55,9 +56,11 @@ bool cfg_interp(char *path){ // load lua configuration lua_State *L = luaL_newstate(); - int config_load_status = luaL_loadfile(L, path); + luaL_openlibs(L); // allow for standard library to be used + int config_load_status = luaL_dofile(L, path); if(config_load_status != 0) { - printf("Error: could not load configuration \"%s\"\nis there a syntax error?\n", path); + printf("Error: could not load configuration \"%s\"\n", path); + lua_error(L); return false; } @@ -65,11 +68,15 @@ bool cfg_interp(char *path){ // TODO set helper variables and functions (e.g., so that Groups table doesn't need to be manually created in the user's config) //lua_newtable(L); //lua_setglobal(L, "Groups"); - lua_pcall(L, 0, 0, 0); + //lua_pcall(L, 0, 0, 0); // demo lua_getglobal(L, "Groups"); i = lua_gettop(L); + if(lua_type(L, i) != LUA_TTABLE) { + printf("Error in config: 'Groups' should be Table, is actually %s\n", lua_typename(L, lua_type(L, i))); + return 1; + } // add each group const char *group_name; lua_pushnil(L); -- cgit From 4e68f637300c0e360d49f8f672d0675d42da0d1f Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Sun, 11 Aug 2024 17:49:28 -0400 Subject: (Currently broken) reimplementation of group and entry --- src/draw.c | 27 ++- src/entry.c | 84 +------- src/group.c | 173 ++-------------- src/include/entry.h | 18 +- src/include/group.h | 24 +-- src/include/read_cfg.h | 17 +- src/read_cfg.c | 551 ++++++------------------------------------------- src/unix/read_cfg.c | 94 --------- 8 files changed, 121 insertions(+), 867 deletions(-) diff --git a/src/draw.c b/src/draw.c index 15a9289..1775329 100644 --- a/src/draw.c +++ b/src/draw.c @@ -42,7 +42,6 @@ int true_hover = 0; //0 = hovering on groups, 1 = hovering on entries GROUP **g; ENTRY **e; int g_count; -int e_count; int g_offset = 0; int *e_offset; @@ -70,15 +69,18 @@ int main(int argc, char **argv){ //Fill Groups //read the contents of the cfg file; print help message if invalid - if(!cfg_interp(cfg_path)){ + g = cfg_interp(cfg_path, &g_count); + if(g == NULL) { print_help(argv[0]); return 1; } + /* //Remove Empty Groups from the Array clean_groups(); g = get_groups(); //retrieve results of cfg_interp g_count = get_gcount(); //retrieve number of groups in g (only do this after removing empty groups) + */ //check that there are is at least one valid group if(g_count == 0){ @@ -91,7 +93,7 @@ int main(int argc, char **argv){ e_offset = calloc(g_count, sizeof(int)); //load cached data - load_cache(g_count, &g_hover, &e_hover, &e_offset, &true_hover, cfg_path); + //load_cache(g_count, &g_hover, &e_hover, &e_offset, &true_hover, cfg_path); //reopen stdout for drawing menu freopen("/dev/tty", "w", stdout); @@ -125,6 +127,7 @@ int main(int argc, char **argv){ update_display(true); //drawing is done, now run a while loop to receive input (ESC ends this loop) + input = 0; while(input != 27){ input = getch(); @@ -151,12 +154,12 @@ int main(int argc, char **argv){ case KEY_NPAGE: //case KEY_SDOWN: - trav_col((true_hover ? e_count : g_count)-1); + trav_col((true_hover ? get_ecount(g[g_hover]) : g_count)-1); break; case KEY_F(3): //jump to random group/entry - trav_col(rand() % (true_hover ? e_count : g_count)); + trav_col(rand() % (true_hover ? get_ecount(g[g_hover]) : g_count)); break; case KEY_F(5): @@ -333,13 +336,16 @@ void fill_col(int mode){ int i; WINDOW *col = (mode ? entry_win : group_win); - int count = (mode ? e_count : g_count); + int count = (mode ? get_ecount(g[g_hover]) : g_count); int offset = (mode ? e_offset[g_hover] : g_offset); int max_len = getmaxx(col)-2; //longest possible string length that can be displayed in the window int ycoord = 1; int max_y = HEIGHT-(6+GAP_SIZE); char *name; + mvwprintw(col, 0, 0, "i: %d\n", offset); + if(offset < 0) offset = 0; + for(i = 0+offset; i < count; i++){ if(ycoord >= max_y) break; //reached the bottom of the terminal window, stop drawing name = (mode ? get_ename(e[i]) : get_gname(g[i])); @@ -421,8 +427,7 @@ void update_col(int mode, int y_hl, bool resize){ break; case 1: - e_count = get_ecount(g[g_hover]); - e = get_entries(get_ghead(g[g_hover]), e_count); + e = get_gentries(g[g_hover]); fill_col(1); if(!resize) mvwchgat(entry_win, y_hl, 1, getmaxx(entry_win)-2, A_DIM, 1, NULL); else mvwchgat(entry_win, 1+e_hover[g_hover]-e_offset[g_hover], 1, getmaxx(entry_win)-2, A_DIM, (true_hover ? 2 : 1), NULL); @@ -464,7 +469,7 @@ void switch_col(){ void trav_col(int new_i){ int *focus = (true_hover ? &(e_hover[g_hover]) : &g_hover); //make it easy to know which column we are looking at int *offset = (true_hover ? &(e_offset[g_hover]) : &g_offset); - int count = (true_hover ? e_count : g_count); + int count = (true_hover ? get_ecount(g[g_hover]) : g_count); int max_hl = HEIGHT-(3+GAP_SIZE); //for some reason, this works int min_hl = 5; int oob_flag = 0; //0 = none, 1 = bottom, 2 = top @@ -520,7 +525,7 @@ int locateChar(char input){ if(fold_case && input >= 97 && input <= 122) input -= 32; if(true_hover){ //hovering on entries - for(i = location+1; i < e_count; i++){ + for(i = location+1; i < get_ecount(g[g_hover]); i++){ first_char = get_ename(e[i])[0]; if(fold_case && first_char >= 97 && first_char <= 122) first_char -= 32; if(input == first_char){ @@ -548,7 +553,7 @@ char *get_launch(){ char *program = get_gprog(g[g_hover]); char *flags = get_gflags(g[g_hover]); char *path = get_epath(e[e_hover[g_hover]]); - bool quotes = get_gquotes(g[g_hover]); + bool quotes = false; char *full_command = malloc(sizeof(char) * BUF_LEN); full_command[0] = '\0'; diff --git a/src/entry.c b/src/entry.c index 6dc5699..dceb424 100644 --- a/src/entry.c +++ b/src/entry.c @@ -7,18 +7,15 @@ #include #include "include/entry.h" -#include "include/group.h" #include "include/read_cfg.h" typedef struct entry{ char name[BUF_LEN]; char path[BUF_LEN]; bool path_force; - bool hidden; - struct entry *next; } ENTRY; -ENTRY *create_entry(char *new_name, char *new_path, bool force){ +ENTRY *create_entry(const char *new_name, const char *new_path, const bool force){ ENTRY *new; new = malloc(sizeof(ENTRY)); @@ -26,85 +23,15 @@ ENTRY *create_entry(char *new_name, char *new_path, bool force){ strcpy(new->name, new_name); strcpy(new->path, new_path); new->path_force = force; - new->hidden = false; - new->next = NULL; return new; } -void entry_rm(ENTRY *e, ENTRY *prev){ - assert(e != NULL); - if(prev != NULL) prev->next = e->next; //maintain linked structure - free(e); -} - -void clear_entries(ENTRY *head){ - ENTRY *temp; - - while(head != NULL){ - temp = head; - head = head->next; - free(temp); - } - - return; -} - -//returns 0 if in the middle, 1 if new head, 2 if new tail, or 3 if both new head and tail -//TODO this is kind of a stupid way of handling things -int entry_add(ENTRY *head, ENTRY *tail, ENTRY *add){ - assert(add != NULL); - ENTRY *ahead; - - //Empty group (no need to sort) - if(head == NULL) return 3; - - //add is the new tail - if(!get_sort() || strcmp(tail->name, add->name) <= 0){ - tail->next = add; - return 2; - } - - //add is the new head - if(strcmp(add->name, head->name) <= 0){ - add->next = head; - return 1; - } - - ahead = head->next; - - while(ahead != NULL){ - if(strcmp(head->name, add->name) <= 0 && strcmp(add->name, ahead->name) <= 0) break; - head = head->next; - ahead = ahead->next; - } - - head->next = add; - add->next = ahead; - - return 0; -} - -ENTRY **get_entries(ENTRY *head, int count){ - ENTRY **arr = malloc(sizeof(ENTRY *) * count); - ENTRY *trav = head; - int i = 0; - - while(i < count){ - if(!trav->hidden){ - arr[i] = trav; - i++; - } - trav = trav->next; - } - - return arr; -} - char *get_ename(ENTRY *e){ assert(e != NULL); return e->name; } + char *get_epath(ENTRY *e){ assert(e != NULL); return e->path; @@ -115,11 +42,7 @@ bool get_eforce(ENTRY *e){ return e->path_force; } -void set_hide(ENTRY *e, bool status){ - assert(e != NULL); - e->hidden = true; -} - +/* void entry_debug(ENTRY *trav){ while(trav != NULL){ @@ -129,3 +52,4 @@ void entry_debug(ENTRY *trav){ return; } +*/ diff --git a/src/group.c b/src/group.c index 0c0d5a0..edf4d7c 100644 --- a/src/group.c +++ b/src/group.c @@ -13,166 +13,27 @@ typedef struct group{ char name[BUF_LEN]; char program[BUF_LEN]; char flags[BUF_LEN]; - struct entry *head; - struct entry *tail; - struct group *next; + struct entry **entries; int entry_count; - bool launcher_quotes; //set by a group option whether or not the launcher should be wrapped by quotes + //bool launcher_quotes; //set by a group option whether or not the launcher should be wrapped by quotes } GROUP; -GROUP *groups_head; -GROUP *gp; //pointer to remember last group that was looked at int group_count = 0; int total_count = 0; -GROUP *create_group(char *new_name){ +GROUP *create_group(const char *new_name, const int entry_count){ GROUP *new = malloc(sizeof(GROUP)); strcpy(new->name, new_name); //by default, group name is equivalent to the path strcpy(new->program, "./"); //by default, launch an entry by executing it new->flags[0] = '\0'; //by default, no command line flags - new->head = NULL; - new->tail = NULL; - new->next = NULL; - new->entry_count = 0; - new->launcher_quotes = true; + new->entries = malloc(sizeof(ENTRY *) * entry_count); + new->entry_count = entry_count; group_count++; return new; } -//add an entry to a group or add a new empty group -//FIXME maybe make this function part of a seperate file to handle a tree (AVL?) -//for now, simple linked list implementation -void group_add(char *gname, ENTRY *addme){ - int i; - GROUP *new; - GROUP *last = NULL; //last element in an existing group list (NULL to start) - - //only adding a new group - if(addme == NULL){ - gp = groups_head; - while(gp != NULL){ - if(!(strcmp(gp->name, gname))){ - printf("config error: %s is already a group!\n", gname); - return; - } - - last = gp; - gp = gp->next; - } - } - - //The previous group is not the same as the new group to add to - if(!(gp != NULL && (!(strcmp(gp->name, gname))))){ - gp = groups_head; - while(gp != NULL){ - //gname matches groups[i]'s name, add entry here - if(!(strcmp(gp->name, gname))) break; - - last = gp; - gp = gp->next; - } - } - - //was unable to find a matching existing group - //need to create new group to insert the entry into - if(gp == NULL){ - new = create_group(gname); - - //first group - if(last == NULL) groups_head = new; - - //add to the end of the groups - else last->next = new; - - gp = new; - } - - //add the entry to the list of entries in the group - if(addme != NULL){ - i = entry_add(gp->head, gp->tail, addme); - switch(i){ - case 1: - gp->head = addme; - break; - - case 2: - gp->tail = addme; - break; - - case 3: - gp->head = addme; - gp->tail = addme; - break; - - } - - gp->entry_count++; - total_count++; - } - - return; -} - -void group_rm(GROUP *g){ - - clear_entries(g->head); - - free(g); - group_count--; - return; -} - -void clean_groups(){ - GROUP *dummy_head; - GROUP *trav; - GROUP *hold; - - if(group_count == 0){ - printf("Error: no groups! "); - refer_to_doc(); - exit(0); - } - - else{ - dummy_head = create_group("dummy"); - dummy_head->next = groups_head; - trav = dummy_head; - - while(trav != NULL){ - //found empty group for removal - if(trav->next != NULL && trav->next->entry_count < 1){ - printf("Omitting empty group \"%s\"\n", trav->next->name); - hold = trav->next; - trav->next = trav->next->next; - group_rm(hold); - } - else trav = trav->next; - } - } - - //ensure groups->head is still correct - groups_head = dummy_head->next; - group_rm(dummy_head); - return; - -} - - -GROUP **get_groups(){ - GROUP **arr = malloc(sizeof(GROUP *) * group_count); - GROUP *trav = groups_head; - int i; - - for(i = 0; i < group_count; i++){ - arr[i] = trav; - trav = trav->next; - } - - return arr; -} - char *get_gname(GROUP *g){ assert(g != NULL); return g->name; @@ -199,9 +60,14 @@ void set_gflags(GROUP *g, char *p){ strcpy(g->flags, p); } -ENTRY *get_ghead(GROUP *g){ +ENTRY **get_gentries(GROUP *g) { + assert(g != NULL); + return g->entries; +} + +void set_gentry(GROUP *g, int entry_index, ENTRY *new_entry) { assert(g != NULL); - return g->head; + g->entries[entry_index] = new_entry; } int get_ecount(GROUP *g){ @@ -214,19 +80,7 @@ void set_ecount(GROUP *g, int new_count){ g->entry_count = new_count; } -void set_gquotes(GROUP *g, bool b){ - assert(g != NULL); - g->launcher_quotes = b; -} - -bool get_gquotes(GROUP *g){ - return g->launcher_quotes; -} - -int get_gcount(){ - return group_count; -} - +/* void group_debug(){ GROUP *trav = groups_head; @@ -238,3 +92,4 @@ void group_debug(){ return; } +*/ diff --git a/src/include/entry.h b/src/include/entry.h index 51e43ca..a46dc46 100644 --- a/src/include/entry.h +++ b/src/include/entry.h @@ -1,17 +1,11 @@ +#include + #ifndef ENTRY_H #define ENTRY_H typedef struct entry ENTRY; -ENTRY *create_entry(char *new_name, char *new_path, bool force); - -void entry_rm(ENTRY *e, ENTRY *prev); - -void clear_entries(ENTRY *head); - -int entry_add(ENTRY *head, ENTRY *tail, ENTRY *add); - -ENTRY **get_entries(ENTRY *head, int count); +ENTRY *create_entry(const char *new_name, const char *new_path, const bool force); char *get_ename(ENTRY *e); @@ -19,10 +13,4 @@ char *get_epath(ENTRY *e); bool get_eforce(ENTRY *e); -void set_hide(ENTRY *e, bool status); - -bool get_hide(ENTRY *e); - -void entry_debug(ENTRY *trav); - #endif diff --git a/src/include/group.h b/src/include/group.h index ab6f409..dc74bcc 100644 --- a/src/include/group.h +++ b/src/include/group.h @@ -1,17 +1,13 @@ #ifndef GROUP_H #define GROUP_H -typedef struct group GROUP; - -GROUP *create_group(char *new_name); - -void group_add(char *gname, ENTRY *addme); +#include -void group_rm(GROUP *g); +#include "entry.h" -void clean_groups(); //remove empty groups from linked list +typedef struct group GROUP; -GROUP **get_groups(); +GROUP *create_group(const char *new_name, const int entry_count); char *get_gname(GROUP *g); @@ -23,18 +19,12 @@ char *get_gflags(GROUP *g); void set_gflags(GROUP *g, char *p); -ENTRY *get_ghead(GROUP *g); +ENTRY **get_gentries(GROUP *g); + +void set_gentry(GROUP *g, int entry_index, ENTRY *new_entry); int get_ecount(GROUP *g); void set_ecount(GROUP *g, int new_count); //for use in hiding entries -void set_gquotes(GROUP *g, bool b); - -bool get_gquotes(GROUP *g); - -int get_gcount(); - -void group_debug(); //debug function to output all groups - #endif diff --git a/src/include/read_cfg.h b/src/include/read_cfg.h index a76e55e..fc40cc0 100644 --- a/src/include/read_cfg.h +++ b/src/include/read_cfg.h @@ -3,23 +3,24 @@ #include +#include "group.h" + #define BUF_LEN 1024 -bool cfg_interp(char *path); +GROUP **cfg_interp(char *path, int *group_count); bool get_sort(); bool get_case_sensitivity(); void refer_to_doc(); -void addme(char *path, char *group, bool force, char *name); -int search_ch(char *str, char c); -int search_last_ch(char *str, char c); -int wild_cmp(char *wild, char *literal); -char *strip_quotes(char *str); -void error_mes(int ln, char *message); +//void addme(char *path, char *group, bool force, char *name); +//int search_ch(char *str, char c); +//int search_last_ch(char *str, char c); +//int wild_cmp(char *wild, char *literal); +//char *strip_quotes(char *str); +//void error_mes(int ln, char *message); //functions that differ by os extern char sep; char *find_config(); void mkconfig_wizard(char *path); -void handle_fname(char *path, char *group, bool recurs, bool force, char *name, int ln); #endif diff --git a/src/read_cfg.c b/src/read_cfg.c index a931a11..b9ac8bc 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -22,9 +22,11 @@ #define OPTION_CNT 14 //private -void check_line(char *buffer, char **options, int ln); -int check_option(char *arg, char **options); -char *autoAlias(char *path); +//void check_line(char *buffer, char **options, int ln); +//int check_option(char *arg, char **options); +int key_count(lua_State *L, int table_stack_index); // counts the number of keys in a table +void add_groups(lua_State *L, int table_stack_index, GROUP ***g); +void add_entries(lua_State *L, int table_stack_index, GROUP *g); //turn on or off sorting (A-Z); On by default bool sort = true; @@ -36,21 +38,20 @@ bool hr = false; bool fold_case = true; //return false if invalid path -bool cfg_interp(char *path){ +GROUP **cfg_interp(char *path, int *group_count){ FILE *fp; char buffer[BUF_LEN]; GROUP **g; - ENTRY **e; - int count; - int e_count; - int i=0; + const char *group_name; + //ENTRY **e; + int i; int j; // check if file path exists fp = fopen(path, "r"); if(fp == NULL){ printf("Error: Invalid Configuration Path \"%s\"\n", path); - return false; + return NULL; } fclose(fp); @@ -61,7 +62,7 @@ bool cfg_interp(char *path){ if(config_load_status != 0) { printf("Error: could not load configuration \"%s\"\n", path); lua_error(L); - return false; + exit(1); } // set up base configuration variables @@ -75,95 +76,17 @@ bool cfg_interp(char *path){ i = lua_gettop(L); if(lua_type(L, i) != LUA_TTABLE) { printf("Error in config: 'Groups' should be Table, is actually %s\n", lua_typename(L, lua_type(L, i))); - return 1; - } - // add each group - const char *group_name; - lua_pushnil(L); - while(lua_next(L, i)) { - // the key is index -2, value is -1 - if(lua_type(L, -2) != LUA_TSTRING) continue; // skip if invalid key - group_name = lua_tostring(L, -2); - group_add(group_name, NULL); - // check for a launcher - if(lua_type(L, -1) != LUA_TTABLE) continue; // skip if invalid value - lua_pushstring(L, "Launcher"); - lua_gettable(L, -2); - if(lua_type(L, -1) == LUA_TSTRING) { - // FIXME the groups '''API''' I built might need some improvements in order for this to not be a headache - //set_gprog(GROUP *g, lua_tostring(L, -1)) - } - lua_pop(L, 1); - // add each entry - lua_pushstring(L, "Entries"); - lua_gettable(L, -2); - j = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, j)) { - if(lua_type(L, -1) != LUA_TSTRING) continue; // skip if invalid value - handle_fname(lua_tostring(L, -1), group_name, false, true, NULL, -1); - lua_pop(L, 1); - } - lua_pop(L, 2); + exit(1); } - //lua_getfield(L, -1, "Pictures"); - //lua_getfield(L, -1, "Entries"); - //lua_rawgeti(L, -1, 1); - //printf("message: %d\n", (int)lua_tonumber(L, -1)); - //lua_rawgeti(L, -2, 2); - //printf("message: %d\n", (int)lua_tonumber(L, -1)); - //lua_rawgeti(L, -3, 3); - //printf("message: %d\n", (int)lua_tonumber(L, -1)); + // create the group array + *group_count = key_count(L, i); + g = malloc(sizeof(GROUP *) * (*group_count)); + // add each group (which also adds each entry to each group) + add_groups(L, i, &g); lua_close(L); - return true; - - /* --- Old code --- */ - //build the options array - char **options = malloc(sizeof(char *) * OPTION_CNT); - options[0] = "add"; - options[1] = "addF"; - options[2] = "addGroup"; - options[3] = "addName"; - options[4] = "addNameF"; - options[5] = "addR"; - options[6] = "autoAlias"; - options[7] = "foldCase"; - options[8] = "hide"; - options[9] = "hideFile"; - options[10] = "setFlags"; - options[11] = "setLauncher"; - options[12] = "setLauncherRaw"; - options[13] = "sort"; - - //Read each line of "config" - while(fgets(buffer, BUF_LEN, fp)){ - printf("%d\n", i); - i++; - check_line(buffer, options, i); - } - - //cleanup - free(options); - - /* - //DEBUG: test to see if the list was added to properly - g = get_groups(); - count = get_gcount(); - for(i = 0; i < count; i++){ - printf("Looking at group %s\n", get_gname(g[i])); - e_count = get_ecount(g[i]); - e = get_entries(get_ghead(g[i]), e_count); - for(j = 0; j < e_count; j++){ - printf("\t%s\n", get_ename(e[j])); - } - } - //END DEBUG - */ - - fclose(fp); - return true; + return g; } bool get_sort(){ @@ -179,409 +102,71 @@ void refer_to_doc(){ return; } -void addme(char *path, char *group, bool force, char *name){ - ENTRY *new; - char auto_name[BUF_LEN]; - - //check if a name was given as argument - if(name != NULL){ - //strip quotes from the name - name = strip_quotes(name); - new = create_entry(name, path, force); - } - - //check if autoAlias is on. If it is, go to the autoAlias function - else if(hr){ - strcpy(auto_name, autoAlias(path)); - new = create_entry(auto_name, path, force); - } - - else new = create_entry(path, path, force); - if(new != NULL) group_add(group, new); - - return; -} - -int search_ch(char *str, char c){ - int i = 0; - - while(str[i] != '\0'){ - if(str[i] == c) return i; - i++; - } - - return -1; -} - -int search_last_ch(char *str, char c){ - int i = 0; - int last_i = -1; +int key_count(lua_State *L, int table_stack_index) { + int output = 0; - while(str[i] != '\0'){ - if(str[i] == c) last_i = i; - i++; + lua_pushnil(L); + while(lua_next(L, table_stack_index)) { + // uses 'key' (at index -2) and 'value' (at index -1) + if(lua_type(L, -2) == LUA_TSTRING) ++output; + lua_pop(L, 1); } - return last_i; + return output; } -//return 0 if match, 1 if not -//TODO only supports one wildcard per entry -int wild_cmp(char *wild, char *literal){ +void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { + const char *group_name; + int entry_table_stack_index; int i; - - while(*wild != '\0'){ - //traverse until wildcard - if(*wild != '*'){ - if(*wild != *literal) return 1; - wild++; - literal++; - } - - //found wildcard, find the end of both names and comapre from the back - else{ - i = 0; - wild++; - while(*wild != '\0'){ - i++; - wild++; - } - while(*literal != '\0'){ - literal++; - } - - while(i > 0){ - wild--; - literal--; - if(*wild != *literal) return 1; - i--; - } - - return 0; - } - } - - return 0; -} - - -char *strip_quotes(char *str){ - char *stripped_str = malloc(sizeof(char) * BUF_LEN); - - if(str[0] == '"'){ - stripped_str = &str[1]; - stripped_str[strlen(stripped_str) - 1] = '\0'; - return stripped_str; - } - - return str; -} - -void error_mes(int ln, char *message){ - - assert(message != NULL); - - printf("Configuration File Error:\nOn line %d: %s\n\n", ln, message); - - return; -} - -//TODO add support for "addR" recursive adding (still needs work...) -//TODO add support for "alias" option -//TODO add support for "hide" option -void check_line(char *buffer, char **options, int ln){ - char *delims = " \t\n"; - char *tok = strtok(buffer, delims); - char args[MAX_ARGS][BUF_LEN]; - GROUP **g; - ENTRY **e; - char *tok_p; - char *arg_p; - int g_count; - int e_count; - int search_res; - int i, j; - char *error_p; //helper for complex error messages - - //ensure line is not blank or commented out - if(tok != NULL && tok[0] != '#' && tok[0] != '\0'){ - //initialize args to 0 - for(i = 0; i < MAX_ARGS; i++){ - args[i][0] = '\0'; - } - - i = 0; - //record all arguments in the line - while(tok != NULL){ - if(i >= MAX_ARGS){ - error_mes(ln, "Too many arguments"); - return; - } - strcpy(args[i], tok); - //handle if an argument has spaces and is wrapped in quotes - if(tok[0] == '"'){ - arg_p = &args[i][0]; - tok_p = &tok[1]; - - while(*tok_p != '"'){ - switch(*tok_p){ - - - case '\0': - tok = strtok(NULL, delims); - tok_p = &tok[0]; - *arg_p = ' '; - arg_p++; - break; - case '\\': - tok_p++; - - default: - *arg_p = *tok_p; - tok_p++; - arg_p++; - - } + lua_pushnil(L); + i = 0; + while(lua_next(L, table_stack_index)) { + // uses 'key' (at index -2) and 'value' (at index -1) + // looking at Groups.TABLE_NAME + if(lua_type(L, -2) == LUA_TSTRING && lua_type(L, -1) == LUA_TTABLE) { + group_name = lua_tostring(L, -2); + if(group_name != NULL) { + // push the Entries table on the stack (to get entry information) + lua_pushstring(L, "Entries"); + // get table Groups.TABLE_NAME.Entries + lua_gettable(L, -2); + entry_table_stack_index = lua_gettop(L); + // check that 'Entries' is a table + if(lua_type(L, entry_table_stack_index) != LUA_TTABLE) { + printf("Error in config: 'Entries' should be Table, is actually %s\n", lua_typename(L, lua_type(L, entry_table_stack_index))); + exit(1); } - - *arg_p = '\0'; - + (*g)[i] = create_group(group_name, key_count(L, entry_table_stack_index)); + // add entries to this group + add_entries(L, entry_table_stack_index, (*g)[i]); } - - tok = strtok(NULL, delims); - i++; - } - - //optimally check which option was specified - search_res = check_option(args[0], options); - - switch(search_res){ - - case 0: //add - //add entry(ies) to a group: first arg is the file(s), second arg is the group to add to - //TODO add sorting functionality - handle_fname(args[1], args[2], 0, 0, NULL, ln); - break; - - case 1: //addF - //force add entry to a group: first arg is the file(s), second arg is the group to add to - handle_fname(args[1], args[2], 0, 1, NULL, ln); - break; - - case 2: //addGroup - //create a new group - group_add(strip_quotes(args[1]), NULL); - break; - - case 3: //addName - //add entry to a group: first arg is the name, second arg is the file, and third arg is the group to add to - handle_fname(args[2], args[3], 0, 0, args[1], ln); - break; - - case 4: //addNameF - //same as addName, but with force on - handle_fname(args[2], args[3], 0, 1, args[1], ln); - break; - - case 5: //addR - //recursively add: that is, also search directories in the given path - //NOTE: experimental - handle_fname(args[1], args[2], 1, 0, NULL, ln); - break; - - case 6: //autoAlias - if(!(strcmp(args[1], "on"))) hr = true; - else if(!(strcmp(args[1], "off"))) hr = false; - break; - - case 7: //foldCase (case insensitive) - if(!(strcmp(args[1], "on"))) fold_case = true; - else if(!(strcmp(args[1], "off"))) fold_case = false; - break; - - //TODO consider having this call handle_fname instead so that '*' can be used - case 8: //hide - case 9: //hideFile - //args[2] is referring to a group - g = get_groups(); - g_count = get_gcount(); - - //look for matching existing group - for(i = 0; i < g_count; i++){ - if(!(strcmp(get_gname(g[i]), args[2]))) break; - } - - if(i < g_count){ - e_count = get_ecount(g[i]); - e = get_entries(get_ghead(g[i]), e_count); - - for(j = 0; j < e_count; j++){ - if(!strcmp((search_res == 8 ? get_ename(e[j]) : get_epath(e[j])), strip_quotes(args[1]))) break; - } - - if(j < e_count){ - set_hide(e[j], true); - set_ecount(g[i], get_ecount(g[i])-1); - } - else{ - error_p = malloc(sizeof(char) * 1024); - sprintf(error_p, "Entry \"%s\" does not exist", args[1]); - error_mes(ln, error_p); - free(error_p); - } - } - - else{ - error_p = malloc(sizeof(char) * 1024); - sprintf(error_p, "Group \"%s\" does not exist", args[2]); - error_mes(ln, error_p); - free(error_p); - } - break; - - case 10: //setFlags - //args[1] is referring to a group - g = get_groups(); - g_count = get_gcount(); - - //look for matching existing group - for(i = 0; i < g_count; i++){ - if(!(strcmp(get_gname(g[i]), args[1]))) break; - } - - //set a group's launcher flags (like ./program -f file for fullscreen) - //assert that a matching group was found - if(i < g_count) set_gflags(g[i], strip_quotes(args[2])); - else{ - error_p = malloc(sizeof(char) * 1024); - sprintf(error_p, "Group \"%s\" does not exist", args[1]); - error_mes(ln, error_p); - free(error_p); - } - break; - - case 11: //setLauncher - case 12: //setLauncherRaw - //args[1] is referring to a group - g = get_groups(); - g_count = get_gcount(); - - //look for matching existing group - for(i = 0; i < g_count; i++){ - if(!(strcmp(get_gname(g[i]), args[1]))) break; - } - - //set a group's launcher (this requires pulling down the existing groups and finding the one that args[1] mentions) - //assert that a matching group was found - if(i < g_count){ - set_gprog(g[i], strip_quotes(args[2])); - if(search_res == 12) set_gquotes(g[i], false); //FIXME don't forget to change this line if adding more options!!! - } - else{ - error_p = malloc(sizeof(char) * 1024); - sprintf(error_p, "Group \"%s\" does not exist", args[1]); - error_mes(ln, error_p); - free(error_p); - } - break; - - case 13: //sort - if(!(strcmp(args[1], "on"))) sort = true; - else if(!(strcmp(args[1], "off"))) sort = false; - break; - - default: - error_p = malloc(sizeof(char) * 1024); - sprintf(error_p, "Unknown config option \"%s\"", args[0]); - error_mes(ln, error_p); - free(error_p); - } - - } - - return; -} - -int check_option(char *arg, char **options){ - int min = 0; - int max = OPTION_CNT-1; - int hover; - int comp_res; - - while(max - min > 1){ - hover = min + (max-min)/2; - comp_res = strcmp(arg, options[hover]); - - if(comp_res > 0) min = hover; - else if(comp_res < 0) max = hover; - else return hover; + lua_pop(L, 1); + ++i; } - - if(max == OPTION_CNT-1 && strcmp(arg, options[max]) == 0) return max; - else if(min == 0 && strcmp(arg, options[min]) == 0) return min; - - return -1; } +void add_entries(lua_State *L, int table_stack_index, GROUP *g) { + const char *entry_name; + int i; -char *autoAlias(char *path){ - char *hr_name = malloc(sizeof(char) * BUF_LEN); - char *p = hr_name; - char *rpath; //necessary so as not to touch the actual path - char *last_dot = NULL; //used to trim the file extension (if there is one) - bool stop = false; //stop when you don't want to add a series of chars to the output - - //get to the relative path name - rpath = strrchr(path, sep); - if(rpath == NULL) rpath = path; - else rpath++; - - while(*rpath != '\0'){ - switch(*rpath){ - case '(': - stop = true; - break; - - case ')': - stop = false; - break; - - case '-': - case '_': - if(*(p-1) != ' ' && !stop){ - *p = ' '; - *p++; - } - break; - - case ' ': - if(*(p-1) != ' ' && !stop){ - *p = *rpath; - *p++; - } - break; - - case '.': - last_dot = p; - - default: - if(!stop){ - *p = *rpath; - *p++; - } + lua_pushnil(L); + i = 0; + while(lua_next(L, table_stack_index)) { + // uses 'key' (at index -2) and 'value' (at index -1) + // looking at Groups.TABLE_NAME.Entries[i] + if(lua_type(L, -1) == LUA_TSTRING) { + entry_name = lua_tostring(L, -1); + if(entry_name != NULL) { + set_gentry(g, i, create_entry(entry_name, entry_name, true)); + } } - *rpath++; + lua_pop(L, 1); + ++i; } - - //close the name - if(last_dot != NULL) *last_dot = '\0'; - else if(*path == '"') *(p-1) = '\0'; //close early to avoid including closing quote - else *p = '\0'; - return hr_name; + // one last pop to pop the key off + lua_pop(L, 1); } - - - diff --git a/src/unix/read_cfg.c b/src/unix/read_cfg.c index 4e58863..6f75ddc 100644 --- a/src/unix/read_cfg.c +++ b/src/unix/read_cfg.c @@ -137,97 +137,3 @@ void mkconfig_wizard(char *path){ return; } - -//TODO augment to involve recurs -//TODO could use some cleanup... -void handle_fname(char *path, char *group, bool recurs, bool force, char *name, int ln){ - ENTRY *new; - char *search; //pointer for traversing path - char full_path_cpy[BUF_LEN]; - char relative_path_cpy[BUF_LEN]; - char arg_cpy[BUF_LEN]; - char auto_name[BUF_LEN]; - int plen = strlen(path); - char *dirname; - char *local_arg; //for use in addR - DIR *dp; - struct dirent *fname; - int i; - char *error_p; //helper for complex error messages - - assert(path != NULL && group != NULL); - - if(path[0] == '\0' || group[0] == '\0'){ - error_mes(ln, "Too few arguments for \"add\""); - return; - } - - //address potential quotes - strcpy(full_path_cpy, strip_quotes(path)); - - //don't check that the path arg is valid when forced - if(force) addme(full_path_cpy, group, force, name); - - //file is not recognized, perhaps it has a wildcard? - //TODO finish rewriting a more robust wildcard thingy - else if(access(full_path_cpy, F_OK) == -1){ - i = search_ch(full_path_cpy, '*'); - if(i > -1){ - //look for a directory - while(full_path_cpy[i] != sep && (i >= 0)){ - i--; - } - dirname = full_path_cpy; - strcpy(arg_cpy, full_path_cpy); - dirname[i+1] = '\0'; - dp = opendir(dirname); - - //the directory is real - if(dp != NULL){ - while((fname = readdir(dp))){ - relative_path_cpy[0] = '\0'; - strcat(relative_path_cpy, dirname); - strcat(relative_path_cpy, fname->d_name); - - //check if path is a file (and not a directory/symlink/etc.) and regex matches - if(fname->d_type == DT_REG && !(wild_cmp(&arg_cpy[i+1], fname->d_name))) addme(relative_path_cpy, group, force, name); - - //if the recursive option was specified and the path is a directory, run handle_fname on this directory, but for security reasons, do not consider directories that start with a '.' - else if(recurs && fname->d_type == DT_DIR && fname->d_name[0] != '.'){ - i = search_last_ch(arg_cpy, sep); - local_arg = &arg_cpy[i+1]; - strcat(relative_path_cpy, &sep); - strcat(relative_path_cpy, local_arg); - handle_fname(relative_path_cpy, group, 1, 0, NULL, ln); - } - - } - - closedir(dp); - } - - //directory is not real, report error to the user - else{ - error_p = malloc(sizeof(char) * 1024); - sprintf(error_p, "\"%s\" bad path", dirname); - error_mes(ln, error_p); - free(error_p); - //printf("Error: \"%s\" bad path\n", dirname); - } - } - - //path is not real, report error to the user - else{ - error_p = malloc(sizeof(char) * 1024); - sprintf(error_p, "\"%s\" bad path", full_path_cpy); - error_mes(ln, error_p); - free(error_p); - } - } - - //file name is okay - //FIXME does not take into account whether the argument is a file (could be a directory, symlink, etc.) - else addme(full_path_cpy, group, force, name); - - return; -} -- cgit From b5dd0df1808429a3c0ed1f86256962512b8273f5 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Tue, 13 Aug 2024 21:06:03 -0400 Subject: Working implementation for lua config --- src/draw.c | 26 +++++++------- src/group.c | 17 +++------ src/include/cache.h | 2 ++ src/include/draw.h | 5 ++- src/include/group.h | 3 ++ src/include/read_cfg.h | 6 ---- src/read_cfg.c | 70 +++++++++++++++++++++++++++++++------ src/windows/read_cfg.c | 93 -------------------------------------------------- 8 files changed, 86 insertions(+), 136 deletions(-) diff --git a/src/draw.c b/src/draw.c index 1775329..99b1a74 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -40,7 +41,6 @@ int g_hover = 0; int *e_hover; int true_hover = 0; //0 = hovering on groups, 1 = hovering on entries GROUP **g; -ENTRY **e; int g_count; int g_offset = 0; int *e_offset; @@ -74,6 +74,10 @@ int main(int argc, char **argv){ print_help(argv[0]); return 1; } + // DEBUG + //for(i = 0; i < g_count; ++i) { + // group_debug(g[i]); + //} /* //Remove Empty Groups from the Array @@ -335,6 +339,7 @@ void fill_col(int mode){ //mode 1 = entry int i; + ENTRY **entries = get_gentries(g[g_hover]); WINDOW *col = (mode ? entry_win : group_win); int count = (mode ? get_ecount(g[g_hover]) : g_count); int offset = (mode ? e_offset[g_hover] : g_offset); @@ -343,15 +348,12 @@ void fill_col(int mode){ int max_y = HEIGHT-(6+GAP_SIZE); char *name; - mvwprintw(col, 0, 0, "i: %d\n", offset); - if(offset < 0) offset = 0; - for(i = 0+offset; i < count; i++){ if(ycoord >= max_y) break; //reached the bottom of the terminal window, stop drawing - name = (mode ? get_ename(e[i]) : get_gname(g[i])); + name = (mode ? get_ename(entries[i]) : get_gname(g[i])); //the name is too long, take the group to the trimming function - if(strlen(name) > max_len) name = trim_name(name, (mode ? get_epath(e[i]) : get_gname(g[i])), max_len); + if(strlen(name) > max_len) name = trim_name(name, (mode ? get_epath(entries[i]) : get_gname(g[i])), max_len); wmove(col, ycoord, 1); wprintw(col, "%s", name); ycoord++; @@ -427,7 +429,6 @@ void update_col(int mode, int y_hl, bool resize){ break; case 1: - e = get_gentries(g[g_hover]); fill_col(1); if(!resize) mvwchgat(entry_win, y_hl, 1, getmaxx(entry_win)-2, A_DIM, 1, NULL); else mvwchgat(entry_win, 1+e_hover[g_hover]-e_offset[g_hover], 1, getmaxx(entry_win)-2, A_DIM, (true_hover ? 2 : 1), NULL); @@ -483,7 +484,6 @@ void trav_col(int new_i){ mvwchgat(group_win, 1+g_hover-g_offset, 1, getmaxx(group_win)-2, A_NORMAL, 0, NULL); *focus = new_i; - //check offsets relating to new highlight, make sure highlight did not go oob while(*focus-*offset+5 > max_hl){ (*offset)++; @@ -517,6 +517,7 @@ void trav_col(int new_i){ } int locateChar(char input){ + ENTRY **entries = get_gentries(g[g_hover]); int location = (true_hover ? e_hover[g_hover] : g_hover); bool fold_case = get_case_sensitivity(); char first_char; @@ -526,7 +527,7 @@ int locateChar(char input){ if(true_hover){ //hovering on entries for(i = location+1; i < get_ecount(g[g_hover]); i++){ - first_char = get_ename(e[i])[0]; + first_char = get_ename(entries[i])[0]; if(fold_case && first_char >= 97 && first_char <= 122) first_char -= 32; if(input == first_char){ location = i; @@ -550,13 +551,12 @@ int locateChar(char input){ } char *get_launch(){ + ENTRY **entries = get_gentries(g[g_hover]); char *program = get_gprog(g[g_hover]); char *flags = get_gflags(g[g_hover]); - char *path = get_epath(e[e_hover[g_hover]]); + char *path = get_epath(entries[e_hover[g_hover]]); bool quotes = false; - char *full_command = malloc(sizeof(char) * BUF_LEN); - - full_command[0] = '\0'; + char *full_command = calloc(BUF_LEN, sizeof(char)); //if the entry is an executable file (doesn't have a launcher) if(!(strcmp(program, "./"))){ diff --git a/src/group.c b/src/group.c index edf4d7c..1d1ebd2 100644 --- a/src/group.c +++ b/src/group.c @@ -80,16 +80,9 @@ void set_ecount(GROUP *g, int new_count){ g->entry_count = new_count; } -/* -void group_debug(){ - GROUP *trav = groups_head; - - while(trav != NULL){ - entry_debug(trav->head); - printf("\tfrom group %s\n", trav->name); - trav = trav->next; - } - - return; +void group_debug(GROUP *g){ + printf("Entering group: %s\n", get_gname(g)); + printf("\tProgram: %s\n", get_gprog(g)); + printf("\tFlags: %s\n", get_gflags(g)); + printf("\tEntry Count: %d\n", get_ecount(g)); } -*/ diff --git a/src/include/cache.h b/src/include/cache.h index 894e4e1..701691f 100644 --- a/src/include/cache.h +++ b/src/include/cache.h @@ -1,6 +1,8 @@ #ifndef CACHE_H #define CACHE_H +#include + void save_to_cache(int g_count, int g_hover, int *e_hover, int *e_offset, int true_hover, char *cfg_name); void load_cache(int g_count, int *g_hover, int **e_hover, int **e_offset, int *true_hover, char *new_cfg_name); diff --git a/src/include/draw.h b/src/include/draw.h index 387ced3..022abe5 100644 --- a/src/include/draw.h +++ b/src/include/draw.h @@ -5,11 +5,14 @@ #define BUF_LEN 1024 +// currently selected group extern int g_hover; +// array of currently selected entries for each group extern int *e_hover; +// array of groups (as loaded from the config) extern struct group **g; -extern struct entry **e; +// returns the command to run for the current entry char *get_launch(); //functions that differ between os diff --git a/src/include/group.h b/src/include/group.h index dc74bcc..89a8422 100644 --- a/src/include/group.h +++ b/src/include/group.h @@ -27,4 +27,7 @@ int get_ecount(GROUP *g); void set_ecount(GROUP *g, int new_count); //for use in hiding entries +// print all group and entry information +void group_debug(GROUP *g); + #endif diff --git a/src/include/read_cfg.h b/src/include/read_cfg.h index fc40cc0..29a36e7 100644 --- a/src/include/read_cfg.h +++ b/src/include/read_cfg.h @@ -11,12 +11,6 @@ GROUP **cfg_interp(char *path, int *group_count); bool get_sort(); bool get_case_sensitivity(); void refer_to_doc(); -//void addme(char *path, char *group, bool force, char *name); -//int search_ch(char *str, char c); -//int search_last_ch(char *str, char c); -//int wild_cmp(char *wild, char *literal); -//char *strip_quotes(char *str); -//void error_mes(int ln, char *message); //functions that differ by os extern char sep; diff --git a/src/read_cfg.c b/src/read_cfg.c index b9ac8bc..97a76ff 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -24,9 +24,11 @@ //private //void check_line(char *buffer, char **options, int ln); //int check_option(char *arg, char **options); -int key_count(lua_State *L, int table_stack_index); // counts the number of keys in a table +int get_group_count(lua_State *L, int table_stack_index); // counts the number of valid groups +int get_entry_count(lua_State *L, int table_stack_index); // counts the number of valid entries for a group void add_groups(lua_State *L, int table_stack_index, GROUP ***g); void add_entries(lua_State *L, int table_stack_index, GROUP *g); +void stack_debug(lua_State *L); //turn on or off sorting (A-Z); On by default bool sort = true; @@ -80,7 +82,7 @@ GROUP **cfg_interp(char *path, int *group_count){ } // create the group array - *group_count = key_count(L, i); + *group_count = get_group_count(L, i); g = malloc(sizeof(GROUP *) * (*group_count)); // add each group (which also adds each entry to each group) @@ -102,22 +104,51 @@ void refer_to_doc(){ return; } -int key_count(lua_State *L, int table_stack_index) { +int get_group_count(lua_State *L, int table_stack_index) { int output = 0; + int entry_table_stack_index; + const char *group_name; lua_pushnil(L); while(lua_next(L, table_stack_index)) { // uses 'key' (at index -2) and 'value' (at index -1) - if(lua_type(L, -2) == LUA_TSTRING) ++output; - lua_pop(L, 1); + if(lua_type(L, -2) == LUA_TSTRING && lua_type(L, -1) == LUA_TTABLE) { + // check validity of this group + group_name = lua_tostring(L, -2); + if(group_name != NULL) { + // check that the Entries table for this group is not empty + lua_pushstring(L, "Entries"); + lua_gettable(L, -2); + entry_table_stack_index = lua_gettop(L); + if(lua_type(L, entry_table_stack_index) == LUA_TTABLE + && get_entry_count(L, entry_table_stack_index) > 0) + ++output; + } + } + // pop the top of the stack down to the key of the group + lua_pop(L, lua_gettop(L)-table_stack_index-1); } return output; } +int get_entry_count(lua_State *L, int table_stack_index) { + int i = 1; + int output = 0; + + do { + lua_rawgeti(L, table_stack_index, i); + if(lua_type(L, -1) == LUA_TSTRING) ++output; + ++i; + } while(lua_type(L, -1) != LUA_TNIL); + + return output; +} + void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { const char *group_name; int entry_table_stack_index; + int entry_count; int i; lua_pushnil(L); @@ -130,20 +161,31 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { if(group_name != NULL) { // push the Entries table on the stack (to get entry information) lua_pushstring(L, "Entries"); + // get table Groups.TABLE_NAME.Entries lua_gettable(L, -2); entry_table_stack_index = lua_gettop(L); + // check that 'Entries' is a table if(lua_type(L, entry_table_stack_index) != LUA_TTABLE) { printf("Error in config: 'Entries' should be Table, is actually %s\n", lua_typename(L, lua_type(L, entry_table_stack_index))); exit(1); } - (*g)[i] = create_group(group_name, key_count(L, entry_table_stack_index)); - // add entries to this group - add_entries(L, entry_table_stack_index, (*g)[i]); + + entry_count = get_entry_count(L, entry_table_stack_index); + // check that the group has at least 1 entry + if(entry_count <= 0) + printf("Skipping empty group '%s'\n", group_name); + + else { + (*g)[i] = create_group(group_name, entry_count); + // add entries to this group + add_entries(L, entry_table_stack_index, (*g)[i]); + } } } - lua_pop(L, 1); + // pop the top of the stack down to the key of the group + lua_pop(L, lua_gettop(L)-table_stack_index-1); ++i; } } @@ -166,7 +208,13 @@ void add_entries(lua_State *L, int table_stack_index, GROUP *g) { lua_pop(L, 1); ++i; } +} - // one last pop to pop the key off - lua_pop(L, 1); +void stack_debug(lua_State *L) { + int i; + + printf("DEBUGGING STACK:\n"); + for(i = 1; i <= lua_gettop(L); ++i) { + printf("\t%d - %s\n", i, lua_typename(L, lua_type(L, i))); + } } diff --git a/src/windows/read_cfg.c b/src/windows/read_cfg.c index 9fa721b..bb337f0 100644 --- a/src/windows/read_cfg.c +++ b/src/windows/read_cfg.c @@ -137,96 +137,3 @@ void mkconfig_wizard(char *path){ return; } - -//TODO augment to involve recurs -//TODO could use some cleanup... -void handle_fname(char *path, char *group, bool recurs, bool force, char *name, int ln){ - ENTRY *new; - char *search; //pointer for traversing path - char full_path_cpy[BUF_LEN]; - char relative_path_cpy[BUF_LEN]; - char arg_cpy[BUF_LEN]; - char auto_name[BUF_LEN]; - int plen = strlen(path); - char *dirname; - char *local_arg; //for use in addR - DIR *dp; - struct dirent *fname; - int i; - char *error_p; //helper for complex error messages - - assert(path != NULL && group != NULL); - - if(path[0] == '\0' || group[0] == '\0'){ - error_mes(ln, "Too few arguments for \"add\""); - return; - } - - //address potential quotes - strcpy(full_path_cpy, strip_quotes(path)); - - //don't check that the path arg is valid when forced - if(force) addme(full_path_cpy, group, force, name); - - //file is not recognized, perhaps it has a wildcard? - //TODO finish rewriting a more robust wildcard thingy - else if(access(full_path_cpy, F_OK) == -1){ - i = search_ch(full_path_cpy, '*'); - if(i > -1){ - //look for a directory - while(full_path_cpy[i] != sep && (i >= 0)){ - i--; - } - dirname = full_path_cpy; - strcpy(arg_cpy, full_path_cpy); - dirname[i+1] = '\0'; - dp = opendir(dirname); - - //the directory is real - if(dp != NULL){ - while(fname = readdir(dp)){ - relative_path_cpy[0] = '\0'; - strcat(relative_path_cpy, dirname); - strcat(relative_path_cpy, fname->d_name); - - //Windows cannot tell file types (TODO), so just add relatively indiscriminantly - if(!(wild_cmp(&arg_cpy[i+1], fname->d_name))) addme(relative_path_cpy, group, force, name); - - //if the recursive option was specified, run handle_fname on this directory, but for security reasons, do not consider directories that start with a '.' - else if(recurs && fname->d_name[0] != '.'){ - i = search_last_ch(arg_cpy, sep); - local_arg = &arg_cpy[i+1]; - strcat(relative_path_cpy, &sep); - strcat(relative_path_cpy, local_arg); - handle_fname(relative_path_cpy, group, 1, 0, NULL, ln); - } - } - - closedir(dp); - } - - //directory is not real, report error to the user - else if(!recurs){ - error_p = malloc(sizeof(char) * 1024); - sprintf(error_p, "\"%s\" bad path", dirname); - error_mes(ln, error_p); - free(error_p); - //printf("Error: \"%s\" bad path\n", dirname); - } - } - - //path is not real, report error to the user - else{ - error_p = malloc(sizeof(char) * 1024); - sprintf(error_p, "\"%s\" bad path", full_path_cpy); - error_mes(ln, error_p); - free(error_p); - } - } - - //file name is okay - //FIXME does not take into account whether the argument is a file (could be a directory, symlink, etc.) - else addme(full_path_cpy, group, force, name); - - return; -} -- cgit From f00cf908fdcdff676e95e563b2a93e2d4af05bc7 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Wed, 14 Aug 2024 14:16:54 -0400 Subject: Compile on Windows --- .gitignore | 3 +++ src/windows/draw.c | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2093e21..7edf854 100644 --- a/.gitignore +++ b/.gitignore @@ -58,7 +58,10 @@ Makefile config.h nsis/installer.nsi spec/terminal-media-launcher.spec +src/icon/*.res src/terminal-media-launcher +src/*.dll +src/*.exe src/*.o src/unix/*.o src/windows/*.o diff --git a/src/windows/draw.c b/src/windows/draw.c index 3b06b9f..cbc565f 100644 --- a/src/windows/draw.c +++ b/src/windows/draw.c @@ -6,10 +6,10 @@ #include "../include/group.h" void launch(){ + ENTRY **e = get_gentries(g[g_hover]); char *program = get_gprog(g[g_hover]); char *flags = get_gflags(g[g_hover]); char *path = get_epath(e[e_hover[g_hover]]); - bool quotes = get_gquotes(g[g_hover]); char file[BUF_LEN]; char params[BUF_LEN]; @@ -24,9 +24,7 @@ void launch(){ } else{ - if(quotes) strcat(file, "\""); strcat(file, program); - if(quotes) strcat(file, "\""); params[0] = '\0'; if(flags[0] != '\0'){ -- cgit From 243853cd1692c56cae8642dd6bb35c3c75ff54f7 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Wed, 14 Aug 2024 16:32:54 -0400 Subject: Working support for setting launcher --- src/group.c | 2 +- src/include/group.h | 2 +- src/read_cfg.c | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/group.c b/src/group.c index 1d1ebd2..e5c3373 100644 --- a/src/group.c +++ b/src/group.c @@ -44,7 +44,7 @@ char *get_gprog(GROUP *g){ return g->program; } -void set_gprog(GROUP *g, char *p){ +void set_gprog(GROUP *g, const char *p){ assert(g != NULL); strcpy(g->program, p); return; diff --git a/src/include/group.h b/src/include/group.h index 89a8422..751b629 100644 --- a/src/include/group.h +++ b/src/include/group.h @@ -13,7 +13,7 @@ char *get_gname(GROUP *g); char *get_gprog(GROUP *g); -void set_gprog(GROUP *g, char *p); +void set_gprog(GROUP *g, const char *p); char *get_gflags(GROUP *g); diff --git a/src/read_cfg.c b/src/read_cfg.c index 97a76ff..d9491bb 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -147,7 +147,8 @@ int get_entry_count(lua_State *L, int table_stack_index) { void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { const char *group_name; - int entry_table_stack_index; + int group_table_index; // index of Groups.TABLE_NAME + int entry_table_stack_index; // index of Groups.TABLE_NAME.Entries int entry_count; int i; @@ -158,12 +159,13 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { // looking at Groups.TABLE_NAME if(lua_type(L, -2) == LUA_TSTRING && lua_type(L, -1) == LUA_TTABLE) { group_name = lua_tostring(L, -2); + group_table_index = lua_gettop(L); if(group_name != NULL) { // push the Entries table on the stack (to get entry information) lua_pushstring(L, "Entries"); // get table Groups.TABLE_NAME.Entries - lua_gettable(L, -2); + lua_gettable(L, group_table_index); entry_table_stack_index = lua_gettop(L); // check that 'Entries' is a table @@ -182,6 +184,14 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { // add entries to this group add_entries(L, entry_table_stack_index, (*g)[i]); } + + // set the launcher, if applicable + lua_pushstring(L, "Launcher"); + lua_gettable(L, group_table_index); + printf("Found launcher: %s\n", lua_tostring(L, -1)); + if(lua_type(L, -1) == LUA_TSTRING) { + set_gprog((*g)[i], lua_tostring(L, -1)); + } } } // pop the top of the stack down to the key of the group -- cgit From 9adae33d5ffa4a72771266ba127f9ccc9b4b5221 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Wed, 14 Aug 2024 16:51:06 -0400 Subject: Working support for setting launcher flags --- src/group.c | 2 +- src/include/group.h | 2 +- src/read_cfg.c | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/group.c b/src/group.c index e5c3373..95d8605 100644 --- a/src/group.c +++ b/src/group.c @@ -55,7 +55,7 @@ char *get_gflags(GROUP *g){ return g->flags; } -void set_gflags(GROUP *g, char *p){ +void set_gflags(GROUP *g, const char *p){ assert(g != NULL); strcpy(g->flags, p); } diff --git a/src/include/group.h b/src/include/group.h index 751b629..bad33a5 100644 --- a/src/include/group.h +++ b/src/include/group.h @@ -17,7 +17,7 @@ void set_gprog(GROUP *g, const char *p); char *get_gflags(GROUP *g); -void set_gflags(GROUP *g, char *p); +void set_gflags(GROUP *g, const char *p); ENTRY **get_gentries(GROUP *g); diff --git a/src/read_cfg.c b/src/read_cfg.c index d9491bb..05146aa 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -188,10 +188,16 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { // set the launcher, if applicable lua_pushstring(L, "Launcher"); lua_gettable(L, group_table_index); - printf("Found launcher: %s\n", lua_tostring(L, -1)); if(lua_type(L, -1) == LUA_TSTRING) { set_gprog((*g)[i], lua_tostring(L, -1)); } + + // set the launcher flags, if applicable + lua_pushstring(L, "Flags"); + lua_gettable(L, group_table_index); + if(lua_type(L, -1) == LUA_TSTRING) { + set_gflags((*g)[i], lua_tostring(L, -1)); + } } } // pop the top of the stack down to the key of the group -- cgit From 002e6c5aac88cc931b838884f9ad21348f2f5641 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Fri, 16 Aug 2024 16:39:39 -0400 Subject: Fix potential group allocation index incrementation issue --- src/draw.c | 2 +- src/read_cfg.c | 40 ++++++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/draw.c b/src/draw.c index 99b1a74..91476e3 100644 --- a/src/draw.c +++ b/src/draw.c @@ -214,7 +214,7 @@ bool *handle_args(int argc, char **argv, char **cfg_path){ {"version", no_argument, NULL, 'v'}, {0, 0, 0, 0} }; - bool *flags_set = calloc(FLAG_COUNT, sizeof(bool)); + bool *flags_set = calloc(FLAG_COUNT+1, sizeof(bool)); int i = 0; while(opt != -1){ diff --git a/src/read_cfg.c b/src/read_cfg.c index 05146aa..a6c20a7 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -83,10 +83,13 @@ GROUP **cfg_interp(char *path, int *group_count){ // create the group array *group_count = get_group_count(L, i); - g = malloc(sizeof(GROUP *) * (*group_count)); + if(*group_count <= 0) g = NULL; + else { + g = malloc(sizeof(GROUP *) * (*group_count)); - // add each group (which also adds each entry to each group) - add_groups(L, i, &g); + // add each group (which also adds each entry to each group) + add_groups(L, i, &g); + } lua_close(L); return g; } @@ -170,7 +173,7 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { // check that 'Entries' is a table if(lua_type(L, entry_table_stack_index) != LUA_TTABLE) { - printf("Error in config: 'Entries' should be Table, is actually %s\n", lua_typename(L, lua_type(L, entry_table_stack_index))); + printf("Error in config: in group '%s': 'Entries' should be Table, is actually %s\n", group_name, lua_typename(L, lua_type(L, entry_table_stack_index))); exit(1); } @@ -183,26 +186,27 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { (*g)[i] = create_group(group_name, entry_count); // add entries to this group add_entries(L, entry_table_stack_index, (*g)[i]); - } - // set the launcher, if applicable - lua_pushstring(L, "Launcher"); - lua_gettable(L, group_table_index); - if(lua_type(L, -1) == LUA_TSTRING) { - set_gprog((*g)[i], lua_tostring(L, -1)); - } - - // set the launcher flags, if applicable - lua_pushstring(L, "Flags"); - lua_gettable(L, group_table_index); - if(lua_type(L, -1) == LUA_TSTRING) { - set_gflags((*g)[i], lua_tostring(L, -1)); + // set the launcher, if applicable + lua_pushstring(L, "Launcher"); + lua_gettable(L, group_table_index); + if(lua_type(L, -1) == LUA_TSTRING) { + set_gprog((*g)[i], lua_tostring(L, -1)); + } + + // set the launcher flags, if applicable + lua_pushstring(L, "Flags"); + lua_gettable(L, group_table_index); + if(lua_type(L, -1) == LUA_TSTRING) { + set_gflags((*g)[i], lua_tostring(L, -1)); + } + + ++i; } } } // pop the top of the stack down to the key of the group lua_pop(L, lua_gettop(L)-table_stack_index-1); - ++i; } } -- cgit From 9c330fafe8ce65acbb0980d3e51af3696135099d Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Fri, 16 Aug 2024 17:22:37 -0400 Subject: Sorting working for entries --- src/read_cfg.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/read_cfg.c b/src/read_cfg.c index a6c20a7..b084b2c 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -24,6 +24,7 @@ //private //void check_line(char *buffer, char **options, int ln); //int check_option(char *arg, char **options); +void get_settings(lua_State *L, int table_stack_index); // gets settings from Settings global variable int get_group_count(lua_State *L, int table_stack_index); // counts the number of valid groups int get_entry_count(lua_State *L, int table_stack_index); // counts the number of valid entries for a group void add_groups(lua_State *L, int table_stack_index, GROUP ***g); @@ -31,6 +32,7 @@ void add_entries(lua_State *L, int table_stack_index, GROUP *g); void stack_debug(lua_State *L); //turn on or off sorting (A-Z); On by default +// TODO allow specifying whether to sort groups or entries (or both, or none) bool sort = true; //set to true to automatically try to create a human readable name for an entry @@ -73,7 +75,15 @@ GROUP **cfg_interp(char *path, int *group_count){ //lua_setglobal(L, "Groups"); //lua_pcall(L, 0, 0, 0); - // demo + // open Settings table + lua_getglobal(L, "Settings"); + i = lua_gettop(L); + if(lua_type(L, i) == LUA_TTABLE) { + // parse settings + get_settings(L, i); + } + + // open Groups table lua_getglobal(L, "Groups"); i = lua_gettop(L); if(lua_type(L, i) != LUA_TTABLE) { @@ -107,6 +117,34 @@ void refer_to_doc(){ return; } +void get_settings(lua_State *L, int table_stack_index) { + bool *setting_vars[] = { + &hr, + &fold_case, + &sort + }; + + char *setting_strings[] = { + "autoAlias", + "foldCase", + "sort" + }; + + int count = 3; + int i; + + // looking at table Settings + + // check if autoAlias is set + for(i = 0; i < count; ++i) { + lua_pushstring(L, setting_strings[i]); + lua_gettable(L, table_stack_index); + if(lua_type(L, -1) == LUA_TBOOLEAN) { + *(setting_vars[i]) = lua_toboolean(L, -1); + } + } +} + int get_group_count(lua_State *L, int table_stack_index) { int output = 0; int entry_table_stack_index; @@ -155,6 +193,11 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { int entry_count; int i; + // sort the groups, if necessary + //if(sort) { + // luaL_dostring(L, "table.sort(Groups)"); + //} + lua_pushnil(L); i = 0; while(lua_next(L, table_stack_index)) { @@ -184,6 +227,13 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { else { (*g)[i] = create_group(group_name, entry_count); + + // sort the entries if necessary + if(sort) { + lua_pushfstring(L, "table.sort(Groups['%s'].Entries)", group_name); + luaL_dostring(L, lua_tostring(L, -1)); + } + // add entries to this group add_entries(L, entry_table_stack_index, (*g)[i]); -- cgit From 70a15daa4367e072268f4302a68b6f73f6acf6c5 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Fri, 16 Aug 2024 18:43:36 -0400 Subject: Support for sorting entries --- src/draw.c | 1 + src/read_cfg.c | 108 ++++++++++++++++++++++++++++++++------------------------- 2 files changed, 61 insertions(+), 48 deletions(-) diff --git a/src/draw.c b/src/draw.c index 91476e3..53185cb 100644 --- a/src/draw.c +++ b/src/draw.c @@ -78,6 +78,7 @@ int main(int argc, char **argv){ //for(i = 0; i < g_count; ++i) { // group_debug(g[i]); //} + //return 0; /* //Remove Empty Groups from the Array diff --git a/src/read_cfg.c b/src/read_cfg.c index b084b2c..f29fe88 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -31,7 +31,7 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g); void add_entries(lua_State *L, int table_stack_index, GROUP *g); void stack_debug(lua_State *L); -//turn on or off sorting (A-Z); On by default +//turn on or off sorting for entries (A-Z); On by default // TODO allow specifying whether to sort groups or entries (or both, or none) bool sort = true; @@ -82,6 +82,7 @@ GROUP **cfg_interp(char *path, int *group_count){ // parse settings get_settings(L, i); } + lua_pop(L, lua_gettop(L)); // open Groups table lua_getglobal(L, "Groups"); @@ -93,7 +94,10 @@ GROUP **cfg_interp(char *path, int *group_count){ // create the group array *group_count = get_group_count(L, i); - if(*group_count <= 0) g = NULL; + if(*group_count <= 0) { + printf("Error: No Groups!\n"); + g = NULL; + } else { g = malloc(sizeof(GROUP *) * (*group_count)); @@ -146,30 +150,34 @@ void get_settings(lua_State *L, int table_stack_index) { } int get_group_count(lua_State *L, int table_stack_index) { + int i = 1; int output = 0; + int group_table_stack_index; int entry_table_stack_index; const char *group_name; - lua_pushnil(L); - while(lua_next(L, table_stack_index)) { - // uses 'key' (at index -2) and 'value' (at index -1) - if(lua_type(L, -2) == LUA_TSTRING && lua_type(L, -1) == LUA_TTABLE) { + do { + lua_rawgeti(L, table_stack_index, i); + group_table_stack_index = lua_gettop(L); + if(lua_type(L, group_table_stack_index) == LUA_TTABLE) { // check validity of this group - group_name = lua_tostring(L, -2); + lua_pushstring(L, "name"); + lua_gettable(L, group_table_stack_index); + group_name = lua_tostring(L, -1); if(group_name != NULL) { // check that the Entries table for this group is not empty lua_pushstring(L, "Entries"); - lua_gettable(L, -2); + lua_gettable(L, group_table_stack_index); entry_table_stack_index = lua_gettop(L); if(lua_type(L, entry_table_stack_index) == LUA_TTABLE && get_entry_count(L, entry_table_stack_index) > 0) ++output; } } - // pop the top of the stack down to the key of the group - lua_pop(L, lua_gettop(L)-table_stack_index-1); - } + ++i; + } while(lua_type(L, group_table_stack_index) != LUA_TNIL); + lua_pop(L, lua_gettop(L)-table_stack_index-1); return output; } @@ -183,35 +191,38 @@ int get_entry_count(lua_State *L, int table_stack_index) { ++i; } while(lua_type(L, -1) != LUA_TNIL); + lua_pop(L, lua_gettop(L)-table_stack_index-1); return output; } void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { const char *group_name; - int group_table_index; // index of Groups.TABLE_NAME + int group_table_stack_index; // index of Groups.TABLE_NAME int entry_table_stack_index; // index of Groups.TABLE_NAME.Entries int entry_count; - int i; + char sort_cmd_lua[BUF_LEN]; // used to store the lua call to table.sort + int i = 1; // index in lua table + int count = 0; // index in C struct // sort the groups, if necessary - //if(sort) { - // luaL_dostring(L, "table.sort(Groups)"); - //} - - lua_pushnil(L); - i = 0; - while(lua_next(L, table_stack_index)) { - // uses 'key' (at index -2) and 'value' (at index -1) - // looking at Groups.TABLE_NAME - if(lua_type(L, -2) == LUA_TSTRING && lua_type(L, -1) == LUA_TTABLE) { - group_name = lua_tostring(L, -2); - group_table_index = lua_gettop(L); + if(sort) { + luaL_dostring(L, "table.sort(Groups)"); + } + + do { + lua_rawgeti(L, table_stack_index, i); + group_table_stack_index = lua_gettop(L); + if(lua_type(L, group_table_stack_index) == LUA_TTABLE) { + // check validity of this group + lua_pushstring(L, "name"); + lua_gettable(L, group_table_stack_index); + group_name = lua_tostring(L, -1); if(group_name != NULL) { // push the Entries table on the stack (to get entry information) lua_pushstring(L, "Entries"); - // get table Groups.TABLE_NAME.Entries - lua_gettable(L, group_table_index); + // get table Groups[i].Entries + lua_gettable(L, group_table_stack_index); entry_table_stack_index = lua_gettop(L); // check that 'Entries' is a table @@ -226,58 +237,59 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { printf("Skipping empty group '%s'\n", group_name); else { - (*g)[i] = create_group(group_name, entry_count); + (*g)[count] = create_group(group_name, entry_count); // sort the entries if necessary if(sort) { - lua_pushfstring(L, "table.sort(Groups['%s'].Entries)", group_name); - luaL_dostring(L, lua_tostring(L, -1)); + sprintf(sort_cmd_lua, "table.sort(Groups[%d].Entries)", i); + luaL_dostring(L, sort_cmd_lua); } // add entries to this group - add_entries(L, entry_table_stack_index, (*g)[i]); + add_entries(L, entry_table_stack_index, (*g)[count]); // set the launcher, if applicable lua_pushstring(L, "Launcher"); - lua_gettable(L, group_table_index); + lua_gettable(L, group_table_stack_index); if(lua_type(L, -1) == LUA_TSTRING) { - set_gprog((*g)[i], lua_tostring(L, -1)); + set_gprog((*g)[count], lua_tostring(L, -1)); } // set the launcher flags, if applicable lua_pushstring(L, "Flags"); - lua_gettable(L, group_table_index); + lua_gettable(L, group_table_stack_index); if(lua_type(L, -1) == LUA_TSTRING) { - set_gflags((*g)[i], lua_tostring(L, -1)); + set_gflags((*g)[count], lua_tostring(L, -1)); } - ++i; + ++count; } } } - // pop the top of the stack down to the key of the group - lua_pop(L, lua_gettop(L)-table_stack_index-1); - } + ++i; + } while(lua_type(L, group_table_stack_index) != LUA_TNIL); + + lua_pop(L, lua_gettop(L)-table_stack_index-1); } void add_entries(lua_State *L, int table_stack_index, GROUP *g) { const char *entry_name; - int i; + int i = 1; // index in lua table + int count = 0; // index in C struct - lua_pushnil(L); - i = 0; - while(lua_next(L, table_stack_index)) { - // uses 'key' (at index -2) and 'value' (at index -1) - // looking at Groups.TABLE_NAME.Entries[i] + do { + lua_rawgeti(L, table_stack_index, i); if(lua_type(L, -1) == LUA_TSTRING) { entry_name = lua_tostring(L, -1); if(entry_name != NULL) { - set_gentry(g, i, create_entry(entry_name, entry_name, true)); + set_gentry(g, count, create_entry(entry_name, entry_name, true)); + ++count; } } - lua_pop(L, 1); ++i; - } + } while(lua_type(L, -1) != LUA_TNIL); + + lua_pop(L, lua_gettop(L)-table_stack_index-1); } void stack_debug(lua_State *L) { -- cgit From 996d3097cfa00363f16ff972b6da347b65ead23f Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Sat, 17 Aug 2024 14:50:07 -0400 Subject: Remove foldcase and hr options --- src/draw.c | 2 +- src/include/read_cfg.h | 2 -- src/read_cfg.c | 20 +------------------- 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/draw.c b/src/draw.c index 53185cb..4dd5d75 100644 --- a/src/draw.c +++ b/src/draw.c @@ -520,7 +520,7 @@ void trav_col(int new_i){ int locateChar(char input){ ENTRY **entries = get_gentries(g[g_hover]); int location = (true_hover ? e_hover[g_hover] : g_hover); - bool fold_case = get_case_sensitivity(); + bool fold_case = true; char first_char; int i; diff --git a/src/include/read_cfg.h b/src/include/read_cfg.h index 29a36e7..1337e32 100644 --- a/src/include/read_cfg.h +++ b/src/include/read_cfg.h @@ -8,8 +8,6 @@ #define BUF_LEN 1024 GROUP **cfg_interp(char *path, int *group_count); -bool get_sort(); -bool get_case_sensitivity(); void refer_to_doc(); //functions that differ by os diff --git a/src/read_cfg.c b/src/read_cfg.c index f29fe88..3b8d24a 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -35,12 +35,6 @@ void stack_debug(lua_State *L); // TODO allow specifying whether to sort groups or entries (or both, or none) bool sort = true; -//set to true to automatically try to create a human readable name for an entry -bool hr = false; - -//turn foldCase (insensitive case searching) on or off; On by default -bool fold_case = true; - //return false if invalid path GROUP **cfg_interp(char *path, int *group_count){ FILE *fp; @@ -108,14 +102,6 @@ GROUP **cfg_interp(char *path, int *group_count){ return g; } -bool get_sort(){ - return sort; -} - -bool get_case_sensitivity(){ - return fold_case; -} - void refer_to_doc(){ printf("Refer to documentation on how to create terminal-media-launcher config file\n"); return; @@ -123,18 +109,14 @@ void refer_to_doc(){ void get_settings(lua_State *L, int table_stack_index) { bool *setting_vars[] = { - &hr, - &fold_case, &sort }; char *setting_strings[] = { - "autoAlias", - "foldCase", "sort" }; - int count = 3; + int count = 1; int i; // looking at table Settings -- cgit From ca77091d63b3600b7a3829db8ae24c765c65440d Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Mon, 19 Aug 2024 20:44:56 -0400 Subject: Ability to set entry attributes --- src/read_cfg.c | 291 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 207 insertions(+), 84 deletions(-) diff --git a/src/read_cfg.c b/src/read_cfg.c index 3b8d24a..6c334ac 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -24,12 +24,13 @@ //private //void check_line(char *buffer, char **options, int ln); //int check_option(char *arg, char **options); -void get_settings(lua_State *L, int table_stack_index); // gets settings from Settings global variable -int get_group_count(lua_State *L, int table_stack_index); // counts the number of valid groups -int get_entry_count(lua_State *L, int table_stack_index); // counts the number of valid entries for a group -void add_groups(lua_State *L, int table_stack_index, GROUP ***g); -void add_entries(lua_State *L, int table_stack_index, GROUP *g); +void get_settings(lua_State *L); // gets settings from Settings global variable +int get_group_count(lua_State *L); // counts the number of valid groups +int get_entry_count(lua_State *L); // counts the number of valid entries for a group +void add_groups(lua_State *L, GROUP ***g); +void add_entries(lua_State *L, GROUP *g); void stack_debug(lua_State *L); +void table_debug(lua_State *L, int print_depth); //turn on or off sorting for entries (A-Z); On by default // TODO allow specifying whether to sort groups or entries (or both, or none) @@ -55,6 +56,7 @@ GROUP **cfg_interp(char *path, int *group_count){ // load lua configuration lua_State *L = luaL_newstate(); + // new lua stack luaL_openlibs(L); // allow for standard library to be used int config_load_status = luaL_dofile(L, path); if(config_load_status != 0) { @@ -71,23 +73,24 @@ GROUP **cfg_interp(char *path, int *group_count){ // open Settings table lua_getglobal(L, "Settings"); - i = lua_gettop(L); - if(lua_type(L, i) == LUA_TTABLE) { + // stack now contains: -1 => Settings + if(lua_type(L, -1) == LUA_TTABLE) { // parse settings - get_settings(L, i); + get_settings(L); } - lua_pop(L, lua_gettop(L)); + lua_pop(L, 1); + // empty stack // open Groups table lua_getglobal(L, "Groups"); - i = lua_gettop(L); - if(lua_type(L, i) != LUA_TTABLE) { - printf("Error in config: 'Groups' should be Table, is actually %s\n", lua_typename(L, lua_type(L, i))); + // stack now contains: -1 => Groups + if(lua_type(L, -1) != LUA_TTABLE) { + printf("Error in config: 'Groups' should be Table, is actually %s\n", lua_typename(L, lua_type(L, -1))); exit(1); } // create the group array - *group_count = get_group_count(L, i); + *group_count = get_group_count(L); if(*group_count <= 0) { printf("Error: No Groups!\n"); g = NULL; @@ -96,7 +99,7 @@ GROUP **cfg_interp(char *path, int *group_count){ g = malloc(sizeof(GROUP *) * (*group_count)); // add each group (which also adds each entry to each group) - add_groups(L, i, &g); + add_groups(L, &g); } lua_close(L); return g; @@ -107,7 +110,9 @@ void refer_to_doc(){ return; } -void get_settings(lua_State *L, int table_stack_index) { +void get_settings(lua_State *L) { + // stack now contains: -1 => table + bool *setting_vars[] = { &sort }; @@ -124,60 +129,87 @@ void get_settings(lua_State *L, int table_stack_index) { // check if autoAlias is set for(i = 0; i < count; ++i) { lua_pushstring(L, setting_strings[i]); - lua_gettable(L, table_stack_index); + // stack now contains: -1 => setting_string; -2 => table + lua_gettable(L, -2); + // stack now contains: -1 => string_value; -2 => table if(lua_type(L, -1) == LUA_TBOOLEAN) { *(setting_vars[i]) = lua_toboolean(L, -1); } + lua_pop(L, 1); + // stack now contains: -1 => table } } -int get_group_count(lua_State *L, int table_stack_index) { - int i = 1; +int get_group_count(lua_State *L) { int output = 0; - int group_table_stack_index; - int entry_table_stack_index; - const char *group_name; - do { - lua_rawgeti(L, table_stack_index, i); - group_table_stack_index = lua_gettop(L); - if(lua_type(L, group_table_stack_index) == LUA_TTABLE) { - // check validity of this group + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(lua_type(L, -1) == LUA_TNUMBER && lua_type(L, -2) == LUA_TTABLE) { lua_pushstring(L, "name"); - lua_gettable(L, group_table_stack_index); - group_name = lua_tostring(L, -1); - if(group_name != NULL) { + // stack now contains: -1 => "name"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table + if(lua_type(L, -1) == LUA_TSTRING) { // check that the Entries table for this group is not empty lua_pushstring(L, "Entries"); - lua_gettable(L, group_table_stack_index); - entry_table_stack_index = lua_gettop(L); - if(lua_type(L, entry_table_stack_index) == LUA_TTABLE - && get_entry_count(L, entry_table_stack_index) > 0) + // stack now contains: -1 => "Entries"; -2 => name; -3 => key; -4 => value; -5 => key; -6 => table + lua_gettable(L, -4); + // stack now contains: -1 => Entries; -2 => name; -3 => key; -4 => value; -5 => key; -6 => table + if(lua_type(L, -1) == LUA_TTABLE && get_entry_count(L) > 0) ++output; + lua_pop(L, 1); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table } + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table } - ++i; - } while(lua_type(L, group_table_stack_index) != LUA_TNIL); + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table + } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key + // but does not push anything.) - lua_pop(L, lua_gettop(L)-table_stack_index-1); return output; } -int get_entry_count(lua_State *L, int table_stack_index) { - int i = 1; +int get_entry_count(lua_State *L) { int output = 0; - do { - lua_rawgeti(L, table_stack_index, i); - if(lua_type(L, -1) == LUA_TSTRING) ++output; - ++i; - } while(lua_type(L, -1) != LUA_TNIL); + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(lua_type(L, -1) == LUA_TNUMBER && lua_type(L, -2) == LUA_TTABLE) { + // check that the entry has a valid name + lua_pushstring(L, "name"); + // stack now contains: -1 => "name"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table + if(lua_type(L, -1) == LUA_TSTRING) ++output; + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + } + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table + } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key + // but does not push anything.) - lua_pop(L, lua_gettop(L)-table_stack_index-1); return output; } -void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { +void add_groups(lua_State *L, GROUP ***g) { const char *group_name; int group_table_stack_index; // index of Groups.TABLE_NAME int entry_table_stack_index; // index of Groups.TABLE_NAME.Entries @@ -186,92 +218,136 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { int i = 1; // index in lua table int count = 0; // index in C struct - // sort the groups, if necessary - if(sort) { - luaL_dostring(L, "table.sort(Groups)"); - } - - do { - lua_rawgeti(L, table_stack_index, i); - group_table_stack_index = lua_gettop(L); - if(lua_type(L, group_table_stack_index) == LUA_TTABLE) { - // check validity of this group + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(lua_type(L, -1) == LUA_TNUMBER && lua_type(L, -2) == LUA_TTABLE) { lua_pushstring(L, "name"); - lua_gettable(L, group_table_stack_index); + // stack now contains: -1 => "name"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table group_name = lua_tostring(L, -1); + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table if(group_name != NULL) { // push the Entries table on the stack (to get entry information) lua_pushstring(L, "Entries"); - - // get table Groups[i].Entries - lua_gettable(L, group_table_stack_index); - entry_table_stack_index = lua_gettop(L); - - // check that 'Entries' is a table - if(lua_type(L, entry_table_stack_index) != LUA_TTABLE) { - printf("Error in config: in group '%s': 'Entries' should be Table, is actually %s\n", group_name, lua_typename(L, lua_type(L, entry_table_stack_index))); + // stack now contains: -1 => "Entries"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => Entries; -2 => key; -3 => value; -4 => key; -5 => table + if(lua_type(L, -1) != LUA_TTABLE) { + printf("Error in config: in group '%s': 'Entries' should be Table, is actually %s\n", group_name, lua_typename(L, lua_type(L, -1))); exit(1); } - entry_count = get_entry_count(L, entry_table_stack_index); + entry_count = get_entry_count(L); + // check that the group has at least 1 entry - if(entry_count <= 0) + if(entry_count <= 0) { printf("Skipping empty group '%s'\n", group_name); - + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + } else { (*g)[count] = create_group(group_name, entry_count); // sort the entries if necessary if(sort) { - sprintf(sort_cmd_lua, "table.sort(Groups[%d].Entries)", i); + sprintf(sort_cmd_lua, "table.sort(Groups[%d].Entries, function(a, b) return a.name < b.name end)", i); luaL_dostring(L, sort_cmd_lua); } // add entries to this group - add_entries(L, entry_table_stack_index, (*g)[count]); + add_entries(L, (*g)[count]); + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table // set the launcher, if applicable lua_pushstring(L, "Launcher"); - lua_gettable(L, group_table_stack_index); + // stack now contains: -1 => "Launcher"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => Launcher; -2 => key; -3 => value; -4 => key; -5 => table if(lua_type(L, -1) == LUA_TSTRING) { set_gprog((*g)[count], lua_tostring(L, -1)); } + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table // set the launcher flags, if applicable lua_pushstring(L, "Flags"); - lua_gettable(L, group_table_stack_index); + // stack now contains: -1 => "Flags"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => Flags; -2 => key; -3 => value; -4 => key; -5 => table if(lua_type(L, -1) == LUA_TSTRING) { set_gflags((*g)[count], lua_tostring(L, -1)); } + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table ++count; } } } + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table ++i; - } while(lua_type(L, group_table_stack_index) != LUA_TNIL); - - lua_pop(L, lua_gettop(L)-table_stack_index-1); + } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key + // but does not push anything.) + // Pop table + lua_pop(L, 1); + // Stack is now the same as it was on entry to this function } -void add_entries(lua_State *L, int table_stack_index, GROUP *g) { +void add_entries(lua_State *L, GROUP *g) { const char *entry_name; + const char *entry_path; + int entry_table_stack_index; int i = 1; // index in lua table int count = 0; // index in C struct - do { - lua_rawgeti(L, table_stack_index, i); - if(lua_type(L, -1) == LUA_TSTRING) { + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(lua_type(L, -1) == LUA_TNUMBER && lua_type(L, -2) == LUA_TTABLE) { + // check that the entry has a valid name + lua_pushstring(L, "name"); + // stack now contains: -1 => "name"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table entry_name = lua_tostring(L, -1); + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(entry_name != NULL) { - set_gentry(g, count, create_entry(entry_name, entry_name, true)); + // get this entry's path, if applicable + lua_pushstring(L, "path"); + // stack now contains: -1 => "path"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => path; -2 => key; -3 => value; -4 => key; -5 => table + if(lua_type(L, -1) == LUA_TSTRING) entry_path = lua_tostring(L, -1); + else entry_path = entry_name; + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + + set_gentry(g, count, create_entry(entry_name, entry_path, true)); ++count; } } - ++i; - } while(lua_type(L, -1) != LUA_TNIL); - - lua_pop(L, lua_gettop(L)-table_stack_index-1); + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table + } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key } void stack_debug(lua_State *L) { @@ -279,6 +355,53 @@ void stack_debug(lua_State *L) { printf("DEBUGGING STACK:\n"); for(i = 1; i <= lua_gettop(L); ++i) { - printf("\t%d - %s\n", i, lua_typename(L, lua_type(L, i))); + printf("\t%d - %s", i, lua_typename(L, lua_type(L, i))); + + switch(lua_type(L, i)) { + case LUA_TSTRING: + printf(" - %s\n", lua_tostring(L, i)); + break; + + //case LUA_TTABLE: + // printf("\n"); + // table_debug(L, 2); + // break; + + default: + printf("\n"); + } + } +} + +// FIXME WIP debugging function +void table_debug(lua_State *L, int print_depth) { + int i; + + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + const char *key = lua_tostring(L, -1); + const char *value = lua_typename(L, lua_type(L, -2)); + for(i = 0; i < print_depth; ++i) { + printf("\t"); + } + printf("%s => %s", key, value); + if(lua_type(L, -2) == LUA_TSTRING) { + printf(" - %s", lua_tostring(L, -2)); + } + printf("\n"); + // pop value + copy of key, leaving original key + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key + // but does not push anything.) + // Pop table + lua_pop(L, 1); + // Stack is now the same as it was on entry to this function } -- cgit From 7f16bf6f85151507e76382ff5beae590b399acf1 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Mon, 26 Aug 2024 17:31:15 -0400 Subject: Update actions recipes --- .gitignore | 1 + actions/Makefile.am | 4 ++-- configure.ac | 2 +- debian/control | 1 + spec/terminal-media-launcher.spec.in | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 7edf854..7cc2a44 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ Makefile *~ *.tar.gz config.h +actions/build nsis/installer.nsi spec/terminal-media-launcher.spec src/icon/*.res diff --git a/actions/Makefile.am b/actions/Makefile.am index f69759f..71c4d77 100644 --- a/actions/Makefile.am +++ b/actions/Makefile.am @@ -8,7 +8,7 @@ clean-local: actions_build_deb: IMAGE_NAME = debian actions_build_deb: IMAGE_VERSION = unstable actions_build_deb: CONTAINER_NAME = $(PACKAGE_NAME)_$@_$(IMAGE_NAME)-$(IMAGE_VERSION) -actions_build_deb: DEPENDENCY_LIST = autoconf-archive debmake devscripts ncurses-dev pkg-config +actions_build_deb: DEPENDENCY_LIST = autoconf-archive debmake devscripts liblua5.1-0-dev lua5.1 ncurses-dev pkg-config actions_build_deb: ../$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz podman pull docker.io/library/$(IMAGE_NAME):$(IMAGE_VERSION) podman container exists "$(CONTAINER_NAME)" || podman run -itd --name "$(CONTAINER_NAME)" "$(IMAGE_NAME):$(IMAGE_VERSION)" @@ -26,7 +26,7 @@ actions_build_deb: ../$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz actions_build_rpm: IMAGE_NAME = fedora actions_build_rpm: IMAGE_VERSION = rawhide actions_build_rpm: CONTAINER_NAME = $(PACKAGE_NAME)_$@_$(IMAGE_NAME)-$(IMAGE_VERSION) -actions_build_rpm: DEPENDENCY_LIST = gcc ncurses-devel rpmdevtools rpmlint +actions_build_rpm: DEPENDENCY_LIST = lua lua-devel gcc ncurses-devel rpmdevtools rpmlint actions_build_rpm: ../$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz podman pull docker.io/library/$(IMAGE_NAME):$(IMAGE_VERSION) podman container exists "$(CONTAINER_NAME)" || podman run -itd --name "$(CONTAINER_NAME)" "$(IMAGE_NAME):$(IMAGE_VERSION)" diff --git a/configure.ac b/configure.ac index f922ecf..72d7df2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([terminal-media-launcher],[0.1.1]) +AC_INIT([terminal-media-launcher],[0.2]) AC_SUBST([PACKAGE_TITLE], ["Terminal Media Launcher"]) AC_CONFIG_SRCDIR([src/draw.c]) AC_CONFIG_HEADERS([config.h]) diff --git a/debian/control b/debian/control index 86a867c..fc7c251 100644 --- a/debian/control +++ b/debian/control @@ -10,6 +10,7 @@ Package: terminal-media-launcher Architecture: amd64 Multi-Arch: foreign Depends: ${misc:Depends}, ${shlibs:Depends} +Recommends: lua-filesystem Description: Lightweight Terminal Media Launcher written in C Terminal Media Launcher is a command line utility to help streamline launching applications and other media diff --git a/spec/terminal-media-launcher.spec.in b/spec/terminal-media-launcher.spec.in index 238282e..f25240b 100644 --- a/spec/terminal-media-launcher.spec.in +++ b/spec/terminal-media-launcher.spec.in @@ -8,6 +8,7 @@ URL: https://github.com/lshprung/terminal-media-launcher Source0: %{name}-%{version}.tar.gz Requires: glibc >= 2.7, ncurses >= 6 +Recommends: lua-filesystem %description Terminal Media Launcher is a command line utility to help streamline @@ -38,7 +39,6 @@ rm -rf $RPM_BUILD_ROOT %{_docdir}/terminal-media-launcher/windows_compile_instructions.md %{_mandir}/man1/terminal-media-launcher.1.gz %{_mandir}/man5/terminal-media-launcher-config.5.gz -%{_mandir}/man5/terminal-media-launcher-config.5.gz %{_datadir}/applications/terminal-media-launcher.desktop %{_datadir}/pixmaps/terminal-media-launcher.svg -- cgit From c3ac3180da729083ab7125ccb0450e1da3d24080 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Tue, 27 Aug 2024 18:11:47 -0400 Subject: Update projects docs --- actions/Makefile.am | 2 +- docs/README.md | 14 +- docs/terminal-media-launcher-config.md | 284 +++++++++++++++++++++------------ docs/windows_compile_instructions.md | 2 + 4 files changed, 188 insertions(+), 114 deletions(-) diff --git a/actions/Makefile.am b/actions/Makefile.am index 71c4d77..3044e4d 100644 --- a/actions/Makefile.am +++ b/actions/Makefile.am @@ -26,7 +26,7 @@ actions_build_deb: ../$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz actions_build_rpm: IMAGE_NAME = fedora actions_build_rpm: IMAGE_VERSION = rawhide actions_build_rpm: CONTAINER_NAME = $(PACKAGE_NAME)_$@_$(IMAGE_NAME)-$(IMAGE_VERSION) -actions_build_rpm: DEPENDENCY_LIST = lua lua-devel gcc ncurses-devel rpmdevtools rpmlint +actions_build_rpm: DEPENDENCY_LIST = gcc lua lua-devel ncurses-devel rpmdevtools rpmlint actions_build_rpm: ../$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz podman pull docker.io/library/$(IMAGE_NAME):$(IMAGE_VERSION) podman container exists "$(CONTAINER_NAME)" || podman run -itd --name "$(CONTAINER_NAME)" "$(IMAGE_NAME):$(IMAGE_VERSION)" diff --git a/docs/README.md b/docs/README.md index cb17fd0..ed1f06a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,20 +6,18 @@ ## Compiling and Running -For Windows instructions, see [here](windows_compile_instructions.md) - -terminal-media-launcher can be compiled on any system with make, gcc, and the ncurses development library installed. It can be compiled and installed on any Linux distribution, and can also be compiled and run on Microsoft Windows. To compile and run terminal-media-launcher: +terminal-media-launcher can be compiled on any system with make, gcc, and the ncurses development library installed. It can be compiled and installed on any Linux distribution, and can also be compiled and run on Microsoft Windows using MinGW (e.g., via [MSYS2](https://www.msys2.org/)). To compile and run terminal-media-launcher: 1. Install dependencies. On Debian and Debian-based systems: ``` -# apt install gcc libncurses-dev make +# apt install gcc liblua5.1-0-dev lua5.1 make ncurses-dev pkg-config ``` On RHEL and RHEL-based systems: ``` -# dnf install gcc ncurses-devel +# dnf install gcc lua lua-devel make ncurses-devel ``` 2. Download the latest `.tar.gz` release @@ -76,12 +74,12 @@ By default, terminal-media-launcher searches in the following order for a config ### Linux -1. `$HOME/.config/terminal-media-launcher/config` -2. `$HOME/.terminal-media-launcher/config` +1. `$HOME/.config/terminal-media-launcher/config.lua` +2. `$HOME/.terminal-media-launcher/config.lua` ### Windows -1. `%APPDATA%\terminal-media-launcher\config` +1. `%APPDATA%\terminal-media-launcher\config.lua` A different configuration file location can also be specified with the `-c` flag: diff --git a/docs/terminal-media-launcher-config.md b/docs/terminal-media-launcher-config.md index 3d12f97..a5bf674 100644 --- a/docs/terminal-media-launcher-config.md +++ b/docs/terminal-media-launcher-config.md @@ -1,106 +1,146 @@ ## Introduction -**config** specifies settings for Terminal Media Launcher, including preferences, groups, entries, and file locations. Each line of `config` is read by terminal-media-launcher unless the line is empty or the line begins with a '#'. terminal-media-launcher can automatically generate a configuration file if no such file is found. An automatically generated configuration file will create groups for Music, Pictures, and Videos, and add entries to each group from the respective directory in the user's home directory. It is highly recommended that the user edit the configuration file manually. +Starting in version 0.2, Terminal Media Launcher is configured via a [lua](https://www.lua.org/) script. This project assumes the configuration will adhere to lua 5.1, but is written to be as agnostic as possbile. The general format of the configuration is outlined below: + +```lua +Groups = { + { + name = , + Launcher = , + Flags = , + Entries = { + { + name = , + path = + }, + ... + } + }, + ... +} +``` + + ## Table of Contents - [Creating a Group](#CreatingAGroup) - - [addGroup](#addgroup) - - [setLauncher](#setlauncher) - - [setLauncherRaw](#setlauncherraw) - - [setFlags](#setflags) - [Adding Entries](#AddingEntries) - - [add](#add) - - [addF](#addf) - - [addName](#addname) - - [addNameF](#addnamef) - - [addR](#addr) - - [hide](#hide) - - [hideFile](#hidefile) + - [Adding Entries using lfs module](#AddingEntriesLfs) - [Settings](#settings) - - [autoAlias](#autoalias) - - [foldCase](#foldcase) - [sort](#sort) - [Example](#example) ## Creating a Group -terminal-media-launcher will not work without any groups, so you will need to know how to create a group. - -### addGroup - -- **addGroup** *name* - -`addGroup` will create a new group with a specified name. By default this group is empty, with zero entries, no launching application specified, and no flags specified. If there is a space in the name, it must be written in quotes (ex. "TV Shows") - -### setLauncher - -- **setLauncher** *group* */path/to/launcher* - -`setLauncher` will set a group's launching application. If no launching application is specified for a group, terminal-media-launcher will treat each entry in that group as an executable file. If there is a space in the path to the launching application, it must be written in quotes (ex. "/usr/bin/my launcher"). *Keep in mind that the path to the launching application should be absolute*. - -### setLauncherRaw - -- **setLauncherRaw** *group* */path/to/launcher* - -`setLauncherRaw` is identical to `setLauncher` with the exception that the launcher application specified will not be wrapped in quotes for the system call when a member of the group is launched. This can be used to specify more complex launching instructions. - -### setFlags - -- **setFlags** *group* *flags* - -`setFlags` will set the flags to be specified for the launching application. If no launching application is specified, any specified flags are ignored. If the specified flags contain a space, they must be written in quotes. +The config must contain at least one valid group. Groups are to be inserted in the `Groups` global variable. `Groups` is an array of tables. Each group is a table containing the following keys: + +- Mandatory keys: + - `name` *string* - a name for the group + - `Entries` *table* - an array of tables. Each table represents an entry. +- Optional keys: + - `Launcher` *string* - the path for a program that launches the entries of this group. If not set, it assumes the entries in this group are executables (and have no launching program) + - `Flags` *string* - flags to pass to the launching program. If not set, no flags are passed + +Here is a helper function you can use in your config to add a group + +```lua +local function addGroup(name, launcher, flags) + assert(type(name) == "string") + + -- create Groups table if needed + if Groups == nil then + Groups = {} + end + + local new_group = {} + new_group.name = name + new_group.Entries = {} + if launcher ~= nil then + new_group.Launcher = launcher + end + if flags ~= nil then + new_group.Flags = flags + end + + table.insert(Groups, new_group) + return new_group +end +``` ## Adding Entries -terminal-media-launcher will hide empty groups, so you will need to know how to add entries to a group. - -### add - -- **add** *path/to/file(s)* *group* - -`add` will add a file to a specified group if the path exists. It can also be used to add mutiple files to a group in one line using the '\*' operator (ex. `add /home/john/Pictures/* Pictures`). If the path to the file(s) contains space(s), it must be written in quotes. - -### addF - -- **addF** *new-entry* *group* - -`addF` will force an entry to be added to a specified group, regardless as to whether it is a valid file or not. Unlike `add`, `addF`'s argument does not need to be a valid file, but `addF` can only specify a single entry and does not support the '\*' operator. If the arg has a space in it, it must be written in quotes. +For a group to be valid, it must contain at least one valid entry. Entries are to be inserted in the `Entries` key of a group table. `Entries` is an array of tables. Each entry is a table containing the following keys: -### addName +- Mandatory keys: + - `name` *string* - a name for the entry +- Optional keys: + - `path` *string* - a path to the file associated with this entry. If not set, the path is the same as the name -- **addName** *name* *path/to/file* *group* +Here is a helper function you can use in your config to add an entry to a group -`addName`, like `add`, will add an entry to a specified group if the path exists. `addName` allows for a name to be specified for this entry (by default, the name is the same as the file name). Unlike `add`, only one entry can be added per line, as `addName` does not support the '\*' operator. If either the name or file path contain a space, they must be written in quotes. +```lua +local function addEntry(parentGroup, name, path) + assert(type(parentGroup) == "table") + assert(type(parentGroup.Entries) == "table") + assert(type(name) == "string") -### addNameF + local new_entry = {} + new_entry.name = name + if path ~= nil then + new_entry.path = path + end -- **addNameF** *name* *new-entry* *group* - -`addNameF` can be used in place of `addF` if you want the forced argument to have a different name displayed for the entry than is called in the system call to launch the entry. Otherwise, it is effectively the same as `addF` - -### addR - -- **addR** *path/to/files* *group* - -`addR` will recursively add entries to a group. `addR` functions like `add`, but will also search sub-directories for matches. - -### hide - -- **hide** *entry* *group* - -`hide` will remove a specified entry from a specified group. The entry argument should refer to the entry's name, rather than the entry's path. This option may be useful to hide certain entries after adding entries with the '\*' operator. *At the moment, hide can only hide a single entry*. - -### hideFile - -- **hideFile** *path* *group* + table.insert(parentGroup.Entries, new_entry) + return new_entry +end +``` -`hideFile` has the exact same functionality as `hide`, but takes the absolute path of the entry to hide as the first argument, instead of the name. +### Adding Entries using lfs module + +It is recommended to install the [lua-filesystem](https://github.com/lunarmodules/luafilesystem) module and use it to add entries more efficiently. This example can be used to descend into a directory and add files matching a `string.match` pattern to a group. + +```lua +local lfs = require "lfs" + +local function addEntries(parentGroup, startDir, filePattern, recursive) + -- recursive arg is a boolean for whether or not to descend into subdirectories (false by default) + assert(type(parentGroup) == "table") + assert(type(parentGroup.Entries) == "table") + assert(type(startDir) == "string") + assert(type(filePattern) == "string") + + for file in lfs.dir(startDir) do + local fullFilePath = startDir .. "/" .. file + if file ~= "." and file ~= ".." then + -- descend into subdirectory if recursive is set to true + if lfs.attributes(fullFilePath).mode == "directory" and recursive == true then + addEntries(parentGroup, fullFilePath, filePattern, recursive) + elseif lfs.attributes(fullFilePath).mode == "file" then + if string.match(file, filePattern) then + table.insert(parentGroup.Entries, { + name = file, + path = fullFilePath + }) + end + end + end + end +end +``` ## Settings -If any of the following settings are specified, they should be at the top of the config file. +Settings can be set via the `Settings` global variable. +```lua +Settings = {} +Settings.sort = +``` + + ### sort -- **sort** *on/off* - -`sort` will sort entries of each group in alphabetical order (though not the list of groups). Turning off `sort` is only recommended when adding one item per line to a group. `sort` is turned on by default. +`sort` will sort entries of each group in alphabetical order (though not the list of groups). `sort` is true by default. ## Example -``` -autoAlias on - -# Adding a Group of Various Applications - -addGroup Applications -addName GIMP /usr/bin/gimp Applications -addName Chromium /usr/bin/chromium-browser Applications -addName Thunderbird /usr/bin/thunderbird Applications - -# Adding a Videos Group that contains mp4 files - -addGroup Videos -setLauncher Videos /usr/bin/vlc -add /home/john/Videos/*mp4 Videos - -# Adding a Pictures Group that contains only jpg and png files as well as all files from an external drive and a single desktop wallpaper - -addGroup Pictures -setLauncher Pictures /usr/bin/sxiv -setFlags Pictures "-s f" -add /home/john/Pictures/*jpg Pictures -add /home/john/Pictures/*png Pictures -addR "/mnt/External_Drive/Johns Photos/*" Pictures -addName "My Desktop Background" "/mnt/External_Drive/desktop wallpaper.jpg" Pictures +Here is an example `config.lua` which creates a Music, Pictures, and, Videos group, and adds all the files from the user's Music, Pictures, and Videos home folders to each group. + +```lua +local lfs = require "lfs" + +local function addGroup(name, launcher, flags) + assert(type(name) == "string") + + -- create Groups table if needed + if Groups == nil then + Groups = {} + end + + local new_group = {} + new_group.name = name + new_group.Entries = {} + if launcher ~= nil then + new_group.Launcher = launcher + end + if flags ~= nil then + new_group.Flags = flags + end + + table.insert(Groups, new_group) + return new_group +end + +local function addEntries(parentGroup, startDir, filePattern, recursive) + -- recursive arg is a boolean for whether or not to descend into subdirectories (false by default) + assert(type(parentGroup) == "table") + assert(type(parentGroup.Entries) == "table") + assert(type(startDir) == "string") + assert(type(filePattern) == "string") + + for file in lfs.dir(startDir) do + local fullFilePath = startDir .. "/" .. file + if file ~= "." and file ~= ".." then + -- descend into subdirectory if recursive is set to true + if lfs.attributes(fullFilePath).mode == "directory" and recursive == true then + addEntries(parentGroup, fullFilePath, filePattern, recursive) + elseif lfs.attributes(fullFilePath).mode == "file" then + if string.match(file, filePattern) then + table.insert(parentGroup.Entries, { + name = file, + path = fullFilePath + }) + end + end + end + end +end + +local music = addGroup("Music", "xdg-open") +addEntries(music, os.getenv("HOME") .. "/Music", ".*", true) + +local pictures = addGroup("Pictures", "xdg-open") +addEntries(pictures, os.getenv("HOME") .. "/Pictures", ".*", true) + +local videos = addGroup("Videos", "xdg-open") +addEntries(videos, os.getenv("HOME") .. "/Videos", ".*", true) ``` diff --git a/docs/windows_compile_instructions.md b/docs/windows_compile_instructions.md index 757dece..4174693 100644 --- a/docs/windows_compile_instructions.md +++ b/docs/windows_compile_instructions.md @@ -1,5 +1,7 @@ # Windows Compilation Instructions +**NOTE: Outdated. Windows users should be just fine following along with instructions on the main README.** + Compiling on Windows requires access to the MinGW toolchain. The easiest way to get the necessary libraries is by installing [MSYS2](https://www.msys2.org/) which provides a package manager: pacman. 1. Download the latest version of MSYS2 from [here](https://www.msys2.org/). -- cgit From 9c397106abfabf8f18b569f4f84ed69822c18978 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Tue, 27 Aug 2024 18:47:38 -0400 Subject: Update man pages --- man/terminal-media-launcher-config.5 | 323 ++++++++++++++++++++++------------- man/terminal-media-launcher.1 | 6 +- 2 files changed, 208 insertions(+), 121 deletions(-) diff --git a/man/terminal-media-launcher-config.5 b/man/terminal-media-launcher-config.5 index 60b814b..0a818b9 100644 --- a/man/terminal-media-launcher-config.5 +++ b/man/terminal-media-launcher-config.5 @@ -1,132 +1,219 @@ -.TH TERMINAL-MEDIA-LAUNCHER-CONFIG 5 +.\" generated with Ronn-NG/v0.9.1 +.TH "TERMINAL\-MEDIA\-LAUNCHER\-CONFIG" 5 -.SH NAME +.SH "NAME" terminal-media-launcher-config - terminal-media-launcher configuration file .SH SYNOPSIS -~/.config/terminal-media-launcher/config (or ~/.terminal-media-launcher/config) +~/.config/terminal-media-launcher/config.lua (or ~/.terminal-media-launcher/config.lua) .SH DESCRIPTION -The configuration file for terminal-media-launcher is a plain text file where commands regarding media groups and entries, along with various settings regarding layout, are specified. These commands are described in the next section. Each line is evaluated on its own, while empty lines and lines beginning with # are ignored. - -A configuration file can be automatically generated if no such file is found. An automatically generated configuration file will create groups for Music, Pictures, and Videos, and add entries to each group from the respective directory in the user's home directory. It is highly recommended that the user edit the configuration file manually. +Starting in version 0\.2, Terminal Media Launcher is configured via a lua \fIhttps://www\.lua\.org/\fR script\. This project assumes the configuration will adhere to lua 5\.1, but is written to be as agnostic as possbile\. The general format of the configuration is outlined below: +.P +.nf +.BI "Groups = { " +.BI " { " +.BI " name = , " +.BI " Launcher = , " +.BI " Flags = , +.BI " Entries = { " +.BI " { " +.BI " name = , " +.BI " path = " +.BI " }, " +.BI " ... " +.BI " } " +.BI " }, " +.BI " ... " +.BI "}" .SH COMMANDS -.SS Creating a Group -\fIterminal-media-launcher-config\fR requires at least one group. - -\fBaddGroup\fR -.RS -This command will create a new group with a specified name. By default, a new group is empty, with zero entries, no launching application specified, and no flags specified. If their is a space in the name, it must be written in quotes (ex. "TV Shows"). -.RE - -\fBsetLauncher\fR -.RS -This command will set a group's launching application. If no launching application is specified for a group, terminal-media-launcher will treat each entry in that group as an executable file. If their is a space in the path to the launching application, it must be written in quotes (ex. "/usr/bin/my launcher"). The path to the launching application should be absolute. -.RE - -\fBsetLauncherRaw\fR -.RS -This command is identical to \fIsetLauncher\fR with the exception that the launcher application specified will not be wrapped in quotes for the system call when a member of the group is launched. This can be used to specify more complex launching instructions. -.RE - -\fBsetFlags\fR -.RS -This command will set the flags to be specified for the launching application. If no launching application is specified, any specified flags are ignored. If the specified flags contain a space, they must be written in quotes. -.RE - -.SS Adding Entries -In order for a created group to be valid, it must contain at least one entry. - -\fBadd\fR -.RS -This command will add a file to a specified group if the path exists. It can also be used to add mutiple files to a group in one line using the '*' operator (ex. add /home/john/Pictures/* Pictures). If the path to the file(s) contains space(s), it must be written in quotes. -.RE - -\fBaddF\fR -.RS -This command will force an entry to be added to a specified group, regardless as to whether it is a valid file or not. Unlike \fIadd\fR, \fIaddF\fR's argument does not need to be a valid file, but \fIaddF\fR can only specify a single entry and does not support the '*' operator. If the arg has a space in it, it must be written in quotes. -.RE - -\fBaddName\fR -.RS -This command, like \fIadd\fR, will add an entry to a specified group if the path exists. \fIaddName\fR allows for a name to be specified for this entry (by default, the name is the same as the file name). Unlike \fIadd\fR, only one entry can be added per line, as \fIaddName\fR does not support the '*' operator. If either the name or file path contain a space, they must be written in quotes. -.RE - -\fBaddNameF\fR -.RS -This command can be used in place of \fIaddF\fR if you want the forced argument to have a different name displayed for the entry than is called in the system call to launch the entry. Otherwise, it is effectively the same as \fIaddF\fR. -.RE - -\fBaddR\fR -.RS -This command will recursively add entries to a group. \fIaddR\fR functions like \fIadd\fR, but will also search sub-directories for matches. -.RE - -\fBhide\fR -.RS -This command will remove a specified entry from a specified group. The entry argument should refer to the entry's name, rather than the entry's path. This option may be useful to hide certain entries after adding many entries with the '*' operator. -.RE - -\fBhideFile\fR -.RS -This command has the exact same functionality as \fIhide\fR, but takes the absolute path of the entry to hide as the first argument, instead of the name. -.RE - -.SS Settings -Settings should be specified at the top of \fIterminal-media-launcher-config\fR - -\fBautoAlias\fR on|off -.RS -This setting will attempt to automatically give entries more human-readable names by: - - 1. Removing any characters inside parenthesis (including parenthesis) - 2. Replacing '-' and '\_' with a space character - 3. Replacing cases of multiple spaces in a row with only one space - 4. Removing file extensions (if the file has an extension) - -\fIautoAlias\fR is turned off by default. -.RE - -\fBfoldCase\fR on|off -.RS -Entering any non-traversal input in terminal-media-launcher can be used to jump to a group or entry. For instance, hitting 'f' on the keyboard will jump the cursor to the next group or entry that starts with an 'f'. This setting determines whether or not this functionality is case insensitive (on) or case sensitive (off). \fIfoldCase\fR is turned on by default. -.RE - -\fBsort\fR on|off -.RS -This setting will sort entries of each group in alphabetical order (though not the list of groups). Turning off \fIsort\fR is only recommended when adding one item per line to a group. \fIsort\fR is turned on by default. -.RE - -.SH EXAMPLE - +.SS "Creating a Group" +The config must contain at least one valid group\. Groups are to be inserted in the \fBGroups\fR global variable\. \fBGroups\fR is an array of tables\. Each group is a table containing the following keys: + +.IP "Mandatory keys:" +.IP "\[ci]" 4 +\fBname\fR \fIstring\fR \- a name for the group +.IP "\[ci]" 4 +\fBEntries\fR \fItable\fR \- an array of tables\. Each table represents an entry\. +.IP "" 0 + +.IP "Optional keys:" +.IP "\[ci]" 4 +\fBLauncher\fR \fIstring\fR \- the path for a program that launches the entries of this group\. If not set, it assumes the entries in this group are executables (and have no launching program) +.IP "\[ci]" 4 +\fBFlags\fR \fIstring\fR \- flags to pass to the launching program\. If not set, no flags are passed +.IP "" 0 + +.IP "" 0 +.P +Here is a helper function you can use in your config to add a group +.P +\fB +.EX +local function addGroup(name, launcher, flags) + assert(type(name) == "string") + + -- create Groups table if needed + if Groups == nil then + Groups = {} + end + + local new_group = {} + new_group.name = name + new_group.Entries = {} + if launcher ~= nil then + new_group.Launcher = launcher + end + if flags ~= nil then + new_group.Flags = flags + end + + table.insert(Groups, new_group) + return new_group +end +\fR + + +.SS "Adding Entries" +For a group to be valid, it must contain at least one valid entry\. Entries are to be inserted in the \fBEntries\fR key of a group table\. \fBEntries\fR is an array of tables\. Each entry is a table containing the following keys: +.IP "Mandatory keys:" +.IP "\[ci]" 4 +\fBname\fR \fIstring\fR \- a name for the entry +.IP "" 0 + +.IP "Optional keys:" +.IP "\[ci]" 4 +\fBpath\fR \fIstring\fR \- a path to the file associated with this entry\. If not set, the path is the same as the name +.IP "" 0 + +.IP "" 0 +.P +Here is a helper function you can use in your config to add an entry to a group +.P +\fB +.EX +local function addEntry(parentGroup, name, path) + assert(type(parentGroup) == "table") + assert(type(parentGroup.Entries) == "table") + assert(type(name) == "string") + + local new_entry = {} + new_entry.name = name + if path ~= nil then + new_entry.path = path + end + + table.insert(parentGroup.Entries, new_entry) + return new_entry +end +\fR + +.IP "" 0 +.SS "Adding Entries using lfs module" +It is recommended to install the lua\-filesystem \fIhttps://github\.com/lunarmodules/luafilesystem\fR module and use it to add entries more efficiently\. This example can be used to descend into a directory and add files matching a \fBstring\.match\fR pattern to a group\. +\fB +.EX +local lfs = require "lfs" + +local function addEntries(parentGroup, startDir, filePattern, recursive) + -- recursive arg is a boolean for whether or not to descend into subdirectories (false by default) + assert(type(parentGroup) == "table") + assert(type(parentGroup.Entries) == "table") + assert(type(startDir) == "string") + assert(type(filePattern) == "string") + + for file in lfs.dir(startDir) do + local fullFilePath = startDir .. "/" .. file + if file ~= "." and file ~= ".." then + -- descend into subdirectory if recursive is set to true + if lfs.attributes(fullFilePath).mode == "directory" and recursive == true then + addEntries(parentGroup, fullFilePath, filePattern, recursive) + elseif lfs.attributes(fullFilePath).mode == "file" then + if string.match(file, filePattern) then + table.insert(parentGroup.Entries, { + name = file, + path = fullFilePath + }) + end + end + end + end +end +\fR + +.SS "Settings" +Settings can be set via the \fBSettings\fR global variable\. +.P .nf -autoAlias on - -# Adding a Group of Various Applications +.BI "Settings = {} " +.BI "Settings\.sort = " -addGroup Applications -addName GIMP /usr/bin/gimp Applications -addName Chromium /usr/bin/chromium-browser Applications -addName Thunderbird /usr/bin/thunderbird Applications +\fBsort\fR will sort entries of each group in alphabetical order (though not the list of groups)\. \fBsort\fR is true by default\. -# Adding a Videos Group that contains mp4 files - -addGroup Videos -setLauncher Videos /usr/bin/vlc -add /home/john/Videos/*mp4 Videos - -.fi -# Adding a Pictures Group that contains only jpg and png files as well as all files from an external drive and a single desktop wallpaper -.nf - -addGroup Pictures -setLauncher Pictures /usr/bin/sxiv -setFlags Pictures "-s f" -add /home/john/Pictures/*jpg Pictures -add /home/john/Pictures/*png Pictures -addR "/mnt/External_Drive/Johns Photos/*" Pictures -addName "My Desktop Background" "/mnt/External_Drive/desktop wallpaper.jpg" Pictures +.SH EXAMPLE +Here is an example \fBconfig\.lua\fR which creates a Music, Pictures, and, Videos group, and adds all the files from the user's Music, Pictures, and Videos home folders to each group\. + +\fB +.EX +local lfs = require "lfs" + +local function addGroup(name, launcher, flags) + assert(type(name) == "string") + + -- create Groups table if needed + if Groups == nil then + Groups = {} + end + + local new_group = {} + new_group.name = name + new_group.Entries = {} + if launcher ~= nil then + new_group.Launcher = launcher + end + if flags ~= nil then + new_group.Flags = flags + end + + table.insert(Groups, new_group) + return new_group +end + +local function addEntries(parentGroup, startDir, filePattern, recursive) + -- recursive arg is a boolean for whether or not to descend into subdirectories (false by default) + assert(type(parentGroup) == "table") + assert(type(parentGroup.Entries) == "table") + assert(type(startDir) == "string") + assert(type(filePattern) == "string") + + for file in lfs.dir(startDir) do + local fullFilePath = startDir .. "/" .. file + if file ~= "." and file ~= ".." then + -- descend into subdirectory if recursive is set to true + if lfs.attributes(fullFilePath).mode == "directory" and recursive == true then + addEntries(parentGroup, fullFilePath, filePattern, recursive) + elseif lfs.attributes(fullFilePath).mode == "file" then + if string.match(file, filePattern) then + table.insert(parentGroup.Entries, { + name = file, + path = fullFilePath + }) + end + end + end + end +end + +local music = addGroup("Music", "xdg-open") +addEntries(music, os.getenv("HOME") .. "/Music", ".*", true) + +local pictures = addGroup("Pictures", "xdg-open") +addEntries(pictures, os.getenv("HOME") .. "/Pictures", ".*", true) + +local videos = addGroup("Videos", "xdg-open") +addEntries(videos, os.getenv("HOME") .. "/Videos", ".*", true) +\fR .fi .SH SEE ALSO diff --git a/man/terminal-media-launcher.1 b/man/terminal-media-launcher.1 index c25b99a..14d4c14 100644 --- a/man/terminal-media-launcher.1 +++ b/man/terminal-media-launcher.1 @@ -71,13 +71,13 @@ Exit the program Any other input will jump to the next matching group/entry that begins with the input character, if one exists (ex. hitting 'f' while focused on the entries column will jump to the next entry that starts with an 'f' unless there is no entry that starts with an 'f'). .SH FILES -\fB~/.config/terminal-media-launcher/config (or ~/.terminal-media-launcher/config)\fR +\fB~/.config/terminal-media-launcher/config.lua (or ~/.terminal-media-launcher/config.lua)\fR .RS When starting, terminal-media-launcher looks for a configuration file in the following order: - 1. ~/.config/terminal-media-launcher/config + 1. ~/.config/terminal-media-launcher/config.lua - 2. ~/.terminal-media-launcher/config + 2. ~/.terminal-media-launcher/config.lua You can specify a custom path using the -c option. For documentation of the config file, see \fBterminal-media-launcher-config\fR(5). .RE -- cgit From c53c16b6e606e16c7db492d05a8ed56574aaf3f9 Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Fri, 30 Aug 2024 14:31:39 -0400 Subject: Update default configurations --- nsis/Makefile.am | 2 +- src/unix/read_cfg.c | 110 +++++++++++++++++++++++++++---------------------- src/windows/read_cfg.c | 107 ++++++++++++++++++++++++++--------------------- 3 files changed, 121 insertions(+), 98 deletions(-) diff --git a/nsis/Makefile.am b/nsis/Makefile.am index 3f47a9f..72f8ab9 100644 --- a/nsis/Makefile.am +++ b/nsis/Makefile.am @@ -1,4 +1,4 @@ -EXTRA_DIST = installer.nsi.in +EXTRA_DIST = find_dlls.sh installer.nsi.in CLEANFILES = $(PACKAGE_NAME)-Setup.exe deps/* diff --git a/src/unix/read_cfg.c b/src/unix/read_cfg.c index 6f75ddc..602c750 100644 --- a/src/unix/read_cfg.c +++ b/src/unix/read_cfg.c @@ -78,56 +78,66 @@ void mkconfig_wizard(char *path){ exit(1); } - //write to file - fprintf(fp, "# This file was auto-generated by terminal-media-launcher. See docs/terminal-media-launcher-config.md or terminal-media-launcher-config(5) for documentation\n" - "# The default launcher is set to \"xdg-open\" which will open files based on the relevant default application set through xdg\n\n" - "# Recursively add files from %s%cMusic%c to Music group\n" - "addGroup Music\n" - "setLauncher Music xdg-open\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.aac Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.aiff Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.alac Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.au Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.flac Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.m4a Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.mp3 Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.ogg Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.pcm Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.wav Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.wma Music\n\n", home, sep, sep); - fprintf(fp, "# Recursively add files from %s%cPictures%c to Pictures group\n" - "addGroup Pictures\n" - "setLauncher Pictures xdg-open\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.epi Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.eps Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.eps2 Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.eps3 Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.epsf Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.epsi Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.ept Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.gif Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.gfa Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.giff Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.jpeg Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.jpg Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.png Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.svg Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.svgz Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.tif Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.tiff Pictures\n\n", home, sep, sep); - fprintf(fp, "# Recursively add files from %s%cVideos%c to Videos group\n" - "addGroup Videos\n" - "setLauncher Videos xdg-open\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.asf Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.avi Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.flv Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.mk3d Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.mkv Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.mov Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.mp4 Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.qt Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.webm Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.wmv Videos\n", home, sep, sep); + fprintf(fp, + "-- This file was auto-generated by terminal-media-launcher. See docs/terminal-media-launcher-config.md or terminal-media-launcher-config(5) for documentation\n" + "-- The default launcher is set to \"xdg-open\" which will open files based on the relevant default application set through xdg\n\n" + "local lfs = require \"lfs\"\n" + "\n" + "local function addGroup(name, launcher, flags)\n" + " assert(type(name) == \"string\")\n" + "\n" + " -- create Groups table if needed\n" + " if Groups == nil then\n" + " Groups = {}\n" + " end\n" + "\n" + " local new_group = {}\n" + " new_group.name = name\n" + " new_group.Entries = {}\n" + " if launcher ~= nil then\n" + " new_group.Launcher = launcher\n" + " end\n" + " if flags ~= nil then\n" + " new_group.Flags = flags\n" + " end\n" + "\n" + " table.insert(Groups, new_group)\n" + " return new_group\n" + "end\n" + "\n" + "local function addEntries(parentGroup, startDir, filePattern, recursive)\n" + " -- recursive arg is a boolean for whether or not to descend into subdirectories (false by default)\n" + " assert(type(parentGroup) == \"table\")\n" + " assert(type(parentGroup.Entries) == \"table\")\n" + " assert(type(startDir) == \"string\")\n" + " assert(type(filePattern) == \"string\")\n" + "\n" + " for file in lfs.dir(startDir) do\n" + " local fullFilePath = startDir .. \"/\" .. file\n" + " if file ~= \".\" and file ~= \"..\" then\n" + " -- descend into subdirectory if recursive is set to true\n" + " if lfs.attributes(fullFilePath).mode == \"directory\" and recursive == true then\n" + " addEntries(parentGroup, fullFilePath, filePattern, recursive)\n" + " elseif lfs.attributes(fullFilePath).mode == \"file\" then\n" + " if string.match(file, filePattern) then\n" + " table.insert(parentGroup.Entries, {\n" + " name = file,\n" + " path = fullFilePath\n" + " })\n" + " end\n" + " end\n" + " end\n" + " end\n" + "end\n" + "\n" + "local music = addGroup(\"Music\", \"xdg-open\")\n" + "addEntries(music, os.getenv(\"HOME\") .. \"/Music\", \".*\", true)\n" + "\n" + "local pictures = addGroup(\"Pictures\", \"xdg-open\")\n" + "addEntries(pictures, os.getenv(\"HOME\") .. \"/Pictures\", \".*\", true)\n" + "\n" + "local videos = addGroup(\"Videos\", \"xdg-open\")\n" + "addEntries(videos, os.getenv(\"HOME\") .. \"/Videos\", \".*\", true)\n"); fclose(fp); printf("done\nIt is highly recommended to further tweak the configuration file! [press any key to continue]"); diff --git a/src/windows/read_cfg.c b/src/windows/read_cfg.c index bb337f0..79e56b7 100644 --- a/src/windows/read_cfg.c +++ b/src/windows/read_cfg.c @@ -81,53 +81,66 @@ void mkconfig_wizard(char *path){ exit(1); } - fprintf(fp, "# This file was auto-generated by terminal-media-launcher. See docs\\terminal-media-launcher-config.md or terminal-media-launcher-config(5) for documentation\n" - "# By default, no launcher is specified for any group. When no launcher is specified on the Windows build of terminal-media-launcher, media files will be opened with their default application.\n" - "# It is generally recommended to specify a launcher for groups containing media files using the \"setLauncher\" command\n\n" - "# Recursively add files from %s%cMusic%c to Music group\n" - "addGroup Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.aac Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.aiff Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.alac Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.au Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.flac Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.m4a Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.mp3 Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.ogg Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.pcm Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.wav Music\n", home, sep, sep); - fprintf(fp, "addR %s%cMusic%c*.wma Music\n\n", home, sep, sep); - fprintf(fp, "# Recursively add files from %s%cPictures%c to Pictures group\n" - "addGroup Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.epi Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.eps Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.eps2 Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.eps3 Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.epsf Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.epsi Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.ept Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.gif Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.gfa Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.giff Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.jpeg Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.jpg Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.png Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.svg Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.svgz Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.tif Pictures\n", home, sep, sep); - fprintf(fp, "addR %s%cPictures%c*.tiff Pictures\n\n", home, sep, sep); - fprintf(fp, "# Recursively add files from %s%cVideos%c to Videos group\n" - "addGroup Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.asf Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.avi Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.flv Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.mk3d Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.mkv Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.mov Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.mp4 Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.qt Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.webm Videos\n", home, sep, sep); - fprintf(fp, "addR %s%cVideos%c*.wmv Videos\n", home, sep, sep); + fprintf(fp, + "-- This file was auto-generated by terminal-media-launcher. See docs\\terminal-media-launcher-config.md or terminal-media-launcher-config(5) for documentation\n" + "-- By default, no launcher is specified for any group. When no launcher is specified on the Windows build of terminal-media-launcher, media files will be opened with their default application.\n\n" + "local lfs = require \"lfs\"\n" + "\n" + "local function addGroup(name, launcher, flags)\n" + " assert(type(name) == \"string\")\n" + "\n" + " -- create Groups table if needed\n" + " if Groups == nil then\n" + " Groups = {}\n" + " end\n" + "\n" + " local new_group = {}\n" + " new_group.name = name\n" + " new_group.Entries = {}\n" + " if launcher ~= nil then\n" + " new_group.Launcher = launcher\n" + " end\n" + " if flags ~= nil then\n" + " new_group.Flags = flags\n" + " end\n" + "\n" + " table.insert(Groups, new_group)\n" + " return new_group\n" + "end\n" + "\n" + "local function addEntries(parentGroup, startDir, filePattern, recursive)\n" + " -- recursive arg is a boolean for whether or not to descend into subdirectories (false by default)\n" + " assert(type(parentGroup) == \"table\")\n" + " assert(type(parentGroup.Entries) == \"table\")\n" + " assert(type(startDir) == \"string\")\n" + " assert(type(filePattern) == \"string\")\n" + "\n" + " for file in lfs.dir(startDir) do\n" + " local fullFilePath = startDir .. \"\\\\\" .. file\n" + " if file ~= \".\" and file ~= \"..\" then\n" + " -- descend into subdirectory if recursive is set to true\n" + " if lfs.attributes(fullFilePath).mode == \"directory\" and recursive == true then\n" + " addEntries(parentGroup, fullFilePath, filePattern, recursive)\n" + " elseif lfs.attributes(fullFilePath).mode == \"file\" then\n" + " if string.match(file, filePattern) then\n" + " table.insert(parentGroup.Entries, {\n" + " name = file,\n" + " path = fullFilePath\n" + " })\n" + " end\n" + " end\n" + " end\n" + " end\n" + "end\n" + "\n" + "local music = addGroup(\"Music\")\n" + "addEntries(music, os.getenv(\"USERPROFILE\") .. \"\\\\Music\", \".*\", true)\n" + "\n" + "local pictures = addGroup(\"Pictures\")\n" + "addEntries(pictures, os.getenv(\"USERPROFILE\") .. \"\\\\Pictures\", \".*\", true)\n" + "\n" + "local videos = addGroup(\"Videos\")\n" + "addEntries(videos, os.getenv(\"USERPROFILE\") .. \"\\\\Videos\", \".*\", true)\n"); fclose(fp); printf("done\nIt is highly recommended to further tweak the configuration file! [press any key to continue]"); -- cgit From a77f5393a584338561f217d3f87832e910bf937a Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Fri, 30 Aug 2024 14:36:35 -0400 Subject: Reenable caching --- src/draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/draw.c b/src/draw.c index 4dd5d75..7303ff6 100644 --- a/src/draw.c +++ b/src/draw.c @@ -97,8 +97,8 @@ int main(int argc, char **argv){ e_hover = calloc(g_count, sizeof(int)); e_offset = calloc(g_count, sizeof(int)); - //load cached data - //load_cache(g_count, &g_hover, &e_hover, &e_offset, &true_hover, cfg_path); + // load cached data + load_cache(g_count, &g_hover, &e_hover, &e_offset, &true_hover, cfg_path); //reopen stdout for drawing menu freopen("/dev/tty", "w", stdout); -- cgit From a3d9eb21789bf3587f176e6d155d610b8bc69dab Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Fri, 30 Aug 2024 14:49:00 -0400 Subject: Remove quotes from get_launch --- src/draw.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/draw.c b/src/draw.c index 7303ff6..3412185 100644 --- a/src/draw.c +++ b/src/draw.c @@ -556,28 +556,21 @@ char *get_launch(){ char *program = get_gprog(g[g_hover]); char *flags = get_gflags(g[g_hover]); char *path = get_epath(entries[e_hover[g_hover]]); - bool quotes = false; char *full_command = calloc(BUF_LEN, sizeof(char)); //if the entry is an executable file (doesn't have a launcher) if(!(strcmp(program, "./"))){ - strcat(full_command, "\""); strcat(full_command, path); - strcat(full_command, "\""); } else{ - if(quotes) strcat(full_command, "\""); strcat(full_command, program); - if(quotes) strcat(full_command, "\""); if(flags[0] !='\0'){ strcat(full_command, " "); strcat(full_command, flags); } strcat(full_command, " "); - strcat(full_command, "\""); strcat(full_command, path); - strcat(full_command, "\""); } return full_command; -- cgit