diff --git a/lib/keydoc.lua b/lib/keydoc.lua new file mode 100644 index 0000000..494c082 --- /dev/null +++ b/lib/keydoc.lua @@ -0,0 +1,123 @@ +-- Document key bindings + +local awful = require("awful") +local table = table +local ipairs = ipairs +local pairs = pairs +local math = math +local string = string +local type = type +local modkey = modkey +local beautiful = require("beautiful") +local naughty = require("naughty") +local capi = { + root = root, + client = client +} + +module("vbe/keydoc") + +local doc = { } +local currentgroup = "Misc" +local orig = awful.key.new + +-- Replacement for awful.key.new +local function new(mod, key, press, release, docstring) + -- Usually, there is no use of release, let's just use it for doc + -- if it's a string. + if press and release and not docstring and type(release) == "string" then + docstring = release + release = nil + end + local k = orig(mod, key, press, release) + -- Remember documentation for this key (we take the first one) + if k and #k > 0 and docstring then + doc[k[1]] = { help = docstring, + group = currentgroup } + end + + return k +end +awful.key.new = new -- monkey patch + +-- Turn a key to a string +local function key2str(key) + local sym = key.keysym or key.key + if sym == "#14" then sym = "#" end + if not key.modifiers or #key.modifiers == 0 then return sym end + local result = "" + local translate = { + [modkey] = "⊞", + Shift = "⇧", + Control = "Ctrl", + } + for _, mod in pairs(key.modifiers) do + if translate[mod] then + mod = translate[mod] + end + result = result .. mod .. " + " + end + return result .. sym +end + +-- Unicode "aware" length function (well, UTF8 aware) +-- See: http://lua-users.org/wiki/LuaUnicode +local function unilen(str) + local _, count = string.gsub(str, "[^\128-\193]", "") + return count +end + +-- Start a new group +function group(name) + currentgroup = name + return {} +end + +local function markup(keys) + local result = "" + + -- Compute longest key combination + local longest = 0 + for _, key in ipairs(keys) do + if doc[key] then + longest = math.max(longest, unilen(key2str(key))) + end + end + + local curgroup = nil + for _, key in ipairs(keys) do + if doc[key] then + local help, group = doc[key].help, doc[key].group + if group ~= curgroup then + if #result > 0 then result = result .. "\n" end + result = result .. + '' .. + group .. "\n" + curgroup = group + end + local skey = key2str(key) + result = result .. + ' ' .. + string.format("%" .. (longest - unilen(skey)) .. "s ", "") .. skey .. + ' ' .. + help .. '\n' + end + end + + return result +end + +-- Display help in a naughty notification +local nid = nil +function display() + local result = markup(capi.root.keys()) + if capi.client.focus then + result = result .. "\n" .. markup(capi.client.focus:keys()) + end + if result then + nid = naughty.notify({ text = result, + replaces_id = nid, + hover_timeout = 0.1, + timeout = 30 }).id + end +end diff --git a/rc/bindings.lua b/rc/bindings.lua index dd5a109..7e8c9fb 100644 --- a/rc/bindings.lua +++ b/rc/bindings.lua @@ -2,6 +2,7 @@ config.keys = {} config.mouse = {} local volume = loadrc("volume", "vbe/volume") local brightness = loadrc("brightness", "vbe/brightness") +local keydoc = loadrc("keydoc", "vbe/keydoc") local function client_info() local v = "" @@ -35,72 +36,94 @@ local function client_info() end config.keys.global = awful.util.table.join( - -- Tag navigation - awful.key({ modkey, }, "Left", awful.tag.viewprev ), - awful.key({ modkey, }, "Right", awful.tag.viewnext ), - awful.key({ modkey, }, "Escape", awful.tag.history.restore), - - -- Focus + keydoc.group("Focus"), awful.key({ modkey, }, "j", function () awful.client.focus.byidx( 1) if client.focus then client.focus:raise() end - end), + end, + "Focus next window"), awful.key({ modkey, }, "k", function () awful.client.focus.byidx(-1) if client.focus then client.focus:raise() end - end), - awful.key({ modkey, }, "u", awful.client.urgent.jumpto), - - -- Layout manipulation - awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end), - awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end), - awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1) end), - awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end), - awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1) end), - awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end), - awful.key({ modkey, }, "space", function () awful.layout.inc(config.layouts, 1) end), - awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(config.layouts, -1) end), - awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end), - awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end), - awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end), - awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end), + end, + "Focus previous window"), awful.key({ modkey, }, "Tab", function () awful.client.focus.history.previous() if client.focus then client.focus:raise() end - end), + end, + "Focus previously focused window"), + awful.key({ modkey, }, "u", awful.client.urgent.jumpto, + "Jump to urgent-flagged window"), + awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end, + "Jump to next screen"), + awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end), + + keydoc.group("Layout manipulation"), + awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end, + "Increase master-width factor"), + awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end, + "Decrease master-width factor"), + awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster( 1) end, + "Increase number of masters"), + awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster(-1) end, + "Decrease number of masters"), + awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol( 1) end, + "Increase number of columns"), + awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol(-1) end, + "Decrease number of columns"), + awful.key({ modkey, }, "space", function () awful.layout.inc(config.layouts, 1) end, + "Next layout"), + awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(config.layouts, -1) end, + "Previous layout"), + awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end, + "Swap with next window"), + awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end, + "Swap with previous window"), -- Spawn a terminal - awful.key({ modkey, }, "Return", function () awful.util.spawn(config.terminal) end), + keydoc.group("Misc"), + awful.key({ modkey, }, "Return", function () awful.util.spawn(config.terminal) end, + "Spawn a terminal"), -- Restart awesome - awful.key({ modkey, "Control" }, "r", awesome.restart), + awful.key({ modkey, "Control" }, "r", awesome.restart, "Restart awesome"), -- Multimedia keys awful.key({ }, "XF86MonBrightnessUp", brightness.increase), awful.key({ }, "XF86MonBrightnessDown", brightness.decrease), awful.key({ }, "XF86AudioRaiseVolume", volume.increase), awful.key({ }, "XF86AudioLowerVolume", volume.decrease), - awful.key({ }, "XF86AudioMute", volume.toggle) + awful.key({ }, "XF86AudioMute", volume.toggle), + + -- Help + awful.key({ modkey, }, "F1", keydoc.display) ) config.keys.client = awful.util.table.join( - awful.key({ modkey, }, "f", function (c) c.fullscreen = not c.fullscreen end), - awful.key({ modkey, }, "x", function (c) c:kill() end), - awful.key({ modkey, }, "o", awful.client.movetoscreen ), - awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ), - awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end), - awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end), - awful.key({ modkey, }, "i", client_info), + keydoc.group("Window-specific bindings"), + awful.key({ modkey, }, "f", function (c) c.fullscreen = not c.fullscreen end, + "Fullscreen"), + awful.key({ modkey, }, "x", function (c) c:kill() end, + "Close"), + awful.key({ modkey, }, "o", awful.client.movetoscreen, "Move to the other screen"), + awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle, "Toggle floating"), + awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end, + "Switch with master window"), + awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end, + "Stay on top"), + awful.key({ modkey, }, "i", client_info, + "Get client-related information"), awful.key({ modkey, }, "m", function (c) c.maximized_horizontal = not c.maximized_horizontal c.maximized_vertical = not c.maximized_vertical - end) + end, + "Maximize") ) config.mouse.client = awful.util.table.join( diff --git a/rc/quake.lua b/rc/quake.lua index b3036e8..69c7a5d 100644 --- a/rc/quake.lua +++ b/rc/quake.lua @@ -64,4 +64,4 @@ end config.keys.global = awful.util.table.join( config.keys.global, - awful.key({ modkey }, "`", toggle)) + awful.key({ modkey }, "`", toggle, "Toggle Quake console")) diff --git a/rc/tags.lua b/rc/tags.lua index 400e316..904ed38 100644 --- a/rc/tags.lua +++ b/rc/tags.lua @@ -1,6 +1,7 @@ -- Tags sharetags = loadrc("sharetags", "vbe/sharetags") +keydoc = loadrc("keydoc", "vbe/keydoc") local otags = config.tags config.tags = {} @@ -38,6 +39,7 @@ for i = 1, #tags do if i <= keynumber then config.keys.global = awful.util.table.join( config.keys.global, + keydoc.group("Tag management"), awful.key({ modkey }, "#" .. i + 9, function () local t = tags[i] @@ -53,7 +55,7 @@ for i = 1, #tags do sharetags.tag_move(t, mouse.screen) end awful.tag.viewonly(tags[i]) - end), + end, i == 5 and "Display only this tag" or nil), awful.key({ modkey, "Control" }, "#" .. i + 9, function () local t = tags[i] @@ -67,18 +69,19 @@ for i = 1, #tags do awful.tag.viewtoggle(t) end end - end), + end, i == 5 and "Toggle display of this tag" or nil), awful.key({ modkey, "Shift" }, "#" .. i + 9, function () if client.focus and tags[i] then awful.client.movetotag(tags[i]) end - end), + end, i == 5 and "Move window to this tag" or nil), awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9, function () if client.focus and tags[i] then awful.client.toggletag(tags[i]) end - end)) + end, i == 5 and "Toggle this tag on this window" or nil), + keydoc.group("Misc")) end end diff --git a/rc/theme.lua b/rc/theme.lua index adf9282..f0dcce9 100644 --- a/rc/theme.lua +++ b/rc/theme.lua @@ -12,7 +12,7 @@ if theme then theme.border_marked = theme.border_marked .. "66" theme.bg_normal = theme.bg_normal .. "99" - theme.bg_focus = theme.bg_focus .. "99" + theme.bg_focus = theme.bg_focus .. "BB" theme.bg_urgent = theme.bg_urgent .. "99" theme.bg_minimize = theme.bg_minimize .. "99" @@ -20,7 +20,7 @@ if theme then theme.bg_widget = "#00000099" theme.fg_widget_label = "#737d8c" theme.fg_widget_value = na(theme.fg_normal) - theme.fg_widget_value_important = na(theme.border_marked) + theme.fg_widget_value_important = "#E80F28" theme.fg_widget_sep = na(theme.fg_normal) theme.fg_widget_border = theme.fg_widget_label theme.fg_widget_clock = na(theme.border_focus) diff --git a/rc/widgets.lua b/rc/widgets.lua index 09f3b4c..0e15f7c 100644 --- a/rc/widgets.lua +++ b/rc/widgets.lua @@ -234,4 +234,5 @@ end config.keys.global = awful.util.table.join( config.keys.global, - awful.key({ modkey }, "r", function () promptbox[mouse.screen]:run() end)) + awful.key({ modkey }, "r", function () promptbox[mouse.screen]:run() end, + "Prompt for a command"))