awesome - 共通事項 - メニュー - 新・組み込みメニュー

 
1. 概要
2. freedesktop を記述
3. カテゴリ名を日本語化
4. コンフィグレーションファイル編集
5. 確認

1. 概要

 前項で、ある程度まで、思い通りにはできましたが・・・。  はたと気づきました。「Manjaro」みたいにしたかったら、「Manjaro」の通りに書けばいいじゃん。  著作権の問題は気になるものの、これが一番うまくいきそうです。

2. freedesktop を記述


/usr/local/share/lua/5.2/freedesktop/
 配下に、以下の3ファイルを作成します。

desktop.lua
init.lua
menu.lua

vi /usr/local/share/lua/5.2/freedesktop/desktop.lua
 下記のように記述します(うひゃ、長いですよ)。
--[[

     Awesome-Freedesktop
     Freedesktop.org compliant desktop entries and menu

     Desktop section

     Licensed under GNU General Public License v2
      * (c) 2016,      Luke Bonham
      * (c) 2009-2015, Antonio Terceiro

--]]

local awful  = require("awful")
local theme  = require("beautiful")
local utils  = require("menubar.utils")
local wibox  = require("wibox")

local capi   = capi
local io     = io
local ipairs = ipairs
local mouse  = mouse
local os     = os
local string = string
local table  = table

-- Desktop icons
-- freedesktop.desktop
local desktop = {
    -- Default desktop basic icons
    baseicons = {
        [1] = {
            label = "This PC",
            icon  = "computer",
            onclick = "computer://"
        },
        [2] = {
            label = "Home",
            icon  = "user-home",
            onclick = os.getenv("HOME")
        },
        [3] = {
            label = "Trash",
            icon  = "user-trash",
            onclick = "trash://"
        }
    },
    -- Default parameters
    iconsize   = { width = 48,  height = 48 },
    labelsize  = { width = 140, height = 20 },
    margin     = { x = 20, y = 20 },
}

-- MIME types list
local mime_types = {}

-- Icons positioning
local desktop_current_pos = {}

-- @return iterator on input pipe
local function pipelines(...)
    local f = assert(io.popen(...))
    return function ()
        local data = f:read()
        if data == nil then f:close() end
        return data
    end
end

-- Adds an icon to desktop
-- @param args settings from desktop.add_icons
-- @param label icon string label
-- @param icon icon string file path
-- @param onclick function to execute on click
function desktop.add_single_icon(args, label, icon, onclick)
    local s = args.screen

    -- define icon dimensions and position
    if not desktop_current_pos[s] then
        desktop_current_pos[s] = { x = (capi.screen[s].geometry.x + args.iconsize.width + args.margin.x), y = 40 }
    end

    local totheight = (icon and args.iconsize.height or 0) + (label and args.labelsize.height or 0)
    if totheight == 0 then return end

    if desktop_current_pos[s].y + totheight > capi.screen[s].geometry.height - 40 then
        desktop_current_pos[s].x = desktop_current_pos[s].x + args.labelsize.width + args.iconsize.width + args.margin.x
        desktop_current_pos[s].y = 40
    end

    local common = { screen = s, bg = "#00000000", visible = true, type = "desktop" }

    -- create icon container
    if icon then
        common.width = args.iconsize.width
        common.height = args.iconsize.height
        common.x = desktop_current_pos[s].x
        common.y = desktop_current_pos[s].y

        icon = wibox.widget {
            image = icon,
            resize = false,
            widget = wibox.widget.imagebox
        }

        icon:buttons(awful.button({ }, 1, nil, onclick))

        icon_container = wibox(common)
        icon_container:set_widget(icon)

        desktop_current_pos[s].y = desktop_current_pos[s].y + args.iconsize.height + 5
    end

    -- create label container
    if label then
        common.width = args.labelsize.width
        common.height = args.labelsize.height
        common.x = desktop_current_pos[s].x - (args.labelsize.width/2) + args.iconsize.width/2
        common.y = desktop_current_pos[s].y

        caption = wibox.widget {
            text          = label,
            align         = "center",
            forced_width  = common.width,
            forced_height = common.height,
            ellipsize     = "middle",
            widget        = wibox.widget.textbox
        }

        caption:buttons(awful.button({ }, 1, onclick))
        caption_container = wibox(common)
        caption_container:set_widget(caption)
    end

    desktop_current_pos[s].y = desktop_current_pos[s].y + args.labelsize.height + args.margin.y
end

-- Adds base icons (This PC, Trash, etc) to desktop
-- @param args settings from desktop.add_icons
function desktop.add_base_icons(args)
    for _,base in ipairs(args.baseicons) do
        desktop.add_single_icon(args, base.label, utils.lookup_icon(base.icon), function()
            awful.spawn(string.format("%s '%s'", args.open_with, base.onclick))
        end)
    end
