intrntbrn / modalisa

hybrid modal keymap framework for awesomewm
MIT License
14 stars 0 forks source link

handling of key sequences when root/leader key is held #3

Open emacsomancer opened 10 months ago

emacsomancer commented 10 months ago

Query about what might be a mode option or some other option I don't understand in terms of how key sequences are processed:

I have Super_L defined as my "root key" and then have (for instance) a key-sequence defined as ff for a function. What I expect to happen is that the function is executed every time I press Super_L-f f, but what happens is that the first time I press this sequence it is indeed executed, but then if I continue to hold Super_L, then pressing just one f causes the function to be executed again. I tried "modal" mode and "hybrid" mode, but this doesn't seem to change the behaviour. Is there another setting that would be relevant? Or something I'm not understanding about the basic functionality of modalisa?

intrntbrn commented 10 months ago

This is the supposed behaviour for hold and hybrid, but modal should always terminate after executing regardless if you're holding the root modifier or not (maybe a bug?).

I am personally used to simply press the root modifier again when I want to reset the tree, but providing a configuration parameter makes totally sense. I'll look into it.

emacsomancer commented 10 months ago

Ok, actually what happens in modal mode is that it won't read any sequences (just passes them through) until I release the root/leader key. (I.e. I have to release and then press the root modifier again to start a new sequence.)

intrntbrn commented 10 months ago

Please checkout branch reset_tree_after_exec and add stay_on_exec = false to your configuration.

Does that work for you?

emacsomancer commented 10 months ago

