aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Araps <dylan.araps@gmail.com>2026-03-14 09:57:57 +0200
committerDylan Araps <dylan.araps@gmail.com>2026-03-14 09:57:57 +0200
commit6b1050575ceaac57976caddf0663d6ce62e855ef (patch)
tree20fda7562cefda0abeaeb416f82a974a6ece7544
parent624a19678d5716a38bc8759b23e9de6887db5092 (diff)
dfm: Add range marking
Normal marking works like Ctrl+click in Windows Explorer. This new act works like Shift+click. It is bound to Alt+Space and also 'V' by default.
-rw-r--r--config_key.h.in3
-rw-r--r--dfm.c33
2 files changed, 36 insertions, 0 deletions
diff --git a/config_key.h.in b/config_key.h.in
index 4c087bf..5fcfdb8 100644
--- a/config_key.h.in
+++ b/config_key.h.in
@@ -102,6 +102,9 @@ static inline void (*fm_key(u32 cp))(struct fm *)
case 'M': return act_cd_mark_directory;
case ' ': return act_mark_toggle;
+ case K(MOD_ALT, ' '): return act_mark_range;
+ case 'v': return act_mark_toggle;
+ case 'V': return act_mark_range;
case K(MOD_CTRL, 'a'): return act_mark_toggle_all;
case 'I': return act_mark_invert;
case 'C': return act_mark_clear;
diff --git a/dfm.c b/dfm.c
index 79664a2..9c21a7d 100644
--- a/dfm.c
+++ b/dfm.c
@@ -3355,6 +3355,39 @@ act_mark_invert(struct fm *p)
p->f |= FM_REDRAW_DIR|FM_REDRAW_NAV;
}
+static inline void
+act_mark_range(struct fm *p)
+{
+ if (p->c == SIZE_MAX) return;
+ if (!(p->f & FM_MARK_PWD))
+ fm_mark_init(p);
+ usize ml = SIZE_MAX;
+ usize nw = BITSET_W(p->dl);
+ for (usize b = 0; b < nw; b++) {
+ u64 w = p->vm[b] & p->v[b];
+ while (w) {
+ usize i = (b << 6) + u64_ctz(w);
+ w &= w - 1;
+ if (i >= p->dl) break;
+ ml = i;
+ }
+ }
+ if (ml == SIZE_MAX) {
+ fm_mark_toggle_idx(p, p->c);
+ p->f |= FM_REDRAW_DIR | FM_REDRAW_NAV;
+ return;
+ }
+ usize lo = MIN(ml, p->c);
+ usize hi = MAX(ml, p->c);
+ for (usize i = lo; i <= hi; i++) {
+ if (!ent_v_geto(p, i, VIS)) continue;
+ if (!ent_v_geto(p, i, MARK))
+ fm_mark_toggle_idx(p, i);
+ }
+ fm_mark_invalidate(p);
+ p->f |= FM_REDRAW_DIR|FM_REDRAW_NAV;
+}
+
// }}}
// Input {{{