end

-- Looks up a suitable icon for filename
-- @param filename string file name
-- @return icon file path (string)
function desktop.lookup_file_icon(filename)
    -- load system MIME types
    if #mime_types == 0 then
        for line in io.lines("/etc/mime.types") do
            if not line:find("^#") then
                local parsed = {}
                for w in line:gmatch("[^%s]+") do
                    table.insert(parsed, w)
                end
                if #parsed > 1 then
                    for i = 2, #parsed do
                        mime_types[parsed[i]] = parsed[1]:gsub("/", "-")
                    end
                end
            end
        end
    end

    -- try to search a possible icon among standards
    local extension = filename:match("%a+$")
    local mime = mime_types[extension] or ""
    local mime_family = mime:match("^%a+") or ""

    local possible_filenames = {
        mime, "gnome-mime-" .. mime,
        mime_family, "gnome-mime-" .. mime_family,
        extension
    }

    for i, filename in ipairs(possible_filenames) do
        local icon = utils.lookup_icon(filename)
        if icon then return icon end
    end

    -- if we don"t find ad icon, then pretend is a plain text file
    return utils.lookup_icon("text-x-generic")
end

-- Parse subdirectories and files list from input directory
-- @input dir directory to parse (string)
-- @return files table with found entries
function desktop.parse_dirs_and_files(dir)
    local files = {}
    local paths = pipelines('find '..dir..' -maxdepth 1 -type d | tail -1')
    for path in paths do
        if path:match("[^/]+$") then
            local file = {}
            file.filename = path:match("[^/]+$")
            file.path = path
            file.show = true
            file.icon = utils.lookup_icon("folder")
            table.insert(files, file)
        end
    end
    local paths = pipelines('find '..dir..' -maxdepth 1 -type f')
    for path in paths do
        if not path:find("%.desktop$") then
            local file = {}
            file.filename = path:match("[^/]+$")
            file.path = path
            file.show = true
            file.icon = desktop.lookup_file_icon(file.filename)
            table.insert(files, file)
        end
    end
    return files
end

-- Adds subdirectories and files icons from args.dir
-- @param args settings from desktop.add_icons
function desktop.add_dirs_and_files_icons(args)
    for _, file in ipairs(desktop.parse_dirs_and_files(args.dir)) do
        if file.show then
            local label = args.showlabels and file.filename or nil
            local onclick = function () awful.spawn(string.format("%s '%s'", args.open_with, file.path)) end
            desktop.add_single_icon(args, label, file.icon, onclick)
        end
    end
end

-- Main function, adds base, directory and files icons
-- @param args user defined settings, with fallback on defaults
function desktop.add_icons(args)
    args            = args or {}
    args.screen     = args.screen or mouse.screen
    args.dir        = args.dir or os.getenv("HOME") .. "/Desktop"
    args.showlabels = args.showlabel or true
    args.open_with  = args.open_with or "xdg_open"
    args.baseicons  = args.baseicons or desktop.baseicons
    args.iconsize   = args.iconsize or desktop.iconsize
    args.labelsize  = args.labelsize or desktop.labelsize
    args.margin     = args.margin or desktop.margin

    -- trying to fallback on Adwaita if theme.icon_theme is not defined
    -- if Adwaita is missing too, no icons will be shown
    if not theme.icon_theme then
        theme.icon_theme = args.icon_theme or "Adwaita"
    end

    desktop.add_base_icons(args)
    desktop.add_dirs_and_files_icons(args)
end

return desktop


vi /usr/local/share/lua/5.2/freedesktop/init.lua
 下記のように記述します(これは前ページと同じだし、短い)。
--[[

     Awesome-Freedesktop
     Freedesktop.org compliant desktop entries and menu

     Licensed under GNU General Public License v2
      * (c) 2016,      Luke Bonham
      * (c) 2009-2015, Antonio Terceiro

--]]

return {
    desktop  = require("freedesktop.desktop"),
    menu     = require("freedesktop.menu")
}


vi /usr/local/share/lua/5.2/freedesktop/menu.lua
 下記のように記述します(これも、少々長い)。
--[[

     Awesome-Freedesktop
     Freedesktop.org compliant desktop entries and menu

     Menu section

     Licensed under GNU General Public License v2
      * (c) 2016, Luke Bonham
      * (c) 2014, Harvey Mittens

--]]

local awful_menu = require("awful.menu")
local menu_gen   = require("menubar.menu_gen")
local menu_utils = require("menubar.utils")
local icon_theme = require("menubar.icon_theme")
local gls        = require("gears.filesystem")