Yes, the reset_tree_after_exec with stay_on_exec = false set the behaviour is different. "modal" mode still, though, seems to require releasing the root/leader key to start a new sequence. "hybrid" mode works closer to what I had imagined, so "Super_L+f Super_L+f" has consistent behaviour in calling the associated function (given a ff definition), but to call a different sequence, I still have to release the root/leader key. (Thus, with a functions bound to both ff and fB, I can continue to execute the ff function by pressing the key sequence, without having to release the root/leader key in-between; but if I've executed the ff function, in order to then execute fB, I have to release the root/leader key in-between.)

intrntbrn commented 10 months ago

modal mode not considering modifier states is exactly what it makes different to hybrid mode in the first place, so this is intended behaviour. However, I am not able to replicate the other behaviour you're describing. While holding down my root modifier, I am able to type as many (different) sequences as I want without having to press or release the modifier in between. Please share your configuration and keymap.

emacsomancer commented 10 months ago

My configuration is in Fennel, which transpiles to slightly unidiomatic Lua, but:

keys:

(local modalisa (require :modalisa))
(local util (require :modalisa.util))
(local sys (require :modalisa.presets.sys))
(local awm (require :modalisa.presets.awesome))
(local c (require :modalisa.presets.client))
(local t (require :modalisa.presets.tag))
(local sp (require :modalisa.presets.spawn))
(local s (require :modalisa.presets.screen))
(local x (require :myfunctions))
(local M {})

(local keys {" " (+ (c.select_picker true) {:opts {:labels util.labels_qwerty}})
             :+ (+ (t.master_count_increase) {:continue true})
             :- (+ (t.master_count_decrease) {:continue true})
             :0 (+ (t.view_only_index 10) {:hidden false})
             :1 (+ (t.view_only_index 1) {:hidden false})
             :2 (+ (t.view_only_index 2) {:hidden false})
             :3 (+ (t.view_only_index 3) {:hidden false})
             :4 (+ (t.view_only_index 4) {:hidden false})
             :5 (+ (t.view_only_index 5) {:hidden false})
             :6 (+ (t.view_only_index 6) {:hidden false})
             :7 (+ (t.view_only_index 7) {:hidden false})
             :8 (+ (t.view_only_index 8) {:hidden false})
             :9 (+ (t.view_only_index 9) {:hidden false})
             :< (+ (t.column_count_decrease) {:continue true})
             ;; my things
             :ff (x.back_to_last_focussed)
             :fb (x.firefox_run_or_raise)
             :fB (x.brave_run_or_raise)
             :fe (+ (sp.spawn_with_shell "emacsclient -c -F \"'(fullscreen . maximized)\""))
             :fE (+ (sp.spawn_with_shell "emacsclient -c -F \"'(fullscreen . maximized)\""))
             "f@" (+ (sp.spawn_with_shell "wmctrl -a *mu4e-headers* [%] - Emacs || wmctrl -a *Article* [%] - Emacs || wmctrl -a *mu4e-view* [%] - Emacs || wmctrl -a *mu4e-main* [%] - Emacs || wmctrl -a *mu4e-raw-view* || wmctrl -a *mu4e-loading* || emacsclient -c -e '(mu4e)' -F \"'(fullscreen . maximized)\"")
                    {:desc "mu4e" :group "applications"})
             ;; " " (x.rofishow)
             "f[" (+ (sp.spawn_with_shell "element-desktop")
                     {:desc "matrix element" :group "applications"})
             "f]" (+ (sp.spawn_with_shell "schildichat-desktop")
                     {:desc "schildichat matrix" :group "applications"})
             "f{" (+ (sp.spawn_with_shell "signal-desktop")
                     {:desc "signal client" :group "applications"})
             "f}" (+ (sp.spawn_with_shell "webcord")
                     {:desc "webcord for discord" :group "applications"})
             "(" (+ (t.layout_prev) {:continue true})
             ")" (+ (t.layout_next) {:continue true})
             " " (+ (sp.spawn_with_shell "rofi -show")
                    {:desc "rofi windows" :group "layout"})
             "," (+ (sp.spawn_with_shell "rofi -show drun")
                    {:desc "rofi execute" :group "layout"})
             :v (+ (sp.spawn_with_shell "rofi -modi \"clipboard:greenclip print\" -show clipboard -run-command '{cmd}'")
                   {:desc "greenclip" :group "layout"})
             "@" (+ (sp.spawn_with_shell "wmctrl -a *mu4e-headers* [%] - Emacs || wmctrl -a *Article* [%] - Emacs || wmctrl -a *mu4e-view* [%] - Emacs || wmctrl -a *mu4e-main* [%] - Emacs || wmctrl -a *mu4e-raw-view* || wmctrl -a *mu4e-loading* || emacsclient -c -e '(mu4e)' -F \"'(fullscreen . maximized)\"")
                    {:desc "mu4e" :group "applications"})
             ;;
             :<C-h> (s.focus_direction :left)
             :<C-j> (s.focus_direction :down)
             :<C-k> (s.focus_direction :up)
             :<C-l> (s.focus_direction :right)
             :<Down> (c.resize_smart :down)
             :<Left> (c.resize_smart :left)
             :<Return> (sp.terminal)
             :<Right> (c.resize_smart :right)
             :<S-Down> (c.size_decrease_floating :down)
             :<S-Left> (c.size_decrease_floating :left)
             :<S-Right> (c.size_decrease_floating :right)
             :<S-Up> (c.size_decrease_floating :up)
             :<Tab> (c.focus_prev)
             :<Up> (c.resize_smart :up)
             :<XF86AudioRaiseVolume> (+ (x.volume_inc)
                                        {:desc "volume raise" :global true})
             :<XF86AudioLowerVolume> (+ (x.volume_dec)
                                        {:desc "volume lower" :global true})
             :<XF86AudioMute> (+ (x.volume_mute_toggle)
                                 {:desc "mute toggle" :global true})
             ;; :<XF86AudioNext> (+ (sys.audio_next) {:global true})
             ;; :<XF86AudioPlay> (+ (sys.audio_play_pause) {:global true})
             ;; :<XF86AudioPrev> (+ (sys.audio_prev) {:global true})
             ;; :<XF86AudioStop> (+ (sys.audio_stop) {:global true})
             :<XF86MonBrightnessDown> (+ (sys.brightness_inc (- 10))
                                         {:desc "brightness decrease"
                                          :global true})
             :<XF86MonBrightnessUp> (+ (sys.brightness_inc 10)
                                       {:desc "brightness increase"
                                        :global true})
             :> (+ (t.column_count_increase) {:continue true})
             :H (c.move_dir_smart :left)
             :J (c.move_dir_smart :down)
             :K (c.move_dir_smart :up)
             :L (c.move_dir_smart :right)
             :Q (c.kill)
             "[" (+ (t.master_width_decrease) {:continue true})
             "]" (+ (t.master_width_increase) {:continue true})
             :f! (awm.run_prompt)
             :a {:desc :awesome :group :awesome :opts {:hints {:enabled true}}}
             :aQ (awm.quit)
             :aR (awm.restart)
             :am (awm.menubar)
             :ap (awm.screen_padding_menu)
             :ar (awm.run_prompt)
             :as (awm.help_popup)
             :at (awm.toggle_wibox)
             :aw (awm.wallpaper_menu 2)
             :ax (awm.execute_lua)
             :b (sp.browser)
             :c {:desc :client :group :client :opts {:hints {:enabled true}}}
             "c " (c.toggle_property :floating)
             :c0 (t.move_client_to_tag_index 10)
             :c1 (t.move_client_to_tag_index 1)
             :c2 (t.move_client_to_tag_index 2)
             :c3 (t.move_client_to_tag_index 3)
             :c4 (t.move_client_to_tag_index 4)
             :c5 (t.move_client_to_tag_index 5)
             :c6 (t.move_client_to_tag_index 6)
             :c7 (t.move_client_to_tag_index 7)
             :c8 (t.move_client_to_tag_index 8)
             :c9 (t.move_client_to_tag_index 9)
             :c<Return> (c.move_to_master)
             :c<Tab> (c.focus_prev)
             :cC (+ (c.set_property :border_color) {:desc :border_color})
             :cK {:desc "kill signal" :group :client.kill}
             :cKi (c.kill_signal :INT)
             :cKk (c.kill_signal :KILL)
             :cKq (c.kill_signal :QUIT)
             :cKt (c.kill_signal :TERM)
             :cS (c.toggle_property :skip_taskbar)
             :cT (+ (c.toggle_titlebar) {:desc "titlebar toggle"})
             :cU (c.toggle_property :urgent)
             :ca (c.toggle_property :above)
             :cb (c.toggle_property :below)
             :cc (c.swap_master_smart)
             :cf (c.toggle_property :fullscreen nil true)
             :ch (c.toggle_property :maximized_horizontally nil true)
             :ck (+ (c.kill) {:desc :kill})
             :cm (c.toggle_property :maximized nil true)
             :cn (c.minimize)
             :co (c.toggle_property :ontop)
             :cp (+ (c.set_property :opacity) {:desc :opacity})
             :cs (c.move_to_screen_menu)
             :ct (c.toggle_tag_menu)
             :cu (+ (c.unminimize_menu false) {:desc :unminize})
             :cv (c.toggle_property :maximized_vertically nil true)
             :cw (+ (c.set_property :border_width) {:desc :border_width})
             :cy (c.toggle_property :sticky)
             ;; :f (c.toggle_property :fullscreen nil true :client)
             :h (c.focus_dir :left)
             :i (+ ((. (require :modalisa.presets.modalisa) :generate))
                   {:highlight {:desc {:bold true :fg "#7DCFFF" :italic true}}
                    :opts {:hints {:enabled true} :mode :forever}})
             :j (c.focus_dir :down)
             :k (c.focus_dir :up)
             :l (c.focus_dir :right)
             :m (c.toggle_property :maximized nil true :client)
             :n (c.minimize)
             :o (sp.appmenu)
             :p {:desc :power :opts {:hints {:enabled true} :mode :hybrid}}
             :pc (sys.power_shutdown_cancel)
             :pr (sys.power_reboot)
             :ps (sys.power_shutdown)
             :pt (sys.power_shutdown_timer)
             :pu (sys.power_suspend)
             :z (c.resize_floating)
             "z " (c.placement :no_offscreen)
             :zb {:desc "bottom placement" :group :placement.bottom :opts {}}
             :zbb (c.placement :bottom)
             :zbh (c.placement :bottom_left)
             :zbl (c.placement :bottom_right)
             :zc (c.placement :centered)
             :zf {:desc "fix manual position"}
             :zfh (+ (c.set_property :height) {:desc :height})
             :zfw (+ (c.set_property :width) {:desc :width})
             :zfx (+ (c.set_property :x) {:desc "x coordinate"})
             :zfy (+ (c.set_property :y) {:desc "y coordinate"})
             :zh (c.placement :left)
             :zj (+ (c.resize_mode_floating)
                    {:desc "decrease size" :opts {:mode :forever}})
             :zjh (c.size_decrease_floating :left)
             :zjj (c.size_decrease_floating :down)
             :zjk (c.size_decrease_floating :up)
             :zjl (c.size_decrease_floating :zight)
             :zk (+ (c.resize_mode_floating)
                    {:desc "increase size" :opts {:mode :forever}})
             :zkh (c.size_decrease_floating :left)
             :zkj (c.size_decrease_floating :down)
             :zkk (c.size_decrease_floating :up)
             :zkl (c.size_decrease_floating :zight)
             :zl (c.placement :zight)
             :zm {:desc "maximize placement"
                  :group :placement.maximize
                  :opts {}}
             :zmh (c.placement :maximize_horizontally)
             :zmm (c.placement :maximize)
             :zmv (c.placement :maximize_vertically)
             :zo (c.placement :no_overlap)
             :zs {:desc "stretch placement" :group :placement.stretch :opts {}}
             :zsh (c.placement :stretch_left)
             :zsj (c.placement :stretch_down)
             :zsk (c.placement :stretch_up)
             :zsl (c.placement :stretch_right)
             :zt {:desc "top placement" :group :placement.top :opts {}}
             :zth (c.placement :top_left)
             :ztl (c.placement :top_right)
             :ztt (c.placement :top)
             :zu (c.placement :under_mouse)
             :s (+ (c.swap_master_smart) {:opts {:labels util.labels_qwerty}})
             :t {:desc :tag :group :tag :opts {:hints {:enabled true}}}
             "t " (+ (t.layout_select_menu)
                     {:opts {:labels util.labels_qwerty :hints {:enabled true}}})
             :t0 (t.move_client_to_tag_index 10)
             :t1 (t.move_client_to_tag_index 1)
             :t2 (t.move_client_to_tag_index 2)
             :t3 (t.move_client_to_tag_index 3)
             :t4 (t.move_client_to_tag_index 4)
             :t5 (t.move_client_to_tag_index 5)
             :t6 (t.move_client_to_tag_index 6)
             :t7 (t.move_client_to_tag_index 7)
             :t8 (t.move_client_to_tag_index 8)
             :t9 (t.move_client_to_tag_index 9)
             :t<Left> (+ (t.view_previous) {:continue true})
             :t<Right> (+ (t.view_next) {:continue true})
             :t<Tab> (t.view_last)
             :tC (+ (t.column_count_decrease) {:continue true})
             :tD (t.delete)
             :tG (t.toggle_property :gap_single_client)
             :tJ (+ (t.layout_prev) {:continue true})
             :tK (+ (t.layout_next) {:continue true})
             :tN (t.new_tag_copy)
             :ta (+ (t.move_all_clients_to_tag_menu)
                    {:opts {:hints {:delay 0 :enabled true}}})
             :tc (+ (t.column_count_increase) {:continue true})
             :tg (t.set_gap)
             :th (+ (t.master_count_decrease) {:continue true})
             :tj (+ (t.master_width_decrease) {:continue true})
             :tk (+ (t.master_width_increase) {:continue true})
             :tl (+ (t.master_count_increase) {:continue true})
             :tn (t.new_tag)
             :tp (t.tag_toggle_policy)
             :tr (t.rename)
             :ts (t.move_tag_to_screen_menu)
             :tt (+ (t.tag_toggle_menu)
                    {:opts {:hints {:delay 0 :enabled true}}})
             :tv (t.toggle_property :volatile)
             :u (+ (c.unminimize_menu false)
                   {:opts {:hints {:delay 0 :enabled true}
                           :labels util.labels_qwerty}})
             :w (+ (c.swap_picker) {:opts {:labels util.labels_qwerty}})
             :x {:desc :execute :group :execute :opts {:hints {:enabled true}}}
             ;; :xa (sp.spawn :alacritty)
             :xb (sp.spawn :brave)
             ;; :xc (sp.spawn :code)
             :xd (sp.spawn :discord)
             :xf (sp.spawn :firefox)
             ;; :xg (+ (sp.spawn_with_shell "chromium || google-chrome-stable")
             ;;        {:desc "google chrome"})
             :xi (sp.spawn :gimp)
             ;; :xk (sp.spawn :kitty)
             :xp (sp.spawn :pavucontrol)
             ;; :xq (sp.spawn :qutebrowser)
             ;; :xr (sp.spawn :arandr)
             ;; :xr (+ (sp.spawn_with_shell "rofi -show")
             ;;        {:desc "rofi windows" :group "layout"})
             :xs (sp.spawn :steam)
             ;; :xt (sp.spawn :thunar)
             :xw (sp.spawn :wezterm)
             :xx (sp.spawn :xterm)
             :fz (s.focus_picker)})
(fn M.get_keys [] keys)
(fn M.setup [_] (modalisa.add_keys keys))
(setmetatable M {:__call (fn [_ ...] (M.setup ...))
                 :__index (fn [_ k] (. keys k))})

transpiles to:

local modalisa = require("modalisa")
local util = require("modalisa.util")
local sys = require("modalisa.presets.sys")
local awm = require("modalisa.presets.awesome")
local c = require("modalisa.presets.client")
local t = require("modalisa.presets.tag")
local sp = require("modalisa.presets.spawn")
local s = require("modalisa.presets.screen")
local x = require("myfunctions")
local M = {}
local keys = 
{[" "] = (sp.spawn_with_shell("rofi -show") + {desc = "rofi windows", group = "layout"}), 
["+"] = (t.master_count_increase() + {continue = true}), 
["-"] = (t.master_count_decrease() + {continue = true}),
["0"] = (t.view_only_index(10) + {hidden = false}),
["1"] = (t.view_only_index(1) + {hidden = false}),
["2"] = (t.view_only_index(2) + {hidden = false}),
["3"] = (t.view_only_index(3) + {hidden = false}),
["4"] = (t.view_only_index(4) + {hidden = false}),
["5"] = (t.view_only_index(5) + {hidden = false}),
["6"] = (t.view_only_index(6) + {hidden = false}),
["7"] = (t.view_only_index(7) + {hidden = false}),
["8"] = (t.view_only_index(8) + {hidden = false}),
["9"] = (t.view_only_index(9) + {hidden = false}),
["<"] = (t.column_count_decrease() + {continue = true}),
ff = x.back_to_last_focussed(),
fb = x.firefox_run_or_raise(),
fB = x.brave_run_or_raise(),
fe = sp.spawn_with_shell("emacsclient -c -F \"'(fullscreen . maximized)\""),
fE = sp.spawn_with_shell("emacsclient -c -F \"'(fullscreen . maximized)\""),
["f@"] = (sp.spawn_with_shell("wmctrl -a *mu4e-headers* [%] - Emacs || wmctrl -a *Article* [%] - Emacs || wmctrl -a *mu4e-view* [%] - Emacs || wmctrl -a *mu4e-main* [%] - Emacs || wmctrl -a *mu4e-raw-view* || wmctrl -a *mu4e-loading* || emacsclient -c -e '(mu4e)' -F \"'(fullscreen . maximized)\"") + {desc = "mu4e",
group = "applications"}),
["f["] = (sp.spawn_with_shell("element-desktop") + {desc = "matrix element",
group = "applications"}),
["f]"] = (sp.spawn_with_shell("schildichat-desktop") + {desc = "schildichat matrix",
group = "applications"}),
["f{"] = (sp.spawn_with_shell("signal-desktop") + {desc = "signal client",
group = "applications"}),
["f}"] = (sp.spawn_with_shell("webcord") + {desc = "webcord for discord",
group = "applications"}),
["("] = (t.layout_prev() + {continue = true}),
[")"] = (t.layout_next() + {continue = true}),
[",
"] = (sp.spawn_with_shell("rofi -show drun") + {desc = "rofi execute",
group = "layout"}),
v = (sp.spawn_with_shell("rofi -modi \"clipboard:greenclip print\" -show clipboard -run-command '{cmd}'") + {desc = "greenclip",
group = "layout"}),
["@"] = (sp.spawn_with_shell("wmctrl -a *mu4e-headers* [%] - Emacs || wmctrl -a *Article* [%] - Emacs || wmctrl -a *mu4e-view* [%] - Emacs || wmctrl -a *mu4e-main* [%] - Emacs || wmctrl -a *mu4e-raw-view* || wmctrl -a *mu4e-loading* || emacsclient -c -e '(mu4e)' -F \"'(fullscreen . maximized)\"") + {desc = "mu4e",
group = "applications"}),
["<C-h>"] = s.focus_direction("left"),
["<C-j>"] = s.focus_direction("down"),
["<C-k>"] = s.focus_direction("up"),
["<C-l>"] = s.focus_direction("right"),
["<Down>"] = c.resize_smart("down"),
["<Left>"] = c.resize_smart("left"),
["<Return>"] = sp.terminal(),
["<Right>"] = c.resize_smart("right"),
["<S-Down>"] = c.size_decrease_floating("down"),
["<S-Left>"] = c.size_decrease_floating("left"),
["<S-Right>"] = c.size_decrease_floating("right"),
["<S-Up>"] = c.size_decrease_floating("up"),
["<Tab>"] = c.focus_prev(),
["<Up>"] = c.resize_smart("up"),
["<XF86AudioRaiseVolume>"] = (x.volume_inc() + {desc = "volume raise",
global = true}),
["<XF86AudioLowerVolume>"] = (x.volume_dec() + {desc = "volume lower",
global = true}),
["<XF86AudioMute>"] = (x.volume_mute_toggle() + {desc = "mute toggle",
global = true}),
["<XF86MonBrightnessDown>"] = (sys.brightness_inc(( - 10)) + {desc = "brightness decrease",
global = true}),
["<XF86MonBrightnessUp>"] = (sys.brightness_inc(10) + {desc = "brightness increase",
global = true}),
[">"] = (t.column_count_increase() + {continue = true}),
H = c.move_dir_smart("left"),
J = c.move_dir_smart("down"),
K = c.move_dir_smart("up"),
L = c.move_dir_smart("right"),
Q = c.kill(),
["["] = (t.master_width_decrease() + {continue = true}),
["]"] = (t.master_width_increase() + {continue = true}),
["f!"] = awm.run_prompt(),
a = {desc = "awesome",
group = "awesome",
opts = {hints = {enabled = true}}},
aQ = awm.quit(),
aR = awm.restart(),
am = awm.menubar(),
ap = awm.screen_padding_menu(),
ar = awm.run_prompt(),
as = awm.help_popup(),
at = awm.toggle_wibox(),
aw = awm.wallpaper_menu(2),
ax = awm.execute_lua(),
b = sp.browser(),
c = {desc = "client",
group = "client",
opts = {hints = {enabled = true}}},
["c "] = c.toggle_property("floating"),
c0 = t.move_client_to_tag_index(10),
c1 = t.move_client_to_tag_index(1),
c2 = t.move_client_to_tag_index(2),
c3 = t.move_client_to_tag_index(3),
c4 = t.move_client_to_tag_index(4),
c5 = t.move_client_to_tag_index(5),
c6 = t.move_client_to_tag_index(6),
c7 = t.move_client_to_tag_index(7),
c8 = t.move_client_to_tag_index(8),
c9 = t.move_client_to_tag_index(9),
["c<Return>"] = c.move_to_master(),
["c<Tab>"] = c.focus_prev(),
cC = (c.set_property("border_color") + {desc = "border_color"}),
cK = {desc = "kill signal",
group = "client.kill"},
cKi = c.kill_signal("INT"),
cKk = c.kill_signal("KILL"),
cKq = c.kill_signal("QUIT"),
cKt = c.kill_signal("TERM"),
cS = c.toggle_property("skip_taskbar"),
cT = (c.toggle_titlebar() + {desc = "titlebar toggle"}),
cU = c.toggle_property("urgent"),
ca = c.toggle_property("above"),
cb = c.toggle_property("below"),
cc = c.swap_master_smart(),
cf = c.toggle_property("fullscreen",
nil,
true),
ch = c.toggle_property("maximized_horizontally",
nil,
true),
ck = (c.kill() + {desc = "kill"}),
cm = c.toggle_property("maximized",
nil,
true),
cn = c.minimize(),
co = c.toggle_property("ontop"),
cp = (c.set_property("opacity") + {desc = "opacity"}),
cs = c.move_to_screen_menu(),
ct = c.toggle_tag_menu(),
cu = (c.unminimize_menu(false) + {desc = "unminize"}),
cv = c.toggle_property("maximized_vertically",
nil,
true),
cw = (c.set_property("border_width") + {desc = "border_width"}),
cy = c.toggle_property("sticky"),
h = c.focus_dir("left"),
i = ((require("modalisa.presets.modalisa")).generate() + {highlight = {desc = {bold = true,
fg = "#7DCFFF",
italic = true}},
opts = {hints = {enabled = true},
mode = "forever"}}),
j = c.focus_dir("down"),
k = c.focus_dir("up"),
l = c.focus_dir("right"),
m = c.toggle_property("maximized",
nil,
true,
"client"),
n = c.minimize(),
o = sp.appmenu(),
p = {desc = "power",
opts = {hints = {enabled = true},
mode = "hybrid"}},
pc = sys.power_shutdown_cancel(),
pr = sys.power_reboot(),
ps = sys.power_shutdown(),
pt = sys.power_shutdown_timer(),
pu = sys.power_suspend(),
z = c.resize_floating(),
["z "] = c.placement("no_offscreen"),
zb = {desc = "bottom placement",
group = "placement.bottom",
opts = {}},
zbb = c.placement("bottom"),
zbh = c.placement("bottom_left"),
zbl = c.placement("bottom_right"),
zc = c.placement("centered"),
zf = {desc = "fix manual position"},
zfh = (c.set_property("height") + {desc = "height"}),
zfw = (c.set_property("width") + {desc = "width"}),
zfx = (c.set_property("x") + {desc = "x coordinate"}),
zfy = (c.set_property("y") + {desc = "y coordinate"}),
zh = c.placement("left"),
zj = (c.resize_mode_floating() + {desc = "decrease size",
opts = {mode = "forever"}}),
zjh = c.size_decrease_floating("left"),
zjj = c.size_decrease_floating("down"),
zjk = c.size_decrease_floating("up"),
zjl = c.size_decrease_floating("zight"),
zk = (c.resize_mode_floating() + {desc = "increase size",
opts = {mode = "forever"}}),
zkh = c.size_decrease_floating("left"),
zkj = c.size_decrease_floating("down"),
zkk = c.size_decrease_floating("up"),
zkl = c.size_decrease_floating("zight"),
zl = c.placement("zight"),
zm = {desc = "maximize placement",
group = "placement.maximize",
opts = {}},
zmh = c.placement("maximize_horizontally"),
zmm = c.placement("maximize"),
zmv = c.placement("maximize_vertically"),
zo = c.placement("no_overlap"),
zs = {desc = "stretch placement",
group = "placement.stretch",
opts = {}},
zsh = c.placement("stretch_left"),
zsj = c.placement("stretch_down"),
zsk = c.placement("stretch_up"),
zsl = c.placement("stretch_right"),
zt = {desc = "top placement",
group = "placement.top",
opts = {}},
zth = c.placement("top_left"),
ztl = c.placement("top_right"),
ztt = c.placement("top"),
zu = c.placement("under_mouse"),
s = (c.swap_master_smart() + {opts = {labels = util.labels_qwerty}}),
t = {desc = "tag",
group = "tag",
opts = {hints = {enabled = true}}},
["t "] = (t.layout_select_menu() + {opts = {labels = util.labels_qwerty,
hints = {enabled = true}}}),
t0 = t.move_client_to_tag_index(10),
t1 = t.move_client_to_tag_index(1),
t2 = t.move_client_to_tag_index(2),
t3 = t.move_client_to_tag_index(3),
t4 = t.move_client_to_tag_index(4),
t5 = t.move_client_to_tag_index(5),
t6 = t.move_client_to_tag_index(6),
t7 = t.move_client_to_tag_index(7),
t8 = t.move_client_to_tag_index(8),
t9 = t.move_client_to_tag_index(9),
["t<Left>"] = (t.view_previous() + {continue = true}),
["t<Right>"] = (t.view_next() + {continue = true}),
["t<Tab>"] = t.view_last(),
tC = (t.column_count_decrease() + {continue = true}),
tD = t.delete(),
tG = t.toggle_property("gap_single_client"),
tJ = (t.layout_prev() + {continue = true}),
tK = (t.layout_next() + {continue = true}),
tN = t.new_tag_copy(),
ta = (t.move_all_clients_to_tag_menu() + {opts = {hints = {delay = 0,
enabled = true}}}),
tc = (t.column_count_increase() + {continue = true}),
tg = t.set_gap(),
th = (t.master_count_decrease() + {continue = true}),
tj = (t.master_width_decrease() + {continue = true}),
tk = (t.master_width_increase() + {continue = true}),
tl = (t.master_count_increase() + {continue = true}),
tn = t.new_tag(),
tp = t.tag_toggle_policy(),
tr = t.rename(),
ts = t.move_tag_to_screen_menu(),
tt = (t.tag_toggle_menu() + {opts = {hints = {delay = 0,
enabled = true}}}),
tv = t.toggle_property("volatile"),
u = (c.unminimize_menu(false) + {opts = {hints = {delay = 0,
enabled = true},
labels = util.labels_qwerty}}),
w = (c.swap_picker() + {opts = {labels = util.labels_qwerty}}),
x = {desc = "execute",
group = "execute",
opts = {hints = {enabled = true}}},
xb = sp.spawn("brave"),
xd = sp.spawn("discord"),
xf = sp.spawn("firefox"),
xi = sp.spawn("gimp"),
xp = sp.spawn("pavucontrol"),
xs = sp.spawn("steam"),
xw = sp.spawn("wezterm"),
xx = sp.spawn("xterm"), fz = s.focus_picker()}
M.get_keys = function()
  return keys
