Moved external shell commands into exec/key-handler script
Gets called on all unset key mappings. Arguments are: key combo and current file. Thanks to Francesco Orsenigo (xarvh) for the idea.
This commit is contained in:
parent
b2eae528ed
commit
f2e0c492bd
4
Makefile
4
Makefile
|
@ -35,8 +35,8 @@ install: all
|
||||||
sed "s!PREFIX!$(PREFIX)!g; s!VERSION!$(VERSION)!g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
|
sed "s!PREFIX!$(PREFIX)!g; s!VERSION!$(VERSION)!g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
|
||||||
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
|
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/sxiv.1
|
||||||
mkdir -p $(DESTDIR)$(PREFIX)/share/sxiv/exec
|
mkdir -p $(DESTDIR)$(PREFIX)/share/sxiv/exec
|
||||||
cp image-info $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info
|
cp exec/* $(DESTDIR)$(PREFIX)/share/sxiv/exec/
|
||||||
chmod 755 $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info
|
chmod 755 $(DESTDIR)$(PREFIX)/share/sxiv/exec/*
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f $(DESTDIR)$(PREFIX)/bin/sxiv
|
rm -f $(DESTDIR)$(PREFIX)/bin/sxiv
|
||||||
|
|
66
commands.c
66
commands.c
|
@ -504,69 +504,3 @@ bool it_toggle_alpha(arg_t a)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool it_open_with(arg_t a)
|
|
||||||
{
|
|
||||||
const char *prog = (const char*) a;
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
if (prog == NULL || *prog == '\0')
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ((pid = fork()) == 0) {
|
|
||||||
execlp(prog, prog,
|
|
||||||
files[mode == MODE_IMAGE ? fileidx : tns.sel].path, NULL);
|
|
||||||
warn("could not exec: %s", prog);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else if (pid < 0) {
|
|
||||||
warn("could not fork. program was: %s", prog);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool it_shell_cmd(arg_t a)
|
|
||||||
{
|
|
||||||
int n, status;
|
|
||||||
const char *cmdline = (const char*) a;
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
if (cmdline == NULL || *cmdline == '\0')
|
|
||||||
return false;
|
|
||||||
|
|
||||||
n = mode == MODE_IMAGE ? fileidx : tns.sel;
|
|
||||||
|
|
||||||
if (setenv("SXIV_IMG", files[n].path, 1) < 0) {
|
|
||||||
warn("could not set env.-variable: SXIV_IMG. command line was: %s",
|
|
||||||
cmdline);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pid = fork()) == 0) {
|
|
||||||
execl("/bin/sh", "/bin/sh", "-c", cmdline, NULL);
|
|
||||||
warn("could not exec: /bin/sh. command line was: %s", cmdline);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else if (pid < 0) {
|
|
||||||
warn("could not fork. command line was: %s", cmdline);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
win_set_cursor(&win, CURSOR_WATCH);
|
|
||||||
|
|
||||||
waitpid(pid, &status, 0);
|
|
||||||
if (WIFEXITED(status) == 0 || WEXITSTATUS(status) != 0)
|
|
||||||
warn("child exited with non-zero return value: %d. command line was: %s",
|
|
||||||
WEXITSTATUS(status), cmdline);
|
|
||||||
|
|
||||||
if (mode == MODE_IMAGE) {
|
|
||||||
img_close(&img, true);
|
|
||||||
load_image(fileidx);
|
|
||||||
}
|
|
||||||
if (!tns_load(&tns, n, &files[n], true, mode == MODE_IMAGE) &&
|
|
||||||
mode == MODE_THUMB)
|
|
||||||
{
|
|
||||||
remove_file(tns.sel, false);
|
|
||||||
tns.dirty = true;
|
|
||||||
if (tns.sel >= tns.cnt)
|
|
||||||
tns.sel = tns.cnt - 1;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
|
@ -69,7 +69,5 @@ bool i_flip(arg_t);
|
||||||
bool i_toggle_antialias(arg_t);
|
bool i_toggle_antialias(arg_t);
|
||||||
bool i_change_gamma(arg_t);
|
bool i_change_gamma(arg_t);
|
||||||
bool it_toggle_alpha(arg_t);
|
bool it_toggle_alpha(arg_t);
|
||||||
bool it_open_with(arg_t);
|
|
||||||
bool it_shell_cmd(arg_t);
|
|
||||||
|
|
||||||
#endif /* COMMANDS_H */
|
#endif /* COMMANDS_H */
|
||||||
|
|
17
config.def.h
17
config.def.h
|
@ -151,23 +151,6 @@ static const keymap_t keys[] = {
|
||||||
{ 0, XK_braceleft, i_change_gamma, (arg_t) -1 },
|
{ 0, XK_braceleft, i_change_gamma, (arg_t) -1 },
|
||||||
{ 0, XK_braceright, i_change_gamma, (arg_t) +1 },
|
{ 0, XK_braceright, i_change_gamma, (arg_t) +1 },
|
||||||
{ ControlMask, XK_G, i_change_gamma, (arg_t) 0 },
|
{ ControlMask, XK_G, i_change_gamma, (arg_t) 0 },
|
||||||
|
|
||||||
/* open current image with given program: */
|
|
||||||
{ ControlMask, XK_g, it_open_with, (arg_t) "gimp" },
|
|
||||||
|
|
||||||
/* run shell command line on current file ("$SXIV_IMG"): */
|
|
||||||
{ ControlMask, XK_less, it_shell_cmd, (arg_t) \
|
|
||||||
"mogrify -rotate -90 \"$SXIV_IMG\"" },
|
|
||||||
{ ControlMask, XK_greater, it_shell_cmd, (arg_t) \
|
|
||||||
"mogrify -rotate +90 \"$SXIV_IMG\"" },
|
|
||||||
{ ControlMask, XK_question, it_shell_cmd, (arg_t) \
|
|
||||||
"mogrify -rotate 180 \"$SXIV_IMG\"" },
|
|
||||||
{ ControlMask, XK_comma, it_shell_cmd, (arg_t) \
|
|
||||||
"jpegtran -rotate 270 -copy all -outfile \"$SXIV_IMG\" \"$SXIV_IMG\"" },
|
|
||||||
{ ControlMask, XK_period, it_shell_cmd, (arg_t) \
|
|
||||||
"jpegtran -rotate 90 -copy all -outfile \"$SXIV_IMG\" \"$SXIV_IMG\"" },
|
|
||||||
{ ControlMask, XK_slash, it_shell_cmd, (arg_t) \
|
|
||||||
"jpegtran -rotate 180 -copy all -outfile \"$SXIV_IMG\" \"$SXIV_IMG\"" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* mouse button mappings for image mode: */
|
/* mouse button mappings for image mode: */
|
||||||
|
|
19
exec/key-handler
Normal file
19
exec/key-handler
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
"C-g")
|
||||||
|
gimp "$2" & ;;
|
||||||
|
"C-comma")
|
||||||
|
exec jpegtran -rotate 270 -copy all -outfile "$2" "$2" ;;
|
||||||
|
"C-period")
|
||||||
|
exec jpegtran -rotate 90 -copy all -outfile "$2" "$2" ;;
|
||||||
|
"C-slash")
|
||||||
|
exec jpegtran -rotate 180 -copy all -outfile "$2" "$2" ;;
|
||||||
|
"C-less")
|
||||||
|
exec mogrify -rotate -90 "$2" ;;
|
||||||
|
"C-greater")
|
||||||
|
exec mogrify -rotate +90 "$2" ;;
|
||||||
|
"C-question")
|
||||||
|
exec mogrify -rotate 180 "$2" ;;
|
||||||
|
esac
|
||||||
|
|
90
main.c
90
main.c
|
@ -46,6 +46,18 @@ enum {
|
||||||
TITLE_LEN = 256
|
TITLE_LEN = 256
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define EXEC_REL_DIR ".sxiv/exec"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
EXEC_INFO,
|
||||||
|
EXEC_KEY
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
char *cmd;
|
||||||
|
} exec_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct timeval when;
|
struct timeval when;
|
||||||
bool active;
|
bool active;
|
||||||
|
@ -71,9 +83,13 @@ int prefix;
|
||||||
|
|
||||||
bool resized = false;
|
bool resized = false;
|
||||||
|
|
||||||
const char * const INFO_SCRIPT = ".sxiv/exec/image-info";
|
exec_t exec[] = {
|
||||||
|
{ "image-info", NULL },
|
||||||
|
{ "key-handler", NULL }
|
||||||
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
char *script;
|
char *cmd;
|
||||||
int fd;
|
int fd;
|
||||||
unsigned int i, lastsep;
|
unsigned int i, lastsep;
|
||||||
bool open;
|
bool open;
|
||||||
|
@ -221,7 +237,7 @@ void open_info(void)
|
||||||
static pid_t pid;
|
static pid_t pid;
|
||||||
int pfd[2];
|
int pfd[2];
|
||||||
|
|
||||||
if (info.script == NULL || info.open || win.bar.h == 0)
|
if (info.cmd == NULL || info.open || win.bar.h == 0)
|
||||||
return;
|
return;
|
||||||
if (info.fd != -1) {
|
if (info.fd != -1) {
|
||||||
close(info.fd);
|
close(info.fd);
|
||||||
|
@ -242,8 +258,8 @@ void open_info(void)
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
close(pfd[0]);
|
close(pfd[0]);
|
||||||
dup2(pfd[1], 1);
|
dup2(pfd[1], 1);
|
||||||
execl(info.script, info.script, files[fileidx].name, NULL);
|
execl(info.cmd, info.cmd, files[fileidx].name, NULL);
|
||||||
warn("could not exec: %s", info.script);
|
warn("could not exec: %s", info.cmd);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,7 +372,7 @@ void update_info(void)
|
||||||
fn, img.multi.sel + 1, img.multi.cnt);
|
fn, img.multi.sel + 1, img.multi.cnt);
|
||||||
}
|
}
|
||||||
n += snprintf(rt + n, rlen - n, "%0*d/%d", fw, sel + 1, filecnt);
|
n += snprintf(rt + n, rlen - n, "%0*d/%d", fw, sel + 1, filecnt);
|
||||||
ow_info = info.script == NULL;
|
ow_info = info.cmd == NULL;
|
||||||
}
|
}
|
||||||
if (ow_info) {
|
if (ow_info) {
|
||||||
fn = strlen(files[sel].name);
|
fn = strlen(files[sel].name);
|
||||||
|
@ -418,6 +434,49 @@ void clear_resize(void)
|
||||||
resized = false;
|
resized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void key_handler(const char *key, unsigned int mask)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
int retval, status, n = mode == MODE_IMAGE ? fileidx : tns.sel;
|
||||||
|
char *cmd = exec[EXEC_KEY].cmd, kstr[32];
|
||||||
|
|
||||||
|
if (cmd == NULL || key == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
snprintf(kstr, sizeof(kstr), "%s%s%s%s",
|
||||||
|
mask & ControlMask ? "C-" : "",
|
||||||
|
mask & Mod1Mask ? "M-" : "",
|
||||||
|
mask & ShiftMask ? "S-" : "", key);
|
||||||
|
|
||||||
|
if ((pid = fork()) == 0) {
|
||||||
|
execl(cmd, cmd, kstr, files[n].path, NULL);
|
||||||
|
warn("could not exec key handler");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else if (pid < 0) {
|
||||||
|
warn("could not fork key handler");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
win_set_cursor(&win, CURSOR_WATCH);
|
||||||
|
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
retval = WEXITSTATUS(status);
|
||||||
|
if (WIFEXITED(status) == 0 || retval != 0)
|
||||||
|
warn("key handler exited with non-zero return value: %d", retval);
|
||||||
|
if (mode == MODE_IMAGE) {
|
||||||
|
img_close(&img, true);
|
||||||
|
load_image(fileidx);
|
||||||
|
}
|
||||||
|
if (!tns_load(&tns, n, &files[n], true, mode == MODE_IMAGE) &&
|
||||||
|
mode == MODE_THUMB)
|
||||||
|
{
|
||||||
|
remove_file(tns.sel, false);
|
||||||
|
tns.dirty = true;
|
||||||
|
if (tns.sel >= tns.cnt)
|
||||||
|
tns.sel = tns.cnt - 1;
|
||||||
|
}
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
#define MODMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask))
|
#define MODMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask))
|
||||||
|
|
||||||
void on_keypress(XKeyEvent *kev)
|
void on_keypress(XKeyEvent *kev)
|
||||||
|
@ -438,6 +497,9 @@ void on_keypress(XKeyEvent *kev)
|
||||||
XLookupString(kev, &key, 1, &ksym, NULL);
|
XLookupString(kev, &key, 1, &ksym, NULL);
|
||||||
sh = (kev->state & ShiftMask) && ksym != shksym ? ShiftMask : 0;
|
sh = (kev->state & ShiftMask) && ksym != shksym ? ShiftMask : 0;
|
||||||
|
|
||||||
|
if (IsModifierKey(ksym))
|
||||||
|
return;
|
||||||
|
|
||||||
if ((ksym == XK_Escape && MODMASK(kev->state) == 0) ||
|
if ((ksym == XK_Escape && MODMASK(kev->state) == 0) ||
|
||||||
(key >= '0' && key <= '9'))
|
(key >= '0' && key <= '9'))
|
||||||
{
|
{
|
||||||
|
@ -456,6 +518,7 @@ void on_keypress(XKeyEvent *kev)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
key_handler(XKeysymToString(ksym), kev->state & ~sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_buttonpress(XButtonEvent *bev)
|
void on_buttonpress(XButtonEvent *bev)
|
||||||
|
@ -706,16 +769,17 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
if ((homedir = getenv("HOME")) == NULL) {
|
if ((homedir = getenv("HOME")) == NULL) {
|
||||||
warn("could not locate home directory");
|
warn("could not locate home directory");
|
||||||
} else {
|
} else for (i = 0; i < ARRLEN(exec); i++) {
|
||||||
len = strlen(homedir) + strlen(INFO_SCRIPT) + 2;
|
len = strlen(homedir) + strlen(EXEC_REL_DIR) + strlen(exec[i].name) + 3;
|
||||||
info.script = (char*) s_malloc(len);
|
exec[i].cmd = (char*) s_malloc(len);
|
||||||
snprintf(info.script, len, "%s/%s", homedir, INFO_SCRIPT);
|
snprintf(exec[i].cmd, len, "%s/%s/%s", homedir, EXEC_REL_DIR, exec[i].name);
|
||||||
if (access(info.script, X_OK) != 0) {
|
if (access(exec[i].cmd, X_OK) != 0) {
|
||||||
free(info.script);
|
free(exec[i].cmd);
|
||||||
info.script = NULL;
|
exec[i].cmd = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info.fd = -1;
|
info.fd = -1;
|
||||||
|
info.cmd = exec[EXEC_INFO].cmd;
|
||||||
|
|
||||||
if (options->thumb_mode) {
|
if (options->thumb_mode) {
|
||||||
mode = MODE_THUMB;
|
mode = MODE_THUMB;
|
||||||
|
|
Loading…
Reference in a new issue