local pairs, string, table, os = pairs, string, table, os

-- Add support for NixOS systems too
table.insert(menu_gen.all_menu_dirs, string.format("%s/.nix-profile/share/applications", os.getenv("HOME")))

-- Remove non existent paths in order to avoid issues
local existent_paths = {}
for k,v in pairs(menu_gen.all_menu_dirs) do
    if gls.is_dir(v) then
        table.insert(existent_paths, v)
    end
end
menu_gen.all_menu_dirs = existent_paths

-- Expecting a wm_name of awesome omits too many applications and tools
menu_utils.wm_name = ""

-- Menu
-- freedesktop.menu
local menu = {}

-- Determines whether an table includes a certain element
-- @param tab a given table
-- @param val the element to search for
-- @return true if the given string is found within the search table; otherwise, false if not
function menu.has_value (tab, val)
    for index, value in pairs(tab) do
        if val:find(value) then
            return true
        end
    end
    return false
end

-- Use MenuBar parsing utils to build a menu for Awesome
-- @return awful.menu
function menu.build(args)
    local args       = args or {}
    local icon_size  = args.icon_size
    local before     = args.before or {}
    local after      = args.after or {}
    local skip_items = args.skip_items or {}
    local sub_menu   = args.sub_menu or false

    local result     = {}
    local _menu      = awful_menu({ items = before })

    menu_gen.generate(function(entries)
        -- Add category icons
        for k, v in pairs(menu_gen.all_categories) do
            table.insert(result, { k, {}, v.icon })
        end

        -- Get items table
        for k, v in pairs(entries) do
            for _, cat in pairs(result) do
                if cat[1] == v.category then
                    if not menu.has_value(skip_items, v.name) then
                        table.insert(cat[2], { v.name, v.cmdline, v.icon })
                    end
                    break
                end
            end
        end

        -- Cleanup things a bit
        for i = #result, 1, -1 do
            local v = result[i]
            if #v[2] == 0 then
                -- Remove unused categories
                table.remove(result, i)
            else
                --Sort entries alphabetically (by name)
                table.sort(v[2], function (a, b) return string.byte(a[1]) < string.byte(b[1]) end)
                -- Replace category name with nice name
                v[1] = menu_gen.all_categories[v[1]].name
            end
        end

        -- Sort categories alphabetically also
        table.sort(result, function(a, b) return string.byte(a[1]) < string.byte(b[1]) end)

        -- Add menu item to hold the generated menu
        if sub_menu then
            result = {{sub_menu, result}}
        end

        -- Add items to menu
        for _, v in pairs(result) do _menu:add(v) end
        for _, v in pairs(after)  do _menu:add(v) end
    end)

    -- Set icon size
    if icon_size then
        for _,v in pairs(menu_gen.all_categories) do
            v.icon = icon_theme():find_icon_path(v.icon_name, icon_size)
        end
    end

    -- Hold the menu in the module
    menu.menu = _menu

    return _menu
end

return menu

3. カテゴリ名を日本語化

 もののついでだ、カテゴリ名を日本語化します。

vi /usr/local/share/awesome/lib/menubar/menu_gen.lua

--- Specify the mapping of .desktop Categories section to the
-- categories in the menubar. If "use" flag is set to false then any of
-- the applications that fall only to this category will not be shown.
menu_gen.all_categories = {
    multimedia = { app_type = "AudioVideo", name = "Multimedia",
                     icon_name = "applications-multimedia", use = true },
    development = { app_type = "Development", name = "Development",
                    icon_name = "applications-development", use = true },
    education = { app_type = "Education", name = "Education",
                  icon_name = "applications-science", use = true },
    games = { app_type = "Game", name = "Games",
              icon_name = "applications-games", use = true },
    graphics = { app_type = "Graphics", name = "Graphics",
                 icon_name = "applications-graphics", use = true },
    office = { app_type = "Office", name = "Office",
               icon_name = "applications-office", use = true },
    internet = { app_type = "Network", name = "Internet",
                icon_name = "applications-internet", use = true },
    science = { app_type = "Science", name="Science",
                icon_name = "applications-science", use = true },
    settings = { app_type = "Settings", name = "Settings",
                 icon_name = "applications-utilities", use = true },
    tools = { app_type = "System", name = "System Tools",
               icon_name = "applications-system", use = true },
    utility = { app_type = "Utility", name = "Accessories",
                icon_name = "applications-accessories", use = true }
}
 を下記のように書き換えます。

