Skip to content

Commit edfac07

Browse files
authored
Generate keybinding documentation (#162)
* Show live-generated keybinding docs on META+/ * Free doc and label as needed * Use 'local' in lua * Mention ALTMETA * avoid `io.output` * Generate a random filename
1 parent 7ad4c76 commit edfac07

8 files changed

+423
-56
lines changed

etc/cfg_bindings.lua

+79-41
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,42 @@
2020
-- modifier to some of the F-key bindings.
2121

2222
defbindings("WScreen", {
23-
bdoc("Switch to n:th object (workspace, full screen client window) "..
24-
"within current screen."),
23+
bdoc("Switch to object 0 (workspace, full screen client window) "..
24+
"within current screen.", "ws 0"),
2525
kpress(META.."1", "WScreen.switch_nth(_, 0)"),
26+
bdoc("Switch to object 1 (workspace, full screen client window) "..
27+
"within current screen.", "ws 1"),
2628
kpress(META.."2", "WScreen.switch_nth(_, 1)"),
29+
bdoc("Switch to object 2 (workspace, full screen client window) "..
30+
"within current screen.", "ws 2"),
2731
kpress(META.."3", "WScreen.switch_nth(_, 2)"),
32+
bdoc("Switch to object 3 (workspace, full screen client window) "..
33+
"within current screen.", "ws 3"),
2834
kpress(META.."4", "WScreen.switch_nth(_, 3)"),
35+
bdoc("Switch to object 4 (workspace, full screen client window) "..
36+
"within current screen.", "ws 4"),
2937
kpress(META.."5", "WScreen.switch_nth(_, 4)"),
38+
bdoc("Switch to object 5 (workspace, full screen client window) "..
39+
"within current screen.", "ws 5"),
3040
kpress(META.."6", "WScreen.switch_nth(_, 5)"),
41+
bdoc("Switch to object 6 (workspace, full screen client window) "..
42+
"within current screen.", "ws 6"),
3143
kpress(META.."7", "WScreen.switch_nth(_, 6)"),
44+
bdoc("Switch to object 7 (workspace, full screen client window) "..
45+
"within current screen.", "ws 7"),
3246
kpress(META.."8", "WScreen.switch_nth(_, 7)"),
47+
bdoc("Switch to object 8 (workspace, full screen client window) "..
48+
"within current screen.", "ws 8"),
3349
kpress(META.."9", "WScreen.switch_nth(_, 8)"),
50+
bdoc("Switch to object 9 (workspace, full screen client window) "..
51+
"within current screen.", "ws 9"),
3452
kpress(META.."0", "WScreen.switch_nth(_, 9)"),
3553

36-
bdoc("Switch to next/previous object within current screen."),
54+
bdoc("Switch to next object (workspace, full screen client window) "..
55+
"within current screen.", "->ws"),
3756
kpress(META.."grave", "WScreen.switch_next(_)"),
57+
bdoc("Switch to previous object (workspace, full screen client window) "..
58+
"within current screen.", "<-ws"),
3859
kpress(ALTMETA.."asciitilde", "WScreen.switch_prev(_)"),
3960

4061
submap(META.."O", {
@@ -51,18 +72,22 @@ defbindings("WScreen", {
5172

5273
}),
5374

54-
bdoc("Go to n:th screen on multihead setup."),
55-
kpress(META.."Shift+1", "ioncore.goto_nth_screen(0)"),
75+
bdoc("Go to screen 0 on multihead setup.", "scr 0"),
76+
kpress(ALTMETA.."1", "ioncore.goto_nth_screen(0)"),
5677
kpress(META.."F1", "ioncore.goto_nth_screen(0)"),
57-
kpress(META.."Shift+2", "ioncore.goto_nth_screen(1)"),
78+
bdoc("Go to screen 1 on multihead setup.", "scr 1"),
79+
kpress(ALTMETA.."2", "ioncore.goto_nth_screen(1)"),
5880
kpress(META.."F2", "ioncore.goto_nth_screen(1)"),
59-
kpress(META.."Shift+3", "ioncore.goto_nth_screen(2)"),
81+
bdoc("Go to screen 2 on multihead setup.", "scr 2"),
82+
kpress(ALTMETA.."3", "ioncore.goto_nth_screen(2)"),
6083
kpress(META.."F3", "ioncore.goto_nth_screen(2)"),
61-
kpress(META.."Shift+4", "ioncore.goto_nth_screen(3)"),
84+
bdoc("Go to screen 3 on multihead setup.", "scr 3"),
85+
kpress(ALTMETA.."4", "ioncore.goto_nth_screen(3)"),
6286
-- kpress(META.."F4", "ioncore.goto_nth_screen(3)"),
6387

64-
bdoc("Go to next/previous screen on multihead setup."),
88+
bdoc("Go to previous screen on multihead setup.", "<-scr"),
6589
kpress(ALTMETA.."Escape", "ioncore.goto_prev_screen()"),
90+
bdoc("Go to next screen on multihead setup.", "->scr"),
6691
kpress(META.."Escape", "ioncore.goto_next_screen()"),
6792

6893
bdoc("Create a new workspace of chosen default type."),
@@ -76,7 +101,7 @@ defbindings("WScreen", {
76101
bdoc("Display the window list menu."),
77102
mpress("Button2", "mod_menu.pmenu(_, _sub, 'windowlist')"),
78103

79-
bdoc("Forward-circulate focus."),
104+
bdoc("Forward-circulate focus.", "->frame"),
80105
-- '_chld' used here stands to for an actual child window that may not
81106
-- be managed by the screen itself, unlike '_sub', that is likely to be
82107
-- the managing group of that window. The right/left directions are
@@ -85,11 +110,11 @@ defbindings("WScreen", {
85110
kpress(META.."Tab", "ioncore.goto_next(_chld, 'right')",
86111
"_chld:non-nil"),
87112

88-
bdoc("Backward-circulate focus."),
113+
bdoc("Backward-circulate focus.", "<-frame"),
89114
kpress(ALTMETA.."Tab", "ioncore.goto_next(_chld, 'left')",
90115
"_chld:non-nil"),
91116

92-
bdoc("Raise focused object, if possible."),
117+
bdoc("Raise focused object, if possible.", "raise"),
93118
kpress(ALTMETA.."R", "WRegion.rqorder(_chld, 'front')",
94119
"_chld:non-nil"),
95120
})
@@ -101,22 +126,22 @@ defbindings("WScreen", {
101126

102127
defbindings("WClientWin", {
103128
bdoc("Nudge the client window. This might help with some "..
104-
"programs' resizing problems."),
129+
"programs' resizing problems.", "nudge"),
105130
kpress_wait(ALTMETA.."L", "WClientWin.nudge(_)"),
106131

107-
bdoc("Kill client owning the client window."),
132+
bdoc("Kill client owning the client window.", "kill"),
108133
kpress(ALTMETA.."C", "WClientWin.kill(_)"),
109134

110135
bdoc("Send next key press to the client window. "..
111-
"Some programs may not allow this by default."),
136+
"Some programs may not allow this by default.", "quote"),
112137
kpress(ALTMETA.."Q", "WClientWin.quote_next(_)"),
113138
})
114139

115140

116141
-- Client window group bindings
117142

118143
defbindings("WGroupCW", {
119-
bdoc("Toggle client window group full-screen mode"),
144+
bdoc("Toggle client window group full-screen mode", "fullscr"),
120145
kpress_wait(META.."Q", "WGroup.set_fullscreen(_, 'toggle')"),
121146
})
122147

@@ -127,10 +152,10 @@ defbindings("WGroupCW", {
127152
-- contexts/objects always gets to handle the key press.
128153

129154
defbindings("WMPlex", {
130-
bdoc("Close current object."),
155+
bdoc("Close current object.", "close"),
131156
kpress_wait(META.."C", "WRegion.rqclose_propagate(_, _sub)"),
132157

133-
bdoc("Detach (float) or reattach an object to its previous location."),
158+
bdoc("Detach (float) or reattach an object to its previous location.", "detach"),
134159
-- By using _chld instead of _sub, we can detach/reattach queries
135160
-- attached to a group. The detach code checks if the parameter
136161
-- (_chld) is a group 'bottom' and detaches the whole group in that
@@ -141,52 +166,56 @@ defbindings("WMPlex", {
141166
-- Frames for transient windows ignore this bindmap
142167

143168
defbindings("WMPlex.toplevel", {
144-
bdoc("Toggle tag of current object."),
169+
bdoc("Toggle tag of current object.", "tag"),
145170
kpress(META.."T", "WRegion.set_tagged(_sub, 'toggle')", "_sub:non-nil"),
146171

147-
bdoc("Clear all tags."),
172+
bdoc("Clear all tags.", "-tags"),
148173
kpress(ALTMETA.."T", "ioncore.clear_tags()"),
149174

150-
bdoc("Lock screen"),
175+
bdoc("Lock screen", "lock"),
151176
kpress(META.."L", "notioncore.exec_on(_, notioncore.lookup_script('notion-lock'))"),
152177

153-
bdoc("Run a terminal emulator."),
178+
bdoc("Run a terminal emulator.", "xterm"),
154179
kpress(META.."Return", "mod_query.exec_on_merr(_, XTERM or 'xterm')"),
155180
kpress("F2", "mod_query.exec_on_merr(_, XTERM or 'xterm')"),
156181

157-
bdoc("Query for command line to execute."),
182+
bdoc("Query for command line to execute.", "run"),
158183
kpress(META.."J", "mod_query.query_exec(_)"),
159184

160-
bdoc("Query for Lua code to execute."),
185+
bdoc("Query for Lua code to execute.", "lua"),
161186
kpress(ALTMETA.."J", "mod_query.query_lua(_)"),
162187

163-
bdoc("Query for host to connect to with SSH."),
188+
bdoc("Query for host to connect to with SSH.", "ssh"),
164189
kpress(ALTMETA.."F4", "mod_query.query_ssh(_, ':ssh')"),
165190

166-
bdoc("Query for file to edit."),
191+
bdoc("Query for file to edit.", "edit"),
167192
kpress(ALTMETA.."F5",
168193
"mod_query.query_editfile(_, 'run-mailcap --action=edit')"),
169194

170-
bdoc("Query for file to view."),
195+
bdoc("Query for file to view.", "view"),
171196
kpress(ALTMETA.."F6",
172197
"mod_query.query_runfile(_, 'run-mailcap --action=view')"),
173198

174-
bdoc("Query for keybinding."),
199+
bdoc("Query for keybinding.", "qkb"),
175200
kpress(META.."F7",
176201
"mod_query.query_binding(_, _sub)"),
177202

178-
bdoc("Query for workspace to go to or create a new one."),
203+
bdoc("Query for workspace to go to or create a new one.", "+ws"),
179204
kpress(ALTMETA.."F9", "mod_query.query_workspace(_)"),
180205

181-
bdoc("Query for a client window to go to."),
206+
bdoc("Query for a client window to go to.", "go"),
182207
kpress(META.."G", "mod_query.query_gotoclient(_)"),
183208

184-
bdoc("Display context menu."),
185-
kpress(META.."M", "mod_menu.menu(_, _sub, 'ctxmenu')"),
186-
kpress(ALTMETA.."M", "mod_query.query_menu(_, _sub, 'ctxmenu', 'Context menu:')"),
209+
bdoc("Display context menu.", "ctx"),
210+
kpress(META.."C", "mod_menu.menu(_, _sub, 'ctxmenu')"),
211+
bdoc("Query for context menu.", "qctx"),
212+
kpress(ALTMETA.."C", "mod_query.query_menu(_, _sub, 'ctxmenu', 'Context menu:')"),
213+
214+
bdoc("Show Notion 'live docs'.", "help"),
215+
kpress(META.."slash", "notioncore.show_live_docs(_)"),
187216

188-
bdoc("Query for manual page to be displayed."),
189-
kpress(META.."slash", "mod_query.query_man(_, ':man')"),
217+
bdoc("Query for manual page to be displayed.", "man"),
218+
kpress(ALTMETA.."slash", "mod_query.query_man(_, ':man')"),
190219
})
191220

192221
-- WFrame context bindings
@@ -195,14 +224,15 @@ defbindings("WMPlex.toplevel", {
195224
-- frame bindings are found in some modules' configuration files.
196225

197226
defbindings("WFrame", {
198-
bdoc("Maximize the frame horizontally/vertically."),
227+
bdoc("Maximize the frame horizontally.", "hmax"),
199228
kpress(ALTMETA.."H", "WFrame.maximize_horiz(_)"),
229+
bdoc("Maximize the frame vertically.", "vmax"),
200230
kpress(ALTMETA.."V", "WFrame.maximize_vert(_)"),
201231

202232
bdoc("Display context menu."),
203233
mpress("Button3", "mod_menu.pmenu(_, _sub, 'ctxmenu')"),
204234

205-
bdoc("Begin move/resize mode."),
235+
bdoc("Begin move/resize mode.", "resize"),
206236
kpress(META.."R", "WFrame.begin_kbresize(_)"),
207237

208238
bdoc("Switch the frame to display the object indicated by the tab."),
@@ -220,34 +250,42 @@ defbindings("WFrame", {
220250
mdrag("Button1@tab", "WFrame.p_tabdrag(_)"),
221251
mdrag("Button2@tab", "WFrame.p_tabdrag(_)"),
222252

223-
bdoc("Switch to next/previous object within the frame."),
253+
bdoc("Switch to next object within the frame.", "->tab"),
224254
-- See docs on how to disable capslock caps behaviour
225255
kpress(META.."Caps_Lock", "WFrame.switch_next(_)"),
226256
mclick(META.."Button4", "WFrame.switch_next(_)"),
257+
258+
bdoc("Switch to previous object within the frame.", "<-tab"),
259+
kpress(ALTMETA.."Caps_Lock", "WFrame.switch_prev(_)"),
227260
mclick(META.."Button5", "WFrame.switch_prev(_)"),
228261
})
229262

230263
-- Frames for transient windows ignore this bindmap
231264

232265
defbindings("WFrame.toplevel", {
233-
bdoc("Query for a client window to attach ('nick')."),
266+
bdoc("Query for a client window to attach ('nick').", "nick"),
234267
kpress(META.."N", "mod_query.query_attachclient(_)"),
235268

269+
bdoc("Switch to tab 0 in this frame.", "tab 0"),
236270
kpress(META.."A", "WFrame.switch_nth(_, 0)"),
271+
bdoc("Switch to tab 1 in this frame.", "tab 1"),
237272
kpress(META.."S", "WFrame.switch_nth(_, 1)"),
273+
bdoc("Switch to tab 2 in this frame.", "tab 2"),
238274
kpress(META.."D", "WFrame.switch_nth(_, 2)"),
275+
bdoc("Switch to tab 3 in this frame.", "tab 3"),
239276
kpress(META.."F", "WFrame.switch_nth(_, 3)"),
240277

241-
bdoc("Move current object within the frame left/right."),
278+
bdoc("Move current tab to the right within the frame.", "tab->"),
242279
kpress(ALTMETA.."comma", "WFrame.dec_index(_, _sub)", "_sub:non-nil"),
280+
bdoc("Move current tab to the left within the frame.", "tab<-"),
243281
kpress(ALTMETA.."period", "WFrame.inc_index(_, _sub)", "_sub:non-nil"),
244282

245283
bdoc("Maximize the frame horizontally/vertically."),
246284
kpress(ALTMETA.."H", "WFrame.maximize_horiz(_)"),
247285
kpress(ALTMETA.."V", "WFrame.maximize_vert(_)"),
248286

249287
bdoc("Attach tagged objects to this frame."),
250-
kpress(META.."Y", "ioncore.tagged_attach(_)"),
288+
kpress(META.."N", "ioncore.tagged_attach(_)"),
251289
})
252290

253291
-- Bindings for floating frames

etc/cfg_tiling.lua

+7-8
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,27 @@
44

55
-- Bindings for the tilings.
66
defbindings("WTiling", {
7-
bdoc("Split current frame horizontally."),
7+
bdoc("Split current frame horizontally.", "hsplit"),
88
kpress(META.."I", "WTiling.split_at(_, _sub, 'right', true)"),
99

10-
bdoc("Split current frame vertically."),
10+
bdoc("Split current frame vertically.", "vsplit"),
1111
kpress(ALTMETA.."I", "WTiling.split_at(_, _sub, 'bottom', true)"),
1212

13-
bdoc("Destroy current frame."),
13+
bdoc("Destroy current frame.", "unsplit"),
1414
kpress(META.."X", "WTiling.unsplit_at(_, _sub)"),
1515

16-
bdoc("Go to frame above/below current frame."),
16+
bdoc("Go to frame below current frame.", "vframe"),
1717
kpress(META.."W", "ioncore.goto_next(_sub, 'down', {no_ascend=_})"),
18+
bdoc("Go to frame above current frame.", "^frame"),
1819
kpress(ALTMETA.."W", "ioncore.goto_next(_sub, 'up', {no_ascend=_})"),
1920
mclick(META.."Shift+Button4", "ioncore.goto_next(_sub, 'up', {no_ascend=_})"),
2021
mclick(META.."Shift+Button5", "ioncore.goto_next(_sub, 'down', {no_ascend=_})"),
2122
})
2223

2324
-- Frame bindings.
2425
defbindings("WFrame.floating", {
25-
submap(META.."K", {
26-
bdoc("Tile frame, if no tiling exists on the workspace"),
27-
kpress("B", "mod_tiling.mkbottom(_)"),
28-
}),
26+
bdoc("Tile frame, if no tiling exists on the workspace", "tile"),
27+
kpress(ALTMETA.."B", "mod_tiling.mkbottom(_)"),
2928
})
3029

3130
-- Context menu for tiled workspaces.

ioncore/binding.c

+10
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ void binding_deinit(WBinding *binding)
163163
bindmap_destroy(binding->submap);
164164
binding->submap=NULL;
165165
}
166+
if(binding->doc){
167+
free(binding->doc);
168+
binding->doc=NULL;
169+
}
170+
if(binding->label){
171+
free(binding->label);
172+
binding->label=NULL;
173+
}
166174

167175
binding->func=extl_unref_fn(binding->func);
168176
}
@@ -171,7 +179,9 @@ void binding_deinit(WBinding *binding)
171179
static void do_destroy_binding(WBinding *binding)
172180
{
173181
assert(binding!=NULL);
182+
174183
binding_deinit(binding);
184+
175185
free(binding);
176186
}
177187

ioncore/binding.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ DECLSTRUCT(WBinding){
4444
WBindmap *submap;
4545
ExtlFn func;
4646
const char *doc;
47+
const char *label;
4748
};
4849

4950

ioncore/bindmaps.c

+1
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ WBindmap *ioncore_create_cycle_bindmap(uint kcb, uint state,
217217
b.submap=NULL;
218218
b.func=extl_ref_fn(cycle);
219219
b.doc=NULL;
220+
b.label=NULL;
220221

221222
if(!bindmap_add_binding(bindmap, &b)){
222223
extl_unref_fn(b.func);

0 commit comments

Comments
 (0)