summaryrefslogtreecommitdiff
path: root/awesome/lib/menubar/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'awesome/lib/menubar/init.lua')
-rw-r--r--awesome/lib/menubar/init.lua480
1 files changed, 0 insertions, 480 deletions
diff --git a/awesome/lib/menubar/init.lua b/awesome/lib/menubar/init.lua
deleted file mode 100644
index 10ad65c..0000000
--- a/awesome/lib/menubar/init.lua
+++ /dev/null
@@ -1,480 +0,0 @@
----------------------------------------------------------------------------
---- Menubar module, which aims to provide a freedesktop menu alternative
---
--- List of menubar keybindings:
--- ---
---
--- * "Left" | "C-j" select an item on the left
--- * "Right" | "C-k" select an item on the right
--- * "Backspace" exit the current category if we are in any
--- * "Escape" exit the current directory or exit menubar
--- * "Home" select the first item
--- * "End" select the last
--- * "Return" execute the entry
--- * "C-Return" execute the command with awful.spawn
--- * "C-M-Return" execute the command in a terminal
---
--- @author Alexander Yakushev <yakushev.alex@gmail.com>
--- @copyright 2011-2012 Alexander Yakushev
--- @module menubar
----------------------------------------------------------------------------
-
--- Grab environment we need
-local capi = {
- client = client,
- mouse = mouse,
- screen = screen
-}
-local awful = require("awful")
-local common = require("awful.widget.common")
-local theme = require("beautiful")
-local wibox = require("wibox")
-
-local function get_screen(s)
- return s and capi.screen[s]
-end
-
--- menubar
-local menubar = { mt = {}, menu_entries = {} }
-menubar.menu_gen = require("menubar.menu_gen")
-menubar.utils = require("menubar.utils")
-local compute_text_width = menubar.utils.compute_text_width
-
--- Options section
-
---- When true the .desktop files will be reparsed only when the
--- extension is initialized. Use this if menubar takes much time to
--- open.
--- @tfield[opt=true] boolean cache_entries
-menubar.cache_entries = true
-
---- When true the categories will be shown alongside application
--- entries.
--- @tfield[opt=true] boolean show_categories
-menubar.show_categories = true
-
---- Specifies the geometry of the menubar. This is a table with the keys
--- x, y, width and height. Missing values are replaced via the screen's
--- geometry. However, missing height is replaced by the font size.
--- @table geometry
--- @tfield number geometry.x A forced horizontal position
--- @tfield number geometry.y A forced vertical position
--- @tfield number geometry.width A forced width
--- @tfield number geometry.height A forced height
-menubar.geometry = { width = nil,
- height = nil,
- x = nil,
- y = nil }
-
---- Width of blank space left in the right side.
--- @tfield number right_margin
-menubar.right_margin = theme.xresources.apply_dpi(8)
-
---- Label used for "Next page", default "▶▶".
--- @tfield[opt="▶▶"] string right_label
-menubar.right_label = "▶▶"
-
---- Label used for "Previous page", default "◀◀".
--- @tfield[opt="◀◀"] string left_label
-menubar.left_label = "◀◀"
-
--- awful.widget.common.list_update adds three times a margin of dpi(4)
--- for each item:
--- @tfield number list_interspace
-local list_interspace = theme.xresources.apply_dpi(4) * 3
-
---- Allows user to specify custom parameters for prompt.run function
--- (like colors).
--- @see awful.prompt
-menubar.prompt_args = {}
-
--- Private section
-local current_item = 1
-local previous_item = nil
-local current_category = nil
-local shownitems = nil
-local instance = { prompt = nil,
- widget = nil,
- wibox = nil }
-
-local common_args = { w = wibox.layout.fixed.horizontal(),
- data = setmetatable({}, { __mode = 'kv' }) }
-
---- Wrap the text with the color span tag.
--- @param s The text.
--- @param c The desired text color.
--- @return the text wrapped in a span tag.
-local function colortext(s, c)
- return "<span color='" .. awful.util.ensure_pango_color(c) .. "'>" .. s .. "</span>"
-end
-
---- Get how the menu item should be displayed.
--- @param o The menu item.
--- @return item name, item background color, background image, item icon.
-local function label(o)
- if o.focused then
- return colortext(o.name, (theme.menu_fg_focus or theme.fg_focus)), (theme.menu_bg_focus or theme.bg_focus), nil, o.icon
- else
- return o.name, (theme.menu_bg_normal or theme.bg_normal), nil, o.icon
- end
-end
-
-local function load_count_table()
- local count_file_name = awful.util.getdir("cache") .. "/menu_count_file"
-
- local count_file = io.open (count_file_name, "r")
- local count_table = {}
-
- -- read weight file
- if count_file then
- io.input (count_file)
- for line in io.lines() do
- local name, count = string.match(line, "([^;]+);([^;]+)")
- if name ~= nil and count ~= nil then
- count_table[name] = count
- end
- end
- end
-
- return count_table
-end
-
-local function write_count_table(count_table)
- local count_file_name = awful.util.getdir("cache") .. "/menu_count_file"
-
- local count_file = io.open (count_file_name, "w")
-
- if count_file then
- io.output (count_file)
-
- for name, count in pairs(count_table) do
- local str = string.format("%s;%d\n", name, count)
- io.write(str)
- end
- io.flush()
- end
-end
-
---- Perform an action for the given menu item.
--- @param o The menu item.
--- @return if the function processed the callback, new awful.prompt command, new awful.prompt prompt text.
-local function perform_action(o)
- if not o then return end
- if o.key then
- current_category = o.key
- local new_prompt = shownitems[current_item].name .. ": "
- previous_item = current_item
- current_item = 1
- return true, "", new_prompt
- elseif shownitems[current_item].cmdline then
- awful.spawn(shownitems[current_item].cmdline)
-
- -- load count_table from cache file
- local count_table = load_count_table()
-
- -- increase count
- local curname = shownitems[current_item].name
- if count_table[curname] ~= nil then
- count_table[curname] = count_table[curname] + 1
- else
- count_table[curname] = 1
- end
-
- -- write updated count table to cache file
- write_count_table(count_table)
-
- -- Let awful.prompt execute dummy exec_callback and
- -- done_callback to stop the keygrabber properly.
- return false
- end
-end
-
--- Cut item list to return only current page.
--- @tparam table all_items All items list.
--- @tparam str query Search query.
--- @tparam number|screen scr Screen
--- @return table List of items for current page.
-local function get_current_page(all_items, query, scr)
- scr = get_screen(scr)
- if not instance.prompt.width then
- instance.prompt.width = compute_text_width(instance.prompt.prompt, scr)
- end
- if not menubar.left_label_width then
- menubar.left_label_width = compute_text_width(menubar.left_label, scr)
- end
- if not menubar.right_label_width then
- menubar.right_label_width = compute_text_width(menubar.right_label, scr)
- end
- local available_space = instance.geometry.width - menubar.right_margin -
- menubar.right_label_width - menubar.left_label_width -
- compute_text_width(query, scr) - instance.prompt.width
-
- local width_sum = 0
- local current_page = {}
- for i, item in ipairs(all_items) do
- item.width = item.width or
- compute_text_width(item.name, scr) +
- (item.icon and instance.geometry.height or 0) + list_interspace
- if width_sum + item.width > available_space then
- if current_item < i then
- table.insert(current_page, { name = menubar.right_label, icon = nil })
- break
- end
- current_page = { { name = menubar.left_label, icon = nil }, item, }
- width_sum = item.width
- else
- table.insert(current_page, item)
- width_sum = width_sum + item.width
- end
- end
- return current_page
-end
-
---- Update the menubar according to the command entered by user.
--- @tparam str query Search query.
--- @tparam number|screen scr Screen
-local function menulist_update(query, scr)
- query = query or ""
- shownitems = {}
- local pattern = awful.util.query_to_pattern(query)
-
- -- All entries are added to a list that will be sorted
- -- according to the priority (first) and weight (second) of its
- -- entries.
- -- If categories are used in the menu, we add the entries matching
- -- the current query with high priority as to ensure they are
- -- displayed first. Afterwards the non-category entries are added.
- -- All entries are weighted according to the number of times they
- -- have been executed previously (stored in count_table).
-
- local count_table = load_count_table()
- local command_list = {}
-
- local PRIO_NONE = 0
- local PRIO_CATEGORY_MATCH = 2
-
- -- Add the categories
- if menubar.show_categories then
- for _, v in pairs(menubar.menu_gen.all_categories) do
- v.focused = false
- if not current_category and v.use then
-
- -- check if current query matches a category
- if string.match(v.name, pattern) then
-
- v.weight = 0
- v.prio = PRIO_CATEGORY_MATCH
-
- -- get use count from count_table if present
- -- and use it as weight
- if string.len(pattern) > 0 and count_table[v.name] ~= nil then
- v.weight = tonumber(count_table[v.name])
- end
-
- -- check for prefix match
- if string.match(v.name, "^" .. pattern) then
- -- increase default priority
- v.prio = PRIO_CATEGORY_MATCH + 1
- else
- v.prio = PRIO_CATEGORY_MATCH
- end
-
- table.insert (command_list, v)
- end
- end
- end
- end
-
- -- Add the applications according to their name and cmdline
- for _, v in ipairs(menubar.menu_entries) do
- v.focused = false
- if not current_category or v.category == current_category then
-
- -- check if the query matches either the name or the commandline
- -- of some entry
- if string.match(v.name, pattern)
- or string.match(v.cmdline, pattern) then
-
- v.weight = 0
- v.prio = PRIO_NONE
-
- -- get use count from count_table if present
- -- and use it as weight
- if string.len(pattern) > 0 and count_table[v.name] ~= nil then
- v.weight = tonumber(count_table[v.name])
- end
-
- -- check for prefix match
- if string.match(v.name, "^" .. pattern)
- or string.match(v.cmdline, "^" .. pattern) then
- -- increase default priority
- v.prio = PRIO_NONE + 1
- else
- v.prio = PRIO_NONE
- end
-
- table.insert (command_list, v)
- end
- end
- end
-
- local function compare_counts(a, b)
- if a.prio == b.prio then
- return a.weight > b.weight
- end
- return a.prio > b.prio
- end
-
- -- sort command_list by weight (highest first)
- table.sort(command_list, compare_counts)
- -- copy into showitems
- shownitems = command_list
-
- if #shownitems > 0 then
- -- Insert a run item value as the last choice
- table.insert(shownitems, { name = "Exec: " .. query, cmdline = query, icon = nil })
-
- if current_item > #shownitems then
- current_item = #shownitems
- end
- shownitems[current_item].focused = true
- else
- table.insert(shownitems, { name = "", cmdline = query, icon = nil })
- end
-
- common.list_update(common_args.w, nil, label,
- common_args.data,
- get_current_page(shownitems, query, scr))
-end
-
---- Create the menubar wibox and widgets.
--- @tparam[opt] screen scr Screen.
-local function initialize(scr)
- instance.wibox = wibox({})
- instance.widget = menubar.get(scr)
- instance.wibox.ontop = true
- instance.prompt = awful.widget.prompt()
- local layout = wibox.layout.fixed.horizontal()
- layout:add(instance.prompt)
- layout:add(instance.widget)
- instance.wibox:set_widget(layout)
-end
-
---- Refresh menubar's cache by reloading .desktop files.
--- @tparam[opt] screen scr Screen.
-function menubar.refresh(scr)
- menubar.menu_gen.generate(function(entries)
- menubar.menu_entries = entries
- menulist_update(nil, scr)
- end)
-end
-
---- Awful.prompt keypressed callback to be used when the user presses a key.
--- @param mod Table of key combination modifiers (Control, Shift).
--- @param key The key that was pressed.
--- @param comm The current command in the prompt.
--- @return if the function processed the callback, new awful.prompt command, new awful.prompt prompt text.
-local function prompt_keypressed_callback(mod, key, comm)
- if key == "Left" or (mod.Control and key == "j") then
- current_item = math.max(current_item - 1, 1)
- return true
- elseif key == "Right" or (mod.Control and key == "k") then
- current_item = current_item + 1
- return true
- elseif key == "BackSpace" then
- if comm == "" and current_category then
- current_category = nil
- current_item = previous_item
- return true, nil, "Run: "
- end
- elseif key == "Escape" then
- if current_category then
- current_category = nil
- current_item = previous_item
- return true, nil, "Run: "
- end
- elseif key == "Home" then
- current_item = 1
- return true
- elseif key == "End" then
- current_item = #shownitems
- return true
- elseif key == "Return" or key == "KP_Enter" then
- if mod.Control then
- current_item = #shownitems
- if mod.Mod1 then
- -- add a terminal to the cmdline
- shownitems[current_item].cmdline = menubar.utils.terminal
- .. " -e " .. shownitems[current_item].cmdline
- end
- end
- return perform_action(shownitems[current_item])
- end
- return false
-end
-
---- Show the menubar on the given screen.
--- @param scr Screen.
-function menubar.show(scr)
- if not instance.wibox then
- initialize(scr)
- elseif instance.wibox.visible then -- Menu already shown, exit
- return
- elseif not menubar.cache_entries then
- menubar.refresh(scr)
- end
-
- -- Set position and size
- scr = scr or awful.screen.focused() or 1
- scr = get_screen(scr)
- local scrgeom = scr.workarea
- local geometry = menubar.geometry
- instance.geometry = {x = geometry.x or scrgeom.x,
- y = geometry.y or scrgeom.y,
- height = geometry.height or awful.util.round(theme.get_font_height() * 1.5),
- width = geometry.width or scrgeom.width}
- instance.wibox:geometry(instance.geometry)
-
- current_item = 1
- current_category = nil
- menulist_update(nil, scr)
-
- local prompt_args = menubar.prompt_args or {}
-
- awful.prompt.run(setmetatable({
- prompt = "Run: ",
- textbox = instance.prompt.widget,
- completion_callback = awful.completion.shell,
- history_path = awful.util.get_cache_dir() .. "/history_menu",
- done_callback = menubar.hide,
- changed_callback = function(query) menulist_update(query, scr) end,
- keypressed_callback = prompt_keypressed_callback
- }, {__index=prompt_args}))
-
- instance.wibox.visible = true
-end
-
---- Hide the menubar.
-function menubar.hide()
- instance.wibox.visible = false
-end
-
---- Get a menubar wibox.
--- @tparam[opt] screen scr Screen.
--- @return menubar wibox.
-function menubar.get(scr)
- menubar.refresh(scr)
- -- Add to each category the name of its key in all_categories
- for k, v in pairs(menubar.menu_gen.all_categories) do
- v.key = k
- end
- return common_args.w
-end
-
-function menubar.mt.__call(_, ...)
- return menubar.get(...)
-end
-
-return setmetatable(menubar, menubar.mt)
-
--- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80