end
M.setup = function(_)
  return modalisa.add_keys(keys)
end
local function _1_(_, ...)
  return M.setup(...)
end
local function _2_(_, k)
  return keys[k]
end
return setmetatable(M, {__call = _1_, __index = _2_}) 

with functions defined as:

(local awful (require :awful))
(local mt (require :modalisa.presets.metatable))
(local M {})

;; (fn M.spawn_with_shell [cmd]
;;   (mt {:desc cmd
;;        :fn (fn [_] (awful.spawn.with_shell cmd))
;;        :group (string.format "spawn.%s" cmd)}))  

(fn M.back_to_last_focussed []
  (mt
   {:desc "go back"
    :fn (fn [] (let [c (. awful.client.focus.history.list 2)]
                  (set client.focus c)
                  (local t
                         (or (and client.focus client.focus.first_tag)
                             nil))
                  (when t (t:view_only))
                  (c:raise)))
    :group :client}))

(fn M.rofishow []
  (mt {:desc "rofi windows"
       :fn (fn [] (awful.util.spawn_with_shell (. "rofi -show" )))}))

(fn M.firefox_run_or_raise []
  (mt {
       :fn (fn [] (fn matcher [c] (awful.rules.match c {:class "firefox-default"}))
         (awful.client.run_or_raise :firefox matcher)
         :desc "run-or-raise firefox browser"
         :group "applications")}))

