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:
M | config.def.h | | | 12 | ++++++------ |
M | noice.1 | | | 17 | +---------------- |
M | noice.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(®ex, file, 0, NULL, 0) == 0) {
- bin = assocs[i].bin;
+ assoc = &assocs[i];
regfree(®ex);
break;
}
regfree(®ex);
}
- 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();
}
}