noice

small file browser
git clone git://git.2f30.org/noice
Log | Files | Refs | README | LICENSE

commit 36de02e0658d7ddbf7d63879c812864d984e66a9
parent ae2cb6f11dc6ea982fbb7e70ae6769d4ed66a160
Author: sin <sin@2f30.org>
Date:   Sun, 31 Mar 2019 11:10:04 +0100

Add support for passing options to file associations

Diffstat:
Mconfig.def.h | 12++++++------
Mnoice.1 | 17+----------------
Mnoice.c | 66+++++++++++++++++++++++++++++++++++++++++++++++++++---------------
3 files changed, 58 insertions(+), 37 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -32,12 +32,12 @@ struct cpair pairs[] = { }; struct assoc assocs[] = { - { "\\.(avi|mp4|mkv|mp3|ogg|flac|mov)$", "mpv" }, - { "\\.(png|jpg|gif)$", "sxiv" }, - { "\\.(html|svg)$", "firefox" }, - { "\\.pdf$", "mupdf" }, - { "\\.sh$", "sh" }, - { ".", "less" }, + { .regex = "\\.(avi|mp4|mkv|mp3|ogg|flac|mov)$", .file = "mpv", .argv = { "mpv", "{}", NULL } }, + { .regex = "\\.(png|jpg|gif)$", .file = "sxiv", .argv = { "sxiv", "{}", NULL} }, + { .regex = "\\.(html|svg)$", .file = "firefox", .argv = { "firefox", "{}", NULL } }, + { .regex = "\\.pdf$", .file = "mupdf", .argv = { "mupdf", "{}", NULL} }, + { .regex = "\\.sh$", .file = "sh", .argv = { "sh", "{}", NULL} }, + { .regex = ".", .file = "less", .argv = { "less", "{}", NULL } }, }; struct key bindings[] = { diff --git a/noice.1 b/noice.1 @@ -1,4 +1,4 @@ -.Dd Jan 19, 2019 +.Dd March 31, 2019 .Dt NOICE 1 .Os .Sh NAME @@ -99,8 +99,6 @@ command in to edit the file using the .Ev EDITOR environment variable. -.Pp -See the examples section below for more information. .Sh FILTERS Filters allow you to use regexes to display only the matched entries in the current directory view. @@ -127,19 +125,6 @@ environment variables take precedence when dealing with the and .Ic p commands respectively. -.Sh EXAMPLES -The following example shows one possible configuration for -file associations which is also the default: -.Bd -literal -struct assoc assocs[] = { - { "\\.(avi|mp4|mkv|mp3|ogg|flac|mov)$", "mpv" }, - { "\\.(png|jpg|gif)$", "sxiv" }, - { "\\.(html|svg)$", "firefox" }, - { "\\.pdf$", "mupdf" }, - { "\\.sh$", "sh" }, - { ".", "less" }, -}; -.Ed .Sh KNOWN ISSUES If you are using .Xr urxvt 1 diff --git a/noice.c b/noice.c @@ -33,6 +33,7 @@ #define DPRINTF_P(x) #endif /* DEBUG */ +#define NR_ARGS 32 #define LEN(x) (sizeof(x) / sizeof(*(x))) #undef MIN #define MIN(x, y) ((x) < (y) ? (x) : (y)) @@ -42,7 +43,8 @@ struct assoc { char *regex; /* Regex to match on filename */ - char *bin; /* Program */ + char *file; + char *argv[NR_ARGS]; }; struct cpair { @@ -178,7 +180,7 @@ xdirname(const char *path) } void -spawn(char *file, char *arg, char *dir) +spawnvp(char *dir, char *file, char *argv[]) { pid_t pid; int status; @@ -187,7 +189,7 @@ spawn(char *file, char *arg, char *dir) if (pid == 0) { if (dir != NULL) chdir(dir); - execlp(file, file, arg, NULL); + execvp(file, argv); _exit(1); } else { /* Ignore interruptions */ @@ -197,6 +199,39 @@ spawn(char *file, char *arg, char *dir) } } +void +spawnlp(char *dir, char *file, char *argv0, ...) +{ + char *argv[NR_ARGS]; + va_list ap; + int argc; + + va_start(ap, argv0); + argv[0] = argv0; + for (argc = 1; argv[argc] = va_arg(ap, char *); argc++) + ; + argv[argc] = NULL; + va_end(ap); + spawnvp(dir, file, argv); +} + +void +spawnassoc(struct assoc *assoc, char *arg) +{ + char *argv[NR_ARGS]; + int i; + + for (i = 0; assoc->argv[i]; i++) { + if (strcmp(assoc->argv[i], "{}") == 0) { + argv[i] = arg; + continue; + } + argv[i] = assoc->argv[i]; + } + argv[i] = NULL; + spawnvp(NULL, assoc->file, argv); +} + char * xgetenv(char *name, char *fallback) { @@ -208,11 +243,11 @@ xgetenv(char *name, char *fallback) return value && value[0] ? value : fallback; } -char * +struct assoc * openwith(char *file) { regex_t regex; - char *bin = NULL; + struct assoc *assoc = NULL; int i; for (i = 0; i < LEN(assocs); i++) { @@ -220,14 +255,14 @@ openwith(char *file) REG_NOSUB | REG_EXTENDED | REG_ICASE) != 0) continue; if (regexec(&regex, file, 0, NULL, 0) == 0) { - bin = assocs[i].bin; + assoc = &assocs[i]; regfree(&regex); break; } regfree(&regex); } - DPRINTF_S(bin); - return bin; + DPRINTF_S(assoc->argv[0]); + return assoc; } int @@ -653,7 +688,8 @@ browse(char *ipath, char *ifilter) { char path[PATH_MAX], oldpath[PATH_MAX], newpath[PATH_MAX]; char fltr[LINE_MAX]; - char *bin, *dir, *tmp, *run, *env; + char *dir, *tmp, *run, *env; + struct assoc *assoc; struct stat sb; regex_t re; int r, fd; @@ -726,13 +762,13 @@ nochange: strlcpy(fltr, ifilter, sizeof(fltr)); goto begin; case S_IFREG: - bin = openwith(newpath); - if (bin == NULL) { + assoc = openwith(newpath); + if (assoc == NULL) { printmsg("No association"); goto nochange; } exitcurses(); - spawn(bin, newpath, NULL); + spawnassoc(assoc, newpath); initcurses(); continue; default: @@ -845,7 +881,7 @@ nochange: mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); run = xgetenv(env, run); exitcurses(); - spawn(run, NULL, path); + spawnlp(path, run, run, NULL); initcurses(); goto begin; case SEL_RUNARG: @@ -854,7 +890,7 @@ nochange: mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); run = xgetenv(env, run); exitcurses(); - spawn(run, dents[cur].name, path); + spawnlp(path, run, run, dents[cur].name, NULL); initcurses(); goto begin; } @@ -862,7 +898,7 @@ nochange: if (idletimeout != 0 && idle == idletimeout) { idle = 0; exitcurses(); - spawn(idlecmd, NULL, NULL); + spawnlp(NULL, idlecmd, idlecmd, NULL); initcurses(); } }