(fn M.brave_run_or_raise []
  (mt {
       :fn (fn [] (fn matcher [c] (awful.rules.match c {:class "Brave-browser"}))
         (awful.client.run_or_raise :brave matcher)
         :desc "run-or-raise brave browser"
         :group "applications")}))

(fn volume-show [opts]
  (let [pamixer-get-master "bash -c 'pamixer --get-volume'"
        pamixer-get-status "bash -c 'pamixer --get-mute'"]
    (awful.spawn.easy_async pamixer-get-master
                            (fn [stdout]
                                (if (= pamixer-get-status :true)
                                    (awesome.emit_signal "modalisa::echo"
                                                         {:volume :muted} opts)
                                    (awesome.emit_signal "modalisa::echo"
                                                           {:volume pamixer-get-master} opts))))))

(fn M.volume_inc []
  (mt {:desc :volume
       :fn (fn [opts]
             (local cmd (os.execute "pamixer -i 5"))
             (awful.spawn.easy_async_with_shell cmd (fn [] (volume-show opts))))
       :group :audio.volume
       :opts {:echo {:show_percentage_as_progressbar true}}}))

(fn M.volume_dec []
  (mt {:desc :volume
       :fn (fn [opts]
             (local cmd (os.execute "pamixer -d 5"))
             (awful.spawn.easy_async_with_shell cmd (fn [] (volume-show opts))))
       :group :audio.volume
       :opts {:echo {:show_percentage_as_progressbar true}}}))

