aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md15
-rw-r--r--config.h.in9
-rw-r--r--config_key.h.in1
-rw-r--r--dfm.c37
4 files changed, 62 insertions, 0 deletions
diff --git a/README.md b/README.md
index 82aab58..a7438e2 100644
--- a/README.md
+++ b/README.md
@@ -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.
+
+![Image viewer](https://private-user-images.githubusercontent.com/6799467/562138699-23bcd982-ad50-47c3-bd40-7fc0f4deca83.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzMzMDg1NTksIm5iZiI6MTc3MzMwODI1OSwicGF0aCI6Ii82Nzk5NDY3LzU2MjEzODY5OS0yM2JjZDk4Mi1hZDUwLTQ3YzMtYmQ0MC03ZmMwZjRkZWNhODMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDMxMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAzMTJUMDkzNzM5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MzhmNDYzYjIyODdiMDhhMTdhMjFkYmRkMjY2Yjc5NjUyNzMwOTk5MTczMDI3MDY3ODk2Njg2NmEyNzhkN2NiOSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.-Qwa4zE0m7zcj9rFFNy7p95A8PoIypitokz8RJx5pd8)
+
+
### 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;
diff --git a/dfm.c b/dfm.c
index 64e3cb0..02eae64 100644
--- a/dfm.c
+++ b/dfm.c
@@ -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;