--- Specify the mapping of .desktop Categories section to the
-- categories in the menubar. If "use" flag is set to false then any of
-- the applications that fall only to this category will not be shown.
menu_gen.all_categories = {
    multimedia = { app_type = "AudioVideo", name = "マルチメディア",
                     icon_name = "applications-multimedia", use = true },
    development = { app_type = "Development", name = "開発",
                    icon_name = "applications-development", use = true },
    education = { app_type = "Education", name = "教育",
                  icon_name = "applications-science", use = true },
    games = { app_type = "Game", name = "ゲーム",
              icon_name = "applications-games", use = true },
    graphics = { app_type = "Graphics", name = "グラフィックス",
                 icon_name = "applications-graphics", use = true },
    office = { app_type = "Office", name = "オフィス",
               icon_name = "applications-office", use = true },
    internet = { app_type = "Network", name = "インターネット",
                icon_name = "applications-internet", use = true },
    science = { app_type = "Science", name="科学",
                icon_name = "applications-science", use = true },
    settings = { app_type = "Settings", name = "設定",
                 icon_name = "applications-utilities", use = true },
    tools = { app_type = "System", name = "システムツール",
               icon_name = "applications-system", use = true },
    utility = { app_type = "Utility", name = "アクセサリ",
                icon_name = "applications-accessories", use = true }
}

4. コンフィグレーションファイル編集

 コンフィグレーションファイルを編集して組み込みます。

vi ~/.config/awesome/rc.lua
 先頭部分で、「freedesktop」を読みこみます。

local hotkeys_popup = require("awful.hotkeys_popup")
-- Enable hotkeys help widget for VIM and other apps
 の箇所を、下記へ(これは前ページと同じ)

local hotkeys_popup = require("awful.hotkeys_popup")
-- Freedesktop menu
local freedesktop = require("freedesktop")
-- Enable hotkeys help widget for VIM and other apps
 メニューのフォントも好みのものへ、変更して、幅を少し広くします。

-- {{{ Variable definitions
-- Themes define colours, icons, font and wallpapers.
beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
 を下記のように書き換えます。

-- {{{ Variable definitions
-- Themes define colours, icons, font and wallpapers.
beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
beautiful.icon_theme            = "Papirus-Dark"
beautiful.menu_font             = "MigMix 1M normal 9"
beautiful.menu_width            = 180
 次の箇所が本番、メニューの組み込みです。

-- {{{ Menu
-- Create a launcher widget and a main menu
myawesomemenu = {
   { "hotkeys", function() hotkeys_popup.show_help(nil, awful.screen.focused()) end },
   { "manual", terminal .. " -e man awesome" },
   { "edit config", editor_cmd .. " " .. awesome.conffile },
   { "restart", awesome.restart },
   { "quit", function() awesome.quit() end },
}

mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
                                    { "open terminal", terminal }
                                  }
                        })

mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
                                     menu = mymainmenu })
 を下記のように書き換えます。

-- {{{ Menu
-- Create a launcher widget and a main menu
myawesomemenu = {
   { "hotkeys", function() hotkeys_popup.show_help(nil, awful.screen.focused()) end, menubar.utils.lookup_icon("preferences-desktop-keyboard-shortcuts") },
   { "manual", terminal .. " -e man awesome", menubar.utils.lookup_icon("system-help") },
   { "edit config", editor_cmd .. " " .. awesome.conffile,  menubar.utils.lookup_icon("accessories-text-editor") },
   { "restart", awesome.restart, menubar.utils.lookup_icon("system-restart") },
   { "quit", function() awesome.quit() end, menubar.utils.lookup_icon("system-log-out") },
}

myexitmenu = {
    { "log out", function() awesome.quit() end, menubar.utils.lookup_icon("system-log-out") },
    { "reboot", "sudo /sbin/reboot", menubar.utils.lookup_icon("system-reboot") },
    { "shutdown", "sudo /sbin/poweroff", menubar.utils.lookup_icon("system-shutdown") }
}

mymainmenu = freedesktop.menu.build({
    icon_size = 32,
    before = { { "Awesome", myawesomemenu,  beautiful.awesome_icon },                   },
    after  = { { "終了",    myexitmenu, menubar.utils.lookup_icon("system-shutdown") }, }
})

mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
                                     menu = mymainmenu })
 コンフィグレーションファイルの書き換えは、こちらの方が、前ページより少ないですね。

5. 確認

 さて、前項まで終わったら、Ctrl+Win+R で、「awesome」をリスタートして、確認します。
「awesome」-「FreeBSD」「組み込みメニュー」「freedesktop」

 ほぼ、思い通りです(フォントは、もう1サイズ小さい方がいいかしら)。

 後は、インストールするアプリケーションが、うまく組み込まれるかを確認するのみです。


 
 
カウンタバックグラウンド