;; (fn volume-toggle-cmd []
;;   "pamixer -t")

(fn M.volume_mute_toggle []
  (mt {:desc "mute toggle"
       :fn (fn [opts]
             (local cmd (os.execute "pamixer -t"))
             (awful.spawn.easy_async_with_shell cmd (fn [] (volume-show opts))))
       :group :audio.volume
       :opts {:echo {:show_percentage_as_progressbar true}}}))  

;; (fn M.)

M

transpiles to:

local awful = require("awful")
local mt = require("modalisa.presets.metatable")
local M = {}
M.back_to_last_focussed = function()
  local function _1_()
    local c = awful.client.focus.history.list[2]
    client.focus = c
    local t = ((client.focus and client.focus.first_tag) or nil)
    if t then
      t:view_only()
    else
    end
    return c:raise()
  end
  return mt({desc = "go back", fn = _1_, group = "client"})
end
M.rofishow = function()
  local function _3_()
    return awful.util.spawn_with_shell("rofi -show")
  end
  return mt({desc = "rofi windows", fn = _3_})
end
M.firefox_run_or_raise = function()
  local function _4_()
    local function matcher(c)
      return awful.rules.match(c, {class = "firefox-default"})
    end
    awful.client.run_or_raise("firefox", matcher)
    return "applications"
  end
  return mt({fn = _4_})
