diff options
| author | Dylan Araps <dylan.araps@gmail.com> | 2026-03-12 11:44:11 +0200 |
|---|---|---|
| committer | Dylan Araps <dylan.araps@gmail.com> | 2026-03-12 11:44:11 +0200 |
| commit | d055a1c256233afd955fa9c6415c3334c3bc697b (patch) | |
| tree | 6fb57d6d08a0353c133a7b26ca83dbdcc464d9b5 | |
| parent | b6814841e7d83076ac38d4e7cf26d478f82860b1 (diff) | |
dfm: Add support for images
| -rw-r--r-- | README.md | 15 | ||||
| -rw-r--r-- | config.h.in | 9 | ||||
| -rw-r--r-- | config_key.h.in | 1 | ||||
| -rw-r--r-- | dfm.c | 37 |
4 files changed, 62 insertions, 0 deletions
@@ -15,6 +15,7 @@ Initial Announcement: https://dylan.gr/1772192922 * Manually implemented interactive line editor * Efficient low-bandwidth partial rendering * UTF8 support (minus grapheme clusters and other unruly things) +* Inline image viewing (sixel, kitty) * Multiple view modes (name, size, permissions, mtime, ...) * Multiple sort modes (name, extension, size, mtime, reverse, ...) * Ranger-style bulk rename @@ -45,6 +46,7 @@ Initial Announcement: https://dylan.gr/1772192922 * [View Modes](#view-modes) * [Sort Modes](#sort-modes) * [Prompt](#prompt) + * [Images](#images) * [Searching](#searching) * [Marking](#marking) * [Commands](#commands) @@ -185,6 +187,8 @@ environment, default values are derived from the `config.h.in` file. - DFM_TRASH (Program to use when trashing files) - DFM_TRASH_DIR (Path to trash directory) + +- DFM_IMG_MODE (Image mode to use: 'chafa' (default), 'kitty') ``` ### CD On Exit @@ -299,6 +303,17 @@ comes time to commit the input it is simply joined together. Make not of this detail as it is necessary to know it when creating your own bound commands. +### Images + +Images can be viewed inside of `dfm` by pressing `i` by default. This will +display the image and wait for a keypress before returning to the directory +listing. Two backends are supported: `sixel` (via `chafa`) and `kitty`. + +The mode can be set in `config.h.in` or at runtime via an environment variable. + + + + ### Searching There are two search modes: `startswith` (default `/`) and `substring` diff --git a/config.h.in b/config.h.in index d7be704..8eb7106 100644 --- a/config.h.in +++ b/config.h.in @@ -34,6 +34,15 @@ #define DFM_BOOKMARK_9 "" // +// Default image viewer. +// The command is executed as follows: +// 'arg0' 'arg1' '{col}x{rol}' 'img' +// +#define DFM_IMG_MODE "chafa" // "kitty" +#define DFM_IMG_KITTY_CMD "kitten", "icat", "--align", "left", "--place" +#define DFM_IMG_CHAFA_CMD "chafa", "--format=sixel", "-s" + +// // Default trash utility. // Can be set at runtime via environment: \$DFM_TRASH // diff --git a/config_key.h.in b/config_key.h.in index d658928..0026853 100644 --- a/config_key.h.in +++ b/config_key.h.in @@ -89,6 +89,7 @@ static inline void (*fm_key(u32 cp))(struct fm *) case 'n': return cmd_mkdir; case 'r': return cmd_rename; case 'x': return act_stat; + case 'i': return act_view_image; case 'z': return act_alt_buffer; case 'p': return cmd_chmod; case 'P': return cmd_chown; @@ -195,6 +195,7 @@ struct fm { s64 tz; u8 nl; + u8 im; }; // Entry Virtual {{{ @@ -3015,6 +3016,41 @@ act_stat(struct fm *p) } static inline void +act_view_image(struct fm *p) +{ + if (p->c == SIZE_MAX) return; + cut e = fm_ent(p, p->c); + u64 m = ent_load(p, p->c); + if (ENT_IS_DIR(ent_get(m, TYPE))) return; + p->f |= FM_REDRAW; + STR_PUSH(&p->io, VT_ED2 VT_CUP1); + fm_draw_flush(p); + p->io.l = 0; + str_push_u32(&p->io, p->col); + str_push_c(&p->io, 'x'); + str_push_u32(&p->io, p->row - 1); + int r = 0; + if (p->im == 'k') { + STR_PUSH(&p->io, "@0x0\0"); + const char *const a[] = { DFM_IMG_KITTY_CMD, p->io.m, e.d, NULL }; + r = fm_exec(p, -1, NULL, a, 0, 0); + } else { + str_terminate(&p->io); + const char *const a[] = { DFM_IMG_CHAFA_CMD, p->io.m, e.d, NULL }; + r = fm_exec(p, -1, NULL, a, 0, 0); + } + p->io.l = 0; + if (r < 0) return; + rl_clear(&p->r); + STR_PUSH(&p->r.cl, VT_DECTCEM_N " viewing: "); + str_push(&p->r.cl, e.d, e.l); + fm_draw_buf(p, CUT(DFM_COL_NAV)); + fm_draw_flush(p); + rl_clear(&p->r); + term_key_read(p->t.fd, &p->k); +} + +static inline void act_open(struct fm *p) { fm_open(p); @@ -3531,6 +3567,7 @@ fm_init(struct fm *p) if (fm_nest(p) == -1) return -1; p->opener = get_env("DFM_OPENER", DFM_OPENER); + p->im = get_env("DFM_IMG_MODE", DFM_IMG_MODE).d[0]; p->dfd = AT_FDCWD; p->ds = DFM_DEFAULT_SORT; p->dv = DFM_DEFAULT_VIEW; |