diff --git a/awesome/freedesktop/desktop.lua b/awesome/freedesktop/desktop.lua index 676ebdb..b5fdb37 100644 --- a/awesome/freedesktop/desktop.lua +++ b/awesome/freedesktop/desktop.lua @@ -11,44 +11,44 @@ --]] -local awful = require("awful") -local theme = require("beautiful") -local utils = require("menubar.utils") -local wibox = require("wibox") +local awful = require('awful') +local theme = require('beautiful') +local utils = require('menubar.utils') +local wibox = require('wibox') -local io = io +local io = io local ipairs = ipairs -local mouse = mouse -local os = os +local mouse = mouse +local os = os local string = string local screen = screen -local table = table +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 }, + -- 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 @@ -59,12 +59,14 @@ 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 + 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 @@ -73,187 +75,198 @@ end -- @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 - local dcp = desktop.current_pos + local s = args.screen + local dcp = desktop.current_pos - -- define icon dimensions and position - if not dcp[s] then - dcp[s] = { x = (screen[s].geometry.x + args.iconsize.width + args.margin.x), y = screen[s].geometry.y + 20 + args.margin.y } - end + -- define icon dimensions and position + if not dcp[s] then + dcp[s] = { + x = (screen[s].geometry.x + args.iconsize.width + args.margin.x), + y = screen[s].geometry.y + 20 + args.margin.y, + } + end - local tot_height = (icon and args.iconsize.height or 0) + (label and args.labelsize.height or 0) - if tot_height == 0 then return end + local tot_height = (icon and args.iconsize.height or 0) + (label and args.labelsize.height or 0) + if tot_height == 0 then + return + end - if dcp[s].y + tot_height > screen[s].geometry.y + screen[s].geometry.height - 20 - args.margin.y then - dcp[s].x = dcp[s].x + args.labelsize.width + args.iconsize.width + args.margin.x - dcp[s].y = 20 + args.margin.y - end + if dcp[s].y + tot_height > screen[s].geometry.y + screen[s].geometry.height - 20 - args.margin.y then + dcp[s].x = dcp[s].x + args.labelsize.width + args.iconsize.width + args.margin.x + dcp[s].y = 20 + args.margin.y + end - local common = { screen = s, bg = "#00000000", visible = true, type = "desktop" } + 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 = dcp[s].x - common.y = dcp[s].y + -- create icon container + if icon then + common.width = args.iconsize.width + common.height = args.iconsize.height + common.x = dcp[s].x + common.y = dcp[s].y - icon = wibox.widget { - image = icon, - resize = false, - widget = wibox.widget.imagebox - } + icon = wibox.widget({ + image = icon, + resize = false, + widget = wibox.widget.imagebox, + }) - icon:buttons(awful.button({ }, 1, nil, onclick)) + icon:buttons(awful.button({}, 1, nil, onclick)) - icon_container = wibox(common) - icon_container:set_widget(icon) + icon_container = wibox(common) + icon_container:set_widget(icon) - dcp[s].y = dcp[s].y + args.iconsize.height + 5 - end + dcp[s].y = dcp[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 = dcp[s].x - (args.labelsize.width/2) + args.iconsize.width/2 - common.y = dcp[s].y + -- create label container + if label then + common.width = args.labelsize.width + common.height = args.labelsize.height + common.x = dcp[s].x - (args.labelsize.width / 2) + args.iconsize.width / 2 + common.y = dcp[s].y - caption = wibox.widget { - text = label, - align = "center", - forced_width = common.width, - forced_height = common.height, - ellipsize = "middle", - widget = wibox.widget.textbox - } + 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 + caption:buttons(awful.button({}, 1, onclick)) + caption_container = wibox(common) + caption_container:set_widget(caption) + end - dcp[s].y = dcp[s].y + args.labelsize.height + args.margin.y + dcp[s].y = dcp[s].y + args.labelsize.height + args.margin.y - desktop.current_pos = dcp + desktop.current_pos = dcp - return dcp + return dcp 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 + 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 + -- 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 "" + -- 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 - } + 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 + 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") + -- 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 |sort|tail -n +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 + local files = {} + local paths = pipelines('find ' .. dir .. ' -maxdepth 1 -type d |sort|tail -n +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 + 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 + 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 + -- 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) + desktop.add_base_icons(args) + desktop.add_dirs_and_files_icons(args) end return desktop diff --git a/awesome/freedesktop/init.lua b/awesome/freedesktop/init.lua index 9350b44..1c66ba6 100644 --- a/awesome/freedesktop/init.lua +++ b/awesome/freedesktop/init.lua @@ -10,6 +10,6 @@ --]] return { - desktop = require("freedesktop.desktop"), - menu = require("freedesktop.menu") + desktop = require('freedesktop.desktop'), + menu = require('freedesktop.menu'), } diff --git a/awesome/freedesktop/menu.lua b/awesome/freedesktop/menu.lua index fed6e6b..55bb668 100644 --- a/awesome/freedesktop/menu.lua +++ b/awesome/freedesktop/menu.lua @@ -1,4 +1,3 @@ - --[[ Awesome-Freedesktop @@ -12,15 +11,15 @@ --]] -local Gio = require("lgi").Gio -local awful_menu = require("awful.menu") -local menu_gen = require("menubar.menu_gen") -local menu_utils = require("menubar.utils") +local Gio = require('lgi').Gio +local awful_menu = require('awful.menu') +local menu_gen = require('menubar.menu_gen') +local menu_utils = require('menubar.utils') local io, pairs, string, table, os = io, pairs, string, table, os -- Expecting a wm_name of awesome omits too many applications and tools -menu_utils.wm_name = "" +menu_utils.wm_name = '' -- Menu -- freedesktop.menu @@ -30,15 +29,15 @@ local menu = {} -- @tparam string path The directory path -- @treturn boolean True if path exists and is a directory function menu.is_dir(path) - return Gio.File.new_for_path(path):query_file_type({}) == "DIRECTORY" + return Gio.File.new_for_path(path):query_file_type({}) == 'DIRECTORY' end -- Remove non existent paths in order to avoid issues local existent_paths = {} -for k,v in pairs(menu_gen.all_menu_dirs) do - if menu.is_dir(v) then - table.insert(existent_paths, v) - end +for k, v in pairs(menu_gen.all_menu_dirs) do + if menu.is_dir(v) then + table.insert(existent_paths, v) + end end menu_gen.all_menu_dirs = existent_paths @@ -46,76 +45,84 @@ menu_gen.all_menu_dirs = existent_paths -- @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 +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 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 args = args or {} + 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 }) + 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 + 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 + -- 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 + -- 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) + -- 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 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) + -- 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) - -- Hold the menu in the module - menu.menu = _menu + -- Hold the menu in the module + menu.menu = _menu - return _menu + return _menu end return menu diff --git a/awesome/lain/helpers.lua b/awesome/lain/helpers.lua index ef9e08b..bedb08f 100644 --- a/awesome/lain/helpers.lua +++ b/awesome/lain/helpers.lua @@ -5,28 +5,27 @@ --]] -local spawn = require("awful.spawn") -local timer = require("gears.timer") -local debug = require("debug") -local io = { lines = io.lines, - open = io.open } -local pairs = pairs +local spawn = require('awful.spawn') +local timer = require('gears.timer') +local debug = require('debug') +local io = { lines = io.lines, open = io.open } +local pairs = pairs local rawget = rawget -local tsort = table.sort +local tsort = table.sort local unpack = unpack or table.unpack -- lua 5.1 retro-compatibility -- Lain helper functions for internal use -- lain.helpers local helpers = {} -helpers.lain_dir = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]] -helpers.icons_dir = helpers.lain_dir .. 'icons/' +helpers.lain_dir = debug.getinfo(1, 'S').source:match([[^@(.*/).*$]]) +helpers.icons_dir = helpers.lain_dir .. 'icons/' helpers.scripts_dir = helpers.lain_dir .. 'scripts/' -- {{{ Modules loader function helpers.wrequire(t, k) - return rawget(t, k) or require(t._NAME .. '.' .. k) + return rawget(t, k) or require(t._NAME .. '.' .. k) end -- }}} @@ -35,47 +34,51 @@ end -- check if the file exists and is readable function helpers.file_exists(path) - local file = io.open(path, "rb") - if file then file:close() end - return file ~= nil + local file = io.open(path, 'rb') + if file then + file:close() + end + return file ~= nil end -- get a table with all lines from a file function helpers.lines_from(path) - local lines = {} - for line in io.lines(path) do - lines[#lines + 1] = line - end - return lines + local lines = {} + for line in io.lines(path) do + lines[#lines + 1] = line + end + return lines end -- get a table with all lines from a file matching regexp function helpers.lines_match(regexp, path) - local lines = {} - for line in io.lines(path) do - if string.match(line, regexp) then - lines[#lines + 1] = line - end - end - return lines + local lines = {} + for line in io.lines(path) do + if string.match(line, regexp) then + lines[#lines + 1] = line + end + end + return lines end -- get first line of a file function helpers.first_line(path) - local file, first = io.open(path, "rb"), nil - if file then - first = file:read("*l") - file:close() - end - return first + local file, first = io.open(path, 'rb'), nil + if file then + first = file:read('*l') + file:close() + end + return first end -- get first non empty line from a file function helpers.first_nonempty_line(path) - for line in io.lines(path) do - if #line then return line end - end - return nil + for line in io.lines(path) do + if #line then + return line + end + end + return nil end -- }}} @@ -85,17 +88,19 @@ end helpers.timer_table = {} function helpers.newtimer(name, timeout, fun, nostart, stoppable) - if not name or #name == 0 then return end - name = (stoppable and name) or timeout - if not helpers.timer_table[name] then - helpers.timer_table[name] = timer({ timeout = timeout }) - helpers.timer_table[name]:start() - end - helpers.timer_table[name]:connect_signal("timeout", fun) - if not nostart then - helpers.timer_table[name]:emit_signal("timeout") - end - return stoppable and helpers.timer_table[name] + if not name or #name == 0 then + return + end + name = (stoppable and name) or timeout + if not helpers.timer_table[name] then + helpers.timer_table[name] = timer({ timeout = timeout }) + helpers.timer_table[name]:start() + end + helpers.timer_table[name]:connect_signal('timeout', fun) + if not nostart then + helpers.timer_table[name]:emit_signal('timeout') + end + return stoppable and helpers.timer_table[name] end -- }}} @@ -107,27 +112,25 @@ end -- @param callback function to execute on cmd output -- @return cmd PID function helpers.async(cmd, callback) - return spawn.easy_async(cmd, - function (stdout, _, _, exit_code) - callback(stdout, exit_code) - end) + return spawn.easy_async(cmd, function(stdout, _, _, exit_code) + callback(stdout, exit_code) + end) end -- like above, but call spawn.easy_async with a shell function helpers.async_with_shell(cmd, callback) - return spawn.easy_async_with_shell(cmd, - function (stdout, _, _, exit_code) - callback(stdout, exit_code) - end) + return spawn.easy_async_with_shell(cmd, function(stdout, _, _, exit_code) + callback(stdout, exit_code) + end) end -- run a command and execute a function on its output line by line function helpers.line_callback(cmd, callback) - return spawn.with_line_callback(cmd, { - stdout = function (line) - callback(line) - end, - }) + return spawn.with_line_callback(cmd, { + stdout = function(line) + callback(line) + end, + }) end -- }}} @@ -137,11 +140,11 @@ end helpers.map_table = {} function helpers.set_map(element, value) - helpers.map_table[element] = value + helpers.map_table[element] = value end function helpers.get_map(element) - return helpers.map_table[element] + return helpers.map_table[element] end -- }}} @@ -150,52 +153,56 @@ end -- check if an element exist on a table function helpers.element_in_table(element, tbl) - for _, i in pairs(tbl) do - if i == element then - return true - end - end - return false + for _, i in pairs(tbl) do + if i == element then + return true + end + end + return false end -- iterate over table of records sorted by keys function helpers.spairs(t) - -- collect the keys - local keys = {} - for k in pairs(t) do keys[#keys+1] = k end + -- collect the keys + local keys = {} + for k in pairs(t) do + keys[#keys + 1] = k + end - tsort(keys) + tsort(keys) - -- return the iterator function - local i = 0 - return function() - i = i + 1 - if keys[i] then - return keys[i], t[keys[i]] - end - end + -- return the iterator function + local i = 0 + return function() + i = i + 1 + if keys[i] then + return keys[i], t[keys[i]] + end + end end -- create the partition of singletons of a given set -- example: the trivial partition set of {a, b, c}, is {{a}, {b}, {c}} function helpers.trivial_partition_set(set) - local ss = {} - for _,e in pairs(set) do - ss[#ss+1] = {e} - end - return ss + local ss = {} + for _, e in pairs(set) do + ss[#ss + 1] = { e } + end + return ss end -- create the powerset of a given set function helpers.powerset(s) - if not s then return {} end - local t = {{}} - for i = 1, #s do - for j = 1, #t do - t[#t+1] = {s[i],unpack(t[j])} - end - end - return t + if not s then + return {} + end + local t = { {} } + for i = 1, #s do + for j = 1, #t do + t[#t + 1] = { s[i], unpack(t[j]) } + end + end + return t end -- }}} diff --git a/awesome/lain/init.lua b/awesome/lain/init.lua index b59d5dd..6770c40 100644 --- a/awesome/lain/init.lua +++ b/awesome/lain/init.lua @@ -9,7 +9,7 @@ --]] return { - layout = require("lain.layout"), - util = require("lain.util"), - widget = require("lain.widget") + layout = require('lain.layout'), + util = require('lain.util'), + widget = require('lain.widget'), } diff --git a/awesome/lain/layout/cascade.lua b/awesome/lain/layout/cascade.lua index cbc3877..1403b97 100644 --- a/awesome/lain/layout/cascade.lua +++ b/awesome/lain/layout/cascade.lua @@ -7,166 +7,184 @@ --]] -local floor = math.floor +local floor = math.floor local screen = screen local cascade = { - name = "cascade", - nmaster = 0, - offset_x = 32, - offset_y = 8, - tile = { - name = "cascadetile", - nmaster = 0, - ncol = 0, - mwfact = 0, - offset_x = 5, - offset_y = 32, - extra_padding = 0 - } + name = 'cascade', + nmaster = 0, + offset_x = 32, + offset_y = 8, + tile = { + name = 'cascadetile', + nmaster = 0, + ncol = 0, + mwfact = 0, + offset_x = 5, + offset_y = 32, + extra_padding = 0, + }, } local function do_cascade(p, tiling) - local t = p.tag or screen[p.screen].selected_tag - local wa = p.workarea - local cls = p.clients + local t = p.tag or screen[p.screen].selected_tag + local wa = p.workarea + local cls = p.clients - if #cls == 0 then return end + if #cls == 0 then + return + end - if not tiling then - -- Cascade windows. + if not tiling then + -- Cascade windows. - local num_c - if cascade.nmaster > 0 then - num_c = cascade.nmaster - else - num_c = t.master_count - end + local num_c + if cascade.nmaster > 0 then + num_c = cascade.nmaster + else + num_c = t.master_count + end - -- Opening a new window will usually force all existing windows to - -- get resized. This wastes a lot of CPU time. So let's set a lower - -- bound to "how_many": This wastes a little screen space but you'll - -- get a much better user experience. - local how_many = (#cls >= num_c and #cls) or num_c + -- Opening a new window will usually force all existing windows to + -- get resized. This wastes a lot of CPU time. So let's set a lower + -- bound to "how_many": This wastes a little screen space but you'll + -- get a much better user experience. + local how_many = (#cls >= num_c and #cls) or num_c - local current_offset_x = cascade.offset_x * (how_many - 1) - local current_offset_y = cascade.offset_y * (how_many - 1) + local current_offset_x = cascade.offset_x * (how_many - 1) + local current_offset_y = cascade.offset_y * (how_many - 1) - -- Iterate. - for i = 1,#cls,1 do - local c = cls[i] - local g = {} + -- Iterate. + for i = 1, #cls, 1 do + local c = cls[i] + local g = {} - g.x = wa.x + (how_many - i) * cascade.offset_x - g.y = wa.y + (i - 1) * cascade.offset_y - g.width = wa.width - current_offset_x - g.height = wa.height - current_offset_y + g.x = wa.x + (how_many - i) * cascade.offset_x + g.y = wa.y + (i - 1) * cascade.offset_y + g.width = wa.width - current_offset_x + g.height = wa.height - current_offset_y - if g.width < 1 then g.width = 1 end - if g.height < 1 then g.height = 1 end + if g.width < 1 then + g.width = 1 + end + if g.height < 1 then + g.height = 1 + end - p.geometries[c] = g - end - else - -- Layout with one fixed column meant for a master window. Its - -- width is calculated according to mwfact. Other clients are - -- cascaded or "tabbed" in a slave column on the right. + p.geometries[c] = g + end + else + -- Layout with one fixed column meant for a master window. Its + -- width is calculated according to mwfact. Other clients are + -- cascaded or "tabbed" in a slave column on the right. - -- (1) (2) (3) (4) - -- +----------+---+ +----------+---+ +----------+---+ +----------+---+ - -- | | | | | 3 | | | 4 | | +---+| - -- | | | -> | | | -> | +---++ -> | +---+|+ - -- | 1 | 2 | | 1 +---++ | 1 | 3 || | 1 +---+|+| - -- | | | | | 2 || | +---++| | +---+|+ | - -- | | | | | || | | 2 | | | | 2 |+ | - -- +----------+---+ +---------+---++ +--------+---+-+ +------+---+---+ + -- (1) (2) (3) (4) + -- +----------+---+ +----------+---+ +----------+---+ +----------+---+ + -- | | | | | 3 | | | 4 | | +---+| + -- | | | -> | | | -> | +---++ -> | +---+|+ + -- | 1 | 2 | | 1 +---++ | 1 | 3 || | 1 +---+|+| + -- | | | | | 2 || | +---++| | +---+|+ | + -- | | | | | || | | 2 | | | | 2 |+ | + -- +----------+---+ +---------+---++ +--------+---+-+ +------+---+---+ - local mwfact - if cascade.tile.mwfact > 0 then - mwfact = cascade.tile.mwfact - else - mwfact = t.master_width_factor - end + local mwfact + if cascade.tile.mwfact > 0 then + mwfact = cascade.tile.mwfact + else + mwfact = t.master_width_factor + end - -- Make slave windows overlap main window? Do this if ncol is 1. - local overlap_main - if cascade.tile.ncol > 0 then - overlap_main = cascade.tile.ncol - else - overlap_main = t.column_count - end + -- Make slave windows overlap main window? Do this if ncol is 1. + local overlap_main + if cascade.tile.ncol > 0 then + overlap_main = cascade.tile.ncol + else + overlap_main = t.column_count + end - -- Minimum space for slave windows? See cascade.tile.lua. - local num_c - if cascade.tile.nmaster > 0 then - num_c = cascade.tile.nmaster - else - num_c = t.master_count - end + -- Minimum space for slave windows? See cascade.tile.lua. + local num_c + if cascade.tile.nmaster > 0 then + num_c = cascade.tile.nmaster + else + num_c = t.master_count + end - local how_many = (#cls - 1 >= num_c and (#cls - 1)) or num_c + local how_many = (#cls - 1 >= num_c and (#cls - 1)) or num_c - local current_offset_x = cascade.tile.offset_x * (how_many - 1) - local current_offset_y = cascade.tile.offset_y * (how_many - 1) + local current_offset_x = cascade.tile.offset_x * (how_many - 1) + local current_offset_y = cascade.tile.offset_y * (how_many - 1) - if #cls <= 0 then return end + if #cls <= 0 then + return + end - -- Main column, fixed width and height. - local c = cls[1] - local g = {} - -- Rounding is necessary to prevent the rendered size of slavewid - -- from being 1 pixel off when the result is not an integer. - local mainwid = floor(wa.width * mwfact) - local slavewid = wa.width - mainwid + -- Main column, fixed width and height. + local c = cls[1] + local g = {} + -- Rounding is necessary to prevent the rendered size of slavewid + -- from being 1 pixel off when the result is not an integer. + local mainwid = floor(wa.width * mwfact) + local slavewid = wa.width - mainwid - if overlap_main == 1 then - g.width = wa.width + if overlap_main == 1 then + g.width = wa.width - -- The size of the main window may be reduced a little bit. - -- This allows you to see if there are any windows below the - -- main window. - -- This only makes sense, though, if the main window is - -- overlapping everything else. - g.width = g.width - cascade.tile.extra_padding - else - g.width = mainwid - end + -- The size of the main window may be reduced a little bit. + -- This allows you to see if there are any windows below the + -- main window. + -- This only makes sense, though, if the main window is + -- overlapping everything else. + g.width = g.width - cascade.tile.extra_padding + else + g.width = mainwid + end - g.height = wa.height - g.x = wa.x - g.y = wa.y + g.height = wa.height + g.x = wa.x + g.y = wa.y - if g.width < 1 then g.width = 1 end - if g.height < 1 then g.height = 1 end + if g.width < 1 then + g.width = 1 + end + if g.height < 1 then + g.height = 1 + end - p.geometries[c] = g + p.geometries[c] = g - -- Remaining clients stacked in slave column, new ones on top. - if #cls <= 1 then return end - for i = 2,#cls do - c = cls[i] - g = {} + -- Remaining clients stacked in slave column, new ones on top. + if #cls <= 1 then + return + end + for i = 2, #cls do + c = cls[i] + g = {} - g.width = slavewid - current_offset_x - g.height = wa.height - current_offset_y + g.width = slavewid - current_offset_x + g.height = wa.height - current_offset_y - g.x = wa.x + mainwid + (how_many - (i - 1)) * cascade.tile.offset_x - g.y = wa.y + (i - 2) * cascade.tile.offset_y + g.x = wa.x + mainwid + (how_many - (i - 1)) * cascade.tile.offset_x + g.y = wa.y + (i - 2) * cascade.tile.offset_y - if g.width < 1 then g.width = 1 end - if g.height < 1 then g.height = 1 end + if g.width < 1 then + g.width = 1 + end + if g.height < 1 then + g.height = 1 + end - p.geometries[c] = g - end - end + p.geometries[c] = g + end + end end function cascade.tile.arrange(p) - return do_cascade(p, true) + return do_cascade(p, true) end function cascade.arrange(p) - return do_cascade(p, false) + return do_cascade(p, false) end return cascade diff --git a/awesome/lain/layout/centerwork.lua b/awesome/lain/layout/centerwork.lua index c105676..30c0e16 100644 --- a/awesome/lain/layout/centerwork.lua +++ b/awesome/lain/layout/centerwork.lua @@ -17,260 +17,274 @@ local mousegrabber = mousegrabber local screen = screen local centerwork = { - name = "centerwork", - horizontal = { name = "centerworkh" } + name = 'centerwork', + horizontal = { name = 'centerworkh' }, } local function arrange(p, layout) - local t = p.tag or screen[p.screen].selected_tag - local wa = p.workarea - local cls = p.clients + local t = p.tag or screen[p.screen].selected_tag + local wa = p.workarea + local cls = p.clients - if #cls == 0 then return end + if #cls == 0 then + return + end - local g = {} + local g = {} - -- Main column, fixed width and height - local mwfact = t.master_width_factor - local mainhei = floor(wa.height * mwfact) - local mainwid = floor(wa.width * mwfact) - local slavewid = wa.width - mainwid - local slaveLwid = floor(slavewid / 2) - local slaveRwid = slavewid - slaveLwid - local slavehei = wa.height - mainhei - local slaveThei = floor(slavehei / 2) - local slaveBhei = slavehei - slaveThei - local nbrFirstSlaves = floor(#cls / 2) - local nbrSecondSlaves = floor((#cls - 1) / 2) + -- Main column, fixed width and height + local mwfact = t.master_width_factor + local mainhei = floor(wa.height * mwfact) + local mainwid = floor(wa.width * mwfact) + local slavewid = wa.width - mainwid + local slaveLwid = floor(slavewid / 2) + local slaveRwid = slavewid - slaveLwid + local slavehei = wa.height - mainhei + local slaveThei = floor(slavehei / 2) + local slaveBhei = slavehei - slaveThei + local nbrFirstSlaves = floor(#cls / 2) + local nbrSecondSlaves = floor((#cls - 1) / 2) - local slaveFirstDim, slaveSecondDim = 0, 0 + local slaveFirstDim, slaveSecondDim = 0, 0 - if layout.name == "centerwork" then -- vertical - if nbrFirstSlaves > 0 then slaveFirstDim = floor(wa.height / nbrFirstSlaves) end - if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.height / nbrSecondSlaves) end + if layout.name == 'centerwork' then -- vertical + if nbrFirstSlaves > 0 then + slaveFirstDim = floor(wa.height / nbrFirstSlaves) + end + if nbrSecondSlaves > 0 then + slaveSecondDim = floor(wa.height / nbrSecondSlaves) + end - g.height = wa.height - g.width = mainwid + g.height = wa.height + g.width = mainwid - g.x = wa.x + slaveLwid - g.y = wa.y - else -- horizontal - if nbrFirstSlaves > 0 then slaveFirstDim = floor(wa.width / nbrFirstSlaves) end - if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.width / nbrSecondSlaves) end + g.x = wa.x + slaveLwid + g.y = wa.y + else -- horizontal + if nbrFirstSlaves > 0 then + slaveFirstDim = floor(wa.width / nbrFirstSlaves) + end + if nbrSecondSlaves > 0 then + slaveSecondDim = floor(wa.width / nbrSecondSlaves) + end - g.height = mainhei - g.width = wa.width + g.height = mainhei + g.width = wa.width - g.x = wa.x - g.y = wa.y + slaveThei - end + g.x = wa.x + g.y = wa.y + slaveThei + end - g.width = max(g.width, 1) - g.height = max(g.height, 1) + g.width = max(g.width, 1) + g.height = max(g.height, 1) - p.geometries[cls[1]] = g + p.geometries[cls[1]] = g - -- Auxiliary clients - if #cls <= 1 then return end - for i = 2, #cls do - g = {} - local idxChecker, dimToAssign + -- Auxiliary clients + if #cls <= 1 then + return + end + for i = 2, #cls do + g = {} + local idxChecker, dimToAssign - local rowIndex = floor(i/2) + local rowIndex = floor(i / 2) - if layout.name == "centerwork" then - if i % 2 == 0 then -- left slave - g.x = wa.x - g.y = wa.y + (rowIndex - 1) * slaveFirstDim - g.width = slaveLwid + if layout.name == 'centerwork' then + if i % 2 == 0 then -- left slave + g.x = wa.x + g.y = wa.y + (rowIndex - 1) * slaveFirstDim + g.width = slaveLwid - idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim - else -- right slave - g.x = wa.x + slaveLwid + mainwid - g.y = wa.y + (rowIndex - 1) * slaveSecondDim - g.width = slaveRwid + idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim + else -- right slave + g.x = wa.x + slaveLwid + mainwid + g.y = wa.y + (rowIndex - 1) * slaveSecondDim + g.width = slaveRwid - idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim - end + idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim + end - -- if last slave in row, use remaining space for it - if rowIndex == idxChecker then - g.height = wa.y + wa.height - g.y - else - g.height = dimToAssign - end - else - if i % 2 == 0 then -- top slave - g.x = wa.x + (rowIndex - 1) * slaveFirstDim - g.y = wa.y - g.height = slaveThei + -- if last slave in row, use remaining space for it + if rowIndex == idxChecker then + g.height = wa.y + wa.height - g.y + else + g.height = dimToAssign + end + else + if i % 2 == 0 then -- top slave + g.x = wa.x + (rowIndex - 1) * slaveFirstDim + g.y = wa.y + g.height = slaveThei - idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim - else -- bottom slave - g.x = wa.x + (rowIndex - 1) * slaveSecondDim - g.y = wa.y + slaveThei + mainhei - g.height = slaveBhei + idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim + else -- bottom slave + g.x = wa.x + (rowIndex - 1) * slaveSecondDim + g.y = wa.y + slaveThei + mainhei + g.height = slaveBhei - idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim - end + idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim + end - -- if last slave in row, use remaining space for it - if rowIndex == idxChecker then - g.width = wa.x + wa.width - g.x - else - g.width = dimToAssign - end - end + -- if last slave in row, use remaining space for it + if rowIndex == idxChecker then + g.width = wa.x + wa.width - g.x + else + g.width = dimToAssign + end + end - g.width = max(g.width, 1) - g.height = max(g.height, 1) + g.width = max(g.width, 1) + g.height = max(g.height, 1) - p.geometries[cls[i]] = g - end + p.geometries[cls[i]] = g + end end local function mouse_resize_handler(c, _, _, _, orientation) - local wa = c.screen.workarea - local mwfact = c.screen.selected_tag.master_width_factor - local g = c:geometry() - local offset = 0 - local cursor = "cross" + local wa = c.screen.workarea + local mwfact = c.screen.selected_tag.master_width_factor + local g = c:geometry() + local offset = 0 + local cursor = 'cross' - local corner_coords + local corner_coords - if orientation == 'vertical' then - if g.height + 15 >= wa.height then - offset = g.height * .5 - cursor = "sb_h_double_arrow" - elseif g.y + g.height + 15 <= wa.y + wa.height then - offset = g.height - end - corner_coords = { x = wa.x + wa.width * (1 - mwfact) / 2, y = g.y + offset } - else - if g.width + 15 >= wa.width then - offset = g.width * .5 - cursor = "sb_v_double_arrow" - elseif g.x + g.width + 15 <= wa.x + wa.width then - offset = g.width - end - corner_coords = { y = wa.y + wa.height * (1 - mwfact) / 2, x = g.x + offset } - end + if orientation == 'vertical' then + if g.height + 15 >= wa.height then + offset = g.height * 0.5 + cursor = 'sb_h_double_arrow' + elseif g.y + g.height + 15 <= wa.y + wa.height then + offset = g.height + end + corner_coords = { x = wa.x + wa.width * (1 - mwfact) / 2, y = g.y + offset } + else + if g.width + 15 >= wa.width then + offset = g.width * 0.5 + cursor = 'sb_v_double_arrow' + elseif g.x + g.width + 15 <= wa.x + wa.width then + offset = g.width + end + corner_coords = { y = wa.y + wa.height * (1 - mwfact) / 2, x = g.x + offset } + end - mouse.coords(corner_coords) + mouse.coords(corner_coords) - local prev_coords = {} + local prev_coords = {} - mousegrabber.run(function(m) - if not c.valid then return false end - for _, v in ipairs(m.buttons) do - if v then - prev_coords = { x = m.x, y = m.y } - local new_mwfact - if orientation == 'vertical' then - new_mwfact = 1 - (m.x - wa.x) / wa.width * 2 - else - new_mwfact = 1 - (m.y - wa.y) / wa.height * 2 - end - c.screen.selected_tag.master_width_factor = math.min(math.max(new_mwfact, 0.01), 0.99) - return true - end - end - return prev_coords.x == m.x and prev_coords.y == m.y - end, cursor) + mousegrabber.run(function(m) + if not c.valid then + return false + end + for _, v in ipairs(m.buttons) do + if v then + prev_coords = { x = m.x, y = m.y } + local new_mwfact + if orientation == 'vertical' then + new_mwfact = 1 - (m.x - wa.x) / wa.width * 2 + else + new_mwfact = 1 - (m.y - wa.y) / wa.height * 2 + end + c.screen.selected_tag.master_width_factor = math.min(math.max(new_mwfact, 0.01), 0.99) + return true + end + end + return prev_coords.x == m.x and prev_coords.y == m.y + end, cursor) end function centerwork.arrange(p) - return arrange(p, centerwork) + return arrange(p, centerwork) end function centerwork.horizontal.arrange(p) - return arrange(p, centerwork.horizontal) + return arrange(p, centerwork.horizontal) end function centerwork.mouse_resize_handler(c, corner, x, y) - return mouse_resize_handler(c, corner, x, y, 'vertical') + return mouse_resize_handler(c, corner, x, y, 'vertical') end function centerwork.horizontal.mouse_resize_handler(c, corner, x, y) - return mouse_resize_handler(c, corner, x, y, 'horizontal') + return mouse_resize_handler(c, corner, x, y, 'horizontal') end - --[[ Make focus.byidx and swap.byidx behave more consistently with other layouts. --]] -local awful = require("awful") -local gears = require("gears") +local awful = require('awful') +local gears = require('gears') local client = client local function compare_position(a, b) - if a.x == b.x then - return a.y < b.y - else - return a.x < b.x - end + if a.x == b.x then + return a.y < b.y + else + return a.x < b.x + end end local function clients_by_position() - local this = client.focus - if this then - local sorted = {} - for _, c in ipairs(client.focus.first_tag:clients()) do - if not c.minimized then sorted[#sorted+1] = c end - end - table.sort(sorted, compare_position) + local this = client.focus + if this then + local sorted = {} + for _, c in ipairs(client.focus.first_tag:clients()) do + if not c.minimized then + sorted[#sorted + 1] = c + end + end + table.sort(sorted, compare_position) - local idx = 0 - for i, that in ipairs(sorted) do - if this.window == that.window then - idx = i - end - end + local idx = 0 + for i, that in ipairs(sorted) do + if this.window == that.window then + idx = i + end + end - if idx > 0 then - return { sorted = sorted, idx = idx } - end - end - return {} + if idx > 0 then + return { sorted = sorted, idx = idx } + end + end + return {} end local function in_centerwork() - return client.focus and client.focus.first_tag.layout.name == "centerwork" + return client.focus and client.focus.first_tag.layout.name == 'centerwork' end centerwork.focus = {} - --[[ Drop in replacements for awful.client.focus.byidx and awful.client.swap.byidx that behaves consistently with other layouts. --]] function centerwork.focus.byidx(i) - if in_centerwork() then - local cls = clients_by_position() - if cls.idx then - local target = cls.sorted[gears.math.cycle(#cls.sorted, cls.idx + i)] - awful.client.focus.byidx(0, target) - end - else - awful.client.focus.byidx(i) - end + if in_centerwork() then + local cls = clients_by_position() + if cls.idx then + local target = cls.sorted[gears.math.cycle(#cls.sorted, cls.idx + i)] + awful.client.focus.byidx(0, target) + end + else + awful.client.focus.byidx(i) + end end centerwork.swap = {} function centerwork.swap.byidx(i) - if in_centerwork() then - local cls = clients_by_position() - if cls.idx then - local target = cls.sorted[gears.math.cycle(#cls.sorted, cls.idx + i)] - client.focus:swap(target) - end - else - awful.client.swap.byidx(i) - end + if in_centerwork() then + local cls = clients_by_position() + if cls.idx then + local target = cls.sorted[gears.math.cycle(#cls.sorted, cls.idx + i)] + client.focus:swap(target) + end + else + awful.client.swap.byidx(i) + end end return centerwork diff --git a/awesome/lain/layout/init.lua b/awesome/lain/layout/init.lua index 6478b06..cdcbad0 100644 --- a/awesome/lain/layout/init.lua +++ b/awesome/lain/layout/init.lua @@ -11,9 +11,9 @@ --]] -local wrequire = require("lain.helpers").wrequire +local wrequire = require('lain.helpers').wrequire local setmetatable = setmetatable -local layout = { _NAME = "lain.layout" } +local layout = { _NAME = 'lain.layout' } return setmetatable(layout, { __index = wrequire }) diff --git a/awesome/lain/layout/termfair.lua b/awesome/lain/layout/termfair.lua index cf018ef..f1fcbe2 100644 --- a/awesome/lain/layout/termfair.lua +++ b/awesome/lain/layout/termfair.lua @@ -8,275 +8,305 @@ --]] -local math = math -local screen = screen +local math = math +local screen = screen local tonumber = tonumber -local termfair = { name = "termfair" } -termfair.center = { name = "centerfair" } -termfair.stable = { name = "stablefair" } +local termfair = { name = 'termfair' } +termfair.center = { name = 'centerfair' } +termfair.stable = { name = 'stablefair' } local function do_fair(p, orientation) - local t = p.tag or screen[p.screen].selected_tag - local wa = p.workarea - local cls = p.clients + local t = p.tag or screen[p.screen].selected_tag + local wa = p.workarea + local cls = p.clients - if #cls == 0 then return end + if #cls == 0 then + return + end - -- How many vertical columns? Read from nmaster on the tag. - local num_x = tonumber(termfair.nmaster) or t.master_count - local ncol = tonumber(termfair.ncol) or t.column_count - if num_x <= 2 then num_x = 2 end - if ncol <= 1 then ncol = 1 end - local width = math.floor(wa.width/num_x) + -- How many vertical columns? Read from nmaster on the tag. + local num_x = tonumber(termfair.nmaster) or t.master_count + local ncol = tonumber(termfair.ncol) or t.column_count + if num_x <= 2 then + num_x = 2 + end + if ncol <= 1 then + ncol = 1 + end + local width = math.floor(wa.width / num_x) - if orientation == "west" then - -- Layout with fixed number of vertical columns (read from nmaster). - -- New windows align from left to right. When a row is full, a new - -- one above it is created. Like this: + if orientation == 'west' then + -- Layout with fixed number of vertical columns (read from nmaster). + -- New windows align from left to right. When a row is full, a new + -- one above it is created. Like this: - -- (1) (2) (3) - -- +---+---+---+ +---+---+---+ +---+---+---+ - -- | | | | | | | | | | | | - -- | 1 | | | -> | 1 | 2 | | -> | 1 | 2 | 3 | -> - -- | | | | | | | | | | | | - -- +---+---+---+ +---+---+---+ +---+---+---+ + -- (1) (2) (3) + -- +---+---+---+ +---+---+---+ +---+---+---+ + -- | | | | | | | | | | | | + -- | 1 | | | -> | 1 | 2 | | -> | 1 | 2 | 3 | -> + -- | | | | | | | | | | | | + -- +---+---+---+ +---+---+---+ +---+---+---+ - -- (4) (5) (6) - -- +---+---+---+ +---+---+---+ +---+---+---+ - -- | 1 | | | | 1 | 2 | | | 1 | 2 | 3 | - -- +---+---+---+ -> +---+---+---+ -> +---+---+---+ - -- | 2 | 3 | 4 | | 3 | 4 | 5 | | 4 | 5 | 6 | - -- +---+---+---+ +---+---+---+ +---+---+---+ + -- (4) (5) (6) + -- +---+---+---+ +---+---+---+ +---+---+---+ + -- | 1 | | | | 1 | 2 | | | 1 | 2 | 3 | + -- +---+---+---+ -> +---+---+---+ -> +---+---+---+ + -- | 2 | 3 | 4 | | 3 | 4 | 5 | | 4 | 5 | 6 | + -- +---+---+---+ +---+---+---+ +---+---+---+ - local num_y = math.max(math.ceil(#cls / num_x), ncol) - local height = math.floor(wa.height/num_y) - local cur_num_x = num_x - local at_x = 0 - local at_y = 0 + local num_y = math.max(math.ceil(#cls / num_x), ncol) + local height = math.floor(wa.height / num_y) + local cur_num_x = num_x + local at_x = 0 + local at_y = 0 - local remaining_clients = #cls + local remaining_clients = #cls - -- We start the first row. Left-align by limiting the number of - -- available slots. - if remaining_clients < num_x then - cur_num_x = remaining_clients - end + -- We start the first row. Left-align by limiting the number of + -- available slots. + if remaining_clients < num_x then + cur_num_x = remaining_clients + end - -- Iterate in reversed order. - for i = #cls,1,-1 do - -- Get x and y position. - local c = cls[i] - local this_x = cur_num_x - at_x - 1 - local this_y = num_y - at_y - 1 + -- Iterate in reversed order. + for i = #cls, 1, -1 do + -- Get x and y position. + local c = cls[i] + local this_x = cur_num_x - at_x - 1 + local this_y = num_y - at_y - 1 - -- Calculate geometry. - local g = {} - if this_x == (num_x - 1) then - g.width = wa.width - (num_x - 1)*width - else - g.width = width - end + -- Calculate geometry. + local g = {} + if this_x == (num_x - 1) then + g.width = wa.width - (num_x - 1) * width + else + g.width = width + end - if this_y == (num_y - 1) then - g.height = wa.height - (num_y - 1)*height - else - g.height = height - end + if this_y == (num_y - 1) then + g.height = wa.height - (num_y - 1) * height + else + g.height = height + end - g.x = wa.x + this_x*width - g.y = wa.y + this_y*height + g.x = wa.x + this_x * width + g.y = wa.y + this_y * height - if g.width < 1 then g.width = 1 end - if g.height < 1 then g.height = 1 end + if g.width < 1 then + g.width = 1 + end + if g.height < 1 then + g.height = 1 + end - p.geometries[c] = g + p.geometries[c] = g - remaining_clients = remaining_clients - 1 + remaining_clients = remaining_clients - 1 - -- Next grid position. - at_x = at_x + 1 - if at_x == num_x then - -- Row full, create a new one above it. - at_x = 0 - at_y = at_y + 1 + -- Next grid position. + at_x = at_x + 1 + if at_x == num_x then + -- Row full, create a new one above it. + at_x = 0 + at_y = at_y + 1 - -- We start a new row. Left-align. - if remaining_clients < num_x then - cur_num_x = remaining_clients - end - end - end - elseif orientation == "stable" then - -- Layout with fixed number of vertical columns (read from nmaster). - -- New windows align from left to right. When a row is full, a new - -- one below it is created. Like this: + -- We start a new row. Left-align. + if remaining_clients < num_x then + cur_num_x = remaining_clients + end + end + end + elseif orientation == 'stable' then + -- Layout with fixed number of vertical columns (read from nmaster). + -- New windows align from left to right. When a row is full, a new + -- one below it is created. Like this: - -- (1) (2) (3) - -- +---+---+---+ +---+---+---+ +---+---+---+ - -- | | | | | | | | | | | | - -- | 1 | | | -> | 1 | 2 | | -> | 1 | 2 | 3 | -> - -- | | | | | | | | | | | | - -- +---+---+---+ +---+---+---+ +---+---+---+ + -- (1) (2) (3) + -- +---+---+---+ +---+---+---+ +---+---+---+ + -- | | | | | | | | | | | | + -- | 1 | | | -> | 1 | 2 | | -> | 1 | 2 | 3 | -> + -- | | | | | | | | | | | | + -- +---+---+---+ +---+---+---+ +---+---+---+ - -- (4) (5) (6) - -- +---+---+---+ +---+---+---+ +---+---+---+ - -- | 1 | 2 | 3 | | 1 | 2 | 3 | | 1 | 2 | 3 | - -- +---+---+---+ +---+---+---+ +---+---+---+ - -- | 4 | | | | 4 | 5 | | | 4 | 5 | 6 | - -- +---+---+---+ -> +---+---+---+ -> +---+---+---+ + -- (4) (5) (6) + -- +---+---+---+ +---+---+---+ +---+---+---+ + -- | 1 | 2 | 3 | | 1 | 2 | 3 | | 1 | 2 | 3 | + -- +---+---+---+ +---+---+---+ +---+---+---+ + -- | 4 | | | | 4 | 5 | | | 4 | 5 | 6 | + -- +---+---+---+ -> +---+---+---+ -> +---+---+---+ - local num_y = math.max(math.ceil(#cls / num_x), ncol) - local height = math.floor(wa.height/num_y) + local num_y = math.max(math.ceil(#cls / num_x), ncol) + local height = math.floor(wa.height / num_y) - for i = #cls,1,-1 do - -- Get x and y position. - local c = cls[i] - local this_x = (i - 1) % num_x - local this_y = math.floor((i - this_x - 1) / num_x) + for i = #cls, 1, -1 do + -- Get x and y position. + local c = cls[i] + local this_x = (i - 1) % num_x + local this_y = math.floor((i - this_x - 1) / num_x) - -- Calculate geometry. - local g = {} - if this_x == (num_x - 1) then - g.width = wa.width - (num_x - 1)*width - else - g.width = width - end + -- Calculate geometry. + local g = {} + if this_x == (num_x - 1) then + g.width = wa.width - (num_x - 1) * width + else + g.width = width + end - if this_y == (num_y - 1) then - g.height = wa.height - (num_y - 1)*height - else - g.height = height - end + if this_y == (num_y - 1) then + g.height = wa.height - (num_y - 1) * height + else + g.height = height + end - g.x = wa.x + this_x*width - g.y = wa.y + this_y*height + g.x = wa.x + this_x * width + g.y = wa.y + this_y * height - if g.width < 1 then g.width = 1 end - if g.height < 1 then g.height = 1 end + if g.width < 1 then + g.width = 1 + end + if g.height < 1 then + g.height = 1 + end - p.geometries[c] = g - end - elseif orientation == "center" then - -- Layout with fixed number of vertical columns (read from nmaster). - -- Cols are centerded until there is nmaster columns, then windows - -- are stacked in the slave columns, with at most ncol clients per - -- column if possible. + p.geometries[c] = g + end + elseif orientation == 'center' then + -- Layout with fixed number of vertical columns (read from nmaster). + -- Cols are centerded until there is nmaster columns, then windows + -- are stacked in the slave columns, with at most ncol clients per + -- column if possible. - -- with nmaster=3 and ncol=1 you'll have - -- (1) (2) (3) - -- +---+---+---+ +-+---+---+-+ +---+---+---+ - -- | | | | | | | | | | | | | - -- | | 1 | | -> | | 1 | 2 | | -> | 1 | 2 | 3 | -> - -- | | | | | | | | | | | | | - -- +---+---+---+ +-+---+---+-+ +---+---+---+ + -- with nmaster=3 and ncol=1 you'll have + -- (1) (2) (3) + -- +---+---+---+ +-+---+---+-+ +---+---+---+ + -- | | | | | | | | | | | | | + -- | | 1 | | -> | | 1 | 2 | | -> | 1 | 2 | 3 | -> + -- | | | | | | | | | | | | | + -- +---+---+---+ +-+---+---+-+ +---+---+---+ - -- (4) (5) - -- +---+---+---+ +---+---+---+ - -- | | | 3 | | | 2 | 4 | - -- + 1 + 2 +---+ -> + 1 +---+---+ - -- | | | 4 | | | 3 | 5 | - -- +---+---+---+ +---+---+---+ + -- (4) (5) + -- +---+---+---+ +---+---+---+ + -- | | | 3 | | | 2 | 4 | + -- + 1 + 2 +---+ -> + 1 +---+---+ + -- | | | 4 | | | 3 | 5 | + -- +---+---+---+ +---+---+---+ - if #cls < num_x then - -- Less clients than the number of columns, let's center it! - local offset_x = wa.x + (wa.width - #cls*width) / 2 - for i = 1, #cls do - local g = { y = wa.y } - g.width = width - g.height = wa.height - if g.width < 1 then g.width = 1 end - if g.height < 1 then g.height = 1 end - g.x = offset_x + (i - 1) * width - p.geometries[cls[i]] = g - end - else - -- More clients than the number of columns, let's arrange it! - -- Master client deserves a special treatement - local g = {} - g.width = wa.width - (num_x - 1)*width - g.height = wa.height - if g.width < 1 then g.width = 1 end - if g.height < 1 then g.height = 1 end - g.x = wa.x - g.y = wa.y - p.geometries[cls[1]] = g + if #cls < num_x then + -- Less clients than the number of columns, let's center it! + local offset_x = wa.x + (wa.width - #cls * width) / 2 + for i = 1, #cls do + local g = { y = wa.y } + g.width = width + g.height = wa.height + if g.width < 1 then + g.width = 1 + end + if g.height < 1 then + g.height = 1 + end + g.x = offset_x + (i - 1) * width + p.geometries[cls[i]] = g + end + else + -- More clients than the number of columns, let's arrange it! + -- Master client deserves a special treatement + local g = {} + g.width = wa.width - (num_x - 1) * width + g.height = wa.height + if g.width < 1 then + g.width = 1 + end + if g.height < 1 then + g.height = 1 + end + g.x = wa.x + g.y = wa.y + p.geometries[cls[1]] = g - -- Treat the other clients + -- Treat the other clients - -- Compute distribution of clients among columns - local num_y = {} - local remaining_clients = #cls-1 - local ncol_min = math.ceil(remaining_clients/(num_x-1)) + -- Compute distribution of clients among columns + local num_y = {} + local remaining_clients = #cls - 1 + local ncol_min = math.ceil(remaining_clients / (num_x - 1)) - if ncol >= ncol_min then - for i = (num_x-1), 1, -1 do - if (remaining_clients-i+1) < ncol then - num_y[i] = remaining_clients-i + 1 - else - num_y[i] = ncol - end - remaining_clients = remaining_clients - num_y[i] - end - else - local rem = remaining_clients % (num_x-1) - if rem == 0 then - for i = 1, num_x-1 do - num_y[i] = ncol_min - end - else - for i = 1, num_x-1 do - num_y[i] = ncol_min - 1 - end - for i = 0, rem-1 do - num_y[num_x-1-i] = num_y[num_x-1-i] + 1 - end - end - end + if ncol >= ncol_min then + for i = (num_x - 1), 1, -1 do + if (remaining_clients - i + 1) < ncol then + num_y[i] = remaining_clients - i + 1 + else + num_y[i] = ncol + end + remaining_clients = remaining_clients - num_y[i] + end + else + local rem = remaining_clients % (num_x - 1) + if rem == 0 then + for i = 1, num_x - 1 do + num_y[i] = ncol_min + end + else + for i = 1, num_x - 1 do + num_y[i] = ncol_min - 1 + end + for i = 0, rem - 1 do + num_y[num_x - 1 - i] = num_y[num_x - 1 - i] + 1 + end + end + end - -- Compute geometry of the other clients - local nclient = 2 -- we start with the 2nd client - local wx = g.x + g.width - for i = 1, (num_x-1) do - local height = math.floor(wa.height / num_y[i]) - local wy = wa.y - for _ = 0, (num_y[i]-2) do - g = {} - g.x = wx - g.y = wy - g.height = height - g.width = width - if g.width < 1 then g.width = 1 end - if g.height < 1 then g.height = 1 end - p.geometries[cls[nclient]] = g - nclient = nclient + 1 - wy = wy + height - end - g = {} - g.x = wx - g.y = wy - g.height = wa.height - (num_y[i] - 1)*height - g.width = width - if g.width < 1 then g.width = 1 end - if g.height < 1 then g.height = 1 end - p.geometries[cls[nclient]] = g - nclient = nclient + 1 - wx = wx + width - end - end - end + -- Compute geometry of the other clients + local nclient = 2 -- we start with the 2nd client + local wx = g.x + g.width + for i = 1, (num_x - 1) do + local height = math.floor(wa.height / num_y[i]) + local wy = wa.y + for _ = 0, (num_y[i] - 2) do + g = {} + g.x = wx + g.y = wy + g.height = height + g.width = width + if g.width < 1 then + g.width = 1 + end + if g.height < 1 then + g.height = 1 + end + p.geometries[cls[nclient]] = g + nclient = nclient + 1 + wy = wy + height + end + g = {} + g.x = wx + g.y = wy + g.height = wa.height - (num_y[i] - 1) * height + g.width = width + if g.width < 1 then + g.width = 1 + end + if g.height < 1 then + g.height = 1 + end + p.geometries[cls[nclient]] = g + nclient = nclient + 1 + wx = wx + width + end + end + end end function termfair.center.arrange(p) - return do_fair(p, "center") + return do_fair(p, 'center') end function termfair.stable.arrange(p) - return do_fair(p, "stable") + return do_fair(p, 'stable') end function termfair.arrange(p) - return do_fair(p, "west") + return do_fair(p, 'west') end return termfair diff --git a/awesome/lain/util/dkjson.lua b/awesome/lain/util/dkjson.lua index 61cccb9..0cd5c08 100644 --- a/awesome/lain/util/dkjson.lua +++ b/awesome/lain/util/dkjson.lua @@ -43,705 +43,767 @@ SOFTWARE. -- global dependencies: local pairs, type, tostring, tonumber, getmetatable, setmetatable = - pairs, type, tostring, tonumber, getmetatable, setmetatable + pairs, type, tostring, tonumber, getmetatable, setmetatable local error, require, pcall, select = error, require, pcall, select local floor, huge = math.floor, math.huge local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat = - string.rep, string.gsub, string.sub, string.byte, string.char, - string.find, string.len, string.format + string.rep, string.gsub, string.sub, string.byte, string.char, string.find, string.len, string.format local strmatch = string.match local concat = table.concat -local json = { version = "dkjson 2.6" } +local json = { version = 'dkjson 2.6' } local jsonlpeg = {} if register_global_module_table then - if always_use_lpeg then - _G[global_module_name] = jsonlpeg - else - _G[global_module_name] = json - end + if always_use_lpeg then + _G[global_module_name] = jsonlpeg + else + _G[global_module_name] = json + end end _ENV = nil -- blocking globals in Lua 5.2 and later -pcall (function() - -- Enable access to blocked metatables. - -- Don't worry, this module doesn't change anything in them. - local debmeta = require "debug".getmetatable - if debmeta then getmetatable = debmeta end +pcall(function() + -- Enable access to blocked metatables. + -- Don't worry, this module doesn't change anything in them. + local debmeta = require('debug').getmetatable + if debmeta then + getmetatable = debmeta + end end) -json.null = setmetatable ({}, { - __tojson = function () return "null" end +json.null = setmetatable({}, { + __tojson = function() + return 'null' + end, }) -local function isarray (tbl) - local max, n, arraylen = 0, 0, 0 - for k,v in pairs (tbl) do - if k == 'n' and type(v) == 'number' then - arraylen = v - if v > max then - max = v - end - else - if type(k) ~= 'number' or k < 1 or floor(k) ~= k then - return false - end - if k > max then - max = k - end - n = n + 1 - end - end - if max > 10 and max > arraylen and max > n * 2 then - return false -- don't create an array with too many holes - end - return true, max +local function isarray(tbl) + local max, n, arraylen = 0, 0, 0 + for k, v in pairs(tbl) do + if k == 'n' and type(v) == 'number' then + arraylen = v + if v > max then + max = v + end + else + if type(k) ~= 'number' or k < 1 or floor(k) ~= k then + return false + end + if k > max then + max = k + end + n = n + 1 + end + end + if max > 10 and max > arraylen and max > n * 2 then + return false -- don't create an array with too many holes + end + return true, max end local escapecodes = { - ["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f", - ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t" + ['"'] = '\\"', + ['\\'] = '\\\\', + ['\b'] = '\\b', + ['\f'] = '\\f', + ['\n'] = '\\n', + ['\r'] = '\\r', + ['\t'] = '\\t', } -local function escapeutf8 (uchar) - local value = escapecodes[uchar] - if value then - return value - end - local a, b, c, d = strbyte (uchar, 1, 4) - a, b, c, d = a or 0, b or 0, c or 0, d or 0 - if a <= 0x7f then - value = a - elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then - value = (a - 0xc0) * 0x40 + b - 0x80 - elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then - value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80 - elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then - value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80 - else - return "" - end - if value <= 0xffff then - return strformat ("\\u%.4x", value) - elseif value <= 0x10ffff then - -- encode as UTF-16 surrogate pair - value = value - 0x10000 - local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400) - return strformat ("\\u%.4x\\u%.4x", highsur, lowsur) - else - return "" - end +local function escapeutf8(uchar) + local value = escapecodes[uchar] + if value then + return value + end + local a, b, c, d = strbyte(uchar, 1, 4) + a, b, c, d = a or 0, b or 0, c or 0, d or 0 + if a <= 0x7f then + value = a + elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then + value = (a - 0xc0) * 0x40 + b - 0x80 + elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then + value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80 + elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then + value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80 + else + return '' + end + if value <= 0xffff then + return strformat('\\u%.4x', value) + elseif value <= 0x10ffff then + -- encode as UTF-16 surrogate pair + value = value - 0x10000 + local highsur, lowsur = 0xD800 + floor(value / 0x400), 0xDC00 + (value % 0x400) + return strformat('\\u%.4x\\u%.4x', highsur, lowsur) + else + return '' + end end -local function fsub (str, pattern, repl) - -- gsub always builds a new string in a buffer, even when no match - -- exists. First using find should be more efficient when most strings - -- don't contain the pattern. - if strfind (str, pattern) then - return gsub (str, pattern, repl) - else - return str - end +local function fsub(str, pattern, repl) + -- gsub always builds a new string in a buffer, even when no match + -- exists. First using find should be more efficient when most strings + -- don't contain the pattern. + if strfind(str, pattern) then + return gsub(str, pattern, repl) + else + return str + end end -local function quotestring (value) - -- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js - value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8) - if strfind (value, "[\194\216\220\225\226\239]") then - value = fsub (value, "\194[\128-\159\173]", escapeutf8) - value = fsub (value, "\216[\128-\132]", escapeutf8) - value = fsub (value, "\220\143", escapeutf8) - value = fsub (value, "\225\158[\180\181]", escapeutf8) - value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8) - value = fsub (value, "\226\129[\160-\175]", escapeutf8) - value = fsub (value, "\239\187\191", escapeutf8) - value = fsub (value, "\239\191[\176-\191]", escapeutf8) - end - return "\"" .. value .. "\"" +local function quotestring(value) + -- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js + value = fsub(value, '[%z\1-\31"\\\127]', escapeutf8) + if strfind(value, '[\194\216\220\225\226\239]') then + value = fsub(value, '\194[\128-\159\173]', escapeutf8) + value = fsub(value, '\216[\128-\132]', escapeutf8) + value = fsub(value, '\220\143', escapeutf8) + value = fsub(value, '\225\158[\180\181]', escapeutf8) + value = fsub(value, '\226\128[\140-\143\168-\175]', escapeutf8) + value = fsub(value, '\226\129[\160-\175]', escapeutf8) + value = fsub(value, '\239\187\191', escapeutf8) + value = fsub(value, '\239\191[\176-\191]', escapeutf8) + end + return '"' .. value .. '"' end json.quotestring = quotestring local function replace(str, o, n) - local i, j = strfind (str, o, 1, true) - if i then - return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1) - else - return str - end + local i, j = strfind(str, o, 1, true) + if i then + return strsub(str, 1, i - 1) .. n .. strsub(str, j + 1, -1) + else + return str + end end -- locale independent num2str and str2num functions local decpoint, numfilter -local function updatedecpoint () - decpoint = strmatch(tostring(0.5), "([^05+])") - -- build a filter that can be used to remove group separators - numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+" +local function updatedecpoint() + decpoint = strmatch(tostring(0.5), '([^05+])') + -- build a filter that can be used to remove group separators + numfilter = '[^0-9%-%+eE' .. gsub(decpoint, '[%^%$%(%)%%%.%[%]%*%+%-%?]', '%%%0') .. ']+' end updatedecpoint() -local function num2str (num) - return replace(fsub(tostring(num), numfilter, ""), decpoint, ".") +local function num2str(num) + return replace(fsub(tostring(num), numfilter, ''), decpoint, '.') end -local function str2num (str) - local num = tonumber(replace(str, ".", decpoint)) - if not num then - updatedecpoint() - num = tonumber(replace(str, ".", decpoint)) - end - return num +local function str2num(str) + local num = tonumber(replace(str, '.', decpoint)) + if not num then + updatedecpoint() + num = tonumber(replace(str, '.', decpoint)) + end + return num end -local function addnewline2 (level, buffer, buflen) - buffer[buflen+1] = "\n" - buffer[buflen+2] = strrep (" ", level) - buflen = buflen + 2 - return buflen +local function addnewline2(level, buffer, buflen) + buffer[buflen + 1] = '\n' + buffer[buflen + 2] = strrep(' ', level) + buflen = buflen + 2 + return buflen end -function json.addnewline (state) - if state.indent then - state.bufferlen = addnewline2 (state.level or 0, - state.buffer, state.bufferlen or #(state.buffer)) - end +function json.addnewline(state) + if state.indent then + state.bufferlen = addnewline2(state.level or 0, state.buffer, state.bufferlen or #state.buffer) + end end local encode2 -- forward declaration -local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state) - local kt = type (key) - if kt ~= 'string' and kt ~= 'number' then - return nil, "type '" .. kt .. "' is not supported as a key by JSON." - end - if prev then - buflen = buflen + 1 - buffer[buflen] = "," - end - if indent then - buflen = addnewline2 (level, buffer, buflen) - end - buffer[buflen+1] = quotestring (key) - buffer[buflen+2] = ":" - return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state) +local function addpair(key, value, prev, indent, level, buffer, buflen, tables, globalorder, state) + local kt = type(key) + if kt ~= 'string' and kt ~= 'number' then + return nil, "type '" .. kt .. "' is not supported as a key by JSON." + end + if prev then + buflen = buflen + 1 + buffer[buflen] = ',' + end + if indent then + buflen = addnewline2(level, buffer, buflen) + end + buffer[buflen + 1] = quotestring(key) + buffer[buflen + 2] = ':' + return encode2(value, indent, level, buffer, buflen + 2, tables, globalorder, state) end local function appendcustom(res, buffer, state) - local buflen = state.bufferlen - if type (res) == 'string' then - buflen = buflen + 1 - buffer[buflen] = res - end - return buflen + local buflen = state.bufferlen + if type(res) == 'string' then + buflen = buflen + 1 + buffer[buflen] = res + end + return buflen end local function exception(reason, value, state, buffer, buflen, defaultmessage) - defaultmessage = defaultmessage or reason - local handler = state.exception - if not handler then - return nil, defaultmessage - else - state.bufferlen = buflen - local ret, msg = handler (reason, value, state, defaultmessage) - if not ret then return nil, msg or defaultmessage end - return appendcustom(ret, buffer, state) - end + defaultmessage = defaultmessage or reason + local handler = state.exception + if not handler then + return nil, defaultmessage + else + state.bufferlen = buflen + local ret, msg = handler(reason, value, state, defaultmessage) + if not ret then + return nil, msg or defaultmessage + end + return appendcustom(ret, buffer, state) + end end function json.encodeexception(_reason, _value, _state, defaultmessage) - return quotestring("<" .. defaultmessage .. ">") + return quotestring('<' .. defaultmessage .. '>') end -encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state) - local valtype = type (value) - local valmeta = getmetatable (value) - valmeta = type (valmeta) == 'table' and valmeta -- only tables - local valtojson = valmeta and valmeta.__tojson - if valtojson then - if tables[value] then - return exception('reference cycle', value, state, buffer, buflen) - end - tables[value] = true - state.bufferlen = buflen - local ret, msg = valtojson (value, state) - if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end - tables[value] = nil - buflen = appendcustom(ret, buffer, state) - elseif value == nil then - buflen = buflen + 1 - buffer[buflen] = "null" - elseif valtype == 'number' then - local s - if value ~= value or value >= huge or -value >= huge then - -- This is the behaviour of the original JSON implementation. - s = "null" - else - s = num2str (value) - end - buflen = buflen + 1 - buffer[buflen] = s - elseif valtype == 'boolean' then - buflen = buflen + 1 - buffer[buflen] = value and "true" or "false" - elseif valtype == 'string' then - buflen = buflen + 1 - buffer[buflen] = quotestring (value) - elseif valtype == 'table' then - if tables[value] then - return exception('reference cycle', value, state, buffer, buflen) - end - tables[value] = true - level = level + 1 - local isa, n = isarray (value) - if n == 0 and valmeta and valmeta.__jsontype == 'object' then - isa = false - end - local msg - if isa then -- JSON array - buflen = buflen + 1 - buffer[buflen] = "[" - for i = 1, n do - buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state) - if not buflen then return nil, msg end - if i < n then - buflen = buflen + 1 - buffer[buflen] = "," - end - end - buflen = buflen + 1 - buffer[buflen] = "]" - else -- JSON object - local prev = false - buflen = buflen + 1 - buffer[buflen] = "{" - local order = valmeta and valmeta.__jsonorder or globalorder - if order then - local used = {} - n = #order - for i = 1, n do - local k = order[i] - local v = value[k] - if v ~= nil then - used[k] = true - buflen, _msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) - prev = true -- add a seperator before the next element - end - end - for k,v in pairs (value) do - if not used[k] then - buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) - if not buflen then return nil, msg end - prev = true -- add a seperator before the next element - end - end - else -- unordered - for k,v in pairs (value) do - buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) - if not buflen then return nil, msg end - prev = true -- add a seperator before the next element - end - end - if indent then - buflen = addnewline2 (level - 1, buffer, buflen) - end - buflen = buflen + 1 - buffer[buflen] = "}" - end - tables[value] = nil - else - return exception ('unsupported type', value, state, buffer, buflen, - "type '" .. valtype .. "' is not supported by JSON.") - end - return buflen +encode2 = function(value, indent, level, buffer, buflen, tables, globalorder, state) + local valtype = type(value) + local valmeta = getmetatable(value) + valmeta = type(valmeta) == 'table' and valmeta -- only tables + local valtojson = valmeta and valmeta.__tojson + if valtojson then + if tables[value] then + return exception('reference cycle', value, state, buffer, buflen) + end + tables[value] = true + state.bufferlen = buflen + local ret, msg = valtojson(value, state) + if not ret then + return exception('custom encoder failed', value, state, buffer, buflen, msg) + end + tables[value] = nil + buflen = appendcustom(ret, buffer, state) + elseif value == nil then + buflen = buflen + 1 + buffer[buflen] = 'null' + elseif valtype == 'number' then + local s + if value ~= value or value >= huge or -value >= huge then + -- This is the behaviour of the original JSON implementation. + s = 'null' + else + s = num2str(value) + end + buflen = buflen + 1 + buffer[buflen] = s + elseif valtype == 'boolean' then + buflen = buflen + 1 + buffer[buflen] = value and 'true' or 'false' + elseif valtype == 'string' then + buflen = buflen + 1 + buffer[buflen] = quotestring(value) + elseif valtype == 'table' then + if tables[value] then + return exception('reference cycle', value, state, buffer, buflen) + end + tables[value] = true + level = level + 1 + local isa, n = isarray(value) + if n == 0 and valmeta and valmeta.__jsontype == 'object' then + isa = false + end + local msg + if isa then -- JSON array + buflen = buflen + 1 + buffer[buflen] = '[' + for i = 1, n do + buflen, msg = encode2(value[i], indent, level, buffer, buflen, tables, globalorder, state) + if not buflen then + return nil, msg + end + if i < n then + buflen = buflen + 1 + buffer[buflen] = ',' + end + end + buflen = buflen + 1 + buffer[buflen] = ']' + else -- JSON object + local prev = false + buflen = buflen + 1 + buffer[buflen] = '{' + local order = valmeta and valmeta.__jsonorder or globalorder + if order then + local used = {} + n = #order + for i = 1, n do + local k = order[i] + local v = value[k] + if v ~= nil then + used[k] = true + buflen, _msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) + prev = true -- add a seperator before the next element + end + end + for k, v in pairs(value) do + if not used[k] then + buflen, msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) + if not buflen then + return nil, msg + end + prev = true -- add a seperator before the next element + end + end + else -- unordered + for k, v in pairs(value) do + buflen, msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) + if not buflen then + return nil, msg + end + prev = true -- add a seperator before the next element + end + end + if indent then + buflen = addnewline2(level - 1, buffer, buflen) + end + buflen = buflen + 1 + buffer[buflen] = '}' + end + tables[value] = nil + else + return exception( + 'unsupported type', + value, + state, + buffer, + buflen, + "type '" .. valtype .. "' is not supported by JSON." + ) + end + return buflen end -function json.encode (value, state) - state = state or {} - local oldbuffer = state.buffer - local buffer = oldbuffer or {} - state.buffer = buffer - updatedecpoint() - local ret, msg = encode2 (value, state.indent, state.level or 0, - buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state) - if not ret then - error (msg, 2) - elseif oldbuffer == buffer then - state.bufferlen = ret - return true - else - state.bufferlen = nil - state.buffer = nil - return concat (buffer) - end +function json.encode(value, state) + state = state or {} + local oldbuffer = state.buffer + local buffer = oldbuffer or {} + state.buffer = buffer + updatedecpoint() + local ret, msg = encode2( + value, + state.indent, + state.level or 0, + buffer, + state.bufferlen or 0, + state.tables or {}, + state.keyorder, + state + ) + if not ret then + error(msg, 2) + elseif oldbuffer == buffer then + state.bufferlen = ret + return true + else + state.bufferlen = nil + state.buffer = nil + return concat(buffer) + end end -local function loc (str, where) - local line, pos, linepos = 1, 1, 0 - while true do - pos = strfind (str, "\n", pos, true) - if pos and pos < where then - line = line + 1 - linepos = pos - pos = pos + 1 - else - break - end - end - return "line " .. line .. ", column " .. (where - linepos) +local function loc(str, where) + local line, pos, linepos = 1, 1, 0 + while true do + pos = strfind(str, '\n', pos, true) + if pos and pos < where then + line = line + 1 + linepos = pos + pos = pos + 1 + else + break + end + end + return 'line ' .. line .. ', column ' .. (where - linepos) end -local function unterminated (str, what, where) - return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where) +local function unterminated(str, what, where) + return nil, strlen(str) + 1, 'unterminated ' .. what .. ' at ' .. loc(str, where) end -local function scanwhite (str, pos) - while true do - pos = strfind (str, "%S", pos) - if not pos then return nil end - local sub2 = strsub (str, pos, pos + 1) - if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then - -- UTF-8 Byte Order Mark - pos = pos + 3 - elseif sub2 == "//" then - pos = strfind (str, "[\n\r]", pos + 2) - if not pos then return nil end - elseif sub2 == "/*" then - pos = strfind (str, "*/", pos + 2) - if not pos then return nil end - pos = pos + 2 - else - return pos - end - end +local function scanwhite(str, pos) + while true do + pos = strfind(str, '%S', pos) + if not pos then + return nil + end + local sub2 = strsub(str, pos, pos + 1) + if sub2 == '\239\187' and strsub(str, pos + 2, pos + 2) == '\191' then + -- UTF-8 Byte Order Mark + pos = pos + 3 + elseif sub2 == '//' then + pos = strfind(str, '[\n\r]', pos + 2) + if not pos then + return nil + end + elseif sub2 == '/*' then + pos = strfind(str, '*/', pos + 2) + if not pos then + return nil + end + pos = pos + 2 + else + return pos + end + end end local escapechars = { - ["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f", - ["n"] = "\n", ["r"] = "\r", ["t"] = "\t" + ['"'] = '"', + ['\\'] = '\\', + ['/'] = '/', + ['b'] = '\b', + ['f'] = '\f', + ['n'] = '\n', + ['r'] = '\r', + ['t'] = '\t', } -local function unichar (value) - if value < 0 then - return nil - elseif value <= 0x007f then - return strchar (value) - elseif value <= 0x07ff then - return strchar (0xc0 + floor(value/0x40), - 0x80 + (floor(value) % 0x40)) - elseif value <= 0xffff then - return strchar (0xe0 + floor(value/0x1000), - 0x80 + (floor(value/0x40) % 0x40), - 0x80 + (floor(value) % 0x40)) - elseif value <= 0x10ffff then - return strchar (0xf0 + floor(value/0x40000), - 0x80 + (floor(value/0x1000) % 0x40), - 0x80 + (floor(value/0x40) % 0x40), - 0x80 + (floor(value) % 0x40)) - else - return nil - end +local function unichar(value) + if value < 0 then + return nil + elseif value <= 0x007f then + return strchar(value) + elseif value <= 0x07ff then + return strchar(0xc0 + floor(value / 0x40), 0x80 + (floor(value) % 0x40)) + elseif value <= 0xffff then + return strchar(0xe0 + floor(value / 0x1000), 0x80 + (floor(value / 0x40) % 0x40), 0x80 + (floor(value) % 0x40)) + elseif value <= 0x10ffff then + return strchar( + 0xf0 + floor(value / 0x40000), + 0x80 + (floor(value / 0x1000) % 0x40), + 0x80 + (floor(value / 0x40) % 0x40), + 0x80 + (floor(value) % 0x40) + ) + else + return nil + end end -local function scanstring (str, pos) - local lastpos = pos + 1 - local buffer, n = {}, 0 - while true do - local nextpos = strfind (str, "[\"\\]", lastpos) - if not nextpos then - return unterminated (str, "string", pos) - end - if nextpos > lastpos then - n = n + 1 - buffer[n] = strsub (str, lastpos, nextpos - 1) - end - if strsub (str, nextpos, nextpos) == "\"" then - lastpos = nextpos + 1 - break - else - local escchar = strsub (str, nextpos + 1, nextpos + 1) - local value - if escchar == "u" then - value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16) - if value then - local value2 - if 0xD800 <= value and value <= 0xDBff then - -- we have the high surrogate of UTF-16. Check if there is a - -- low surrogate escaped nearby to combine them. - if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then - value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16) - if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then - value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000 - else - value2 = nil -- in case it was out of range for a low surrogate - end - end - end - value = value and unichar (value) - if value then - if value2 then - lastpos = nextpos + 12 - else - lastpos = nextpos + 6 - end - end - end - end - if not value then - value = escapechars[escchar] or escchar - lastpos = nextpos + 2 - end - n = n + 1 - buffer[n] = value - end - end - if n == 1 then - return buffer[1], lastpos - elseif n > 1 then - return concat (buffer), lastpos - else - return "", lastpos - end +local function scanstring(str, pos) + local lastpos = pos + 1 + local buffer, n = {}, 0 + while true do + local nextpos = strfind(str, '["\\]', lastpos) + if not nextpos then + return unterminated(str, 'string', pos) + end + if nextpos > lastpos then + n = n + 1 + buffer[n] = strsub(str, lastpos, nextpos - 1) + end + if strsub(str, nextpos, nextpos) == '"' then + lastpos = nextpos + 1 + break + else + local escchar = strsub(str, nextpos + 1, nextpos + 1) + local value + if escchar == 'u' then + value = tonumber(strsub(str, nextpos + 2, nextpos + 5), 16) + if value then + local value2 + if 0xD800 <= value and value <= 0xDBff then + -- we have the high surrogate of UTF-16. Check if there is a + -- low surrogate escaped nearby to combine them. + if strsub(str, nextpos + 6, nextpos + 7) == '\\u' then + value2 = tonumber(strsub(str, nextpos + 8, nextpos + 11), 16) + if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then + value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000 + else + value2 = nil -- in case it was out of range for a low surrogate + end + end + end + value = value and unichar(value) + if value then + if value2 then + lastpos = nextpos + 12 + else + lastpos = nextpos + 6 + end + end + end + end + if not value then + value = escapechars[escchar] or escchar + lastpos = nextpos + 2 + end + n = n + 1 + buffer[n] = value + end + end + if n == 1 then + return buffer[1], lastpos + elseif n > 1 then + return concat(buffer), lastpos + else + return '', lastpos + end end local scanvalue -- forward declaration -local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta) - local tbl, n = {}, 0 - local pos = startpos + 1 - if what == 'object' then - setmetatable (tbl, objectmeta) - else - setmetatable (tbl, arraymeta) - end - while true do - pos = scanwhite (str, pos) - if not pos then return unterminated (str, what, startpos) end - local char = strsub (str, pos, pos) - if char == closechar then - return tbl, pos + 1 - end - local val1, err - val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta) - if err then return nil, pos, err end - pos = scanwhite (str, pos) - if not pos then return unterminated (str, what, startpos) end - char = strsub (str, pos, pos) - if char == ":" then - if val1 == nil then - return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")" - end - pos = scanwhite (str, pos + 1) - if not pos then return unterminated (str, what, startpos) end - local val2 - val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta) - if err then return nil, pos, err end - tbl[val1] = val2 - pos = scanwhite (str, pos) - if not pos then return unterminated (str, what, startpos) end - char = strsub (str, pos, pos) - else - n = n + 1 - tbl[n] = val1 - end - if char == "," then - pos = pos + 1 - end - end +local function scantable(what, closechar, str, startpos, nullval, objectmeta, arraymeta) + local tbl, n = {}, 0 + local pos = startpos + 1 + if what == 'object' then + setmetatable(tbl, objectmeta) + else + setmetatable(tbl, arraymeta) + end + while true do + pos = scanwhite(str, pos) + if not pos then + return unterminated(str, what, startpos) + end + local char = strsub(str, pos, pos) + if char == closechar then + return tbl, pos + 1 + end + local val1, err + val1, pos, err = scanvalue(str, pos, nullval, objectmeta, arraymeta) + if err then + return nil, pos, err + end + pos = scanwhite(str, pos) + if not pos then + return unterminated(str, what, startpos) + end + char = strsub(str, pos, pos) + if char == ':' then + if val1 == nil then + return nil, pos, 'cannot use nil as table index (at ' .. loc(str, pos) .. ')' + end + pos = scanwhite(str, pos + 1) + if not pos then + return unterminated(str, what, startpos) + end + local val2 + val2, pos, err = scanvalue(str, pos, nullval, objectmeta, arraymeta) + if err then + return nil, pos, err + end + tbl[val1] = val2 + pos = scanwhite(str, pos) + if not pos then + return unterminated(str, what, startpos) + end + char = strsub(str, pos, pos) + else + n = n + 1 + tbl[n] = val1 + end + if char == ',' then + pos = pos + 1 + end + end end -scanvalue = function (str, pos, nullval, objectmeta, arraymeta) - pos = pos or 1 - pos = scanwhite (str, pos) - if not pos then - return nil, strlen (str) + 1, "no valid JSON value (reached the end)" - end - local char = strsub (str, pos, pos) - if char == "{" then - return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta) - elseif char == "[" then - return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta) - elseif char == "\"" then - return scanstring (str, pos) - else - local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos) - if pstart then - local number = str2num (strsub (str, pstart, pend)) - if number then - return number, pend + 1 - end - end - pstart, pend = strfind (str, "^%a%w*", pos) - if pstart then - local name = strsub (str, pstart, pend) - if name == "true" then - return true, pend + 1 - elseif name == "false" then - return false, pend + 1 - elseif name == "null" then - return nullval, pend + 1 - end - end - return nil, pos, "no valid JSON value at " .. loc (str, pos) - end +scanvalue = function(str, pos, nullval, objectmeta, arraymeta) + pos = pos or 1 + pos = scanwhite(str, pos) + if not pos then + return nil, strlen(str) + 1, 'no valid JSON value (reached the end)' + end + local char = strsub(str, pos, pos) + if char == '{' then + return scantable('object', '}', str, pos, nullval, objectmeta, arraymeta) + elseif char == '[' then + return scantable('array', ']', str, pos, nullval, objectmeta, arraymeta) + elseif char == '"' then + return scanstring(str, pos) + else + local pstart, pend = strfind(str, '^%-?[%d%.]+[eE]?[%+%-]?%d*', pos) + if pstart then + local number = str2num(strsub(str, pstart, pend)) + if number then + return number, pend + 1 + end + end + pstart, pend = strfind(str, '^%a%w*', pos) + if pstart then + local name = strsub(str, pstart, pend) + if name == 'true' then + return true, pend + 1 + elseif name == 'false' then + return false, pend + 1 + elseif name == 'null' then + return nullval, pend + 1 + end + end + return nil, pos, 'no valid JSON value at ' .. loc(str, pos) + end end local function optionalmetatables(...) - if select("#", ...) > 0 then - return ... - else - return {__jsontype = 'object'}, {__jsontype = 'array'} - end + if select('#', ...) > 0 then + return ... + else + return { __jsontype = 'object' }, { __jsontype = 'array' } + end end -function json.decode (str, pos, nullval, ...) - local objectmeta, arraymeta = optionalmetatables(...) - return scanvalue (str, pos, nullval, objectmeta, arraymeta) +function json.decode(str, pos, nullval, ...) + local objectmeta, arraymeta = optionalmetatables(...) + return scanvalue(str, pos, nullval, objectmeta, arraymeta) end -function json.use_lpeg () - local g = require ("lpeg") +function json.use_lpeg() + local g = require('lpeg') - if g.version() == "0.11" then - error "due to a bug in LPeg 0.11, it cannot be used for JSON matching" - end + if g.version() == '0.11' then + error('due to a bug in LPeg 0.11, it cannot be used for JSON matching') + end - local pegmatch = g.match - local P, S, R = g.P, g.S, g.R + local pegmatch = g.match + local P, S, R = g.P, g.S, g.R - local function ErrorCall (str, pos, msg, state) - if not state.msg then - state.msg = msg .. " at " .. loc (str, pos) - state.pos = pos - end - return false - end + local function ErrorCall(str, pos, msg, state) + if not state.msg then + state.msg = msg .. ' at ' .. loc(str, pos) + state.pos = pos + end + return false + end - local function Err (msg) - return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall) - end + local function Err(msg) + return g.Cmt(g.Cc(msg) * g.Carg(2), ErrorCall) + end - local function ErrorUnterminatedCall (str, pos, what, state) - return ErrorCall (str, pos - 1, "unterminated " .. what, state) - end + local function ErrorUnterminatedCall(str, pos, what, state) + return ErrorCall(str, pos - 1, 'unterminated ' .. what, state) + end - local SingleLineComment = P"//" * (1 - S"\n\r")^0 - local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/" - local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0 + local SingleLineComment = P('//') * (1 - S('\n\r')) ^ 0 + local MultiLineComment = P('/*') * (1 - P('*/')) ^ 0 * P('*/') + local Space = (S(' \n\r\t') + P('\239\187\191') + SingleLineComment + MultiLineComment) ^ 0 - local function ErrUnterminated (what) - return g.Cmt (g.Cc (what) * g.Carg (2), ErrorUnterminatedCall) - end + local function ErrUnterminated(what) + return g.Cmt(g.Cc(what) * g.Carg(2), ErrorUnterminatedCall) + end - local PlainChar = 1 - S"\"\\\n\r" - local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars - local HexDigit = R("09", "af", "AF") - local function UTF16Surrogate (_match, _pos, high, low) - high, low = tonumber (high, 16), tonumber (low, 16) - if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then - return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000) - else - return false - end - end - local function UTF16BMP (hex) - return unichar (tonumber (hex, 16)) - end - local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit)) - local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP - local Char = UnicodeEscape + EscapeSequence + PlainChar - local String = P"\"" * (g.Cs (Char ^ 0) * P"\"" + ErrUnterminated "string") - local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0)) - local Fractal = P"." * R"09"^0 - local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1 - local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num - local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1) - local SimpleValue = Number + String + Constant - local ArrayContent, ObjectContent + local PlainChar = 1 - S('"\\\n\r') + local EscapeSequence = (P('\\') * g.C(S('"\\/bfnrt') + Err('unsupported escape sequence'))) / escapechars + local HexDigit = R('09', 'af', 'AF') + local function UTF16Surrogate(_match, _pos, high, low) + high, low = tonumber(high, 16), tonumber(low, 16) + if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then + return true, unichar((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000) + else + return false + end + end + local function UTF16BMP(hex) + return unichar(tonumber(hex, 16)) + end + local U16Sequence = (P('\\u') * g.C(HexDigit * HexDigit * HexDigit * HexDigit)) + local UnicodeEscape = g.Cmt(U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence / UTF16BMP + local Char = UnicodeEscape + EscapeSequence + PlainChar + local String = P('"') * (g.Cs(Char ^ 0) * P('"') + ErrUnterminated('string')) + local Integer = P('-') ^ -1 * (P('0') + (R('19') * R('09') ^ 0)) + local Fractal = P('.') * R('09') ^ 0 + local Exponent = (S('eE')) * (S('+-')) ^ -1 * R('09') ^ 1 + local Number = (Integer * Fractal ^ -1 * Exponent ^ -1) / str2num + local Constant = P('true') * g.Cc(true) + P('false') * g.Cc(false) + P('null') * g.Carg(1) + local SimpleValue = Number + String + Constant + local ArrayContent, ObjectContent - -- The functions parsearray and parseobject parse only a single value/pair - -- at a time and store them directly to avoid hitting the LPeg limits. - local function parsearray (str, pos, nullval, state) - local obj, cont - local start = pos - local npos - local t, nt = {}, 0 - repeat - obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state) - if cont == 'end' then - return ErrorUnterminatedCall (str, start, "array", state) - end - pos = npos - if cont == 'cont' or cont == 'last' then - nt = nt + 1 - t[nt] = obj - end - until cont ~= 'cont' - return pos, setmetatable (t, state.arraymeta) - end + -- The functions parsearray and parseobject parse only a single value/pair + -- at a time and store them directly to avoid hitting the LPeg limits. + local function parsearray(str, pos, nullval, state) + local obj, cont + local start = pos + local npos + local t, nt = {}, 0 + repeat + obj, cont, npos = pegmatch(ArrayContent, str, pos, nullval, state) + if cont == 'end' then + return ErrorUnterminatedCall(str, start, 'array', state) + end + pos = npos + if cont == 'cont' or cont == 'last' then + nt = nt + 1 + t[nt] = obj + end + until cont ~= 'cont' + return pos, setmetatable(t, state.arraymeta) + end - local function parseobject (str, pos, nullval, state) - local obj, key, cont - local start = pos - local npos - local t = {} - repeat - key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state) - if cont == 'end' then - return ErrorUnterminatedCall (str, start, "object", state) - end - pos = npos - if cont == 'cont' or cont == 'last' then - t[key] = obj - end - until cont ~= 'cont' - return pos, setmetatable (t, state.objectmeta) - end + local function parseobject(str, pos, nullval, state) + local obj, key, cont + local start = pos + local npos + local t = {} + repeat + key, obj, cont, npos = pegmatch(ObjectContent, str, pos, nullval, state) + if cont == 'end' then + return ErrorUnterminatedCall(str, start, 'object', state) + end + pos = npos + if cont == 'cont' or cont == 'last' then + t[key] = obj + end + until cont ~= 'cont' + return pos, setmetatable(t, state.objectmeta) + end - local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) - local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) - local Value = Space * (Array + Object + SimpleValue) - local ExpectedValue = Value + Space * Err "value expected" - local ExpectedKey = String + Err "key expected" - local End = P(-1) * g.Cc'end' - local ErrInvalid = Err "invalid JSON" - ArrayContent = (Value * Space * (P"," * g.Cc'cont' + P"]" * g.Cc'last'+ End + ErrInvalid) + g.Cc(nil) * (P"]" * g.Cc'empty' + End + ErrInvalid)) * g.Cp() - local Pair = g.Cg (Space * ExpectedKey * Space * (P":" + Err "colon expected") * ExpectedValue) - ObjectContent = (g.Cc(nil) * g.Cc(nil) * P"}" * g.Cc'empty' + End + (Pair * Space * (P"," * g.Cc'cont' + P"}" * g.Cc'last' + End + ErrInvalid) + ErrInvalid)) * g.Cp() - local DecodeValue = ExpectedValue * g.Cp () + local Array = P('[') * g.Cmt(g.Carg(1) * g.Carg(2), parsearray) + local Object = P('{') * g.Cmt(g.Carg(1) * g.Carg(2), parseobject) + local Value = Space * (Array + Object + SimpleValue) + local ExpectedValue = Value + Space * Err('value expected') + local ExpectedKey = String + Err('key expected') + local End = P(-1) * g.Cc('end') + local ErrInvalid = Err('invalid JSON') + ArrayContent = ( + Value * Space * (P(',') * g.Cc('cont') + P(']') * g.Cc('last') + End + ErrInvalid) + + g.Cc(nil) * (P(']') * g.Cc('empty') + End + ErrInvalid) + ) * g.Cp() + local Pair = g.Cg(Space * ExpectedKey * Space * (P(':') + Err('colon expected')) * ExpectedValue) + ObjectContent = ( + g.Cc(nil) * g.Cc(nil) * P('}') * g.Cc('empty') + + End + + (Pair * Space * (P(',') * g.Cc('cont') + P('}') * g.Cc('last') + End + ErrInvalid) + ErrInvalid) + ) * g.Cp() + local DecodeValue = ExpectedValue * g.Cp() - jsonlpeg.version = json.version - jsonlpeg.encode = json.encode - jsonlpeg.null = json.null - jsonlpeg.quotestring = json.quotestring - jsonlpeg.addnewline = json.addnewline - jsonlpeg.encodeexception = json.encodeexception - jsonlpeg.using_lpeg = true + jsonlpeg.version = json.version + jsonlpeg.encode = json.encode + jsonlpeg.null = json.null + jsonlpeg.quotestring = json.quotestring + jsonlpeg.addnewline = json.addnewline + jsonlpeg.encodeexception = json.encodeexception + jsonlpeg.using_lpeg = true - function jsonlpeg.decode (str, pos, nullval, ...) - local state = {} - state.objectmeta, state.arraymeta = optionalmetatables(...) - local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state) - if state.msg then - return nil, state.pos, state.msg - else - return obj, retpos - end - end + function jsonlpeg.decode(str, pos, nullval, ...) + local state = {} + state.objectmeta, state.arraymeta = optionalmetatables(...) + local obj, retpos = pegmatch(DecodeValue, str, pos, nullval, state) + if state.msg then + return nil, state.pos, state.msg + else + return obj, retpos + end + end - -- cache result of this function: - json.use_lpeg = function () return jsonlpeg end - jsonlpeg.use_lpeg = json.use_lpeg + -- cache result of this function: + json.use_lpeg = function() + return jsonlpeg + end + jsonlpeg.use_lpeg = json.use_lpeg - return jsonlpeg + return jsonlpeg end if always_use_lpeg then - return json.use_lpeg() + return json.use_lpeg() end return json - diff --git a/awesome/lain/util/init.lua b/awesome/lain/util/init.lua index 5ae0523..accd219 100644 --- a/awesome/lain/util/init.lua +++ b/awesome/lain/util/init.lua @@ -11,180 +11,200 @@ --]] -local awful = require("awful") -local sqrt = math.sqrt -local pairs = pairs -local client = client -local tonumber = tonumber -local wrequire = require("lain.helpers").wrequire +local awful = require('awful') +local sqrt = math.sqrt +local pairs = pairs +local client = client +local tonumber = tonumber +local wrequire = require('lain.helpers').wrequire local setmetatable = setmetatable -- Lain utilities submodule -- lain.util -local util = { _NAME = "lain.util" } +local util = { _NAME = 'lain.util' } -- Like awful.menu.clients, but only show clients of currently selected tags function util.menu_clients_current_tags(menu, args) - -- List of currently selected tags. - local cls_tags = awful.screen.focused().selected_tags + -- List of currently selected tags. + local cls_tags = awful.screen.focused().selected_tags - if cls_tags == nil then return nil end + if cls_tags == nil then + return nil + end - -- Final list of menu items. - local cls_t = {} + -- Final list of menu items. + local cls_t = {} - -- For each selected tag get all clients of that tag and add them to - -- the menu. A click on a menu item will raise that client. - for i = 1,#cls_tags do - local t = cls_tags[i] - local cls = t:clients() + -- For each selected tag get all clients of that tag and add them to + -- the menu. A click on a menu item will raise that client. + for i = 1, #cls_tags do + local t = cls_tags[i] + local cls = t:clients() - for _, c in pairs(cls) do - cls_t[#cls_t + 1] = { awful.util.escape(c.name) or "", - function () - c.minimized = false - client.focus = c - c:raise() - end, - c.icon } - end - end + for _, c in pairs(cls) do + cls_t[#cls_t + 1] = { + awful.util.escape(c.name) or '', + function() + c.minimized = false + client.focus = c + c:raise() + end, + c.icon, + } + end + end - -- No clients? Then quit. - if #cls_t <= 0 then return nil end + -- No clients? Then quit. + if #cls_t <= 0 then + return nil + end - -- menu may contain some predefined values, otherwise start with a - -- fresh menu. - if not menu then menu = {} end + -- menu may contain some predefined values, otherwise start with a + -- fresh menu. + if not menu then + menu = {} + end - -- Set the list of items and show the menu. - menu.items = cls_t - local m = awful.menu(menu) - m:show(args) + -- Set the list of items and show the menu. + menu.items = cls_t + local m = awful.menu(menu) + m:show(args) - return m + return m end -- Magnify a client: set it to "float" and resize it. function util.magnify_client(c, width_f, height_f) - if c and not c.floating then - util.magnified_client = c - util.mc(c, width_f, height_f) - else - util.magnified_client = nil - c.floating = false - end + if c and not c.floating then + util.magnified_client = c + util.mc(c, width_f, height_f) + else + util.magnified_client = nil + c.floating = false + end end -- https://github.com/lcpz/lain/issues/195 function util.mc(c, width_f, height_f) - c = c or util.magnified_client - if not c then return end + c = c or util.magnified_client + if not c then + return + end - c.floating = true - local s = awful.screen.focused() - local mg = s.workarea - local g = {} - local mwfact = width_f or s.selected_tag.master_width_factor or 0.5 - g.width = sqrt(mwfact) * mg.width - g.height = sqrt(height_f or mwfact) * mg.height - g.x = mg.x + (mg.width - g.width) / 2 - g.y = mg.y + (mg.height - g.height) / 2 + c.floating = true + local s = awful.screen.focused() + local mg = s.workarea + local g = {} + local mwfact = width_f or s.selected_tag.master_width_factor or 0.5 + g.width = sqrt(mwfact) * mg.width + g.height = sqrt(height_f or mwfact) * mg.height + g.x = mg.x + (mg.width - g.width) / 2 + g.y = mg.y + (mg.height - g.height) / 2 - if c then c:geometry(g) end -- if c is still a valid object + if c then + c:geometry(g) + end -- if c is still a valid object end -- Non-empty tag browsing -- direction in {-1, 1} <-> {previous, next} non-empty tag -function util.tag_view_nonempty(direction,sc) - direction = direction or 1 - local s = sc or awful.screen.focused() - local tags = s.tags - local sel = s.selected_tag +function util.tag_view_nonempty(direction, sc) + direction = direction or 1 + local s = sc or awful.screen.focused() + local tags = s.tags + local sel = s.selected_tag - local i = sel.index - repeat - i = i + direction + local i = sel.index + repeat + i = i + direction - -- Wrap around when we reach one of the bounds - if i > #tags then - i = i - #tags - end - if i < 1 then - i = i + #tags - end + -- Wrap around when we reach one of the bounds + if i > #tags then + i = i - #tags + end + if i < 1 then + i = i + #tags + end - local t = tags[i] + local t = tags[i] - -- Stop when we get back to where we started - if t == sel then - break - end + -- Stop when we get back to where we started + if t == sel then + break + end - -- If it's The One, view it. - if #t:clients() > 0 then - t:view_only() - return - end - until false + -- If it's The One, view it. + if #t:clients() > 0 then + t:view_only() + return + end + until false end -- {{{ Dynamic tagging -- Add a new tag function util.add_tag(layout) - awful.prompt.run { - prompt = "New tag name: ", - textbox = awful.screen.focused().mypromptbox.widget, - exe_callback = function(name) - if not name or #name == 0 then return end - awful.tag.add(name, { screen = awful.screen.focused(), layout = layout or awful.layout.suit.tile }):view_only() - end - } + awful.prompt.run({ + prompt = 'New tag name: ', + textbox = awful.screen.focused().mypromptbox.widget, + exe_callback = function(name) + if not name or #name == 0 then + return + end + awful.tag + .add(name, { screen = awful.screen.focused(), layout = layout or awful.layout.suit.tile }) + :view_only() + end, + }) end -- Rename current tag function util.rename_tag() - awful.prompt.run { - prompt = "Rename tag: ", - textbox = awful.screen.focused().mypromptbox.widget, - exe_callback = function(new_name) - if not new_name or #new_name == 0 then return end - local t = awful.screen.focused().selected_tag - if t then - t.name = new_name - end - end - } + awful.prompt.run({ + prompt = 'Rename tag: ', + textbox = awful.screen.focused().mypromptbox.widget, + exe_callback = function(new_name) + if not new_name or #new_name == 0 then + return + end + local t = awful.screen.focused().selected_tag + if t then + t.name = new_name + end + end, + }) end -- Move current tag -- pos in {-1, 1} <-> {previous, next} tag position function util.move_tag(pos) - local tag = awful.screen.focused().selected_tag - if tonumber(pos) <= -1 then - awful.tag.move(tag.index - 1, tag) - else - awful.tag.move(tag.index + 1, tag) - end + local tag = awful.screen.focused().selected_tag + if tonumber(pos) <= -1 then + awful.tag.move(tag.index - 1, tag) + else + awful.tag.move(tag.index + 1, tag) + end end -- Delete current tag -- Any rule set on the tag shall be broken function util.delete_tag() - local t = awful.screen.focused().selected_tag - if not t then return end - t:delete() + local t = awful.screen.focused().selected_tag + if not t then + return + end + t:delete() end -- }}} -- On the fly useless gaps change function util.useless_gaps_resize(thatmuch, s, t) - local scr = s or awful.screen.focused() - local tag = t or scr.selected_tag - tag.gap = tag.gap + tonumber(thatmuch) - awful.layout.arrange(scr) + local scr = s or awful.screen.focused() + local tag = t or scr.selected_tag + tag.gap = tag.gap + tonumber(thatmuch) + awful.layout.arrange(scr) end return setmetatable(util, { __index = wrequire }) diff --git a/awesome/lain/util/markup.lua b/awesome/lain/util/markup.lua index 63f9486..831b83d 100644 --- a/awesome/lain/util/markup.lua +++ b/awesome/lain/util/markup.lua @@ -15,52 +15,78 @@ local setmetatable = setmetatable local markup = { fg = {}, bg = {} } -- Convenience tags -function markup.bold(text) return format("%s", text) end -function markup.italic(text) return format("%s", text) end -function markup.strike(text) return format("%s", text) end -function markup.underline(text) return format("%s", text) end -function markup.monospace(text) return format("%s", text) end -function markup.big(text) return format("%s", text) end -function markup.small(text) return format("%s", text) end +function markup.bold(text) + return format('%s', text) +end +function markup.italic(text) + return format('%s', text) +end +function markup.strike(text) + return format('%s', text) +end +function markup.underline(text) + return format('%s', text) +end +function markup.monospace(text) + return format('%s', text) +end +function markup.big(text) + return format('%s', text) +end +function markup.small(text) + return format('%s', text) +end -- Set the font function markup.font(font, text) - return format("%s", font, text) + return format("%s", font, text) end -- Set the foreground function markup.fg.color(color, text) - return format("%s", color, text) + return format("%s", color, text) end -- Set the background function markup.bg.color(color, text) - return format("%s", color, text) + return format("%s", color, text) end -- Set foreground and background function markup.color(fg, bg, text) - return format("%s", fg, bg, text) + return format("%s", fg, bg, text) end -- Set font and foreground function markup.fontfg(font, fg, text) - return format("%s", font, fg, text) + return format("%s", font, fg, text) end -- Set font and background function markup.fontbg(font, bg, text) - return format("%s", font, bg, text) + return format("%s", font, bg, text) end -- Set font, foreground and background function markup.fontcolor(font, fg, bg, text) - return format("%s", font, fg, bg, text) + return format("%s", font, fg, bg, text) end -- link markup.{fg,bg}(...) calls to markup.{fg,bg}.color(...) -setmetatable(markup.fg, { __call = function(_, ...) return markup.fg.color(...) end }) -setmetatable(markup.bg, { __call = function(_, ...) return markup.bg.color(...) end }) +setmetatable(markup.fg, { + __call = function(_, ...) + return markup.fg.color(...) + end, +}) +setmetatable(markup.bg, { + __call = function(_, ...) + return markup.bg.color(...) + end, +}) -- link markup(...) calls to markup.fg.color(...) -return setmetatable(markup, { __call = function(_, ...) return markup.fg.color(...) end }) +return setmetatable(markup, { + __call = function(_, ...) + return markup.fg.color(...) + end, +}) diff --git a/awesome/lain/util/menu_iterator.lua b/awesome/lain/util/menu_iterator.lua index d457473..104544f 100644 --- a/awesome/lain/util/menu_iterator.lua +++ b/awesome/lain/util/menu_iterator.lua @@ -10,28 +10,30 @@ -- Menu iterator with Naughty notifications -- lain.util.menu_iterator -local naughty = require("naughty") -local helpers = require("lain.helpers") -local atable = require("awful.util").table -local assert = assert -local pairs = pairs +local naughty = require('naughty') +local helpers = require('lain.helpers') +local atable = require('awful.util').table +local assert = assert +local pairs = pairs local tconcat = table.concat local unpack = unpack or table.unpack -- lua 5.1 retro-compatibility local state = { cid = nil } local function naughty_destroy_callback(reason) - local closed = naughty.notificationClosedReason - if reason == closed.expired or reason == closed.dismissedByUser then - local actions = state.index and state.menu[state.index - 1][2] - if actions then - for _,action in pairs(actions) do - -- don't try to call nil callbacks - if action then action() end - end - state.index = nil - end - end + local closed = naughty.notificationClosedReason + if reason == closed.expired or reason == closed.dismissedByUser then + local actions = state.index and state.menu[state.index - 1][2] + if actions then + for _, action in pairs(actions) do + -- don't try to call nil callbacks + if action then + action() + end + end + state.index = nil + end + end end -- Iterates over a menu. @@ -41,35 +43,35 @@ end -- * timeout: time to wait before confirming the menu selection -- * icon: icon to display in the notification of the chosen label local function iterate(menu, timeout, icon) - timeout = timeout or 4 -- default timeout for each menu entry - icon = icon or nil -- icon to display on the menu + timeout = timeout or 4 -- default timeout for each menu entry + icon = icon or nil -- icon to display on the menu - -- Build the list of choices - if not state.index then - state.menu = menu - state.index = 1 - end + -- Build the list of choices + if not state.index then + state.menu = menu + state.index = 1 + end - -- Select one and display the appropriate notification - local label - local next = state.menu[state.index] - state.index = state.index + 1 + -- Select one and display the appropriate notification + local label + local next = state.menu[state.index] + state.index = state.index + 1 - if not next then - label = "Cancel" - state.index = nil - else - label, _ = unpack(next) - end + if not next then + label = 'Cancel' + state.index = nil + else + label, _ = unpack(next) + end - state.cid = naughty.notify({ - text = label, - icon = icon, - timeout = timeout, - screen = mouse.screen, - replaces_id = state.cid, - destroy = naughty_destroy_callback - }).id + state.cid = naughty.notify({ + text = label, + icon = icon, + timeout = timeout, + screen = mouse.screen, + replaces_id = state.cid, + destroy = naughty_destroy_callback, + }).id end -- Generates a menu compatible with the first argument of `iterate` function and @@ -95,50 +97,55 @@ end -- Output: -- * m: menu to be iterated over. local function menu(args) - local choices = assert(args.choices or args[1]) - local name = assert(args.name or args[2]) - local selected_cb = args.selected_cb - local rejected_cb = args.rejected_cb - local extra_choices = args.extra_choices or {} + local choices = assert(args.choices or args[1]) + local name = assert(args.name or args[2]) + local selected_cb = args.selected_cb + local rejected_cb = args.rejected_cb + local extra_choices = args.extra_choices or {} - local ch_combinations = args.combination == "powerset" and helpers.powerset(choices) or helpers.trivial_partition_set(choices) + local ch_combinations = args.combination == 'powerset' and helpers.powerset(choices) + or helpers.trivial_partition_set(choices) - for _, c in pairs(extra_choices) do - ch_combinations = atable.join(ch_combinations, {{c[1]}}) - end + for _, c in pairs(extra_choices) do + ch_combinations = atable.join(ch_combinations, { { c[1] } }) + end - local m = {} -- the menu + local m = {} -- the menu - for _,c in pairs(ch_combinations) do - if #c > 0 then - local cbs = {} + for _, c in pairs(ch_combinations) do + if #c > 0 then + local cbs = {} - -- selected choices - for _,ch in pairs(c) do - if atable.hasitem(choices, ch) then - cbs[#cbs + 1] = selected_cb and function() selected_cb(ch) end or nil - end - end + -- selected choices + for _, ch in pairs(c) do + if atable.hasitem(choices, ch) then + cbs[#cbs + 1] = selected_cb and function() + selected_cb(ch) + end or nil + end + end - -- rejected choices - for _,ch in pairs(choices) do - if not atable.hasitem(c, ch) and atable.hasitem(choices, ch) then - cbs[#cbs + 1] = rejected_cb and function() rejected_cb(ch) end or nil - end - end + -- rejected choices + for _, ch in pairs(choices) do + if not atable.hasitem(c, ch) and atable.hasitem(choices, ch) then + cbs[#cbs + 1] = rejected_cb and function() + rejected_cb(ch) + end or nil + end + end - -- add user extra choices (like the choice "None" for example) - for _,x in pairs(extra_choices) do - if x[1] == c[1] then - cbs[#cbs + 1] = x[2] - end - end + -- add user extra choices (like the choice "None" for example) + for _, x in pairs(extra_choices) do + if x[1] == c[1] then + cbs[#cbs + 1] = x[2] + end + end - m[#m + 1] = { name .. ": " .. tconcat(c, " + "), cbs } - end - end + m[#m + 1] = { name .. ': ' .. tconcat(c, ' + '), cbs } + end + end - return m + return m end return { iterate = iterate, menu = menu } diff --git a/awesome/lain/util/quake.lua b/awesome/lain/util/quake.lua index 8bc68a7..0fbd748 100644 --- a/awesome/lain/util/quake.lua +++ b/awesome/lain/util/quake.lua @@ -6,12 +6,12 @@ --]] -local awful = require("awful") -local capi = { client = client } -local math = math -local string = string -local pairs = pairs -local screen = screen +local awful = require('awful') +local capi = { client = client } +local math = math +local string = string +local pairs = pairs +local screen = screen local setmetatable = setmetatable -- Quake-like Dropdown application spawn @@ -22,158 +22,182 @@ local quake = {} -- run into problems with focus. function quake:display() - if self.followtag then self.screen = awful.screen.focused() end + if self.followtag then + self.screen = awful.screen.focused() + end - -- First, we locate the client - local client = nil - local i = 0 - for c in awful.client.iterate(function (c) - -- c.name may be changed! - return c.instance == self.name - end) - do - i = i + 1 - if i == 1 then - client = c - else - -- Additional matching clients, let's remove the sticky bit - -- which may persist between awesome restarts. We don't close - -- them as they may be valuable. They will just turn into - -- normal clients. - c.sticky = false - c.ontop = false - c.above = false - end - end + -- First, we locate the client + local client = nil + local i = 0 + for c in + awful.client.iterate(function(c) + -- c.name may be changed! + return c.instance == self.name + end) + do + i = i + 1 + if i == 1 then + client = c + else + -- Additional matching clients, let's remove the sticky bit + -- which may persist between awesome restarts. We don't close + -- them as they may be valuable. They will just turn into + -- normal clients. + c.sticky = false + c.ontop = false + c.above = false + end + end - if not client and not self.visible then return end + if not client and not self.visible then + return + end - if not client then - -- The client does not exist, we spawn it - local cmd = string.format("%s %s %s", self.app, - string.format(self.argname, self.name), self.extra) - awful.spawn(cmd, { tag = self.screen.selected_tag }) - return - end + if not client then + -- The client does not exist, we spawn it + local cmd = string.format('%s %s %s', self.app, string.format(self.argname, self.name), self.extra) + awful.spawn(cmd, { tag = self.screen.selected_tag }) + return + end - -- Set geometry - client.floating = true - client.border_width = self.border - client.size_hints_honor = false - local maximized = client.maximized - local fullscreen = client.fullscreen - client:geometry(self.geometry[self.screen.index] or self:compute_size()) + -- Set geometry + client.floating = true + client.border_width = self.border + client.size_hints_honor = false + local maximized = client.maximized + local fullscreen = client.fullscreen + client:geometry(self.geometry[self.screen.index] or self:compute_size()) - -- Set not sticky and on top - client.sticky = false - client.ontop = true - client.above = true - client.skip_taskbar = true + -- Set not sticky and on top + client.sticky = false + client.ontop = true + client.above = true + client.skip_taskbar = true - -- Additional user settings - if self.settings then self.settings(client) end + -- Additional user settings + if self.settings then + self.settings(client) + end - -- Toggle display - if self.visible then - client.hidden = false - client.maximized = self.maximized - client.fullscreen = self.fullscreen - client:raise() - self.last_tag = self.screen.selected_tag - client:tags({self.screen.selected_tag}) - capi.client.focus = client - else - self.maximized = maximized - self.fullscreen = fullscreen - client.maximized = false - client.fullscreen = false - client.hidden = true - local ctags = client:tags() - for j, _ in pairs(ctags) do - ctags[j] = nil - end - client:tags(ctags) - end + -- Toggle display + if self.visible then + client.hidden = false + client.maximized = self.maximized + client.fullscreen = self.fullscreen + client:raise() + self.last_tag = self.screen.selected_tag + client:tags({ self.screen.selected_tag }) + capi.client.focus = client + else + self.maximized = maximized + self.fullscreen = fullscreen + client.maximized = false + client.fullscreen = false + client.hidden = true + local ctags = client:tags() + for j, _ in pairs(ctags) do + ctags[j] = nil + end + client:tags(ctags) + end - return client + return client end function quake:compute_size() - -- skip if we already have a geometry for this screen - if not self.geometry[self.screen.index] then - local geom - if not self.overlap then - geom = screen[self.screen.index].workarea - else - geom = screen[self.screen.index].geometry - end - local width, height = self.width, self.height - if width <= 1 then width = math.floor(geom.width * width) - 2 * self.border end - if height <= 1 then height = math.floor(geom.height * height) end - local x, y - if self.horiz == "left" then x = geom.x - elseif self.horiz == "right" then x = geom.width + geom.x - width - else x = geom.x + (geom.width - width)/2 end - if self.vert == "top" then y = geom.y - elseif self.vert == "bottom" then y = geom.height + geom.y - height - else y = geom.y + (geom.height - height)/2 end - self.geometry[self.screen.index] = { x = x, y = y, width = width, height = height } - end - return self.geometry[self.screen.index] + -- skip if we already have a geometry for this screen + if not self.geometry[self.screen.index] then + local geom + if not self.overlap then + geom = screen[self.screen.index].workarea + else + geom = screen[self.screen.index].geometry + end + local width, height = self.width, self.height + if width <= 1 then + width = math.floor(geom.width * width) - 2 * self.border + end + if height <= 1 then + height = math.floor(geom.height * height) + end + local x, y + if self.horiz == 'left' then + x = geom.x + elseif self.horiz == 'right' then + x = geom.width + geom.x - width + else + x = geom.x + (geom.width - width) / 2 + end + if self.vert == 'top' then + y = geom.y + elseif self.vert == 'bottom' then + y = geom.height + geom.y - height + else + y = geom.y + (geom.height - height) / 2 + end + self.geometry[self.screen.index] = { x = x, y = y, width = width, height = height } + end + return self.geometry[self.screen.index] end function quake:toggle() - if self.followtag then self.screen = awful.screen.focused() end - local current_tag = self.screen.selected_tag - if current_tag and self.last_tag ~= current_tag and self.visible then - local c=self:display() - if c then - c:move_to_tag(current_tag) - end - else - self.visible = not self.visible - self:display() - end + if self.followtag then + self.screen = awful.screen.focused() + end + local current_tag = self.screen.selected_tag + if current_tag and self.last_tag ~= current_tag and self.visible then + local c = self:display() + if c then + c:move_to_tag(current_tag) + end + else + self.visible = not self.visible + self:display() + end end function quake.new(conf) - conf = conf or {} + conf = conf or {} - conf.app = conf.app or "xterm" -- application to spawn - conf.name = conf.name or "QuakeDD" -- window name - conf.argname = conf.argname or "-name %s" -- how to specify window name - conf.extra = conf.extra or "" -- extra arguments - conf.border = conf.border or 1 -- client border width - conf.visible = conf.visible or false -- initially not visible - conf.followtag = conf.followtag or false -- spawn on currently focused screen - conf.overlap = conf.overlap or false -- overlap wibox - conf.screen = conf.screen or awful.screen.focused() - conf.settings = conf.settings + conf.app = conf.app or 'xterm' -- application to spawn + conf.name = conf.name or 'QuakeDD' -- window name + conf.argname = conf.argname or '-name %s' -- how to specify window name + conf.extra = conf.extra or '' -- extra arguments + conf.border = conf.border or 1 -- client border width + conf.visible = conf.visible or false -- initially not visible + conf.followtag = conf.followtag or false -- spawn on currently focused screen + conf.overlap = conf.overlap or false -- overlap wibox + conf.screen = conf.screen or awful.screen.focused() + conf.settings = conf.settings - -- If width or height <= 1 this is a proportion of the workspace - conf.height = conf.height or 0.25 -- height - conf.width = conf.width or 1 -- width - conf.vert = conf.vert or "top" -- top, bottom or center - conf.horiz = conf.horiz or "left" -- left, right or center - conf.geometry = {} -- internal use + -- If width or height <= 1 this is a proportion of the workspace + conf.height = conf.height or 0.25 -- height + conf.width = conf.width or 1 -- width + conf.vert = conf.vert or 'top' -- top, bottom or center + conf.horiz = conf.horiz or 'left' -- left, right or center + conf.geometry = {} -- internal use - conf.maximized = false - conf.fullscreen = false + conf.maximized = false + conf.fullscreen = false - local dropdown = setmetatable(conf, { __index = quake }) + local dropdown = setmetatable(conf, { __index = quake }) - capi.client.connect_signal("manage", function(c) - if c.instance == dropdown.name and c.screen == dropdown.screen then - dropdown:display() - end - end) - capi.client.connect_signal("unmanage", function(c) - if c.instance == dropdown.name and c.screen == dropdown.screen then - dropdown.visible = false - end - end) + capi.client.connect_signal('manage', function(c) + if c.instance == dropdown.name and c.screen == dropdown.screen then + dropdown:display() + end + end) + capi.client.connect_signal('unmanage', function(c) + if c.instance == dropdown.name and c.screen == dropdown.screen then + dropdown.visible = false + end + end) - return dropdown + return dropdown end -return setmetatable(quake, { __call = function(_, ...) return quake.new(...) end }) +return setmetatable(quake, { + __call = function(_, ...) + return quake.new(...) + end, +}) diff --git a/awesome/lain/util/separators.lua b/awesome/lain/util/separators.lua index 04402bb..9b5675b 100644 --- a/awesome/lain/util/separators.lua +++ b/awesome/lain/util/separators.lua @@ -6,9 +6,9 @@ --]] -local wibox = require("wibox") -local gears = require("gears") -local beautiful = require("beautiful") +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') -- Lain Cairo separators util submodule -- lain.util.separators @@ -18,99 +18,99 @@ local separators = { height = beautiful.separators_height or 0, width = beautifu -- Right function separators.arrow_right(col1, col2) - local widget = wibox.widget.base.make_widget() - widget.col1 = col1 - widget.col2 = col2 + local widget = wibox.widget.base.make_widget() + widget.col1 = col1 + widget.col2 = col2 - widget.fit = function(_, _, _) - return separators.width, separators.height - end + widget.fit = function(_, _, _) + return separators.width, separators.height + end - widget.update = function(_, _) - widget.col1 = col1 - widget.col2 = col2 - widget:emit_signal("widget::redraw_needed") - end + widget.update = function(_, _) + widget.col1 = col1 + widget.col2 = col2 + widget:emit_signal('widget::redraw_needed') + end - widget.draw = function(_, _, cr, width, height) - if widget.col2 ~= "alpha" then - cr:set_source_rgba(gears.color.parse_color(widget.col2)) - cr:new_path() - cr:move_to(0, 0) - cr:line_to(width, height/2) - cr:line_to(width, 0) - cr:close_path() - cr:fill() + widget.draw = function(_, _, cr, width, height) + if widget.col2 ~= 'alpha' then + cr:set_source_rgba(gears.color.parse_color(widget.col2)) + cr:new_path() + cr:move_to(0, 0) + cr:line_to(width, height / 2) + cr:line_to(width, 0) + cr:close_path() + cr:fill() - cr:new_path() - cr:move_to(0, height) - cr:line_to(width, height/2) - cr:line_to(width, height) - cr:close_path() - cr:fill() - end + cr:new_path() + cr:move_to(0, height) + cr:line_to(width, height / 2) + cr:line_to(width, height) + cr:close_path() + cr:fill() + end - if widget.col1 ~= "alpha" then - cr:set_source_rgba(gears.color.parse_color(widget.col1)) - cr:new_path() - cr:move_to(0, 0) - cr:line_to(width, height/2) - cr:line_to(0, height) - cr:close_path() - cr:fill() - end - end + if widget.col1 ~= 'alpha' then + cr:set_source_rgba(gears.color.parse_color(widget.col1)) + cr:new_path() + cr:move_to(0, 0) + cr:line_to(width, height / 2) + cr:line_to(0, height) + cr:close_path() + cr:fill() + end + end - return widget + return widget end -- Left function separators.arrow_left(col1, col2) - local widget = wibox.widget.base.make_widget() - widget.col1 = col1 - widget.col2 = col2 + local widget = wibox.widget.base.make_widget() + widget.col1 = col1 + widget.col2 = col2 - widget.fit = function(_, _, _) - return separators.width, separators.height - end + widget.fit = function(_, _, _) + return separators.width, separators.height + end - widget.update = function(c1, c2) - widget.col1 = c1 - widget.col2 = c2 - widget:emit_signal("widget::redraw_needed") - end + widget.update = function(c1, c2) + widget.col1 = c1 + widget.col2 = c2 + widget:emit_signal('widget::redraw_needed') + end - widget.draw = function(_, _, cr, width, height) - if widget.col1 ~= "alpha" then - cr:set_source_rgba(gears.color.parse_color(widget.col1)) - cr:new_path() - cr:move_to(width, 0) - cr:line_to(0, height/2) - cr:line_to(0, 0) - cr:close_path() - cr:fill() + widget.draw = function(_, _, cr, width, height) + if widget.col1 ~= 'alpha' then + cr:set_source_rgba(gears.color.parse_color(widget.col1)) + cr:new_path() + cr:move_to(width, 0) + cr:line_to(0, height / 2) + cr:line_to(0, 0) + cr:close_path() + cr:fill() - cr:new_path() - cr:move_to(width, height) - cr:line_to(0, height/2) - cr:line_to(0, height) - cr:close_path() - cr:fill() - end + cr:new_path() + cr:move_to(width, height) + cr:line_to(0, height / 2) + cr:line_to(0, height) + cr:close_path() + cr:fill() + end - if widget.col2 ~= "alpha" then - cr:new_path() - cr:move_to(width, 0) - cr:line_to(0, height/2) - cr:line_to(width, height) - cr:close_path() + if widget.col2 ~= 'alpha' then + cr:new_path() + cr:move_to(width, 0) + cr:line_to(0, height / 2) + cr:line_to(width, height) + cr:close_path() - cr:set_source_rgba(gears.color.parse_color(widget.col2)) - cr:fill() - end - end + cr:set_source_rgba(gears.color.parse_color(widget.col2)) + cr:fill() + end + end - return widget + return widget end -- ]] diff --git a/awesome/lain/widget/alsa.lua b/awesome/lain/widget/alsa.lua index 202dc98..d8fca56 100644 --- a/awesome/lain/widget/alsa.lua +++ b/awesome/lain/widget/alsa.lua @@ -6,49 +6,52 @@ --]] -local helpers = require("lain.helpers") -local shell = require("awful.util").shell -local wibox = require("wibox") -local string = string +local helpers = require('lain.helpers') +local shell = require('awful.util').shell +local wibox = require('wibox') +local string = string -- ALSA volume -- lain.widget.alsa local function factory(args) - args = args or {} - local alsa = { widget = args.widget or wibox.widget.textbox() } - local timeout = args.timeout or 5 - local settings = args.settings or function() end + args = args or {} + local alsa = { widget = args.widget or wibox.widget.textbox() } + local timeout = args.timeout or 5 + local settings = args.settings or function() end - alsa.cmd = args.cmd or "amixer" - alsa.channel = args.channel or "Master" - alsa.togglechannel = args.togglechannel + alsa.cmd = args.cmd or 'amixer' + alsa.channel = args.channel or 'Master' + alsa.togglechannel = args.togglechannel - local format_cmd = string.format("%s get %s", alsa.cmd, alsa.channel) + local format_cmd = string.format('%s get %s', alsa.cmd, alsa.channel) - if alsa.togglechannel then - format_cmd = { shell, "-c", string.format("%s get %s; %s get %s", - alsa.cmd, alsa.channel, alsa.cmd, alsa.togglechannel) } - end + if alsa.togglechannel then + format_cmd = { + shell, + '-c', + string.format('%s get %s; %s get %s', alsa.cmd, alsa.channel, alsa.cmd, alsa.togglechannel), + } + end - alsa.last = {} + alsa.last = {} - function alsa.update() - helpers.async(format_cmd, function(mixer) - local l,s = string.match(mixer, "([%d]+)%%.*%[([%l]*)") - l = tonumber(l) - if alsa.last.level ~= l or alsa.last.status ~= s then - volume_now = { level = l, status = s } - widget = alsa.widget - settings() - alsa.last = volume_now - end - end) - end + function alsa.update() + helpers.async(format_cmd, function(mixer) + local l, s = string.match(mixer, '([%d]+)%%.*%[([%l]*)') + l = tonumber(l) + if alsa.last.level ~= l or alsa.last.status ~= s then + volume_now = { level = l, status = s } + widget = alsa.widget + settings() + alsa.last = volume_now + end + end) + end - helpers.newtimer(string.format("alsa-%s-%s", alsa.cmd, alsa.channel), timeout, alsa.update) + helpers.newtimer(string.format('alsa-%s-%s', alsa.cmd, alsa.channel), timeout, alsa.update) - return alsa + return alsa end return factory diff --git a/awesome/lain/widget/alsabar.lua b/awesome/lain/widget/alsabar.lua index 8e8cd3a..fbbd3ab 100644 --- a/awesome/lain/widget/alsabar.lua +++ b/awesome/lain/widget/alsabar.lua @@ -6,161 +6,167 @@ --]] -local helpers = require("lain.helpers") -local awful = require("awful") -local naughty = require("naughty") -local wibox = require("wibox") -local math = math -local string = string -local type = type +local helpers = require('lain.helpers') +local awful = require('awful') +local naughty = require('naughty') +local wibox = require('wibox') +local math = math +local string = string +local type = type local tonumber = tonumber -- ALSA volume bar -- lain.widget.alsabar local function factory(args) - local alsabar = { - colors = { - background = "#000000", - mute = "#EB8F8F", - unmute = "#A4CE8A" - }, + local alsabar = { + colors = { + background = '#000000', + mute = '#EB8F8F', + unmute = '#A4CE8A', + }, - _current_level = 0, - _playback = "off" - } + _current_level = 0, + _playback = 'off', + } - args = args or {} + args = args or {} - local timeout = args.timeout or 5 - local settings = args.settings or function() end - local width = args.width or 63 - local height = args.height or 1 - local margins = args.margins or 1 - local ticks = args.ticks or false - local ticks_size = args.ticks_size or 7 - local tick = args.tick or "|" - local tick_pre = args.tick_pre or "[" - local tick_post = args.tick_post or "]" - local tick_none = args.tick_none or " " + local timeout = args.timeout or 5 + local settings = args.settings or function() end + local width = args.width or 63 + local height = args.height or 1 + local margins = args.margins or 1 + local ticks = args.ticks or false + local ticks_size = args.ticks_size or 7 + local tick = args.tick or '|' + local tick_pre = args.tick_pre or '[' + local tick_post = args.tick_post or ']' + local tick_none = args.tick_none or ' ' - alsabar.cmd = args.cmd or "amixer" - alsabar.channel = args.channel or "Master" - alsabar.togglechannel = args.togglechannel - alsabar.colors = args.colors or alsabar.colors - alsabar.followtag = args.followtag or false - alsabar.notification_preset = args.notification_preset + alsabar.cmd = args.cmd or 'amixer' + alsabar.channel = args.channel or 'Master' + alsabar.togglechannel = args.togglechannel + alsabar.colors = args.colors or alsabar.colors + alsabar.followtag = args.followtag or false + alsabar.notification_preset = args.notification_preset - if not alsabar.notification_preset then - alsabar.notification_preset = { font = "Monospace 10" } - end + if not alsabar.notification_preset then + alsabar.notification_preset = { font = 'Monospace 10' } + end - local format_cmd = string.format("%s get %s", alsabar.cmd, alsabar.channel) + local format_cmd = string.format('%s get %s', alsabar.cmd, alsabar.channel) - if alsabar.togglechannel then - format_cmd = { awful.util.shell, "-c", string.format("%s get %s; %s get %s", - alsabar.cmd, alsabar.channel, alsabar.cmd, alsabar.togglechannel) } - end + if alsabar.togglechannel then + format_cmd = { + awful.util.shell, + '-c', + string.format('%s get %s; %s get %s', alsabar.cmd, alsabar.channel, alsabar.cmd, alsabar.togglechannel), + } + end - alsabar.bar = wibox.widget { - color = alsabar.colors.unmute, - background_color = alsabar.colors.background, - forced_height = height, - forced_width = width, - margins = margins, - paddings = margins, - ticks = ticks, - ticks_size = ticks_size, - widget = wibox.widget.progressbar - } + alsabar.bar = wibox.widget({ + color = alsabar.colors.unmute, + background_color = alsabar.colors.background, + forced_height = height, + forced_width = width, + margins = margins, + paddings = margins, + ticks = ticks, + ticks_size = ticks_size, + widget = wibox.widget.progressbar, + }) - alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } }) + alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } }) - function alsabar.update(callback) - helpers.async(format_cmd, function(mixer) - local vol, playback = string.match(mixer, "([%d]+)%%.*%[([%l]*)") + function alsabar.update(callback) + helpers.async(format_cmd, function(mixer) + local vol, playback = string.match(mixer, '([%d]+)%%.*%[([%l]*)') - if not vol or not playback then return end + if not vol or not playback then + return + end - if vol ~= alsabar._current_level or playback ~= alsabar._playback then - alsabar._current_level = tonumber(vol) - alsabar.bar:set_value(alsabar._current_level / 100) - if alsabar._current_level == 0 or playback == "off" then - alsabar._playback = playback - alsabar.tooltip:set_text("[Muted]") - alsabar.bar.color = alsabar.colors.mute - else - alsabar._playback = "on" - alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, vol)) - alsabar.bar.color = alsabar.colors.unmute - end + if vol ~= alsabar._current_level or playback ~= alsabar._playback then + alsabar._current_level = tonumber(vol) + alsabar.bar:set_value(alsabar._current_level / 100) + if alsabar._current_level == 0 or playback == 'off' then + alsabar._playback = playback + alsabar.tooltip:set_text('[Muted]') + alsabar.bar.color = alsabar.colors.mute + else + alsabar._playback = 'on' + alsabar.tooltip:set_text(string.format('%s: %s', alsabar.channel, vol)) + alsabar.bar.color = alsabar.colors.unmute + end - volume_now = { - level = alsabar._current_level, - status = alsabar._playback - } + volume_now = { + level = alsabar._current_level, + status = alsabar._playback, + } - settings() + settings() - if type(callback) == "function" then callback() end - end - end) - end + if type(callback) == 'function' then + callback() + end + end + end) + end - function alsabar.notify() - alsabar.update(function() - local preset = alsabar.notification_preset + function alsabar.notify() + alsabar.update(function() + local preset = alsabar.notification_preset - preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level) + preset.title = string.format('%s - %s%%', alsabar.channel, alsabar._current_level) - if alsabar._playback == "off" then - preset.title = preset.title .. " Muted" - end + if alsabar._playback == 'off' then + preset.title = preset.title .. ' Muted' + end - -- tot is the maximum number of ticks to display in the notification - local tot = alsabar.notification_preset.max_ticks + -- tot is the maximum number of ticks to display in the notification + local tot = alsabar.notification_preset.max_ticks - if not tot then - local wib = awful.screen.focused().mywibox - -- if we can grab mywibox, tot is defined as its height if - -- horizontal, or width otherwise - if wib then - if wib.position == "left" or wib.position == "right" then - tot = wib.width - else - tot = wib.height - end - -- fallback: default horizontal wibox height - else - tot = 20 - end - end + if not tot then + local wib = awful.screen.focused().mywibox + -- if we can grab mywibox, tot is defined as its height if + -- horizontal, or width otherwise + if wib then + if wib.position == 'left' or wib.position == 'right' then + tot = wib.width + else + tot = wib.height + end + -- fallback: default horizontal wibox height + else + tot = 20 + end + end - local int = math.modf((alsabar._current_level / 100) * tot) - preset.text = string.format( - "%s%s%s%s", - tick_pre, - string.rep(tick, int), - string.rep(tick_none, tot - int), - tick_post - ) + local int = math.modf((alsabar._current_level / 100) * tot) + preset.text = + string.format('%s%s%s%s', tick_pre, string.rep(tick, int), string.rep(tick_none, tot - int), tick_post) - if alsabar.followtag then preset.screen = awful.screen.focused() end + if alsabar.followtag then + preset.screen = awful.screen.focused() + end - if not alsabar.notification then - alsabar.notification = naughty.notify { - preset = preset, - destroy = function() alsabar.notification = nil end - } - else - naughty.replace_text(alsabar.notification, preset.title, preset.text) - end - end) - end + if not alsabar.notification then + alsabar.notification = naughty.notify({ + preset = preset, + destroy = function() + alsabar.notification = nil + end, + }) + else + naughty.replace_text(alsabar.notification, preset.title, preset.text) + end + end) + end - helpers.newtimer(string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel), timeout, alsabar.update) + helpers.newtimer(string.format('alsabar-%s-%s', alsabar.cmd, alsabar.channel), timeout, alsabar.update) - return alsabar + return alsabar end return factory diff --git a/awesome/lain/widget/bat.lua b/awesome/lain/widget/bat.lua index 260f4b9..bed1570 100644 --- a/awesome/lain/widget/bat.lua +++ b/awesome/lain/widget/bat.lua @@ -6,231 +6,232 @@ --]] -local helpers = require("lain.helpers") -local fs = require("gears.filesystem") -local naughty = require("naughty") -local wibox = require("wibox") -local math = math -local string = string -local ipairs = ipairs +local helpers = require('lain.helpers') +local fs = require('gears.filesystem') +local naughty = require('naughty') +local wibox = require('wibox') +local math = math +local string = string +local ipairs = ipairs local tonumber = tonumber -- Battery infos -- lain.widget.bat local function factory(args) - local pspath = args.pspath or "/sys/class/power_supply/" + local pspath = args.pspath or '/sys/class/power_supply/' - if not fs.is_dir(pspath) then - naughty.notify { text = "lain.widget.bat: invalid power supply path", timeout = 0 } - return - end + if not fs.is_dir(pspath) then + naughty.notify({ text = 'lain.widget.bat: invalid power supply path', timeout = 0 }) + return + end - args = args or {} + args = args or {} - local bat = { widget = args.widget or wibox.widget.textbox() } - local timeout = args.timeout or 30 - local notify = args.notify or "on" - local full_notify = args.full_notify or notify - local n_perc = args.n_perc or { 5, 15 } - local batteries = args.batteries or (args.battery and {args.battery}) or {} - local ac = args.ac or "AC0" - local settings = args.settings or function() end + local bat = { widget = args.widget or wibox.widget.textbox() } + local timeout = args.timeout or 30 + local notify = args.notify or 'on' + local full_notify = args.full_notify or notify + local n_perc = args.n_perc or { 5, 15 } + local batteries = args.batteries or (args.battery and { args.battery }) or {} + local ac = args.ac or 'AC0' + local settings = args.settings or function() end - function bat.get_batteries() - helpers.line_callback("ls -1 " .. pspath, function(line) - local bstr = string.match(line, "BAT%w+") - if bstr then - batteries[#batteries + 1] = bstr - else - ac = string.match(line, "A%w+") or ac - end - end) - end + function bat.get_batteries() + helpers.line_callback('ls -1 ' .. pspath, function(line) + local bstr = string.match(line, 'BAT%w+') + if bstr then + batteries[#batteries + 1] = bstr + else + ac = string.match(line, 'A%w+') or ac + end + end) + end - if #batteries == 0 then bat.get_batteries() end + if #batteries == 0 then + bat.get_batteries() + end - bat_notification_critical_preset = { - title = "Battery exhausted", - text = "Shutdown imminent", - timeout = 15, - fg = "#000000", - bg = "#FFFFFF" - } + bat_notification_critical_preset = { + title = 'Battery exhausted', + text = 'Shutdown imminent', + timeout = 15, + fg = '#000000', + bg = '#FFFFFF', + } - bat_notification_low_preset = { - title = "Battery low", - text = "Plug the cable!", - timeout = 15, - fg = "#202020", - bg = "#CDCDCD" - } + bat_notification_low_preset = { + title = 'Battery low', + text = 'Plug the cable!', + timeout = 15, + fg = '#202020', + bg = '#CDCDCD', + } - bat_notification_charged_preset = { - title = "Battery full", - text = "You can unplug the cable", - timeout = 15, - fg = "#202020", - bg = "#CDCDCD" - } + bat_notification_charged_preset = { + title = 'Battery full', + text = 'You can unplug the cable', + timeout = 15, + fg = '#202020', + bg = '#CDCDCD', + } - bat_now = { - status = "N/A", - ac_status = "N/A", - perc = "N/A", - time = "N/A", - watt = "N/A", - capacity = "N/A" - } + bat_now = { + status = 'N/A', + ac_status = 'N/A', + perc = 'N/A', + time = 'N/A', + watt = 'N/A', + capacity = 'N/A', + } - bat_now.n_status = {} - bat_now.n_perc = {} - bat_now.n_capacity = {} - for i = 1, #batteries do - bat_now.n_status[i] = "N/A" - bat_now.n_perc[i] = 0 - bat_now.n_capacity[i] = 0 - end + bat_now.n_status = {} + bat_now.n_perc = {} + bat_now.n_capacity = {} + for i = 1, #batteries do + bat_now.n_status[i] = 'N/A' + bat_now.n_perc[i] = 0 + bat_now.n_capacity[i] = 0 + end - -- used to notify full charge only once before discharging - local fullnotification = false + -- used to notify full charge only once before discharging + local fullnotification = false - function bat.update() - -- luacheck: globals bat_now - local sum_rate_current = 0 - local sum_rate_voltage = 0 - local sum_rate_power = 0 - local sum_rate_energy = 0 - local sum_energy_now = 0 - local sum_energy_full = 0 - local sum_charge_full = 0 - local sum_charge_design = 0 + function bat.update() + -- luacheck: globals bat_now + local sum_rate_current = 0 + local sum_rate_voltage = 0 + local sum_rate_power = 0 + local sum_rate_energy = 0 + local sum_energy_now = 0 + local sum_energy_full = 0 + local sum_charge_full = 0 + local sum_charge_design = 0 - for i, battery in ipairs(batteries) do - local bstr = pspath .. battery - local present = helpers.first_line(bstr .. "/present") + for i, battery in ipairs(batteries) do + local bstr = pspath .. battery + local present = helpers.first_line(bstr .. '/present') - if tonumber(present) == 1 then - -- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW] - local rate_current = tonumber(helpers.first_line(bstr .. "/current_now")) - local rate_voltage = tonumber(helpers.first_line(bstr .. "/voltage_now")) - local rate_power = tonumber(helpers.first_line(bstr .. "/power_now")) - local charge_full = tonumber(helpers.first_line(bstr .. "/charge_full")) - local charge_design = tonumber(helpers.first_line(bstr .. "/charge_full_design")) + if tonumber(present) == 1 then + -- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW] + local rate_current = tonumber(helpers.first_line(bstr .. '/current_now')) + local rate_voltage = tonumber(helpers.first_line(bstr .. '/voltage_now')) + local rate_power = tonumber(helpers.first_line(bstr .. '/power_now')) + local charge_full = tonumber(helpers.first_line(bstr .. '/charge_full')) + local charge_design = tonumber(helpers.first_line(bstr .. '/charge_full_design')) - -- energy_now(P)[uWh], charge_now(I)[uAh] - local energy_now = tonumber(helpers.first_line(bstr .. "/energy_now") or - helpers.first_line(bstr .. "/charge_now")) + -- energy_now(P)[uWh], charge_now(I)[uAh] + local energy_now = + tonumber(helpers.first_line(bstr .. '/energy_now') or helpers.first_line(bstr .. '/charge_now')) - -- energy_full(P)[uWh], charge_full(I)[uAh] - local energy_full = tonumber(helpers.first_line(bstr .. "/energy_full") or - charge_full) + -- energy_full(P)[uWh], charge_full(I)[uAh] + local energy_full = tonumber(helpers.first_line(bstr .. '/energy_full') or charge_full) - local energy_percentage = tonumber(helpers.first_line(bstr .. "/capacity")) or - math.floor((energy_now / energy_full) * 100) + local energy_percentage = tonumber(helpers.first_line(bstr .. '/capacity')) + or math.floor((energy_now / energy_full) * 100) - bat_now.n_status[i] = helpers.first_line(bstr .. "/status") or "N/A" - bat_now.n_perc[i] = energy_percentage or bat_now.n_perc[i] + bat_now.n_status[i] = helpers.first_line(bstr .. '/status') or 'N/A' + bat_now.n_perc[i] = energy_percentage or bat_now.n_perc[i] - if not charge_design or charge_design == 0 then - bat_now.n_capacity[i] = 0 - else - bat_now.n_capacity[i] = math.floor((charge_full / charge_design) * 100) - end + if not charge_design or charge_design == 0 then + bat_now.n_capacity[i] = 0 + else + bat_now.n_capacity[i] = math.floor((charge_full / charge_design) * 100) + end - sum_rate_current = sum_rate_current + (rate_current or 0) - sum_rate_voltage = sum_rate_voltage + (rate_voltage or 0) - sum_rate_power = sum_rate_power + (rate_power or 0) - sum_rate_energy = sum_rate_energy + (rate_power or (((rate_voltage or 0) * (rate_current or 0)) / 1e6)) - sum_energy_now = sum_energy_now + (energy_now or 0) - sum_energy_full = sum_energy_full + (energy_full or 0) - sum_charge_full = sum_charge_full + (charge_full or 0) - sum_charge_design = sum_charge_design + (charge_design or 0) - end - end + sum_rate_current = sum_rate_current + (rate_current or 0) + sum_rate_voltage = sum_rate_voltage + (rate_voltage or 0) + sum_rate_power = sum_rate_power + (rate_power or 0) + sum_rate_energy = sum_rate_energy + (rate_power or (((rate_voltage or 0) * (rate_current or 0)) / 1e6)) + sum_energy_now = sum_energy_now + (energy_now or 0) + sum_energy_full = sum_energy_full + (energy_full or 0) + sum_charge_full = sum_charge_full + (charge_full or 0) + sum_charge_design = sum_charge_design + (charge_design or 0) + end + end - bat_now.capacity = math.floor(math.min(100, (sum_charge_full / sum_charge_design) * 100)) + bat_now.capacity = math.floor(math.min(100, (sum_charge_full / sum_charge_design) * 100)) - -- When one of the battery is charging, others' status are either - -- "Full", "Unknown" or "Charging". When the laptop is not plugged in, - -- one or more of the batteries may be full, but only one battery - -- discharging suffices to set global status to "Discharging". - bat_now.status = bat_now.n_status[1] or "N/A" - for _,status in ipairs(bat_now.n_status) do - if status == "Discharging" or status == "Charging" then - bat_now.status = status - end - end - bat_now.ac_status = tonumber(helpers.first_line(string.format("%s%s/online", pspath, ac))) or "N/A" + -- When one of the battery is charging, others' status are either + -- "Full", "Unknown" or "Charging". When the laptop is not plugged in, + -- one or more of the batteries may be full, but only one battery + -- discharging suffices to set global status to "Discharging". + bat_now.status = bat_now.n_status[1] or 'N/A' + for _, status in ipairs(bat_now.n_status) do + if status == 'Discharging' or status == 'Charging' then + bat_now.status = status + end + end + bat_now.ac_status = tonumber(helpers.first_line(string.format('%s%s/online', pspath, ac))) or 'N/A' - if bat_now.status ~= "N/A" then - if bat_now.status ~= "Full" and sum_rate_power == 0 and bat_now.ac_status == 1 then - bat_now.perc = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100)) - bat_now.time = "00:00" - bat_now.watt = 0 + if bat_now.status ~= 'N/A' then + if bat_now.status ~= 'Full' and sum_rate_power == 0 and bat_now.ac_status == 1 then + bat_now.perc = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100)) + bat_now.time = '00:00' + bat_now.watt = 0 - -- update {perc,time,watt} iff battery not full and rate > 0 - elseif bat_now.status ~= "Full" then - local rate_time = 0 - -- Calculate time and watt if rates are greater then 0 - if (sum_rate_power > 0 or sum_rate_current > 0) then - local div = (sum_rate_power > 0 and sum_rate_power) or sum_rate_current + -- update {perc,time,watt} iff battery not full and rate > 0 + elseif bat_now.status ~= 'Full' then + local rate_time = 0 + -- Calculate time and watt if rates are greater then 0 + if sum_rate_power > 0 or sum_rate_current > 0 then + local div = (sum_rate_power > 0 and sum_rate_power) or sum_rate_current - if bat_now.status == "Charging" then - rate_time = (sum_energy_full - sum_energy_now) / div - else -- Discharging - rate_time = sum_energy_now / div - end + if bat_now.status == 'Charging' then + rate_time = (sum_energy_full - sum_energy_now) / div + else -- Discharging + rate_time = sum_energy_now / div + end - if 0 < rate_time and rate_time < 0.01 then -- check for magnitude discrepancies (#199) - rate_time_magnitude = math.abs(math.floor(math.log10(rate_time))) - rate_time = rate_time * 10^(rate_time_magnitude - 2) - end - end + if 0 < rate_time and rate_time < 0.01 then -- check for magnitude discrepancies (#199) + rate_time_magnitude = math.abs(math.floor(math.log10(rate_time))) + rate_time = rate_time * 10 ^ (rate_time_magnitude - 2) + end + end - local hours = math.floor(rate_time) - local minutes = math.floor((rate_time - hours) * 60) - bat_now.perc = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100)) - bat_now.time = string.format("%02d:%02d", hours, minutes) - bat_now.watt = tonumber(string.format("%.2f", sum_rate_energy / 1e6)) - elseif bat_now.status == "Full" then - bat_now.perc = 100 - bat_now.time = "00:00" - bat_now.watt = 0 - end - end + local hours = math.floor(rate_time) + local minutes = math.floor((rate_time - hours) * 60) + bat_now.perc = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100)) + bat_now.time = string.format('%02d:%02d', hours, minutes) + bat_now.watt = tonumber(string.format('%.2f', sum_rate_energy / 1e6)) + elseif bat_now.status == 'Full' then + bat_now.perc = 100 + bat_now.time = '00:00' + bat_now.watt = 0 + end + end - widget = bat.widget - settings() + widget = bat.widget + settings() - -- notifications for critical, low, and full levels - if notify == "on" then - if bat_now.status == "Discharging" then - if tonumber(bat_now.perc) <= n_perc[1] then - bat.id = naughty.notify({ - preset = bat_notification_critical_preset, - replaces_id = bat.id - }).id - elseif tonumber(bat_now.perc) <= n_perc[2] then - bat.id = naughty.notify({ - preset = bat_notification_low_preset, - replaces_id = bat.id - }).id - end - fullnotification = false - elseif bat_now.status == "Full" and full_notify == "on" and not fullnotification then - bat.id = naughty.notify({ - preset = bat_notification_charged_preset, - replaces_id = bat.id - }).id - fullnotification = true - end - end - end + -- notifications for critical, low, and full levels + if notify == 'on' then + if bat_now.status == 'Discharging' then + if tonumber(bat_now.perc) <= n_perc[1] then + bat.id = naughty.notify({ + preset = bat_notification_critical_preset, + replaces_id = bat.id, + }).id + elseif tonumber(bat_now.perc) <= n_perc[2] then + bat.id = naughty.notify({ + preset = bat_notification_low_preset, + replaces_id = bat.id, + }).id + end + fullnotification = false + elseif bat_now.status == 'Full' and full_notify == 'on' and not fullnotification then + bat.id = naughty.notify({ + preset = bat_notification_charged_preset, + replaces_id = bat.id, + }).id + fullnotification = true + end + end + end - helpers.newtimer("batteries", timeout, bat.update) + helpers.newtimer('batteries', timeout, bat.update) - return bat + return bat end return factory diff --git a/awesome/lain/widget/cal.lua b/awesome/lain/widget/cal.lua index 97dced8..cb556e5 100644 --- a/awesome/lain/widget/cal.lua +++ b/awesome/lain/widget/cal.lua @@ -5,16 +5,16 @@ --]] -local helpers = require("lain.helpers") -local markup = require("lain.util.markup") -local awful = require("awful") -local naughty = require("naughty") -local floor = math.floor -local os = os -local pairs = pairs -local string = string -local tconcat = table.concat -local type = type +local helpers = require('lain.helpers') +local markup = require('lain.util.markup') +local awful = require('awful') +local naughty = require('naughty') +local floor = math.floor +local os = os +local pairs = pairs +local string = string +local tconcat = table.concat +local type = type local tonumber = tonumber local tostring = tostring @@ -22,170 +22,205 @@ local tostring = tostring -- lain.widget.cal local function factory(args) - args = args or {} - local cal = { - attach_to = args.attach_to or {}, - week_start = args.week_start or 2, - three = args.three or false, - followtag = args.followtag or false, - week_number = args.week_number or "none", - week_number_format = args.week_number_format or args.week_number == "left" and "%3d | " or "| %-3d", - icons = args.icons or helpers.icons_dir .. "cal/white/", - notification_preset = args.notification_preset or { - font = "Monospace 10", fg = "#FFFFFF", bg = "#000000" - } - } + args = args or {} + local cal = { + attach_to = args.attach_to or {}, + week_start = args.week_start or 2, + three = args.three or false, + followtag = args.followtag or false, + week_number = args.week_number or 'none', + week_number_format = args.week_number_format or args.week_number == 'left' and '%3d | ' or '| %-3d', + icons = args.icons or helpers.icons_dir .. 'cal/white/', + notification_preset = args.notification_preset or { + font = 'Monospace 10', + fg = '#FFFFFF', + bg = '#000000', + }, + } - function cal.get_week_number(m, st_day, x) - local date = os.date("*t", m) + function cal.get_week_number(m, st_day, x) + local date = os.date('*t', m) - local week_step = (x ~= 0 and floor((x + st_day) / 7) - 1 or 0); + local week_step = (x ~= 0 and floor((x + st_day) / 7) - 1 or 0) - local display_time = os.time { - year = date.year, month = date.month, day = date.day + 7 * week_step - } + local display_time = os.time({ + year = date.year, + month = date.month, + day = date.day + 7 * week_step, + }) - return string.format(cal.week_number_format, os.date("%V", display_time)) - end + return string.format(cal.week_number_format, os.date('%V', display_time)) + end - function cal.sum_week_days(x, y) - return (x + y) % 7 - end + function cal.sum_week_days(x, y) + return (x + y) % 7 + end - function cal.build(month, year) - local current_month, current_year = tonumber(os.date("%m")), tonumber(os.date("%Y")) - local is_current_month = (not month or not year) or (month == current_month and year == current_year) - local today = is_current_month and tonumber(os.date("%d")) -- otherwise nil and not highlighted - local t = os.time { year = year or current_year, month = month and month+1 or current_month+1, day = 0 } - local d = os.date("*t", t) - local mth_days, st_day, this_month = d.day, (d.wday-d.day-cal.week_start+1)%7, os.date("%B %Y", t) - local notifytable = { [1] = string.format("%s%s\n", string.rep(" ", floor((28 - this_month:len())/2)), markup.bold(this_month)) } - for day_num = 0, 6 do - notifytable[#notifytable+1] = string.format("%3s ", os.date("%a", os.time { year = 2006, month = 1, day = day_num + cal.week_start })) - end - notifytable[#notifytable] = string.format("%s\n%s", notifytable[#notifytable]:sub(1, -2), string.rep(" ", st_day*4)) - local strx - for x = 1,mth_days do - strx = x - if x == today then - if x < 10 then x = " " .. x end - strx = markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. " ") - end - strx = string.format("%s%s", string.rep(" ", 3 - tostring(x):len()), strx) - notifytable[#notifytable+1] = string.format("%-4s%s", strx, (x+st_day)%7==0 and x ~= mth_days and "\n" or "") - end - if string.len(cal.icons or "") > 0 and today then cal.icon = cal.icons .. today .. ".png" end - cal.month, cal.year = d.month, d.year + function cal.build(month, year) + local current_month, current_year = tonumber(os.date('%m')), tonumber(os.date('%Y')) + local is_current_month = (not month or not year) or (month == current_month and year == current_year) + local today = is_current_month and tonumber(os.date('%d')) -- otherwise nil and not highlighted + local t = os.time({ year = year or current_year, month = month and month + 1 or current_month + 1, day = 0 }) + local d = os.date('*t', t) + local mth_days, st_day, this_month = d.day, (d.wday - d.day - cal.week_start + 1) % 7, os.date('%B %Y', t) + local notifytable = { + [1] = string.format('%s%s\n', string.rep(' ', floor((28 - this_month:len()) / 2)), markup.bold(this_month)), + } + for day_num = 0, 6 do + notifytable[#notifytable + 1] = string.format( + '%3s ', + os.date('%a', os.time({ year = 2006, month = 1, day = day_num + cal.week_start })) + ) + end + notifytable[#notifytable] = + string.format('%s\n%s', notifytable[#notifytable]:sub(1, -2), string.rep(' ', st_day * 4)) + local strx + for x = 1, mth_days do + strx = x + if x == today then + if x < 10 then + x = ' ' .. x + end + strx = markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. ' ') + end + strx = string.format('%s%s', string.rep(' ', 3 - tostring(x):len()), strx) + notifytable[#notifytable + 1] = + string.format('%-4s%s', strx, (x + st_day) % 7 == 0 and x ~= mth_days and '\n' or '') + end + if string.len(cal.icons or '') > 0 and today then + cal.icon = cal.icons .. today .. '.png' + end + cal.month, cal.year = d.month, d.year - if cal.week_number ~= "none" then - local m = os.time { year = year or current_year, month = month and month or current_month, day = 1 } - local head_prepend = string.rep(" ", tostring(string.format(cal.week_number_format, 0)):len()) + if cal.week_number ~= 'none' then + local m = os.time({ year = year or current_year, month = month and month or current_month, day = 1 }) + local head_prepend = string.rep(' ', tostring(string.format(cal.week_number_format, 0)):len()) - if cal.week_number == "left" then - notifytable[1] = head_prepend .. notifytable[1] -- month-year row - notifytable[2] = head_prepend .. notifytable[2] -- weekdays row - notifytable[8] = notifytable[8]:gsub("\n", "\n" .. cal.get_week_number(m, st_day, 0)) -- first week of the month + if cal.week_number == 'left' then + notifytable[1] = head_prepend .. notifytable[1] -- month-year row + notifytable[2] = head_prepend .. notifytable[2] -- weekdays row + notifytable[8] = notifytable[8]:gsub('\n', '\n' .. cal.get_week_number(m, st_day, 0)) -- first week of the month - for x = 10,#notifytable do - if cal.sum_week_days(st_day, x) == 2 then - notifytable[x] = cal.get_week_number(m, st_day, x) .. notifytable[x] - end - end - elseif cal.week_number == "right" then - notifytable[8] = notifytable[8]:gsub("\n", head_prepend .. "\n") -- weekdays row - for x = 9,#notifytable do - if cal.sum_week_days(st_day, x) == 1 then - notifytable[x] = notifytable[x]:gsub("\n", cal.get_week_number(m, st_day, x - 7) .. "\n") - end - end - -- last week of the month - local end_days = cal.sum_week_days(st_day, mth_days) - if end_days ~= 0 then end_days = 7 - end_days end - notifytable[#notifytable] = notifytable[#notifytable] .. string.rep(" ", 4 * end_days) .. cal.get_week_number(m, st_day, mth_days + end_days) - end - end + for x = 10, #notifytable do + if cal.sum_week_days(st_day, x) == 2 then + notifytable[x] = cal.get_week_number(m, st_day, x) .. notifytable[x] + end + end + elseif cal.week_number == 'right' then + notifytable[8] = notifytable[8]:gsub('\n', head_prepend .. '\n') -- weekdays row + for x = 9, #notifytable do + if cal.sum_week_days(st_day, x) == 1 then + notifytable[x] = notifytable[x]:gsub('\n', cal.get_week_number(m, st_day, x - 7) .. '\n') + end + end + -- last week of the month + local end_days = cal.sum_week_days(st_day, mth_days) + if end_days ~= 0 then + end_days = 7 - end_days + end + notifytable[#notifytable] = notifytable[#notifytable] + .. string.rep(' ', 4 * end_days) + .. cal.get_week_number(m, st_day, mth_days + end_days) + end + end - return notifytable - end + return notifytable + end - function cal.getdate(month, year, offset) - if not month or not year then - month = tonumber(os.date("%m")) - year = tonumber(os.date("%Y")) - end + function cal.getdate(month, year, offset) + if not month or not year then + month = tonumber(os.date('%m')) + year = tonumber(os.date('%Y')) + end - month = month + offset + month = month + offset - while month > 12 do - month = month - 12 - year = year + 1 - end + while month > 12 do + month = month - 12 + year = year + 1 + end - while month < 1 do - month = month + 12 - year = year - 1 - end + while month < 1 do + month = month + 12 + year = year - 1 + end - return month, year - end + return month, year + end - function cal.hide() - if not cal.notification then return end - naughty.destroy(cal.notification) - cal.notification = nil - end + function cal.hide() + if not cal.notification then + return + end + naughty.destroy(cal.notification) + cal.notification = nil + end - function cal.show(seconds, month, year, scr) - local text = tconcat(cal.build(month, year)) + function cal.show(seconds, month, year, scr) + local text = tconcat(cal.build(month, year)) - if cal.three then - local current_month, current_year = cal.month, cal.year - local prev_month, prev_year = cal.getdate(cal.month, cal.year, -1) - local next_month, next_year = cal.getdate(cal.month, cal.year, 1) - text = string.format("%s\n\n%s\n\n%s", - tconcat(cal.build(prev_month, prev_year)), text, - tconcat(cal.build(next_month, next_year))) - cal.month, cal.year = current_month, current_year - end + if cal.three then + local current_month, current_year = cal.month, cal.year + local prev_month, prev_year = cal.getdate(cal.month, cal.year, -1) + local next_month, next_year = cal.getdate(cal.month, cal.year, 1) + text = string.format( + '%s\n\n%s\n\n%s', + tconcat(cal.build(prev_month, prev_year)), + text, + tconcat(cal.build(next_month, next_year)) + ) + cal.month, cal.year = current_month, current_year + end - if cal.notification then - local title = cal.notification_preset.title or nil - naughty.replace_text(cal.notification, title, text) - return - end + if cal.notification then + local title = cal.notification_preset.title or nil + naughty.replace_text(cal.notification, title, text) + return + end - cal.notification = naughty.notify { - preset = cal.notification_preset, - screen = cal.followtag and awful.screen.focused() or scr or 1, - icon = cal.icon, - timeout = type(seconds) == "number" and seconds or cal.notification_preset.timeout or 5, - text = text - } - end + cal.notification = naughty.notify({ + preset = cal.notification_preset, + screen = cal.followtag and awful.screen.focused() or scr or 1, + icon = cal.icon, + timeout = type(seconds) == 'number' and seconds or cal.notification_preset.timeout or 5, + text = text, + }) + end - function cal.hover_on() cal.show(0) end - function cal.move(offset) - offset = offset or 0 - cal.month, cal.year = cal.getdate(cal.month, cal.year, offset) - cal.show(0, cal.month, cal.year) - end - function cal.prev() cal.move(-1) end - function cal.next() cal.move( 1) end + function cal.hover_on() + cal.show(0) + end + function cal.move(offset) + offset = offset or 0 + cal.month, cal.year = cal.getdate(cal.month, cal.year, offset) + cal.show(0, cal.month, cal.year) + end + function cal.prev() + cal.move(-1) + end + function cal.next() + cal.move(1) + end - function cal.attach(widget) - widget:connect_signal("mouse::enter", cal.hover_on) - widget:connect_signal("mouse::leave", cal.hide) - widget:buttons(awful.util.table.join( - awful.button({}, 1, cal.prev), - awful.button({}, 3, cal.next), - awful.button({}, 2, cal.hover_on), - awful.button({}, 5, cal.prev), - awful.button({}, 4, cal.next))) - end + function cal.attach(widget) + widget:connect_signal('mouse::enter', cal.hover_on) + widget:connect_signal('mouse::leave', cal.hide) + widget:buttons( + awful.util.table.join( + awful.button({}, 1, cal.prev), + awful.button({}, 3, cal.next), + awful.button({}, 2, cal.hover_on), + awful.button({}, 5, cal.prev), + awful.button({}, 4, cal.next) + ) + ) + end - for _, widget in pairs(cal.attach_to) do cal.attach(widget) end + for _, widget in pairs(cal.attach_to) do + cal.attach(widget) + end - return cal + return cal end return factory diff --git a/awesome/lain/widget/contrib/init.lua b/awesome/lain/widget/contrib/init.lua index 9e863a5..f245ac1 100644 --- a/awesome/lain/widget/contrib/init.lua +++ b/awesome/lain/widget/contrib/init.lua @@ -10,9 +10,9 @@ --]] -local wrequire = require("lain.helpers").wrequire +local wrequire = require('lain.helpers').wrequire local setmetatable = setmetatable -local widget = { _NAME = "lain.widget.contrib" } +local widget = { _NAME = 'lain.widget.contrib' } return setmetatable(widget, { __index = wrequire }) diff --git a/awesome/lain/widget/contrib/moc.lua b/awesome/lain/widget/contrib/moc.lua index ad6452e..682b0fe 100644 --- a/awesome/lain/widget/contrib/moc.lua +++ b/awesome/lain/widget/contrib/moc.lua @@ -5,93 +5,103 @@ --]] -local helpers = require("lain.helpers") -local shell = require("awful.util").shell -local focused = require("awful.screen").focused -local escape_f = require("awful.util").escape -local naughty = require("naughty") -local wibox = require("wibox") -local os = os -local string = string +local helpers = require('lain.helpers') +local shell = require('awful.util').shell +local focused = require('awful.screen').focused +local escape_f = require('awful.util').escape +local naughty = require('naughty') +local wibox = require('wibox') +local os = os +local string = string -- MOC audio player -- lain.widget.contrib.moc local function factory(args) - args = args or {} + args = args or {} - local moc = { widget = args.widget or wibox.widget.textbox() } - local timeout = args.timeout or 2 - local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" - local cover_pattern = args.cover_pattern or "*\\.(jpg|jpeg|png|gif)$" - local cover_size = args.cover_size or 100 - local default_art = args.default_art or "" - local followtag = args.followtag or false - local settings = args.settings or function() end + local moc = { widget = args.widget or wibox.widget.textbox() } + local timeout = args.timeout or 2 + local music_dir = args.music_dir or os.getenv('HOME') .. '/Music' + local cover_pattern = args.cover_pattern or '*\\.(jpg|jpeg|png|gif)$' + local cover_size = args.cover_size or 100 + local default_art = args.default_art or '' + local followtag = args.followtag or false + local settings = args.settings or function() end - moc_notification_preset = { title = "Now playing", timeout = 6 } + moc_notification_preset = { title = 'Now playing', timeout = 6 } - helpers.set_map("current moc track", nil) + helpers.set_map('current moc track', nil) - function moc.update() - helpers.async("mocp -i", function(f) - moc_now = { - state = "N/A", - file = "N/A", - artist = "N/A", - title = "N/A", - album = "N/A", - elapsed = "N/A", - total = "N/A" - } + function moc.update() + helpers.async('mocp -i', function(f) + moc_now = { + state = 'N/A', + file = 'N/A', + artist = 'N/A', + title = 'N/A', + album = 'N/A', + elapsed = 'N/A', + total = 'N/A', + } - for line in string.gmatch(f, "[^\n]+") do - for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do - if k == "State" then moc_now.state = v - elseif k == "File" then moc_now.file = v - elseif k == "Artist" then moc_now.artist = escape_f(v) - elseif k == "SongTitle" then moc_now.title = escape_f(v) - elseif k == "Album" then moc_now.album = escape_f(v) - elseif k == "CurrentTime" then moc_now.elapsed = escape_f(v) - elseif k == "TotalTime" then moc_now.total = escape_f(v) - end - end - end + for line in string.gmatch(f, '[^\n]+') do + for k, v in string.gmatch(line, '([%w]+):[%s](.*)$') do + if k == 'State' then + moc_now.state = v + elseif k == 'File' then + moc_now.file = v + elseif k == 'Artist' then + moc_now.artist = escape_f(v) + elseif k == 'SongTitle' then + moc_now.title = escape_f(v) + elseif k == 'Album' then + moc_now.album = escape_f(v) + elseif k == 'CurrentTime' then + moc_now.elapsed = escape_f(v) + elseif k == 'TotalTime' then + moc_now.total = escape_f(v) + end + end + end - moc_notification_preset.text = string.format("%s (%s) - %s\n%s", moc_now.artist, - moc_now.album, moc_now.total, moc_now.title) - widget = moc.widget - settings() + moc_notification_preset.text = + string.format('%s (%s) - %s\n%s', moc_now.artist, moc_now.album, moc_now.total, moc_now.title) + widget = moc.widget + settings() - if moc_now.state == "PLAY" then - if moc_now.title ~= helpers.get_map("current moc track") then - helpers.set_map("current moc track", moc_now.title) + if moc_now.state == 'PLAY' then + if moc_now.title ~= helpers.get_map('current moc track') then + helpers.set_map('current moc track', moc_now.title) - if followtag then moc_notification_preset.screen = focused() end + if followtag then + moc_notification_preset.screen = focused() + end - local common = { - preset = moc_notification_preset, - icon = default_art, - icon_size = cover_size, - replaces_id = moc.id, - } + local common = { + preset = moc_notification_preset, + icon = default_art, + icon_size = cover_size, + replaces_id = moc.id, + } - local path = string.format("%s/%s", music_dir, string.match(moc_now.file, ".*/")) - local cover = string.format("find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'", path, cover_pattern) - helpers.async({ shell, "-c", cover }, function(current_icon) - common.icon = current_icon:gsub("\n", "") - moc.id = naughty.notify(common).id - end) - end - elseif moc_now.state ~= "PAUSE" then - helpers.set_map("current moc track", nil) - end - end) - end + local path = string.format('%s/%s', music_dir, string.match(moc_now.file, '.*/')) + local cover = + string.format("find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'", path, cover_pattern) + helpers.async({ shell, '-c', cover }, function(current_icon) + common.icon = current_icon:gsub('\n', '') + moc.id = naughty.notify(common).id + end) + end + elseif moc_now.state ~= 'PAUSE' then + helpers.set_map('current moc track', nil) + end + end) + end - moc.timer = helpers.newtimer("moc", timeout, moc.update, true, true) + moc.timer = helpers.newtimer('moc', timeout, moc.update, true, true) - return moc + return moc end return factory diff --git a/awesome/lain/widget/contrib/redshift.lua b/awesome/lain/widget/contrib/redshift.lua index d91d941..0d9f278 100644 --- a/awesome/lain/widget/contrib/redshift.lua +++ b/awesome/lain/widget/contrib/redshift.lua @@ -6,36 +6,36 @@ --]] -local async = require("lain.helpers").async -local awful = require("awful") +local async = require('lain.helpers').async +local awful = require('awful') local execute = os.execute -local type = type +local type = type -- Redshift -- lain.widget.contrib.redshift local redshift = { active = false, pid = nil } function redshift.start() - execute("pkill redshift") - awful.spawn.with_shell("redshift -x") -- clear adjustments - redshift.pid = awful.spawn.with_shell("redshift") - redshift.active = true - if type(redshift.update_fun) == "function" then - redshift.update_fun(redshift.active) - end + execute('pkill redshift') + awful.spawn.with_shell('redshift -x') -- clear adjustments + redshift.pid = awful.spawn.with_shell('redshift') + redshift.active = true + if type(redshift.update_fun) == 'function' then + redshift.update_fun(redshift.active) + end end function redshift.toggle() - async({ awful.util.shell, "-c", string.format("ps -p %d -o pid=", redshift.pid) }, function(f) - if f and #f > 0 then -- redshift is running - -- Sending -USR1 toggles redshift (See project website) - execute("pkill -USR1 redshift") - redshift.active = not redshift.active - else -- not started or killed, (re)start it - redshift.start() - end - redshift.update_fun(redshift.active) - end) + async({ awful.util.shell, '-c', string.format('ps -p %d -o pid=', redshift.pid) }, function(f) + if f and #f > 0 then -- redshift is running + -- Sending -USR1 toggles redshift (See project website) + execute('pkill -USR1 redshift') + redshift.active = not redshift.active + else -- not started or killed, (re)start it + redshift.start() + end + redshift.update_fun(redshift.active) + end) end -- Attach to a widget @@ -44,11 +44,15 @@ end -- @param fun: Function to be run each time redshift is toggled (optional). -- Use it to update widget text or icons on status change. function redshift.attach(widget, fun) - redshift.update_fun = fun or function() end - if not redshift.pid then redshift.start() end - if widget then - widget:buttons(awful.util.table.join(awful.button({}, 1, function () redshift.toggle() end))) - end + redshift.update_fun = fun or function() end + if not redshift.pid then + redshift.start() + end + if widget then + widget:buttons(awful.util.table.join(awful.button({}, 1, function() + redshift.toggle() + end))) + end end return redshift diff --git a/awesome/lain/widget/contrib/task.lua b/awesome/lain/widget/contrib/task.lua index 2311996..bb30726 100644 --- a/awesome/lain/widget/contrib/task.lua +++ b/awesome/lain/widget/contrib/task.lua @@ -5,88 +5,92 @@ --]] -local helpers = require("lain.helpers") -local markup = require("lain.util").markup -local awful = require("awful") -local naughty = require("naughty") -local mouse = mouse +local helpers = require('lain.helpers') +local markup = require('lain.util').markup +local awful = require('awful') +local naughty = require('naughty') +local mouse = mouse -- Taskwarrior notification -- lain.widget.contrib.task local task = {} function task.hide() - if not task.notification then return end - naughty.destroy(task.notification) - task.notification = nil + if not task.notification then + return + end + naughty.destroy(task.notification) + task.notification = nil end function task.show(scr) - task.notification_preset.screen = task.followtag and awful.screen.focused() or scr or 1 + task.notification_preset.screen = task.followtag and awful.screen.focused() or scr or 1 - helpers.async({ awful.util.shell, "-c", task.show_cmd }, function(f) - local widget_focused = true + helpers.async({ awful.util.shell, '-c', task.show_cmd }, function(f) + local widget_focused = true - if mouse.current_widgets then - widget_focused = false - for _,v in ipairs(mouse.current_widgets) do - if task.widget == v then - widget_focused = true - break - end - end - end + if mouse.current_widgets then + widget_focused = false + for _, v in ipairs(mouse.current_widgets) do + if task.widget == v then + widget_focused = true + break + end + end + end - if widget_focused then - task.hide() - task.notification = naughty.notify { - preset = task.notification_preset, - title = "task next", - text = markup.font(task.notification_preset.font, - awful.util.escape(f:gsub("\n*$", ""))) - } - end - end) + if widget_focused then + task.hide() + task.notification = naughty.notify({ + preset = task.notification_preset, + title = 'task next', + text = markup.font(task.notification_preset.font, awful.util.escape(f:gsub('\n*$', ''))), + }) + end + end) end function task.prompt() - awful.prompt.run { - prompt = task.prompt_text, - textbox = awful.screen.focused().mypromptbox.widget, - exe_callback = function(t) - helpers.async(t, function(f) - naughty.notify { - preset = task.notification_preset, - title = t, - text = markup.font(task.notification_preset.font, - awful.util.escape(f:gsub("\n*$", ""))) - } - end) - end, - history_path = awful.util.getdir("cache") .. "/history_task" - } + awful.prompt.run({ + prompt = task.prompt_text, + textbox = awful.screen.focused().mypromptbox.widget, + exe_callback = function(t) + helpers.async(t, function(f) + naughty.notify({ + preset = task.notification_preset, + title = t, + text = markup.font(task.notification_preset.font, awful.util.escape(f:gsub('\n*$', ''))), + }) + end) + end, + history_path = awful.util.getdir('cache') .. '/history_task', + }) end function task.attach(widget, args) - args = args or {} + args = args or {} - task.show_cmd = args.show_cmd or "task next" - task.prompt_text = args.prompt_text or "Enter task command: " - task.followtag = args.followtag or false - task.notification_preset = args.notification_preset - task.widget = widget + task.show_cmd = args.show_cmd or 'task next' + task.prompt_text = args.prompt_text or 'Enter task command: ' + task.followtag = args.followtag or false + task.notification_preset = args.notification_preset + task.widget = widget - if not task.notification_preset then - task.notification_preset = { - font = "Monospace 10", - icon = helpers.icons_dir .. "/taskwarrior.png" - } - end + if not task.notification_preset then + task.notification_preset = { + font = 'Monospace 10', + icon = helpers.icons_dir .. '/taskwarrior.png', + } + end - if widget then - widget:connect_signal("mouse::enter", function () task.show() end) - widget:connect_signal("mouse::leave", function () task.hide() end) - end + if widget then + widget:connect_signal('mouse::enter', function() + task.show() + end) + widget:connect_signal('mouse::leave', function() + task.hide() + end) + end end return task diff --git a/awesome/lain/widget/contrib/tp_smapi.lua b/awesome/lain/widget/contrib/tp_smapi.lua index 87c5e51..5dbf4ad 100644 --- a/awesome/lain/widget/contrib/tp_smapi.lua +++ b/awesome/lain/widget/contrib/tp_smapi.lua @@ -6,142 +6,159 @@ --]] -local helpers = require("lain.helpers") -local focused = require("awful.screen").focused -local naughty = require("naughty") -local wibox = require("wibox") -local string = string -local type = type +local helpers = require('lain.helpers') +local focused = require('awful.screen').focused +local naughty = require('naughty') +local wibox = require('wibox') +local string = string +local type = type -- ThinkPad battery infos and widget creator -- http://www.thinkwiki.org/wiki/Tp_smapi -- lain.widget.contrib.tp_smapi local function factory(apipath) - local tp_smapi = { - path = apipath or "/sys/devices/platform/smapi" - } + local tp_smapi = { + path = apipath or '/sys/devices/platform/smapi', + } - function tp_smapi.get(batid, feature) - return helpers.first_line(string.format("%s/%s/%s", tp_smapi.path, batid or "BAT0", feature or "")) - end + function tp_smapi.get(batid, feature) + return helpers.first_line(string.format('%s/%s/%s', tp_smapi.path, batid or 'BAT0', feature or '')) + end - function tp_smapi.installed(batid) - return tp_smapi.get(batid, "installed") == "1" - end + function tp_smapi.installed(batid) + return tp_smapi.get(batid, 'installed') == '1' + end - function tp_smapi.status(batid) - return tp_smapi.get(batid, "state") - end + function tp_smapi.status(batid) + return tp_smapi.get(batid, 'state') + end - function tp_smapi.percentage(batid) - return tp_smapi.get(batid, "remaining_percent") - end + function tp_smapi.percentage(batid) + return tp_smapi.get(batid, 'remaining_percent') + end - -- either running or charging time - function tp_smapi.time(batid) - local status = tp_smapi.status(batid) - local mins_left = tp_smapi.get(batid, string.match(string.lower(status), "discharging") and "remaining_running_time" or "remaining_charging_time") - if not string.find(mins_left, "^%d+") then return "N/A" end - return string.format("%02d:%02d", math.floor(mins_left / 60), mins_left % 60) -- HH:mm - end + -- either running or charging time + function tp_smapi.time(batid) + local status = tp_smapi.status(batid) + local mins_left = tp_smapi.get( + batid, + string.match(string.lower(status), 'discharging') and 'remaining_running_time' or 'remaining_charging_time' + ) + if not string.find(mins_left, '^%d+') then + return 'N/A' + end + return string.format('%02d:%02d', math.floor(mins_left / 60), mins_left % 60) -- HH:mm + end - function tp_smapi.hide() - if not tp_smapi.notification then return end - naughty.destroy(tp_smapi.notification) - tp_smapi.notification = nil - end + function tp_smapi.hide() + if not tp_smapi.notification then + return + end + naughty.destroy(tp_smapi.notification) + tp_smapi.notification = nil + end - function tp_smapi.show(batid, seconds, scr) - if not tp_smapi.installed(batid) then return end + function tp_smapi.show(batid, seconds, scr) + if not tp_smapi.installed(batid) then + return + end - local mfgr = tp_smapi.get(batid, "manufacturer") or "no_mfgr" - local model = tp_smapi.get(batid, "model") or "no_model" - local chem = tp_smapi.get(batid, "chemistry") or "no_chem" - local status = tp_smapi.get(batid, "state") - local time = tp_smapi.time(batid) - local msg + local mfgr = tp_smapi.get(batid, 'manufacturer') or 'no_mfgr' + local model = tp_smapi.get(batid, 'model') or 'no_model' + local chem = tp_smapi.get(batid, 'chemistry') or 'no_chem' + local status = tp_smapi.get(batid, 'state') + local time = tp_smapi.time(batid) + local msg - if status and status ~= "idle" then - msg = string.format("[%s] %s %s", status, time ~= "N/A" and time or "unknown remaining time", - string.lower(status):gsub(" ", ""):gsub("\n", "") == "charging" and " until charged" or " remaining") - else - msg = "On AC power" - end + if status and status ~= 'idle' then + msg = string.format( + '[%s] %s %s', + status, + time ~= 'N/A' and time or 'unknown remaining time', + string.lower(status):gsub(' ', ''):gsub('\n', '') == 'charging' and ' until charged' or ' remaining' + ) + else + msg = 'On AC power' + end - tp_smapi.hide() - tp_smapi.notification = naughty.notify { - title = string.format("%s: %s %s (%s)", batid, mfgr, model, chem), - text = msg, - timeout = type(seconds) == "number" and seconds or 0, - screen = scr or focused() - } - end + tp_smapi.hide() + tp_smapi.notification = naughty.notify({ + title = string.format('%s: %s %s (%s)', batid, mfgr, model, chem), + text = msg, + timeout = type(seconds) == 'number' and seconds or 0, + screen = scr or focused(), + }) + end - function tp_smapi.create_widget(args) - args = args or {} + function tp_smapi.create_widget(args) + args = args or {} - local pspath = args.pspath or "/sys/class/power_supply/" - local batteries = args.batteries or (args.battery and {args.battery}) or {} - local timeout = args.timeout or 30 - local settings = args.settings or function() end + local pspath = args.pspath or '/sys/class/power_supply/' + local batteries = args.batteries or (args.battery and { args.battery }) or {} + local timeout = args.timeout or 30 + local settings = args.settings or function() end - if #batteries == 0 then - helpers.line_callback("ls -1 " .. pspath, function(line) - local bstr = string.match(line, "BAT%w+") - if bstr then batteries[#batteries + 1] = bstr end - end) - end + if #batteries == 0 then + helpers.line_callback('ls -1 ' .. pspath, function(line) + local bstr = string.match(line, 'BAT%w+') + if bstr then + batteries[#batteries + 1] = bstr + end + end) + end - local all_batteries_installed = true + local all_batteries_installed = true - for _, battery in ipairs(batteries) do - if not tp_smapi.installed(battery) then - naughty.notify { - preset = naughty.config.critical, - title = "tp_smapi: error while creating widget", - text = string.format("battery %s is not installed", battery) - } - all_batteries_installed = false - break - end - end + for _, battery in ipairs(batteries) do + if not tp_smapi.installed(battery) then + naughty.notify({ + preset = naughty.config.critical, + title = 'tp_smapi: error while creating widget', + text = string.format('battery %s is not installed', battery), + }) + all_batteries_installed = false + break + end + end - if not all_batteries_installed then return end + if not all_batteries_installed then + return + end - tpbat = { - batteries = batteries, - widget = args.widget or wibox.widget.textbox() - } + tpbat = { + batteries = batteries, + widget = args.widget or wibox.widget.textbox(), + } - function tpbat.update() - tpbat_now = { - n_status = {}, - n_perc = {}, - n_time = {}, - status = "N/A" - } + function tpbat.update() + tpbat_now = { + n_status = {}, + n_perc = {}, + n_time = {}, + status = 'N/A', + } - for i = 1, #batteries do - tpbat_now.n_status[i] = tp_smapi.status(batteries[i]) or "N/A" - tpbat_now.n_perc[i] = tp_smapi.percentage(batteries[i]) - tpbat_now.n_time[i] = tp_smapi.time(batteries[i]) or "N/A" + for i = 1, #batteries do + tpbat_now.n_status[i] = tp_smapi.status(batteries[i]) or 'N/A' + tpbat_now.n_perc[i] = tp_smapi.percentage(batteries[i]) + tpbat_now.n_time[i] = tp_smapi.time(batteries[i]) or 'N/A' - if not tpbat_now.n_status[i]:lower():match("full") then - tpbat_now.status = tpbat_now.n_status[i] - end - end + if not tpbat_now.n_status[i]:lower():match('full') then + tpbat_now.status = tpbat_now.n_status[i] + end + end - widget = tpbat.widget -- backwards compatibility - settings() - end + widget = tpbat.widget -- backwards compatibility + settings() + end - helpers.newtimer("thinkpad-batteries", timeout, tpbat.update) + helpers.newtimer('thinkpad-batteries', timeout, tpbat.update) - return tpbat - end + return tpbat + end - return tp_smapi + return tp_smapi end return factory diff --git a/awesome/lain/widget/cpu.lua b/awesome/lain/widget/cpu.lua index 6c51115..7f590cd 100644 --- a/awesome/lain/widget/cpu.lua +++ b/awesome/lain/widget/cpu.lua @@ -6,70 +6,69 @@ --]] -local helpers = require("lain.helpers") -local wibox = require("wibox") -local math = math -local string = string +local helpers = require('lain.helpers') +local wibox = require('wibox') +local math = math +local string = string -- CPU usage -- lain.widget.cpu local function factory(args) - args = args or {} + args = args or {} - local cpu = { core = {}, widget = args.widget or wibox.widget.textbox() } - local timeout = args.timeout or 2 - local settings = args.settings or function() end + local cpu = { core = {}, widget = args.widget or wibox.widget.textbox() } + local timeout = args.timeout or 2 + local settings = args.settings or function() end - function cpu.update() - -- Read the amount of time the CPUs have spent performing - -- different kinds of work. Read the first line of /proc/stat - -- which is the sum of all CPUs. - for index,time in pairs(helpers.lines_match("cpu","/proc/stat")) do - local coreid = index - 1 - local core = cpu.core[coreid] or - { last_active = 0 , last_total = 0, usage = 0 } - local at = 1 - local idle = 0 - local total = 0 + function cpu.update() + -- Read the amount of time the CPUs have spent performing + -- different kinds of work. Read the first line of /proc/stat + -- which is the sum of all CPUs. + for index, time in pairs(helpers.lines_match('cpu', '/proc/stat')) do + local coreid = index - 1 + local core = cpu.core[coreid] or { last_active = 0, last_total = 0, usage = 0 } + local at = 1 + local idle = 0 + local total = 0 - for field in string.gmatch(time, "[%s]+([^%s]+)") do - -- 4 = idle, 5 = ioWait. Essentially, the CPUs have done - -- nothing during these times. - if at == 4 or at == 5 then - idle = idle + field - end - total = total + field - at = at + 1 - end + for field in string.gmatch(time, '[%s]+([^%s]+)') do + -- 4 = idle, 5 = ioWait. Essentially, the CPUs have done + -- nothing during these times. + if at == 4 or at == 5 then + idle = idle + field + end + total = total + field + at = at + 1 + end - local active = total - idle + local active = total - idle - if core.last_active ~= active or core.last_total ~= total then - -- Read current data and calculate relative values. - local dactive = active - core.last_active - local dtotal = total - core.last_total - local usage = math.ceil(math.abs((dactive / dtotal) * 100)) + if core.last_active ~= active or core.last_total ~= total then + -- Read current data and calculate relative values. + local dactive = active - core.last_active + local dtotal = total - core.last_total + local usage = math.ceil(math.abs((dactive / dtotal) * 100)) - core.last_active = active - core.last_total = total - core.usage = usage + core.last_active = active + core.last_total = total + core.usage = usage - -- Save current data for the next run. - cpu.core[coreid] = core - end - end + -- Save current data for the next run. + cpu.core[coreid] = core + end + end - cpu_now = cpu.core - cpu_now.usage = cpu_now[0].usage - widget = cpu.widget + cpu_now = cpu.core + cpu_now.usage = cpu_now[0].usage + widget = cpu.widget - settings() - end + settings() + end - helpers.newtimer("cpu", timeout, cpu.update) + helpers.newtimer('cpu', timeout, cpu.update) - return cpu + return cpu end return factory diff --git a/awesome/lain/widget/fs.lua b/awesome/lain/widget/fs.lua index b3a2dad..10e830f 100644 --- a/awesome/lain/widget/fs.lua +++ b/awesome/lain/widget/fs.lua @@ -7,150 +7,168 @@ --]] -local helpers = require("lain.helpers") -local Gio = require("lgi").Gio -local focused = require("awful.screen").focused -local wibox = require("wibox") -local naughty = require("naughty") -local gears = require("gears") -local math = math -local string = string -local tconcat = table.concat -local type = type +local helpers = require('lain.helpers') +local Gio = require('lgi').Gio +local focused = require('awful.screen').focused +local wibox = require('wibox') +local naughty = require('naughty') +local gears = require('gears') +local math = math +local string = string +local tconcat = table.concat +local type = type local query_size = Gio.FILE_ATTRIBUTE_FILESYSTEM_SIZE local query_free = Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE local query_used = Gio.FILE_ATTRIBUTE_FILESYSTEM_USED -local query = query_size .. "," .. query_free .. "," .. query_used +local query = query_size .. ',' .. query_free .. ',' .. query_used -- File systems info -- lain.widget.fs local function factory(args) - args = args or {} + args = args or {} - local fs = { - widget = args.widget or wibox.widget.textbox(), - units = { - [1] = "Kb", [2] = "Mb", [3] = "Gb", - [4] = "Tb", [5] = "Pb", [6] = "Eb", - [7] = "Zb", [8] = "Yb" - } - } + local fs = { + widget = args.widget or wibox.widget.textbox(), + units = { + [1] = 'Kb', + [2] = 'Mb', + [3] = 'Gb', + [4] = 'Tb', + [5] = 'Pb', + [6] = 'Eb', + [7] = 'Zb', + [8] = 'Yb', + }, + } - function fs.hide() - if not fs.notification then return end - naughty.destroy(fs.notification) - fs.notification = nil - end + function fs.hide() + if not fs.notification then + return + end + naughty.destroy(fs.notification) + fs.notification = nil + end - function fs.show(seconds, scr) - fs.hide() - fs.update(function() - fs.notification_preset.screen = fs.followtag and focused() or scr or 1 - fs.notification = naughty.notify { - preset = fs.notification_preset, - timeout = type(seconds) == "number" and seconds or 5 - } - end) - end + function fs.show(seconds, scr) + fs.hide() + fs.update(function() + fs.notification_preset.screen = fs.followtag and focused() or scr or 1 + fs.notification = naughty.notify({ + preset = fs.notification_preset, + timeout = type(seconds) == 'number' and seconds or 5, + }) + end) + end - local timeout = args.timeout or 600 - local partition = args.partition - local threshold = args.threshold or 99 - local showpopup = args.showpopup or "on" - local settings = args.settings or function() end + local timeout = args.timeout or 600 + local partition = args.partition + local threshold = args.threshold or 99 + local showpopup = args.showpopup or 'on' + local settings = args.settings or function() end - fs.followtag = args.followtag or false - fs.notification_preset = args.notification_preset + fs.followtag = args.followtag or false + fs.notification_preset = args.notification_preset - if not fs.notification_preset then - fs.notification_preset = { - font = "Monospace 10", - fg = "#FFFFFF", - bg = "#000000" - } - end + if not fs.notification_preset then + fs.notification_preset = { + font = 'Monospace 10', + fg = '#FFFFFF', + bg = '#000000', + } + end - local function update_synced() - local pathlen = 10 - fs_now = {} + local function update_synced() + local pathlen = 10 + fs_now = {} - local notifypaths = {} - for _, mount in ipairs(Gio.unix_mounts_get()) do - local path = Gio.unix_mount_get_mount_path(mount) - local root = Gio.File.new_for_path(path) - local info = root:query_filesystem_info(query) + local notifypaths = {} + for _, mount in ipairs(Gio.unix_mounts_get()) do + local path = Gio.unix_mount_get_mount_path(mount) + local root = Gio.File.new_for_path(path) + local info = root:query_filesystem_info(query) - if info then - local size = info:get_attribute_uint64(query_size) - local used = info:get_attribute_uint64(query_used) - local free = info:get_attribute_uint64(query_free) + if info then + local size = info:get_attribute_uint64(query_size) + local used = info:get_attribute_uint64(query_used) + local free = info:get_attribute_uint64(query_free) - if size > 0 then - local units = math.floor(math.log(size)/math.log(1024)) + if size > 0 then + local units = math.floor(math.log(size) / math.log(1024)) - fs_now[path] = { - units = fs.units[units], - percentage = math.floor(100 * used / size), -- used percentage - size = size / math.pow(1024, units), - used = used / math.pow(1024, units), - free = free / math.pow(1024, units) - } + fs_now[path] = { + units = fs.units[units], + percentage = math.floor(100 * used / size), -- used percentage + size = size / math.pow(1024, units), + used = used / math.pow(1024, units), + free = free / math.pow(1024, units), + } - if fs_now[path].percentage > 0 then -- don't notify unused file systems - notifypaths[#notifypaths+1] = path + if fs_now[path].percentage > 0 then -- don't notify unused file systems + notifypaths[#notifypaths + 1] = path - if #path > pathlen then - pathlen = #path - end - end - end - end - end + if #path > pathlen then + pathlen = #path + end + end + end + end + end - widget = fs.widget - settings() + widget = fs.widget + settings() - if partition and fs_now[partition] and fs_now[partition].percentage >= threshold then - if not helpers.get_map(partition) then - naughty.notify { - preset = naughty.config.presets.critical, - title = "Warning", - text = string.format("%s is above %d%% (%d%%)", partition, threshold, fs_now[partition].percentage) - } - helpers.set_map(partition, true) - else - helpers.set_map(partition, false) - end - end + if partition and fs_now[partition] and fs_now[partition].percentage >= threshold then + if not helpers.get_map(partition) then + naughty.notify({ + preset = naughty.config.presets.critical, + title = 'Warning', + text = string.format('%s is above %d%% (%d%%)', partition, threshold, fs_now[partition].percentage), + }) + helpers.set_map(partition, true) + else + helpers.set_map(partition, false) + end + end - local fmt = "%-" .. tostring(pathlen) .. "s %4s\t%6s\t%6s\n" - local notifytable = { [1] = string.format(fmt, "path", "used", "free", "size") } - fmt = "\n%-" .. tostring(pathlen) .. "s %3s%%\t%6.2f\t%6.2f %s" - for _, path in ipairs(notifypaths) do - notifytable[#notifytable+1] = string.format(fmt, path, fs_now[path].percentage, fs_now[path].free, fs_now[path].size, fs_now[path].units) - end + local fmt = '%-' .. tostring(pathlen) .. 's %4s\t%6s\t%6s\n' + local notifytable = { [1] = string.format(fmt, 'path', 'used', 'free', 'size') } + fmt = '\n%-' .. tostring(pathlen) .. 's %3s%%\t%6.2f\t%6.2f %s' + for _, path in ipairs(notifypaths) do + notifytable[#notifytable + 1] = string.format( + fmt, + path, + fs_now[path].percentage, + fs_now[path].free, + fs_now[path].size, + fs_now[path].units + ) + end - fs.notification_preset.text = tconcat(notifytable) - end + fs.notification_preset.text = tconcat(notifytable) + end - function fs.update(callback) - Gio.Async.start(gears.protected_call.call)(function() - update_synced() - if type(callback) == "function" and callback then - callback() - end - end) - end + function fs.update(callback) + Gio.Async.start(gears.protected_call.call)(function() + update_synced() + if type(callback) == 'function' and callback then + callback() + end + end) + end - if showpopup == "on" then - fs.widget:connect_signal('mouse::enter', function () fs.show(0) end) - fs.widget:connect_signal('mouse::leave', function () fs.hide() end) - end + if showpopup == 'on' then + fs.widget:connect_signal('mouse::enter', function() + fs.show(0) + end) + fs.widget:connect_signal('mouse::leave', function() + fs.hide() + end) + end - helpers.newtimer(partition or "fs", timeout, fs.update) + helpers.newtimer(partition or 'fs', timeout, fs.update) - return fs + return fs end return factory diff --git a/awesome/lain/widget/imap.lua b/awesome/lain/widget/imap.lua index e3f7baa..59aafc6 100644 --- a/awesome/lain/widget/imap.lua +++ b/awesome/lain/widget/imap.lua @@ -5,90 +5,111 @@ --]] -local helpers = require("lain.helpers") -local naughty = require("naughty") -local wibox = require("wibox") -local awful = require("awful") -local string = string -local type = type +local helpers = require('lain.helpers') +local naughty = require('naughty') +local wibox = require('wibox') +local awful = require('awful') +local string = string +local type = type local tonumber = tonumber -- Mail IMAP check -- lain.widget.imap local function factory(args) - args = args or {} + args = args or {} - local imap = { widget = args.widget or wibox.widget.textbox() } - local server = args.server - local mail = args.mail - local password = args.password - local port = args.port or 993 - local timeout = args.timeout or 60 - local pwdtimeout = args.pwdtimeout or 10 - local is_plain = args.is_plain or false - local followtag = args.followtag or false - local notify = args.notify or "on" - local settings = args.settings or function() end + local imap = { widget = args.widget or wibox.widget.textbox() } + local server = args.server + local mail = args.mail + local password = args.password + local port = args.port or 993 + local timeout = args.timeout or 60 + local pwdtimeout = args.pwdtimeout or 10 + local is_plain = args.is_plain or false + local followtag = args.followtag or false + local notify = args.notify or 'on' + local settings = args.settings or function() end - local head_command = "curl --connect-timeout 3 -fsm 3" - local request = "-X 'STATUS INBOX (MESSAGES RECENT UNSEEN)'" + local head_command = 'curl --connect-timeout 3 -fsm 3' + local request = "-X 'STATUS INBOX (MESSAGES RECENT UNSEEN)'" - if not server or not mail or not password then return end + if not server or not mail or not password then + return + end - mail_notification_preset = { - icon = helpers.icons_dir .. "mail.png", - position = "top_left" - } + mail_notification_preset = { + icon = helpers.icons_dir .. 'mail.png', + position = 'top_left', + } - helpers.set_map(mail, 0) + helpers.set_map(mail, 0) - if not is_plain then - if type(password) == "string" or type(password) == "table" then - helpers.async(password, function(f) password = f:gsub("\n", "") end) - elseif type(password) == "function" then - imap.pwdtimer = helpers.newtimer(mail .. "-password", pwdtimeout, function() - local retrieved_password, try_again = password() - if not try_again then - imap.pwdtimer:stop() -- stop trying to retrieve - password = retrieved_password or "" -- failsafe - end - end, true, true) - end - end + if not is_plain then + if type(password) == 'string' or type(password) == 'table' then + helpers.async(password, function(f) + password = f:gsub('\n', '') + end) + elseif type(password) == 'function' then + imap.pwdtimer = helpers.newtimer(mail .. '-password', pwdtimeout, function() + local retrieved_password, try_again = password() + if not try_again then + imap.pwdtimer:stop() -- stop trying to retrieve + password = retrieved_password or '' -- failsafe + end + end, true, true) + end + end - function imap.update() - -- do not update if the password has not been retrieved yet - if type(password) ~= "string" then return end + function imap.update() + -- do not update if the password has not been retrieved yet + if type(password) ~= 'string' then + return + end - local curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:'%s' %s -k", - head_command, server, port, mail, password, request) + local curl = string.format( + "%s --url imaps://%s:%s/INBOX -u %s:'%s' %s -k", + head_command, + server, + port, + mail, + password, + request + ) - helpers.async(curl, function(f) - imap_now = { ["MESSAGES"] = 0, ["RECENT"] = 0, ["UNSEEN"] = 0 } + helpers.async(curl, function(f) + imap_now = { ['MESSAGES'] = 0, ['RECENT'] = 0, ['UNSEEN'] = 0 } - for s,d in f:gmatch("(%w+)%s+(%d+)") do imap_now[s] = tonumber(d) end - mailcount = imap_now["UNSEEN"] -- backwards compatibility - widget = imap.widget + for s, d in f:gmatch('(%w+)%s+(%d+)') do + imap_now[s] = tonumber(d) + end + mailcount = imap_now['UNSEEN'] -- backwards compatibility + widget = imap.widget - settings() + settings() - if notify == "on" and mailcount and mailcount >= 1 and mailcount > helpers.get_map(mail) then - if followtag then mail_notification_preset.screen = awful.screen.focused() end - naughty.notify { - preset = mail_notification_preset, - text = string.format("%s has %d new message%s", mail, mailcount, mailcount == 1 and "" or "s") - } - end + if notify == 'on' and mailcount and mailcount >= 1 and mailcount > helpers.get_map(mail) then + if followtag then + mail_notification_preset.screen = awful.screen.focused() + end + naughty.notify({ + preset = mail_notification_preset, + text = string.format( + '%s has %d new message%s', + mail, + mailcount, + mailcount == 1 and '' or 's' + ), + }) + end - helpers.set_map(mail, imap_now["UNSEEN"]) - end) + helpers.set_map(mail, imap_now['UNSEEN']) + end) + end - end + imap.timer = helpers.newtimer(mail, timeout, imap.update, true, true) - imap.timer = helpers.newtimer(mail, timeout, imap.update, true, true) - - return imap + return imap end return factory diff --git a/awesome/lain/widget/init.lua b/awesome/lain/widget/init.lua index 57b86bb..1ba8be9 100644 --- a/awesome/lain/widget/init.lua +++ b/awesome/lain/widget/init.lua @@ -11,9 +11,9 @@ --]] -local wrequire = require("lain.helpers").wrequire +local wrequire = require('lain.helpers').wrequire local setmetatable = setmetatable -local widget = { _NAME = "lain.widget" } +local widget = { _NAME = 'lain.widget' } return setmetatable(widget, { __index = wrequire }) diff --git a/awesome/lain/widget/mem.lua b/awesome/lain/widget/mem.lua index 0318494..597d15f 100644 --- a/awesome/lain/widget/mem.lua +++ b/awesome/lain/widget/mem.lua @@ -6,46 +6,53 @@ --]] -local helpers = require("lain.helpers") -local wibox = require("wibox") +local helpers = require('lain.helpers') +local wibox = require('wibox') local gmatch, lines, floor = string.gmatch, io.lines, math.floor -- Memory usage (ignoring caches) -- lain.widget.mem local function factory(args) - args = args or {} + args = args or {} - local mem = { widget = args.widget or wibox.widget.textbox() } - local timeout = args.timeout or 2 - local settings = args.settings or function() end + local mem = { widget = args.widget or wibox.widget.textbox() } + local timeout = args.timeout or 2 + local settings = args.settings or function() end - function mem.update() - mem_now = {} - for line in lines("/proc/meminfo") do - for k, v in gmatch(line, "([%a]+):[%s]+([%d]+).+") do - if k == "MemTotal" then mem_now.total = floor(v / 1024 + 0.5) - elseif k == "MemFree" then mem_now.free = floor(v / 1024 + 0.5) - elseif k == "Buffers" then mem_now.buf = floor(v / 1024 + 0.5) - elseif k == "Cached" then mem_now.cache = floor(v / 1024 + 0.5) - elseif k == "SwapTotal" then mem_now.swap = floor(v / 1024 + 0.5) - elseif k == "SwapFree" then mem_now.swapf = floor(v / 1024 + 0.5) - elseif k == "SReclaimable" then mem_now.srec = floor(v / 1024 + 0.5) - end - end - end + function mem.update() + mem_now = {} + for line in lines('/proc/meminfo') do + for k, v in gmatch(line, '([%a]+):[%s]+([%d]+).+') do + if k == 'MemTotal' then + mem_now.total = floor(v / 1024 + 0.5) + elseif k == 'MemFree' then + mem_now.free = floor(v / 1024 + 0.5) + elseif k == 'Buffers' then + mem_now.buf = floor(v / 1024 + 0.5) + elseif k == 'Cached' then + mem_now.cache = floor(v / 1024 + 0.5) + elseif k == 'SwapTotal' then + mem_now.swap = floor(v / 1024 + 0.5) + elseif k == 'SwapFree' then + mem_now.swapf = floor(v / 1024 + 0.5) + elseif k == 'SReclaimable' then + mem_now.srec = floor(v / 1024 + 0.5) + end + end + end - mem_now.used = mem_now.total - mem_now.free - mem_now.buf - mem_now.cache - mem_now.srec - mem_now.swapused = mem_now.swap - mem_now.swapf - mem_now.perc = math.floor(mem_now.used / mem_now.total * 100) + mem_now.used = mem_now.total - mem_now.free - mem_now.buf - mem_now.cache - mem_now.srec + mem_now.swapused = mem_now.swap - mem_now.swapf + mem_now.perc = math.floor(mem_now.used / mem_now.total * 100) - widget = mem.widget - settings() - end + widget = mem.widget + settings() + end - helpers.newtimer("mem", timeout, mem.update) + helpers.newtimer('mem', timeout, mem.update) - return mem + return mem end return factory diff --git a/awesome/lain/widget/mpd.lua b/awesome/lain/widget/mpd.lua index 55d3649..d786d14 100644 --- a/awesome/lain/widget/mpd.lua +++ b/awesome/lain/widget/mpd.lua @@ -6,130 +6,154 @@ --]] -local helpers = require("lain.helpers") -local shell = require("awful.util").shell -local escape_f = require("awful.util").escape -local focused = require("awful.screen").focused -local naughty = require("naughty") -local wibox = require("wibox") -local os = os -local string = string +local helpers = require('lain.helpers') +local shell = require('awful.util').shell +local escape_f = require('awful.util').escape +local focused = require('awful.screen').focused +local naughty = require('naughty') +local wibox = require('wibox') +local os = os +local string = string -- MPD infos -- lain.widget.mpd local function factory(args) - args = args or {} + args = args or {} - local mpd = { widget = args.widget or wibox.widget.textbox() } - local timeout = args.timeout or 2 - local password = (args.password and #args.password > 0 and string.format("password %s\\n", args.password)) or "" - local host = args.host or os.getenv("MPD_HOST") or "127.0.0.1" - local port = args.port or os.getenv("MPD_PORT") or "6600" - local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" - local cover_pattern = args.cover_pattern or "*\\.(jpg|jpeg|png|gif)$" - local cover_size = args.cover_size or 100 - local default_art = args.default_art - local notify = args.notify or "on" - local followtag = args.followtag or false - local settings = args.settings or function() end + local mpd = { widget = args.widget or wibox.widget.textbox() } + local timeout = args.timeout or 2 + local password = (args.password and #args.password > 0 and string.format('password %s\\n', args.password)) or '' + local host = args.host or os.getenv('MPD_HOST') or '127.0.0.1' + local port = args.port or os.getenv('MPD_PORT') or '6600' + local music_dir = args.music_dir or os.getenv('HOME') .. '/Music' + local cover_pattern = args.cover_pattern or '*\\.(jpg|jpeg|png|gif)$' + local cover_size = args.cover_size or 100 + local default_art = args.default_art + local notify = args.notify or 'on' + local followtag = args.followtag or false + local settings = args.settings or function() end - local mpdh = string.format("telnet://%s:%s", host, port) - local echo = string.format("printf \"%sstatus\\ncurrentsong\\nclose\\n\"", password) - local cmd = string.format("%s | curl --connect-timeout 1 -fsm 3 %s", echo, mpdh) + local mpdh = string.format('telnet://%s:%s', host, port) + local echo = string.format('printf "%sstatus\\ncurrentsong\\nclose\\n"', password) + local cmd = string.format('%s | curl --connect-timeout 1 -fsm 3 %s', echo, mpdh) - mpd_notification_preset = { title = "Now playing", timeout = 6 } + mpd_notification_preset = { title = 'Now playing', timeout = 6 } - helpers.set_map("current mpd track", nil) + helpers.set_map('current mpd track', nil) - function mpd.update() - helpers.async({ shell, "-c", cmd }, function(f) - mpd_now = { - random_mode = false, - single_mode = false, - repeat_mode = false, - consume_mode = false, - pls_pos = "N/A", - pls_len = "N/A", - state = "N/A", - file = "N/A", - name = "N/A", - artist = "N/A", - title = "N/A", - album = "N/A", - genre = "N/A", - track = "N/A", - date = "N/A", - time = "N/A", - elapsed = "N/A", - volume = "N/A" - } + function mpd.update() + helpers.async({ shell, '-c', cmd }, function(f) + mpd_now = { + random_mode = false, + single_mode = false, + repeat_mode = false, + consume_mode = false, + pls_pos = 'N/A', + pls_len = 'N/A', + state = 'N/A', + file = 'N/A', + name = 'N/A', + artist = 'N/A', + title = 'N/A', + album = 'N/A', + genre = 'N/A', + track = 'N/A', + date = 'N/A', + time = 'N/A', + elapsed = 'N/A', + volume = 'N/A', + } - for line in string.gmatch(f, "[^\n]+") do - for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do - if k == "state" then mpd_now.state = v - elseif k == "file" then mpd_now.file = v - elseif k == "Name" then mpd_now.name = escape_f(v) - elseif k == "Artist" then mpd_now.artist = escape_f(v) - elseif k == "Title" then mpd_now.title = escape_f(v) - elseif k == "Album" then mpd_now.album = escape_f(v) - elseif k == "Genre" then mpd_now.genre = escape_f(v) - elseif k == "Track" then mpd_now.track = escape_f(v) - elseif k == "Date" then mpd_now.date = escape_f(v) - elseif k == "Time" then mpd_now.time = v - elseif k == "elapsed" then mpd_now.elapsed = string.match(v, "%d+") - elseif k == "song" then mpd_now.pls_pos = v - elseif k == "playlistlength" then mpd_now.pls_len = v - elseif k == "repeat" then mpd_now.repeat_mode = v ~= "0" - elseif k == "single" then mpd_now.single_mode = v ~= "0" - elseif k == "random" then mpd_now.random_mode = v ~= "0" - elseif k == "consume" then mpd_now.consume_mode = v ~= "0" - elseif k == "volume" then mpd_now.volume = v - end - end - end + for line in string.gmatch(f, '[^\n]+') do + for k, v in string.gmatch(line, '([%w]+):[%s](.*)$') do + if k == 'state' then + mpd_now.state = v + elseif k == 'file' then + mpd_now.file = v + elseif k == 'Name' then + mpd_now.name = escape_f(v) + elseif k == 'Artist' then + mpd_now.artist = escape_f(v) + elseif k == 'Title' then + mpd_now.title = escape_f(v) + elseif k == 'Album' then + mpd_now.album = escape_f(v) + elseif k == 'Genre' then + mpd_now.genre = escape_f(v) + elseif k == 'Track' then + mpd_now.track = escape_f(v) + elseif k == 'Date' then + mpd_now.date = escape_f(v) + elseif k == 'Time' then + mpd_now.time = v + elseif k == 'elapsed' then + mpd_now.elapsed = string.match(v, '%d+') + elseif k == 'song' then + mpd_now.pls_pos = v + elseif k == 'playlistlength' then + mpd_now.pls_len = v + elseif k == 'repeat' then + mpd_now.repeat_mode = v ~= '0' + elseif k == 'single' then + mpd_now.single_mode = v ~= '0' + elseif k == 'random' then + mpd_now.random_mode = v ~= '0' + elseif k == 'consume' then + mpd_now.consume_mode = v ~= '0' + elseif k == 'volume' then + mpd_now.volume = v + end + end + end - mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist, - mpd_now.album, mpd_now.date, mpd_now.title) - widget = mpd.widget - settings() + mpd_notification_preset.text = + string.format('%s (%s) - %s\n%s', mpd_now.artist, mpd_now.album, mpd_now.date, mpd_now.title) + widget = mpd.widget + settings() - if mpd_now.state == "play" then - if notify == "on" and mpd_now.title ~= helpers.get_map("current mpd track") then - helpers.set_map("current mpd track", mpd_now.title) + if mpd_now.state == 'play' then + if notify == 'on' and mpd_now.title ~= helpers.get_map('current mpd track') then + helpers.set_map('current mpd track', mpd_now.title) - if followtag then mpd_notification_preset.screen = focused() end + if followtag then + mpd_notification_preset.screen = focused() + end - local common = { - preset = mpd_notification_preset, - icon = default_art, - icon_size = cover_size, - replaces_id = mpd.id - } + local common = { + preset = mpd_notification_preset, + icon = default_art, + icon_size = cover_size, + replaces_id = mpd.id, + } - if not string.match(mpd_now.file, "http.*://") then -- local file instead of http stream - local path = string.format("%s/%s", music_dir, string.match(mpd_now.file, ".*/")) - local cover = string.format("find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'", - path:gsub("'", "'\\''"), cover_pattern) - helpers.async({ shell, "-c", cover }, function(current_icon) - common.icon = current_icon:gsub("\n", "") - if #common.icon == 0 then common.icon = nil end - mpd.id = naughty.notify(common).id - end) - else - mpd.id = naughty.notify(common).id - end + if not string.match(mpd_now.file, 'http.*://') then -- local file instead of http stream + local path = string.format('%s/%s', music_dir, string.match(mpd_now.file, '.*/')) + local cover = string.format( + "find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'", + path:gsub("'", "'\\''"), + cover_pattern + ) + helpers.async({ shell, '-c', cover }, function(current_icon) + common.icon = current_icon:gsub('\n', '') + if #common.icon == 0 then + common.icon = nil + end + mpd.id = naughty.notify(common).id + end) + else + mpd.id = naughty.notify(common).id + end + end + elseif mpd_now.state ~= 'pause' then + helpers.set_map('current mpd track', nil) + end + end) + end - end - elseif mpd_now.state ~= "pause" then - helpers.set_map("current mpd track", nil) - end - end) - end + mpd.timer = helpers.newtimer('mpd', timeout, mpd.update, true, true) - mpd.timer = helpers.newtimer("mpd", timeout, mpd.update, true, true) - - return mpd + return mpd end return factory diff --git a/awesome/lain/widget/net.lua b/awesome/lain/widget/net.lua index 9b7b165..5a95900 100644 --- a/awesome/lain/widget/net.lua +++ b/awesome/lain/widget/net.lua @@ -6,117 +6,128 @@ --]] -local helpers = require("lain.helpers") -local naughty = require("naughty") -local wibox = require("wibox") -local string = string +local helpers = require('lain.helpers') +local naughty = require('naughty') +local wibox = require('wibox') +local string = string -- Network infos -- lain.widget.net local function factory(args) - args = args or {} + args = args or {} - local net = { widget = args.widget or wibox.widget.textbox(), devices = {} } - local timeout = args.timeout or 2 - local units = args.units or 1024 -- KB - local notify = args.notify or "on" - local wifi_state = args.wifi_state or "off" - local eth_state = args.eth_state or "off" - local screen = args.screen or 1 - local format = args.format or "%.1f" - local settings = args.settings or function() end + local net = { widget = args.widget or wibox.widget.textbox(), devices = {} } + local timeout = args.timeout or 2 + local units = args.units or 1024 -- KB + local notify = args.notify or 'on' + local wifi_state = args.wifi_state or 'off' + local eth_state = args.eth_state or 'off' + local screen = args.screen or 1 + local format = args.format or '%.1f' + local settings = args.settings or function() end - -- Compatibility with old API where iface was a string corresponding to 1 interface - net.iface = (args.iface and (type(args.iface) == "string" and {args.iface}) or - (type(args.iface) == "table" and args.iface)) or {} + -- Compatibility with old API where iface was a string corresponding to 1 interface + net.iface = ( + args.iface and (type(args.iface) == 'string' and { args.iface }) + or (type(args.iface) == 'table' and args.iface) + ) or {} - function net.get_devices() - net.iface = {} -- reset at every call - helpers.line_callback("ip link", function(line) - net.iface[#net.iface + 1] = not string.match(line, "LOOPBACK") and string.match(line, "(%w+): <") or nil - end) - end + function net.get_devices() + net.iface = {} -- reset at every call + helpers.line_callback('ip link', function(line) + net.iface[#net.iface + 1] = not string.match(line, 'LOOPBACK') and string.match(line, '(%w+): <') or nil + end) + end - if #net.iface == 0 then net.get_devices() end + if #net.iface == 0 then + net.get_devices() + end - function net.update() - -- These are the totals over all specified interfaces - net_now = { - devices = {}, - -- Bytes since last iteration - sent = 0, - received = 0 - } + function net.update() + -- These are the totals over all specified interfaces + net_now = { + devices = {}, + -- Bytes since last iteration + sent = 0, + received = 0, + } - for _, dev in ipairs(net.iface) do - local dev_now = {} - local dev_before = net.devices[dev] or { last_t = 0, last_r = 0 } - local now_t = tonumber(helpers.first_line(string.format("/sys/class/net/%s/statistics/tx_bytes", dev)) or 0) - local now_r = tonumber(helpers.first_line(string.format("/sys/class/net/%s/statistics/rx_bytes", dev)) or 0) + for _, dev in ipairs(net.iface) do + local dev_now = {} + local dev_before = net.devices[dev] or { last_t = 0, last_r = 0 } + local now_t = tonumber(helpers.first_line(string.format('/sys/class/net/%s/statistics/tx_bytes', dev)) or 0) + local now_r = tonumber(helpers.first_line(string.format('/sys/class/net/%s/statistics/rx_bytes', dev)) or 0) - dev_now.carrier = helpers.first_line(string.format("/sys/class/net/%s/carrier", dev)) or "0" - dev_now.state = helpers.first_line(string.format("/sys/class/net/%s/operstate", dev)) or "down" + dev_now.carrier = helpers.first_line(string.format('/sys/class/net/%s/carrier', dev)) or '0' + dev_now.state = helpers.first_line(string.format('/sys/class/net/%s/operstate', dev)) or 'down' - dev_now.sent = (now_t - dev_before.last_t) / timeout / units - dev_now.received = (now_r - dev_before.last_r) / timeout / units + dev_now.sent = (now_t - dev_before.last_t) / timeout / units + dev_now.received = (now_r - dev_before.last_r) / timeout / units - net_now.sent = net_now.sent + dev_now.sent - net_now.received = net_now.received + dev_now.received + net_now.sent = net_now.sent + dev_now.sent + net_now.received = net_now.received + dev_now.received - dev_now.sent = string.format(format, dev_now.sent) - dev_now.received = string.format(format, dev_now.received) + dev_now.sent = string.format(format, dev_now.sent) + dev_now.received = string.format(format, dev_now.received) - dev_now.last_t = now_t - dev_now.last_r = now_r + dev_now.last_t = now_t + dev_now.last_r = now_r - if wifi_state == "on" and helpers.first_line(string.format("/sys/class/net/%s/uevent", dev)) == "DEVTYPE=wlan" then - dev_now.wifi = true - if string.match(dev_now.carrier, "1") then - dev_now.signal = tonumber(string.match(helpers.lines_from("/proc/net/wireless")[3], "(%-%d+%.)")) or nil - end - else - dev_now.wifi = false - end + if + wifi_state == 'on' + and helpers.first_line(string.format('/sys/class/net/%s/uevent', dev)) == 'DEVTYPE=wlan' + then + dev_now.wifi = true + if string.match(dev_now.carrier, '1') then + dev_now.signal = tonumber(string.match(helpers.lines_from('/proc/net/wireless')[3], '(%-%d+%.)')) + or nil + end + else + dev_now.wifi = false + end - if eth_state == "on" and helpers.first_line(string.format("/sys/class/net/%s/uevent", dev)) ~= "DEVTYPE=wlan" then - dev_now.ethernet = true - else - dev_now.ethernet = false - end + if + eth_state == 'on' + and helpers.first_line(string.format('/sys/class/net/%s/uevent', dev)) ~= 'DEVTYPE=wlan' + then + dev_now.ethernet = true + else + dev_now.ethernet = false + end - net.devices[dev] = dev_now + net.devices[dev] = dev_now - -- Notify only once when connection is lost - if string.match(dev_now.carrier, "0") and notify == "on" and helpers.get_map(dev) then - naughty.notify { - title = dev, - text = "No carrier", - icon = helpers.icons_dir .. "no_net.png", - screen = screen - } - helpers.set_map(dev, false) - elseif string.match(dev_now.carrier, "1") then - helpers.set_map(dev, true) - end + -- Notify only once when connection is lost + if string.match(dev_now.carrier, '0') and notify == 'on' and helpers.get_map(dev) then + naughty.notify({ + title = dev, + text = 'No carrier', + icon = helpers.icons_dir .. 'no_net.png', + screen = screen, + }) + helpers.set_map(dev, false) + elseif string.match(dev_now.carrier, '1') then + helpers.set_map(dev, true) + end - net_now.carrier = dev_now.carrier - net_now.state = dev_now.state - net_now.devices[dev] = dev_now - -- net_now.sent and net_now.received will be - -- the totals across all specified devices - end + net_now.carrier = dev_now.carrier + net_now.state = dev_now.state + net_now.devices[dev] = dev_now + -- net_now.sent and net_now.received will be + -- the totals across all specified devices + end - net_now.sent = string.format(format, net_now.sent) - net_now.received = string.format(format, net_now.received) + net_now.sent = string.format(format, net_now.sent) + net_now.received = string.format(format, net_now.received) - widget = net.widget - settings() - end + widget = net.widget + settings() + end - helpers.newtimer("network", timeout, net.update) + helpers.newtimer('network', timeout, net.update) - return net + return net end return factory diff --git a/awesome/lain/widget/pulse.lua b/awesome/lain/widget/pulse.lua index 69f4d70..7c3845c 100644 --- a/awesome/lain/widget/pulse.lua +++ b/awesome/lain/widget/pulse.lua @@ -5,54 +5,56 @@ --]] -local helpers = require("lain.helpers") -local shell = require("awful.util").shell -local wibox = require("wibox") -local string = string -local type = type +local helpers = require('lain.helpers') +local shell = require('awful.util').shell +local wibox = require('wibox') +local string = string +local type = type -- PulseAudio volume -- lain.widget.pulse local function factory(args) - args = args or {} + args = args or {} - local pulse = { widget = args.widget or wibox.widget.textbox(), device = "N/A" } - local timeout = args.timeout or 5 - local settings = args.settings or function() end + local pulse = { widget = args.widget or wibox.widget.textbox(), device = 'N/A' } + local timeout = args.timeout or 5 + local settings = args.settings or function() end - pulse.devicetype = args.devicetype or "sink" - pulse.cmd = args.cmd or "pacmd list-" .. pulse.devicetype .. "s | sed -n -e '/*/,$!d' -e '/index/p' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'" + pulse.devicetype = args.devicetype or 'sink' + pulse.cmd = args.cmd + or 'pacmd list-' + .. pulse.devicetype + .. "s | sed -n -e '/*/,$!d' -e '/index/p' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'" - function pulse.update() - helpers.async({ shell, "-c", type(pulse.cmd) == "string" and pulse.cmd or pulse.cmd() }, - function(s) - volume_now = { - index = string.match(s, "index: (%S+)") or "N/A", - device = string.match(s, "device.string = \"(%S+)\"") or "N/A", - muted = string.match(s, "muted: (%S+)") or "N/A" - } + function pulse.update() + helpers.async({ shell, '-c', type(pulse.cmd) == 'string' and pulse.cmd or pulse.cmd() }, function(s) + volume_now = { + index = string.match(s, 'index: (%S+)') or 'N/A', + device = string.match(s, 'device.string = "(%S+)"') or 'N/A', + muted = string.match(s, 'muted: (%S+)') or 'N/A', + } - pulse.device = volume_now.index + pulse.device = volume_now.index - local ch = 1 - volume_now.channel = {} - for v in string.gmatch(s, ":.-(%d+)%%") do - volume_now.channel[ch] = v - ch = ch + 1 - end + local ch = 1 + volume_now.channel = {} + for v in string.gmatch(s, ':.-(%d+)%%') do + volume_now.channel[ch] = v + ch = ch + 1 + end - volume_now.left = volume_now.channel[1] or "N/A" - volume_now.right = volume_now.channel[2] or "N/A" + volume_now.left = volume_now.channel[1] or 'N/A' + volume_now.right = volume_now.channel[2] or 'N/A' - widget = pulse.widget - settings() - end) - end + widget = pulse.widget + settings() + end) + end - helpers.newtimer("pulse", timeout, pulse.update) + helpers.newtimer('pulse', timeout, pulse.update) - return pulse + return pulse end return factory diff --git a/awesome/lain/widget/pulsebar.lua b/awesome/lain/widget/pulsebar.lua index 19e73b9..3cd5f07 100644 --- a/awesome/lain/widget/pulsebar.lua +++ b/awesome/lain/widget/pulsebar.lua @@ -6,170 +6,180 @@ --]] -local helpers = require("lain.helpers") -local awful = require("awful") -local naughty = require("naughty") -local wibox = require("wibox") -local math = math -local string = string -local type = type +local helpers = require('lain.helpers') +local awful = require('awful') +local naughty = require('naughty') +local wibox = require('wibox') +local math = math +local string = string +local type = type local tonumber = tonumber -- PulseAudio volume bar -- lain.widget.pulsebar local function factory(args) - local pulsebar = { - colors = { - background = "#000000", - mute_background = "#000000", - mute = "#EB8F8F", - unmute = "#A4CE8A" - }, + local pulsebar = { + colors = { + background = '#000000', + mute_background = '#000000', + mute = '#EB8F8F', + unmute = '#A4CE8A', + }, - _current_level = 0, - _mute = "no", - device = "N/A" - } + _current_level = 0, + _mute = 'no', + device = 'N/A', + } - args = args or {} + args = args or {} - local timeout = args.timeout or 5 - local settings = args.settings or function() end - local width = args.width or 63 - local height = args.height or 1 - local margins = args.margins or 1 - local paddings = args.paddings or 1 - local ticks = args.ticks or false - local ticks_size = args.ticks_size or 7 - local tick = args.tick or "|" - local tick_pre = args.tick_pre or "[" - local tick_post = args.tick_post or "]" - local tick_none = args.tick_none or " " + local timeout = args.timeout or 5 + local settings = args.settings or function() end + local width = args.width or 63 + local height = args.height or 1 + local margins = args.margins or 1 + local paddings = args.paddings or 1 + local ticks = args.ticks or false + local ticks_size = args.ticks_size or 7 + local tick = args.tick or '|' + local tick_pre = args.tick_pre or '[' + local tick_post = args.tick_post or ']' + local tick_none = args.tick_none or ' ' - pulsebar.colors = args.colors or pulsebar.colors - pulsebar.followtag = args.followtag or false - pulsebar.notification_preset = args.notification_preset - pulsebar.devicetype = args.devicetype or "sink" - pulsebar.cmd = args.cmd or "pacmd list-" .. pulsebar.devicetype .. "s | sed -n -e '/*/,$!d' -e '/index/p' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'" + pulsebar.colors = args.colors or pulsebar.colors + pulsebar.followtag = args.followtag or false + pulsebar.notification_preset = args.notification_preset + pulsebar.devicetype = args.devicetype or 'sink' + pulsebar.cmd = args.cmd + or 'pacmd list-' + .. pulsebar.devicetype + .. "s | sed -n -e '/*/,$!d' -e '/index/p' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'" - if not pulsebar.notification_preset then - pulsebar.notification_preset = { - font = "Monospace 10" - } - end + if not pulsebar.notification_preset then + pulsebar.notification_preset = { + font = 'Monospace 10', + } + end - pulsebar.bar = wibox.widget { - color = pulsebar.colors.unmute, - background_color = pulsebar.colors.background, - forced_height = height, - forced_width = width, - margins = margins, - paddings = paddings, - ticks = ticks, - ticks_size = ticks_size, - widget = wibox.widget.progressbar, - } + pulsebar.bar = wibox.widget({ + color = pulsebar.colors.unmute, + background_color = pulsebar.colors.background, + forced_height = height, + forced_width = width, + margins = margins, + paddings = paddings, + ticks = ticks, + ticks_size = ticks_size, + widget = wibox.widget.progressbar, + }) - pulsebar.tooltip = awful.tooltip({ objects = { pulsebar.bar } }) + pulsebar.tooltip = awful.tooltip({ objects = { pulsebar.bar } }) - function pulsebar.update(callback) - helpers.async({ awful.util.shell, "-c", type(pulsebar.cmd) == "string" and pulsebar.cmd or pulsebar.cmd() }, - function(s) - volume_now = { - index = string.match(s, "index: (%S+)") or "N/A", - device = string.match(s, "device.string = \"(%S+)\"") or "N/A", - muted = string.match(s, "muted: (%S+)") or "N/A" - } + function pulsebar.update(callback) + helpers.async( + { awful.util.shell, '-c', type(pulsebar.cmd) == 'string' and pulsebar.cmd or pulsebar.cmd() }, + function(s) + volume_now = { + index = string.match(s, 'index: (%S+)') or 'N/A', + device = string.match(s, 'device.string = "(%S+)"') or 'N/A', + muted = string.match(s, 'muted: (%S+)') or 'N/A', + } - pulsebar.device = volume_now.index + pulsebar.device = volume_now.index - local ch = 1 - volume_now.channel = {} - for v in string.gmatch(s, ":.-(%d+)%%") do - volume_now.channel[ch] = v - ch = ch + 1 - end + local ch = 1 + volume_now.channel = {} + for v in string.gmatch(s, ':.-(%d+)%%') do + volume_now.channel[ch] = v + ch = ch + 1 + end - volume_now.left = volume_now.channel[1] or "N/A" - volume_now.right = volume_now.channel[2] or "N/A" + volume_now.left = volume_now.channel[1] or 'N/A' + volume_now.right = volume_now.channel[2] or 'N/A' - local volu = volume_now.left - local mute = volume_now.muted + local volu = volume_now.left + local mute = volume_now.muted - if volu:match("N/A") or mute:match("N/A") then return end + if volu:match('N/A') or mute:match('N/A') then + return + end - if volu ~= pulsebar._current_level or mute ~= pulsebar._mute then - pulsebar._current_level = tonumber(volu) - pulsebar.bar:set_value(pulsebar._current_level / 100) - if pulsebar._current_level == 0 or mute == "yes" then - pulsebar._mute = mute - pulsebar.tooltip:set_text ("[muted]") - pulsebar.bar.color = pulsebar.colors.mute - pulsebar.bar.background_color = pulsebar.colors.mute_background - else - pulsebar._mute = "no" - pulsebar.tooltip:set_text(string.format("%s %s: %s", pulsebar.devicetype, pulsebar.device, volu)) - pulsebar.bar.color = pulsebar.colors.unmute - pulsebar.bar.background_color = pulsebar.colors.background - end + if volu ~= pulsebar._current_level or mute ~= pulsebar._mute then + pulsebar._current_level = tonumber(volu) + pulsebar.bar:set_value(pulsebar._current_level / 100) + if pulsebar._current_level == 0 or mute == 'yes' then + pulsebar._mute = mute + pulsebar.tooltip:set_text('[muted]') + pulsebar.bar.color = pulsebar.colors.mute + pulsebar.bar.background_color = pulsebar.colors.mute_background + else + pulsebar._mute = 'no' + pulsebar.tooltip:set_text( + string.format('%s %s: %s', pulsebar.devicetype, pulsebar.device, volu) + ) + pulsebar.bar.color = pulsebar.colors.unmute + pulsebar.bar.background_color = pulsebar.colors.background + end - settings() + settings() - if type(callback) == "function" then callback() end - end - end) - end + if type(callback) == 'function' then + callback() + end + end + end + ) + end - function pulsebar.notify() - pulsebar.update(function() - local preset = pulsebar.notification_preset + function pulsebar.notify() + pulsebar.update(function() + local preset = pulsebar.notification_preset - preset.title = string.format("%s %s - %s%%", pulsebar.devicetype, pulsebar.device, pulsebar._current_level) + preset.title = string.format('%s %s - %s%%', pulsebar.devicetype, pulsebar.device, pulsebar._current_level) - if pulsebar._mute == "yes" then - preset.title = preset.title .. " muted" - end + if pulsebar._mute == 'yes' then + preset.title = preset.title .. ' muted' + end - -- tot is the maximum number of ticks to display in the notification - -- fallback: default horizontal wibox height - local wib, tot = awful.screen.focused().mywibox, 20 + -- tot is the maximum number of ticks to display in the notification + -- fallback: default horizontal wibox height + local wib, tot = awful.screen.focused().mywibox, 20 - -- if we can grab mywibox, tot is defined as its height if - -- horizontal, or width otherwise - if wib then - if wib.position == "left" or wib.position == "right" then - tot = wib.width - else - tot = wib.height - end - end + -- if we can grab mywibox, tot is defined as its height if + -- horizontal, or width otherwise + if wib then + if wib.position == 'left' or wib.position == 'right' then + tot = wib.width + else + tot = wib.height + end + end - local int = math.modf((pulsebar._current_level / 100) * tot) - preset.text = string.format( - "%s%s%s%s", - tick_pre, - string.rep(tick, int), - string.rep(tick_none, tot - int), - tick_post - ) + local int = math.modf((pulsebar._current_level / 100) * tot) + preset.text = + string.format('%s%s%s%s', tick_pre, string.rep(tick, int), string.rep(tick_none, tot - int), tick_post) - if pulsebar.followtag then preset.screen = awful.screen.focused() end + if pulsebar.followtag then + preset.screen = awful.screen.focused() + end - if not pulsebar.notification then - pulsebar.notification = naughty.notify { - preset = preset, - destroy = function() pulsebar.notification = nil end - } - else - naughty.replace_text(pulsebar.notification, preset.title, preset.text) - end - end) - end + if not pulsebar.notification then + pulsebar.notification = naughty.notify({ + preset = preset, + destroy = function() + pulsebar.notification = nil + end, + }) + else + naughty.replace_text(pulsebar.notification, preset.title, preset.text) + end + end) + end - helpers.newtimer(string.format("pulsebar-%s-%s", pulsebar.devicetype, pulsebar.device), timeout, pulsebar.update) + helpers.newtimer(string.format('pulsebar-%s-%s', pulsebar.devicetype, pulsebar.device), timeout, pulsebar.update) - return pulsebar + return pulsebar end return factory diff --git a/awesome/lain/widget/sysload.lua b/awesome/lain/widget/sysload.lua index 7260524..1704432 100644 --- a/awesome/lain/widget/sysload.lua +++ b/awesome/lain/widget/sysload.lua @@ -6,34 +6,34 @@ --]] -local helpers = require("lain.helpers") -local wibox = require("wibox") +local helpers = require('lain.helpers') +local wibox = require('wibox') local open, match = io.open, string.match -- System load -- lain.widget.sysload local function factory(args) - args = args or {} + args = args or {} - local sysload = { widget = args.widget or wibox.widget.textbox() } - local timeout = args.timeout or 2 - local settings = args.settings or function() end + local sysload = { widget = args.widget or wibox.widget.textbox() } + local timeout = args.timeout or 2 + local settings = args.settings or function() end - function sysload.update() - local f = open("/proc/loadavg") - local ret = f:read("*all") - f:close() + function sysload.update() + local f = open('/proc/loadavg') + local ret = f:read('*all') + f:close() - load_1, load_5, load_15 = match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") + load_1, load_5, load_15 = match(ret, '([^%s]+) ([^%s]+) ([^%s]+)') - widget = sysload.widget - settings() - end + widget = sysload.widget + settings() + end - helpers.newtimer("sysload", timeout, sysload.update) + helpers.newtimer('sysload', timeout, sysload.update) - return sysload + return sysload end return factory diff --git a/awesome/lain/widget/temp.lua b/awesome/lain/widget/temp.lua index 99f8700..ed0f24a 100644 --- a/awesome/lain/widget/temp.lua +++ b/awesome/lain/widget/temp.lua @@ -5,46 +5,46 @@ --]] -local helpers = require("lain.helpers") -local wibox = require("wibox") +local helpers = require('lain.helpers') +local wibox = require('wibox') local tonumber = tonumber -- {thermal,core} temperature info -- lain.widget.temp local function factory(args) - args = args or {} + args = args or {} - local temp = { widget = args.widget or wibox.widget.textbox() } - local timeout = args.timeout or 30 - local tempfile = args.tempfile or "/sys/devices/virtual/thermal/thermal_zone0/temp" - local format = args.format or "%.1f" - local settings = args.settings or function() end + local temp = { widget = args.widget or wibox.widget.textbox() } + local timeout = args.timeout or 30 + local tempfile = args.tempfile or '/sys/devices/virtual/thermal/thermal_zone0/temp' + local format = args.format or '%.1f' + local settings = args.settings or function() end - function temp.update() - helpers.async({"find", "/sys/devices", "-type", "f", "-name", "*temp*"}, function(f) - temp_now = {} - local temp_fl, temp_value - for t in f:gmatch("[^\n]+") do - temp_fl = helpers.first_line(t) - if temp_fl then - temp_value = tonumber(temp_fl) - temp_now[t] = temp_value and temp_value/1e3 or temp_fl - end - end - if temp_now[tempfile] then - coretemp_now = string.format(format, temp_now[tempfile]) - else - coretemp_now = "N/A" - end - widget = temp.widget - settings() - end) - end + function temp.update() + helpers.async({ 'find', '/sys/devices', '-type', 'f', '-name', '*temp*' }, function(f) + temp_now = {} + local temp_fl, temp_value + for t in f:gmatch('[^\n]+') do + temp_fl = helpers.first_line(t) + if temp_fl then + temp_value = tonumber(temp_fl) + temp_now[t] = temp_value and temp_value / 1e3 or temp_fl + end + end + if temp_now[tempfile] then + coretemp_now = string.format(format, temp_now[tempfile]) + else + coretemp_now = 'N/A' + end + widget = temp.widget + settings() + end) + end - helpers.newtimer("thermal", timeout, temp.update) + helpers.newtimer('thermal', timeout, temp.update) - return temp + return temp end return factory diff --git a/awesome/lain/widget/weather.lua b/awesome/lain/widget/weather.lua index 6937ca3..e042ab6 100644 --- a/awesome/lain/widget/weather.lua +++ b/awesome/lain/widget/weather.lua @@ -5,15 +5,15 @@ --]] -local helpers = require("lain.helpers") -local json = require("lain.util").dkjson -local focused = require("awful.screen").focused -local naughty = require("naughty") -local wibox = require("wibox") -local math = math -local os = os -local string = string -local type = type +local helpers = require('lain.helpers') +local json = require('lain.util').dkjson +local focused = require('awful.screen').focused +local naughty = require('naughty') +local wibox = require('wibox') +local math = math +local os = os +local string = string +local type = type local tonumber = tonumber -- OpenWeatherMap @@ -21,126 +21,131 @@ local tonumber = tonumber -- lain.widget.weather local function factory(args) - args = args or {} + args = args or {} - local weather = { widget = args.widget or wibox.widget.textbox() } - local APPID = args.APPID -- mandatory - local timeout = args.timeout or 60 * 15 -- 15 min - local current_call = args.current_call or "curl -s 'https://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s&APPID=%s'" - local forecast_call = args.forecast_call or "curl -s 'https://api.openweathermap.org/data/2.5/forecast?id=%s&units=%s&lang=%s&APPID=%s'" - local city_id = args.city_id or 0 -- placeholder - local units = args.units or "metric" - local lang = args.lang or "en" - local cnt = args.cnt or 5 - local icons_path = args.icons_path or helpers.icons_dir .. "openweathermap/" - local notification_preset = args.notification_preset or {} - local notification_text_fun = args.notification_text_fun or - function (wn) - local day = os.date("%a %d", wn["dt"]) - local temp = math.floor(wn["main"]["temp"]) - local desc = wn["weather"][1]["description"] - return string.format("%s: %s, %d ", day, desc, temp) - end - local weather_na_markup = args.weather_na_markup or " N/A " - local followtag = args.followtag or false - local showpopup = args.showpopup or "on" - local settings = args.settings or function() end + local weather = { widget = args.widget or wibox.widget.textbox() } + local APPID = args.APPID -- mandatory + local timeout = args.timeout or 60 * 15 -- 15 min + local current_call = args.current_call + or "curl -s 'https://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s&APPID=%s'" + local forecast_call = args.forecast_call + or "curl -s 'https://api.openweathermap.org/data/2.5/forecast?id=%s&units=%s&lang=%s&APPID=%s'" + local city_id = args.city_id or 0 -- placeholder + local units = args.units or 'metric' + local lang = args.lang or 'en' + local cnt = args.cnt or 5 + local icons_path = args.icons_path or helpers.icons_dir .. 'openweathermap/' + local notification_preset = args.notification_preset or {} + local notification_text_fun = args.notification_text_fun + or function(wn) + local day = os.date('%a %d', wn['dt']) + local temp = math.floor(wn['main']['temp']) + local desc = wn['weather'][1]['description'] + return string.format('%s: %s, %d ', day, desc, temp) + end + local weather_na_markup = args.weather_na_markup or ' N/A ' + local followtag = args.followtag or false + local showpopup = args.showpopup or 'on' + local settings = args.settings or function() end - weather.widget:set_markup(weather_na_markup) - weather.icon_path = icons_path .. "na.png" - weather.icon = wibox.widget.imagebox(weather.icon_path) + weather.widget:set_markup(weather_na_markup) + weather.icon_path = icons_path .. 'na.png' + weather.icon = wibox.widget.imagebox(weather.icon_path) - function weather.show(seconds) - weather.hide() + function weather.show(seconds) + weather.hide() - if followtag then - notification_preset.screen = focused() - end + if followtag then + notification_preset.screen = focused() + end - if not weather.notification_text then - weather.update() - weather.forecast_update() - end + if not weather.notification_text then + weather.update() + weather.forecast_update() + end - weather.notification = naughty.notify { - preset = notification_preset, - text = weather.notification_text, - icon = weather.icon_path, - timeout = type(seconds) == "number" and seconds or notification_preset.timeout - } - end + weather.notification = naughty.notify({ + preset = notification_preset, + text = weather.notification_text, + icon = weather.icon_path, + timeout = type(seconds) == 'number' and seconds or notification_preset.timeout, + }) + end - function weather.hide() - if weather.notification then - naughty.destroy(weather.notification) - weather.notification = nil - end - end + function weather.hide() + if weather.notification then + naughty.destroy(weather.notification) + weather.notification = nil + end + end - function weather.attach(obj) - obj:connect_signal("mouse::enter", function() - weather.show(0) - end) - obj:connect_signal("mouse::leave", function() - weather.hide() - end) - end + function weather.attach(obj) + obj:connect_signal('mouse::enter', function() + weather.show(0) + end) + obj:connect_signal('mouse::leave', function() + weather.hide() + end) + end - function weather.forecast_update() - local cmd = string.format(forecast_call, city_id, units, lang, APPID) - helpers.async(cmd, function(f) - local err - weather_now, _, err = json.decode(f, 1, nil) + function weather.forecast_update() + local cmd = string.format(forecast_call, city_id, units, lang, APPID) + helpers.async(cmd, function(f) + local err + weather_now, _, err = json.decode(f, 1, nil) - if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then - weather.notification_text = "" - for i = 1, weather_now["cnt"], math.floor(weather_now["cnt"] / cnt) do - weather.notification_text = weather.notification_text .. - notification_text_fun(weather_now["list"][i]) - if i < weather_now["cnt"] then - weather.notification_text = weather.notification_text .. "\n" - end - end - end - end) - end + if not err and type(weather_now) == 'table' and tonumber(weather_now['cod']) == 200 then + weather.notification_text = '' + for i = 1, weather_now['cnt'], math.floor(weather_now['cnt'] / cnt) do + weather.notification_text = weather.notification_text + .. notification_text_fun(weather_now['list'][i]) + if i < weather_now['cnt'] then + weather.notification_text = weather.notification_text .. '\n' + end + end + end + end) + end - function weather.update() - local cmd = string.format(current_call, city_id, units, lang, APPID) - helpers.async(cmd, function(f) - local err - weather_now, _, err = json.decode(f, 1, nil) + function weather.update() + local cmd = string.format(current_call, city_id, units, lang, APPID) + helpers.async(cmd, function(f) + local err + weather_now, _, err = json.decode(f, 1, nil) - if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then - local sunrise = tonumber(weather_now["sys"]["sunrise"]) - local sunset = tonumber(weather_now["sys"]["sunset"]) - local icon = weather_now["weather"][1]["icon"] - local loc_now = os.time() + if not err and type(weather_now) == 'table' and tonumber(weather_now['cod']) == 200 then + local sunrise = tonumber(weather_now['sys']['sunrise']) + local sunset = tonumber(weather_now['sys']['sunset']) + local icon = weather_now['weather'][1]['icon'] + local loc_now = os.time() - if sunrise <= loc_now and loc_now <= sunset then - icon = string.gsub(icon, "n", "d") - else - icon = string.gsub(icon, "d", "n") - end + if sunrise <= loc_now and loc_now <= sunset then + icon = string.gsub(icon, 'n', 'd') + else + icon = string.gsub(icon, 'd', 'n') + end - weather.icon_path = icons_path .. icon .. ".png" - widget = weather.widget - settings() - else - weather.icon_path = icons_path .. "na.png" - weather.widget:set_markup(weather_na_markup) - end + weather.icon_path = icons_path .. icon .. '.png' + widget = weather.widget + settings() + else + weather.icon_path = icons_path .. 'na.png' + weather.widget:set_markup(weather_na_markup) + end - weather.icon:set_image(weather.icon_path) - end) - end + weather.icon:set_image(weather.icon_path) + end) + end - if showpopup == "on" then weather.attach(weather.widget) end + if showpopup == 'on' then + weather.attach(weather.widget) + end - weather.timer = helpers.newtimer("weather-" .. city_id, timeout, weather.update, false, true) - weather.timer_forecast = helpers.newtimer("weather_forecast-" .. city_id, timeout, weather.forecast_update, false, true) + weather.timer = helpers.newtimer('weather-' .. city_id, timeout, weather.update, false, true) + weather.timer_forecast = + helpers.newtimer('weather_forecast-' .. city_id, timeout, weather.forecast_update, false, true) - return weather + return weather end return factory diff --git a/awesome/theme.lua b/awesome/theme.lua index b3810f2..2b0347f 100644 --- a/awesome/theme.lua +++ b/awesome/theme.lua @@ -10,13 +10,29 @@ local lain = require('lain') local awful = require('awful') local wibox = require('wibox') local dpi = require('beautiful.xresources').apply_dpi +local naughty = require('naughty') +local settings = (function() + local status, settings = pcall(function() + return dofile(os.getenv('HOME') .. '/.config/awesome/settings.lua') + end) + if status then + return settings + else + naughty.notify({ + preset = naughty.config.presets.critical, + title = 'Error while parsing settings!', + text = settings, + }) + return {} + end +end)() local os = os local my_table = awful.util.table or gears.table -- 4.{0,1} compatibility local theme = {} theme.confdir = os.getenv('HOME') .. '/.config/awesome/' -theme.wallpaper = os.getenv('HOME') .. '/.config/awesome/wall.png' +theme.wallpaper = os.getenv('HOME') .. '/.config/awesome/' .. (settings['wallpaper'] or 'wall.png') theme.font = 'Terminus 8' theme.menu_bg_normal = '#000000' theme.menu_bg_focus = '#000000' @@ -146,29 +162,39 @@ local cpu = lain.widget.cpu({ end, }) +local optional = {} + -- Coretemp ---[[local tempicon = wibox.widget.imagebox(theme.widget_temp) -local temp = lain.widget.temp({ - settings = function() - widget:set_markup(markup.fontfg(theme.font, "#f1af5f", coretemp_now .. "°C ")) - end -})]] --- +if settings['show_temp'] == true then + local tempicon = wibox.widget.imagebox(theme.widget_temp) + local temp = lain.widget.temp({ + settings = function() + -- luacheck: globals widget coretemp_now + widget:set_markup(markup.fontfg(theme.font, '#f1af5f', coretemp_now .. '°C ')) + end, + }) + table.insert(optional, tempicon) + table.insert(optional, temp) +end -- Battery ---[[local baticon = wibox.widget.imagebox(theme.widget_batt) -local bat = lain.widget.bat({ - settings = function() - local perc = bat_now.perc ~= "N/A" and bat_now.perc .. "%" or bat_now.perc +if settings['show_battery'] == true then + local baticon = wibox.widget.imagebox(theme.widget_batt) + local bat = lain.widget.bat({ + settings = function() + -- luacheck: globals widget bat_now + local perc = bat_now.perc ~= 'N/A' and bat_now.perc .. '%' or bat_now.perc - if bat_now.ac_status == 1 then - perc = perc .. " plug" - end + if bat_now.ac_status == 1 then + perc = perc .. ' plug' + end - widget:set_markup(markup.fontfg(theme.font, theme.fg_normal, perc .. " ")) - end -})]] --- + widget:set_markup(markup.fontfg(theme.font, theme.fg_normal, perc .. ' ')) + end, + }) + table.insert(optional, baticon) + table.insert(optional, bat) +end -- ALSA volume local volicon = wibox.widget.imagebox(theme.widget_vol) @@ -331,44 +357,43 @@ function theme.at_screen_connect(s) }, s.mytasklist, -- Middle widget --nil, - { -- Right widgets - layout = wibox.layout.fixed.horizontal, - wibox.widget.systray(), - --mailicon, - --theme.mail.widget, - { + gears.table.join( + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + wibox.widget.systray(), + --mailicon, + --theme.mail.widget, { { - layout = wibox.layout.fixed.horizontal, - netdownicon, - netdowninfo, - netupicon, - netupinfo.widget, + { + layout = wibox.layout.fixed.horizontal, + netdownicon, + netdowninfo, + netupicon, + netupinfo.widget, + }, + halign = 'right', + widget = wibox.container.place, }, - halign = 'right', - widget = wibox.container.place, + width = 120, + strategy = 'exact', + layout = wibox.layout.constraint, }, - width = 120, - strategy = 'exact', - layout = wibox.layout.constraint, + volicon, + theme.volume.widget, + memicon, + memory.widget, + cpuicon, + cpu.widget, + fsicon, + theme.fs.widget, }, - volicon, - theme.volume.widget, - memicon, - memory.widget, - cpuicon, - cpu.widget, - fsicon, - theme.fs.widget, - --weathericon, - --theme.weather.widget, - --tempicon, - --temp.widget, - --baticon, - --bat.widget, - clockicon, - mytextclock, - }, + optional, + { + clockicon, + mytextclock, + } + ), }) end diff --git a/awesome/wall2.png b/awesome/wall2.png new file mode 100644 index 0000000..308bebd Binary files /dev/null and b/awesome/wall2.png differ