end
M.brave_run_or_raise = function()
  local function _5_()
    local function matcher(c)
      return awful.rules.match(c, {class = "Brave-browser"})
    end
    awful.client.run_or_raise("brave", matcher)
    return "applications"
  end
  return mt({fn = _5_})
end
local function volume_show(opts)
  local pamixer_get_master = "bash -c 'pamixer --get-volume'"
  local pamixer_get_status = "bash -c 'pamixer --get-mute'"
  local function _6_(stdout)
    if (pamixer_get_status == "true") then
      return awesome.emit_signal("modalisa::echo", {volume = "muted"}, opts)
    else
      return awesome.emit_signal("modalisa::echo", {volume = pamixer_get_master}, opts)
    end
  end
  return awful.spawn.easy_async(pamixer_get_master, _6_)
end
M.volume_inc = function()
  local function _8_(opts)
    local cmd = os.execute("pamixer -i 5")
    local function _9_()
      return volume_show(opts)
    end
    return awful.spawn.easy_async_with_shell(cmd, _9_)
  end
  return mt({desc = "volume", fn = _8_, group = "audio.volume", opts = {echo = {show_percentage_as_progressbar = true}}})
end
M.volume_dec = function()
  local function _10_(opts)
    local cmd = os.execute("pamixer -d 5")
    local function _11_()
      return volume_show(opts)
    end
    return awful.spawn.easy_async_with_shell(cmd, _11_)
  end
  return mt({desc = "volume", fn = _10_, group = "audio.volume", opts = {echo = {show_percentage_as_progressbar = true}}})
