summaryrefslogtreecommitdiffstats
path: root/.config/awesome/bowl.lua
diff options
context:
space:
mode:
Diffstat (limited to '.config/awesome/bowl.lua')
-rw-r--r--.config/awesome/bowl.lua205
1 files changed, 205 insertions, 0 deletions
diff --git a/.config/awesome/bowl.lua b/.config/awesome/bowl.lua
new file mode 100644
index 0000000..bf6af7b
--- /dev/null
+++ b/.config/awesome/bowl.lua
@@ -0,0 +1,205 @@
+-- -*- coding: utf-8 -*-
+--------------------------------------------------------------------------------
+-- @author Nicolas Berthier <nberthier@gmail.com>
+-- @copyright 2010 Nicolas Berthier
+--------------------------------------------------------------------------------
+--
+-- Bowls are kind of helpers that can be drawn (at the bottom --- for now) of an
+-- area, and displaying the current key prefix. It is inspired by emacs'
+-- behavior, that prints prefix keys in the minibuffer after a certain time.
+--
+-- I call it `bowl' as a reference to the bowl that one might have at home,
+-- where one puts its actual keys... A more serious name would be `hint' or
+-- `tooltip' (but they do not fit well for this usage).
+--
+-- Example usage: see `rc.lua' file.
+--
+--------------------------------------------------------------------------------
+
+--{{{ Grab environment (mostly aliases)
+local setmetatable = setmetatable
+local ipairs = ipairs
+local type = type
+local pairs = pairs
+local string = string
+local print = print
+local error = error
+
+local capi = capi
+local client = client
+local awesome = awesome
+local root = root
+local timer = timer
+
+local infoline = require ("infoline")
+--}}}
+
+module ("bowl")
+
+-- Privata data: we use weak keys in order to allow collection of private data
+-- if keys (clients) are collected (i.e., no longer used, after having been
+-- killed for instance)
+local data = setmetatable ({}, { __mode = 'k' })
+
+--{{{ Default values
+
+--- Default modifier filter
+local modfilter = {
+ ["Mod1"] = "M",
+ ["Mod4"] = "S",
+ ["Control"] = "C",
+ ["Shift"] = string.upper,
+}
+
+-- Timers configuration
+local use_timers = true
+local timeout = 2.0
+
+--}}}
+
+--{{{ Keychain pretty-printing
+
+function mod_to_string (mods, k)
+ local ret, k = "", k
+ for _, mod in ipairs (mods) do
+ if modfilter[mod] then
+ local t = type (modfilter[mod])
+ if t == "function" then
+ k = modfilter[mod](k)
+ elseif t == "string" then
+ ret = ret .. modfilter[mod] .. "-"
+ else
+ error ("Invalid modifier key filter: got a " .. t)
+ end
+ else
+ ret = ret .. mod .. "-"
+ end
+ end
+ return ret, k
+end
+
+function ks_to_string (m, k)
+ local m, k = mod_to_string (m, k)
+ return m .. k
+end
+
+--}}}
+
+--{{{ Timer management
+
+local function delete_timer_maybe (d)
+ if d.timer then -- stop and remove the timer
+ d.timer:remove_signal ("timeout", d.timer_function)
+ d.timer:stop ()
+ d.timer = nil
+ d.timer_expired = true
+ end
+end
+
+local function delayed_call_maybe (d, f)
+ if use_timers then
+ if not d.timer_expired and not d.timer then
+ -- create and start the timer
+ d.timer = timer ({ timeout = timeout })
+ d.timer_function = function () f (); delete_timer_maybe (d) end
+ d.timer:add_signal ("timeout", d.timer_function)
+ d.timer:start ()
+ d.timer_expired = false
+ elseif not d.timer_expired then
+ -- restart the timer...
+
+ -- XXX: What is the actual semantics of the call to `start' (ie,
+ -- does it restart the timer with the initial timeout)?
+ d.timer:stop ()
+ d.timer.timeout = timeout -- reset timeout
+ d.timer:start ()
+ end
+ else -- timers disabled
+ f () -- call the given function directly
+ end
+end
+
+--}}}
+
+--{{{ Infoline management
+
+function dispose (w)
+ local d = data[w]
+ if d.bowl then -- if bowl was enabled... (should always be true...)
+ infoline.dispose (d.bowl)
+ d.bowl = nil
+ end
+ delete_timer_maybe (d)
+ data[w] = nil
+end
+
+function append (w, m, k)
+ local d = data[w]
+ local pretty_ks = ks_to_string (m, k) .. " "
+ infoline.set_text (d.bowl, infoline.get_text (d.bowl) .. pretty_ks)
+
+ local function enable_bowl ()
+ -- XXX: is there a possible bad interleaving that could make
+ -- this function execute while the bowl has already been
+ -- disposed of? in which case the condition should be checked
+ -- first...
+
+ -- if d.bowl then
+ infoline.attach (d.bowl, w)
+ -- end
+ end
+
+ delayed_call_maybe (d, enable_bowl)
+end
+
+function create (w)
+ -- XXX: Note the prefix text could be customizable...
+ data[w] = { bowl = infoline.new (" ") }
+end
+
+--}}}
+
+
+--- Initializes the bowl module, with given properties; should be called before
+--- ANY other function of this module.
+-- Configurations fields include:
+--
+-- `use_timers', `timeout': A boolean defining whether bowls drawing should be
+-- delayed, along with a number being this time shift, in seconds (Default
+-- values are `true' and `2').
+--
+-- `modfilter': A table associating modifiers (Mod1, Mod4, Control, Shift, etc.)
+-- with either a string (in this case it will replace the modifier when printed
+-- in heplers) or functions (in this case the key string will be repaced by a
+-- call to this function with the key string as parameter). Default value is:
+-- { ["Mod1"] = "M", ["Mod4"] = "S", ["Control"] = "C", ["Shift"] =
+-- string.upper }
+--
+-- @param c The table of properties.
+function init (c)
+ local c = c or { }
+ modfilter = c.modfilter and c.modfilter or modfilter
+ if c.use_timers ~= nil then use_timers = c.use_timers end
+ if use_timers then
+ timeout = c.timeout ~= nil and c.timeout or timeout
+ end
+end
+
+--- Setup signal listeners, that trigger appropriate functions for a default
+--- behavior.
+function default_setup ()
+ local function to_root (f) return function (...) f (root, ...) end end
+ client.add_signal ("keychain::enter", create)
+ client.add_signal ("keychain::append", append)
+ client.add_signal ("keychain::leave", dispose)
+ awesome.add_signal ("keychain::enter", to_root (create))
+ awesome.add_signal ("keychain::append", to_root (append))
+ awesome.add_signal ("keychain::leave", to_root (dispose))
+end
+
+-- Local variables:
+-- indent-tabs-mode: nil
+-- fill-column: 80
+-- lua-indent-level: 4
+-- End:
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80