Implement startup configuration file support (issue #08)
Load ~/.config/lush/config and config.d/*.lua at REPL startup, respecting XDG_CONFIG_HOME. Suppressed by -E flag.
This commit is contained in:
82
lua.c
82
lua.c
@@ -13,6 +13,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "lua.h"
|
||||
@@ -722,6 +724,79 @@ static void doREPL (lua_State *L) {
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** Configuration file support
|
||||
** ===================================================================
|
||||
*/
|
||||
|
||||
static const char *get_config_dir (char *buf, size_t bufsize) {
|
||||
const char *xdg = getenv("XDG_CONFIG_HOME");
|
||||
const char *home = getenv("HOME");
|
||||
if (xdg && xdg[0] != '\0')
|
||||
snprintf(buf, bufsize, "%s/lush", xdg);
|
||||
else if (home && home[0] != '\0')
|
||||
snprintf(buf, bufsize, "%s/.config/lush", home);
|
||||
else
|
||||
return NULL;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static int cmpstr (const void *a, const void *b) {
|
||||
return strcmp(*(const char **)a, *(const char **)b);
|
||||
}
|
||||
|
||||
|
||||
static void run_config_dir (lua_State *L, const char *dirpath) {
|
||||
char *names[256];
|
||||
int count = 0;
|
||||
int i;
|
||||
struct dirent *entry;
|
||||
DIR *d = opendir(dirpath);
|
||||
if (d == NULL) return; /* directory doesn't exist — skip silently */
|
||||
|
||||
/* collect .lua filenames */
|
||||
while ((entry = readdir(d)) != NULL && count < 256) {
|
||||
size_t len = strlen(entry->d_name);
|
||||
if (len > 4 && strcmp(entry->d_name + len - 4, ".lua") == 0)
|
||||
names[count++] = strdup(entry->d_name);
|
||||
}
|
||||
closedir(d);
|
||||
|
||||
/* sort lexicographically */
|
||||
qsort(names, (size_t)count, sizeof(char *), cmpstr);
|
||||
|
||||
/* execute each file */
|
||||
for (i = 0; i < count; i++) {
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "%s/%s", dirpath, names[i]);
|
||||
dofile(L, path); /* errors reported but not fatal */
|
||||
free(names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void handle_lushconfig (lua_State *L) {
|
||||
char configdir[PATH_MAX];
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (get_config_dir(configdir, sizeof(configdir)) == NULL)
|
||||
return; /* no HOME or XDG_CONFIG_HOME — skip silently */
|
||||
|
||||
/* 1. Run ~/.config/lush/config if it exists */
|
||||
snprintf(path, sizeof(path), "%s/config", configdir);
|
||||
if (access(path, R_OK) == 0)
|
||||
dofile(L, path); /* errors are reported but not fatal */
|
||||
|
||||
/* 2. Run config.d/ lua files in sorted order */
|
||||
snprintf(path, sizeof(path), "%s/config.d", configdir);
|
||||
run_config_dir(L, path);
|
||||
}
|
||||
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** Main body of stand-alone interpreter (to be called in protected mode).
|
||||
** Reads the options and handles them all.
|
||||
@@ -757,11 +832,16 @@ static int pmain (lua_State *L) {
|
||||
if (handle_script(L, argv + script) != LUA_OK)
|
||||
return 0; /* interrupt in case of error */
|
||||
}
|
||||
if (args & has_i) /* -i option? */
|
||||
if (args & has_i) { /* -i option? */
|
||||
if (!(args & has_E))
|
||||
handle_lushconfig(L);
|
||||
doREPL(L); /* do read-eval-print loop */
|
||||
}
|
||||
else if (script < 1 && !(args & (has_e | has_v))) { /* no active option? */
|
||||
if (lua_stdin_is_tty()) { /* running in interactive mode? */
|
||||
print_version();
|
||||
if (!(args & has_E))
|
||||
handle_lushconfig(L);
|
||||
doREPL(L); /* do read-eval-print loop */
|
||||
}
|
||||
else dofile(L, NULL); /* executes stdin as a file */
|
||||
|
||||
Reference in New Issue
Block a user