end
M.volume_mute_toggle = function()
  local function _12_(opts)
    local cmd = os.execute("pamixer -t")
    local function _13_()
      return volume_show(opts)
    end
    return awful.spawn.easy_async_with_shell(cmd, _13_)
  end
  return mt({desc = "mute toggle", fn = _12_, group = "audio.volume", opts = {echo = {show_percentage_as_progressbar = true}}})
end
return M 

and in my config, calling modalisa:

;; modalisa
((. (require :modalisa) :setup) {:back_keys [:<BackSpace>]
                                 :include_default_keys false
                                 :mode :hybrid
                                 :stay_on_exec false
                                 :hints {:enabled false}
                                 :awesome {:terminal :terminology}
                                 :root_keys [:<Super_L>]
                                 ;; :root_keys [:<M-f>]
                                 ;; :stop_keys [:<Escape>]
                                 :stop_keys [:<C-g> :<Escape>]
                                 ;; :theme {}
                                 }
 )

transpiles to:

return (require("modalisa")).setup({back_keys = {"<BackSpace>"},
mode = "hybrid",
hints = {enabled = false},
awesome = {terminal = "terminology"},
root_keys = {"<Super_L>"},
stop_keys = {"<C-g>",
"<Escape>"},
include_default_keys = false,
stay_on_exec = false})
emacsomancer commented 10 months ago

Just to update/elucidate: with the stay_on_exec branch and stay_on_exec set to 'false", if I use hybrid mode, then while I can continue to hold "Super" and do as many <Super+[single character]> commands as I like, I still have to release "Super" if I want to execute a command that involves a sequence. E.g., so I can hold "Super" and press "1", "2", "3", "4", etc. and jump from tag to tag, but if I press "Super+2" and then continue to hold "Super" and press "f !" nothing happens. I have to release "Super" before the "(Super)-f !" sequence will work.

If I use modal mode, then I have to release and repress "Super" between every command.