From 7d32959bbb7941c5fe682e2b36310ac0b9782923 Mon Sep 17 00:00:00 2001 From: Nikita Ivanov Date: Tue, 21 Jun 2022 01:08:53 +0500 Subject: [PATCH] Add option to force kitty images --- sh/clear.sh | 6 ++--- sh/helpers.sh | 2 +- src/config.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/ctpv.c | 31 +++++++++++----------- src/ctpv.h | 17 ++++++++++++ src/preview.c | 5 +--- src/server.c | 17 +++--------- src/shell.c | 17 +++++++++++- src/shell.h | 4 ++- src/utils.c | 2 +- src/utils.h | 4 ++- 11 files changed, 136 insertions(+), 42 deletions(-) diff --git a/sh/clear.sh b/sh/clear.sh index b493694..af9cf5c 100644 --- a/sh/clear.sh +++ b/sh/clear.sh @@ -1,7 +1,7 @@ setup_fifo 1 -if use_ueberzug; then - printf '{"action": "remove", "identifier": "preview"}\n' > "$fifo" -elif use_kitty; then +if use_kitty; then kitty +kitten icat --clear --transfer-mode file +elif use_ueberzug; then + printf '{"action": "remove", "identifier": "preview"}\n' > "$fifo" fi diff --git a/sh/helpers.sh b/sh/helpers.sh index 234a01a..15f7e8d 100644 --- a/sh/helpers.sh +++ b/sh/helpers.sh @@ -11,7 +11,7 @@ use_ueberzug() { } use_kitty() { - use_ueberzug && return 1 + [ -z "$force_kitty" ] && use_ueberzug && return 1 is_kitty } diff --git a/src/config.c b/src/config.c index 5e5602b..587d62e 100644 --- a/src/config.c +++ b/src/config.c @@ -17,6 +17,19 @@ #define ACCEPT(x) CHECK_OK(accept(x)) #define NOT_ACCEPT(x) CHECK_NULL(accept(x)) +struct Option { + char *name; + enum { + OPTION_BOOL, + OPTION_INT, + OPTION_STR, + } arg_type; + union { + int *i; + char **s; + } arg_val; +}; + enum { STAT_OK, STAT_ERR, @@ -27,6 +40,10 @@ static Lexer *lexer; static Token token; static VectorPreview *previews; +static struct Option options[] = { + { "forcekitty", OPTION_BOOL, { .i = &ctpv.opts.force_kitty } }, +}; + static void any_type_null(char **s) { if (*s && strcmp(*s, any_type) == 0) @@ -36,6 +53,9 @@ static void any_type_null(char **s) static void add_preview(char *name, char *script, char *type, char *subtype, char *ext) { + if (!previews) + return; + any_type_null(&type); any_type_null(&subtype); @@ -57,6 +77,9 @@ static void add_preview(char *name, char *script, char *type, char *subtype, static int add_priority(char *name, int priority) { + if (!previews) + return OK; + int found = 0; for (size_t i = 0; i < previews->len; i++) { @@ -72,6 +95,9 @@ static int add_priority(char *name, int priority) static int remove_preview(char *name) { + if (!previews) + return OK; + int found = 0; for (ssize_t i = previews->len - 1; i >= 0; i--) { @@ -151,6 +177,49 @@ static int preview_type(char **type, char **subtype, char **ext) return preview_type_mime(type, subtype); } +static struct Option *get_option(char *name) +{ + for (size_t i = 0; i < LEN(options); i++) { + if (strcmp(name, options[i].name) == 0) + return options + i; + } + + return NULL; +} + +static int cmd_set(void) +{ + Token name = token; + EXPECT(TOK_STR); + + struct Option *opt = get_option(name.val.s); + if (!opt) { + PARSEERROR(name, "option '%s' does not exist", name.val.s); + return STAT_ERR; + } + + Token value = token; + + switch (opt->arg_type) { + case OPTION_BOOL: + *opt->arg_val.i = accept(TOK_INT) == STAT_OK ? value.val.i : 1; + break; + case OPTION_INT: + EXPECT(TOK_INT); + *opt->arg_val.i = value.val.i; + break; + case OPTION_STR: + EXPECT(TOK_STR); + *opt->arg_val.s = value.val.s; + break; + default: + PRINTINTERR("unknowm type: %d", opt->arg_type); + abort(); + } + + return STAT_OK; +} + static int cmd_preview(void) { Token name = token; @@ -207,7 +276,9 @@ static int command(void) Token cmd = token; EXPECT(TOK_STR); - if (strcmp(cmd.val.s, "preview") == 0) + if (strcmp(cmd.val.s, "set") == 0) + return cmd_set(); + else if (strcmp(cmd.val.s, "preview") == 0) return cmd_preview(); else if (strcmp(cmd.val.s, "priority") == 0) return cmd_priority(cmd); diff --git a/src/ctpv.c b/src/ctpv.c index acbb5a3..da1f408 100644 --- a/src/ctpv.c +++ b/src/ctpv.c @@ -16,22 +16,12 @@ #include "preview.h" #include "../previews.h" +struct CTPV ctpv; + const char any_type[] = ANY_TYPE; static magic_t magic; -static struct { - enum { - MODE_PREVIEW, - MODE_SERVER, - MODE_CLEAR, - MODE_END, - MODE_LIST, - MODE_MIME, - } mode; - char *server_id_s; -} ctpv = { .mode = MODE_PREVIEW }; - static VectorPreview *previews; static void cleanup(void) @@ -75,6 +65,16 @@ static int get_config_file(char *buf, size_t len) return OK; } +static int config(int prevs) +{ + char config_file[FILENAME_MAX]; + get_config_file(config_file, LEN(config_file)); + + ERRCHK_RET_OK(config_load(prevs ? previews : NULL, config_file)); + + return OK; +} + static int init_previews(void) { /* 20 is some arbitrary number, it's here in order to @@ -82,10 +82,7 @@ static int init_previews(void) previews = vectorPreview_new(LEN(b_previews) + 20); vectorPreview_append_arr(previews, b_previews, LEN(b_previews)); - char config_file[FILENAME_MAX]; - get_config_file(config_file, LEN(config_file)); - - ERRCHK_RET_OK(config_load(previews, config_file)); + ERRCHK_RET_OK(config(1)); previews_init(previews->buf, previews->len); @@ -263,11 +260,13 @@ static int server(void) static int clear(void) { + ERRCHK_RET_OK(config(0)); return server_clear(ctpv.server_id_s); } static int end(void) { + ERRCHK_RET_OK(config(0)); return server_end(ctpv.server_id_s); } diff --git a/src/ctpv.h b/src/ctpv.h index 5dde894..0578a29 100644 --- a/src/ctpv.h +++ b/src/ctpv.h @@ -3,6 +3,23 @@ #define ANY_TYPE "*" +struct CTPV { + enum { + MODE_PREVIEW = 0, /* default mode */ + MODE_SERVER, + MODE_CLEAR, + MODE_END, + MODE_LIST, + MODE_MIME, + } mode; + char *server_id_s; + struct { + int force_kitty; + } opts; +}; + +extern struct CTPV ctpv; + extern const char any_type[]; #endif diff --git a/src/preview.c b/src/preview.c index 89c3024..861acb6 100644 --- a/src/preview.c +++ b/src/preview.c @@ -123,11 +123,8 @@ static int run(Preview *p, int *exitcode, int *signal) int sp_arg[] = { pipe_fds[0], pipe_fds[1], STDERR_FILENO }; - char *script = prepend_helpers(p->script, p->script_len); - char *args[] = SHELL_ARGS(script); - int ret = spawn(args, NULL, exitcode, signal, spawn_redirect, sp_arg); + int ret = run_script(p->script, p->script_len, exitcode, signal, spawn_redirect, sp_arg); - free(script); close(pipe_fds[1]); if (*exitcode != FAILED_PREVIEW_EC) { diff --git a/src/server.c b/src/server.c index 9b6f37d..10602ef 100644 --- a/src/server.c +++ b/src/server.c @@ -169,18 +169,9 @@ exit: return ret; } -static int run_script(char *script, size_t script_len, char *arg) +static inline int run_server_script(char *script, size_t script_len, char *arg) { - int ret = OK; - - char *s = prepend_helpers(script, script_len); - char *args[] = SHELL_ARGS(s, arg); - int exitcode; - ERRCHK_GOTO_OK(spawn(args, NULL, &exitcode, NULL, NULL, NULL), ret, cleanup); - -cleanup: - free(s); - return ret; + return run_script(script, script_len, NULL, NULL, NULL, NULL); } int server_set_fifo_var(const char *id_s) @@ -196,12 +187,12 @@ int server_clear(const char *id_s) { ERRCHK_RET_OK(server_set_fifo_var(id_s)); - return run_script(scr_clear_sh, LEN(scr_clear_sh), (char *)id_s); + return run_server_script(scr_clear_sh, LEN(scr_clear_sh), (char *)id_s); } int server_end(const char *id_s) { ERRCHK_RET_OK(server_set_fifo_var(id_s)); - return run_script(scr_end_sh, LEN(scr_end_sh), (char *)id_s); + return run_server_script(scr_end_sh, LEN(scr_end_sh), (char *)id_s); } diff --git a/src/shell.c b/src/shell.c index b06a1a8..1bd8104 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1,5 +1,6 @@ #include +#include "ctpv.h" #include "shell.h" #include "error.h" #include "../gen/helpers.h" @@ -9,7 +10,7 @@ * * User must call free() */ -char *prepend_helpers(char *str, size_t len) +static char *prepend_helpers(char *str, size_t len) { char *buf, *b; size_t l, helpers_len = LEN(scr_helpers_sh) - 1; @@ -29,3 +30,17 @@ char *prepend_helpers(char *str, size_t len) return buf; } + +int run_script(char *script, size_t script_len, int *exitcode, int *signal, + SpawnProg sp, void *sp_arg) +{ + ERRCHK_RET_ERN(setenv("force_kitty", ctpv.opts.force_kitty ? "1" : "", 1) == -1); + + char *scr = prepend_helpers(script, script_len); + char *args[] = SHELL_ARGS(scr); + int ret = spawn(args, NULL, exitcode, signal, sp, sp_arg); + + free(scr); + + return ret; +} diff --git a/src/shell.h b/src/shell.h index bdce8cc..87d2100 100644 --- a/src/shell.h +++ b/src/shell.h @@ -6,6 +6,8 @@ #define SHELL_ARGS(script, ...) \ { "/bin/sh", "-c", script, "/bin/sh", __VA_ARGS__ __VA_OPT__(,) NULL } -char *prepend_helpers(char *str, size_t len); + +int run_script(char *script, size_t script_len, int *exitcode, int *signal, + SpawnProg sp, void *sp_arg); #endif diff --git a/src/utils.c b/src/utils.c index 75a6882..894bd6c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -51,7 +51,7 @@ int spawn_wait(int pid, int *exitcode, int *signal) * * cfunc is a function to call when child process is created */ -int spawn(char *args[], int *cpid, int *exitcode, int *signal, int (*cfunc)(const void *), +int spawn(char *args[], int *cpid, int *exitcode, int *signal, SpawnProg cfunc, const void *carg) { if (exitcode) diff --git a/src/utils.h b/src/utils.h index 04f0380..3e8194f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -21,12 +21,14 @@ va_end(args); \ } while (0) +typedef int (*SpawnProg)(const void *); + extern char *program; int spawn_redirect(const void *arg); int spawn_wait(int pid, int *exitcode, int *signal); int spawn(char *args[], int *cpid, int *exitcode, int *signal, - int (*cfunc)(const void *), const void *carg); + SpawnProg cfunc, const void *carg); int strcmpnull(const char *s1, const char *s2); int strlennull(const char *s);