Added settings.lua
This commit is contained in:
parent
80cc950271
commit
5cf452e053
@ -11,10 +11,10 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local theme = require("beautiful")
|
local theme = require('beautiful')
|
||||||
local utils = require("menubar.utils")
|
local utils = require('menubar.utils')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
|
|
||||||
local io = io
|
local io = io
|
||||||
local ipairs = ipairs
|
local ipairs = ipairs
|
||||||
@ -30,20 +30,20 @@ local desktop = {
|
|||||||
-- Default desktop basic icons
|
-- Default desktop basic icons
|
||||||
baseicons = {
|
baseicons = {
|
||||||
[1] = {
|
[1] = {
|
||||||
label = "This PC",
|
label = 'This PC',
|
||||||
icon = "computer",
|
icon = 'computer',
|
||||||
onclick = "computer://"
|
onclick = 'computer://',
|
||||||
},
|
},
|
||||||
[2] = {
|
[2] = {
|
||||||
label = "Home",
|
label = 'Home',
|
||||||
icon = "user-home",
|
icon = 'user-home',
|
||||||
onclick = os.getenv("HOME")
|
onclick = os.getenv('HOME'),
|
||||||
},
|
},
|
||||||
[3] = {
|
[3] = {
|
||||||
label = "Trash",
|
label = 'Trash',
|
||||||
icon = "user-trash",
|
icon = 'user-trash',
|
||||||
onclick = "trash://"
|
onclick = 'trash://',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
-- Default parameters
|
-- Default parameters
|
||||||
iconsize = { width = 48, height = 48 },
|
iconsize = { width = 48, height = 48 },
|
||||||
@ -62,7 +62,9 @@ local function pipelines(...)
|
|||||||
local f = assert(io.popen(...))
|
local f = assert(io.popen(...))
|
||||||
return function()
|
return function()
|
||||||
local data = f:read()
|
local data = f:read()
|
||||||
if data == nil then f:close() end
|
if data == nil then
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -78,18 +80,23 @@ function desktop.add_single_icon(args, label, icon, onclick)
|
|||||||
|
|
||||||
-- define icon dimensions and position
|
-- define icon dimensions and position
|
||||||
if not dcp[s] then
|
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 }
|
dcp[s] = {
|
||||||
|
x = (screen[s].geometry.x + args.iconsize.width + args.margin.x),
|
||||||
|
y = screen[s].geometry.y + 20 + args.margin.y,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local tot_height = (icon and args.iconsize.height or 0) + (label and args.labelsize.height or 0)
|
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 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
|
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].x = dcp[s].x + args.labelsize.width + args.iconsize.width + args.margin.x
|
||||||
dcp[s].y = 20 + args.margin.y
|
dcp[s].y = 20 + args.margin.y
|
||||||
end
|
end
|
||||||
|
|
||||||
local common = { screen = s, bg = "#00000000", visible = true, type = "desktop" }
|
local common = { screen = s, bg = '#00000000', visible = true, type = 'desktop' }
|
||||||
|
|
||||||
-- create icon container
|
-- create icon container
|
||||||
if icon then
|
if icon then
|
||||||
@ -98,11 +105,11 @@ function desktop.add_single_icon(args, label, icon, onclick)
|
|||||||
common.x = dcp[s].x
|
common.x = dcp[s].x
|
||||||
common.y = dcp[s].y
|
common.y = dcp[s].y
|
||||||
|
|
||||||
icon = wibox.widget {
|
icon = wibox.widget({
|
||||||
image = icon,
|
image = icon,
|
||||||
resize = false,
|
resize = false,
|
||||||
widget = wibox.widget.imagebox
|
widget = wibox.widget.imagebox,
|
||||||
}
|
})
|
||||||
|
|
||||||
icon:buttons(awful.button({}, 1, nil, onclick))
|
icon:buttons(awful.button({}, 1, nil, onclick))
|
||||||
|
|
||||||
@ -119,14 +126,14 @@ function desktop.add_single_icon(args, label, icon, onclick)
|
|||||||
common.x = dcp[s].x - (args.labelsize.width / 2) + args.iconsize.width / 2
|
common.x = dcp[s].x - (args.labelsize.width / 2) + args.iconsize.width / 2
|
||||||
common.y = dcp[s].y
|
common.y = dcp[s].y
|
||||||
|
|
||||||
caption = wibox.widget {
|
caption = wibox.widget({
|
||||||
text = label,
|
text = label,
|
||||||
align = "center",
|
align = 'center',
|
||||||
forced_width = common.width,
|
forced_width = common.width,
|
||||||
forced_height = common.height,
|
forced_height = common.height,
|
||||||
ellipsize = "middle",
|
ellipsize = 'middle',
|
||||||
widget = wibox.widget.textbox
|
widget = wibox.widget.textbox,
|
||||||
}
|
})
|
||||||
|
|
||||||
caption:buttons(awful.button({}, 1, onclick))
|
caption:buttons(awful.button({}, 1, onclick))
|
||||||
caption_container = wibox(common)
|
caption_container = wibox(common)
|
||||||
@ -156,15 +163,15 @@ end
|
|||||||
function desktop.lookup_file_icon(filename)
|
function desktop.lookup_file_icon(filename)
|
||||||
-- load system MIME types
|
-- load system MIME types
|
||||||
if #mime_types == 0 then
|
if #mime_types == 0 then
|
||||||
for line in io.lines("/etc/mime.types") do
|
for line in io.lines('/etc/mime.types') do
|
||||||
if not line:find("^#") then
|
if not line:find('^#') then
|
||||||
local parsed = {}
|
local parsed = {}
|
||||||
for w in line:gmatch("[^%s]+") do
|
for w in line:gmatch('[^%s]+') do
|
||||||
table.insert(parsed, w)
|
table.insert(parsed, w)
|
||||||
end
|
end
|
||||||
if #parsed > 1 then
|
if #parsed > 1 then
|
||||||
for i = 2, #parsed do
|
for i = 2, #parsed do
|
||||||
mime_types[parsed[i]] = parsed[1]:gsub("/", "-")
|
mime_types[parsed[i]] = parsed[1]:gsub('/', '-')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -172,23 +179,27 @@ function desktop.lookup_file_icon(filename)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- try to search a possible icon among standards
|
-- try to search a possible icon among standards
|
||||||
local extension = filename:match("%a+$")
|
local extension = filename:match('%a+$')
|
||||||
local mime = mime_types[extension] or ""
|
local mime = mime_types[extension] or ''
|
||||||
local mime_family = mime:match("^%a+") or ""
|
local mime_family = mime:match('^%a+') or ''
|
||||||
|
|
||||||
local possible_filenames = {
|
local possible_filenames = {
|
||||||
mime, "gnome-mime-" .. mime,
|
mime,
|
||||||
mime_family, "gnome-mime-" .. mime_family,
|
'gnome-mime-' .. mime,
|
||||||
extension
|
mime_family,
|
||||||
|
'gnome-mime-' .. mime_family,
|
||||||
|
extension,
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, filename in ipairs(possible_filenames) do
|
for i, filename in ipairs(possible_filenames) do
|
||||||
local icon = utils.lookup_icon(filename)
|
local icon = utils.lookup_icon(filename)
|
||||||
if icon then return icon end
|
if icon then
|
||||||
|
return icon
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- if we don"t find ad icon, then pretend is a plain text file
|
-- if we don"t find ad icon, then pretend is a plain text file
|
||||||
return utils.lookup_icon("text-x-generic")
|
return utils.lookup_icon('text-x-generic')
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Parse subdirectories and files list from input directory
|
-- Parse subdirectories and files list from input directory
|
||||||
@ -198,20 +209,20 @@ function desktop.parse_dirs_and_files(dir)
|
|||||||
local files = {}
|
local files = {}
|
||||||
local paths = pipelines('find ' .. dir .. ' -maxdepth 1 -type d |sort|tail -n +1')
|
local paths = pipelines('find ' .. dir .. ' -maxdepth 1 -type d |sort|tail -n +1')
|
||||||
for path in paths do
|
for path in paths do
|
||||||
if path:match("[^/]+$") then
|
if path:match('[^/]+$') then
|
||||||
local file = {}
|
local file = {}
|
||||||
file.filename = path:match("[^/]+$")
|
file.filename = path:match('[^/]+$')
|
||||||
file.path = path
|
file.path = path
|
||||||
file.show = true
|
file.show = true
|
||||||
file.icon = utils.lookup_icon("folder")
|
file.icon = utils.lookup_icon('folder')
|
||||||
table.insert(files, file)
|
table.insert(files, file)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local paths = pipelines('find ' .. dir .. ' -maxdepth 1 -type f')
|
local paths = pipelines('find ' .. dir .. ' -maxdepth 1 -type f')
|
||||||
for path in paths do
|
for path in paths do
|
||||||
if not path:find("%.desktop$") then
|
if not path:find('%.desktop$') then
|
||||||
local file = {}
|
local file = {}
|
||||||
file.filename = path:match("[^/]+$")
|
file.filename = path:match('[^/]+$')
|
||||||
file.path = path
|
file.path = path
|
||||||
file.show = true
|
file.show = true
|
||||||
file.icon = desktop.lookup_file_icon(file.filename)
|
file.icon = desktop.lookup_file_icon(file.filename)
|
||||||
@ -227,7 +238,9 @@ function desktop.add_dirs_and_files_icons(args)
|
|||||||
for _, file in ipairs(desktop.parse_dirs_and_files(args.dir)) do
|
for _, file in ipairs(desktop.parse_dirs_and_files(args.dir)) do
|
||||||
if file.show then
|
if file.show then
|
||||||
local label = args.showlabels and file.filename or nil
|
local label = args.showlabels and file.filename or nil
|
||||||
local onclick = function () awful.spawn(string.format("%s '%s'", args.open_with, file.path)) end
|
local onclick = function()
|
||||||
|
awful.spawn(string.format("%s '%s'", args.open_with, file.path))
|
||||||
|
end
|
||||||
desktop.add_single_icon(args, label, file.icon, onclick)
|
desktop.add_single_icon(args, label, file.icon, onclick)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -238,9 +251,9 @@ end
|
|||||||
function desktop.add_icons(args)
|
function desktop.add_icons(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
args.screen = args.screen or mouse.screen
|
args.screen = args.screen or mouse.screen
|
||||||
args.dir = args.dir or os.getenv("HOME") .. "/Desktop"
|
args.dir = args.dir or os.getenv('HOME') .. '/Desktop'
|
||||||
args.showlabels = args.showlabel or true
|
args.showlabels = args.showlabel or true
|
||||||
args.open_with = args.open_with or "xdg_open"
|
args.open_with = args.open_with or 'xdg_open'
|
||||||
args.baseicons = args.baseicons or desktop.baseicons
|
args.baseicons = args.baseicons or desktop.baseicons
|
||||||
args.iconsize = args.iconsize or desktop.iconsize
|
args.iconsize = args.iconsize or desktop.iconsize
|
||||||
args.labelsize = args.labelsize or desktop.labelsize
|
args.labelsize = args.labelsize or desktop.labelsize
|
||||||
@ -249,7 +262,7 @@ function desktop.add_icons(args)
|
|||||||
-- trying to fallback on Adwaita if theme.icon_theme is not defined
|
-- trying to fallback on Adwaita if theme.icon_theme is not defined
|
||||||
-- if Adwaita is missing too, no icons will be shown
|
-- if Adwaita is missing too, no icons will be shown
|
||||||
if not theme.icon_theme then
|
if not theme.icon_theme then
|
||||||
theme.icon_theme = args.icon_theme or "Adwaita"
|
theme.icon_theme = args.icon_theme or 'Adwaita'
|
||||||
end
|
end
|
||||||
|
|
||||||
desktop.add_base_icons(args)
|
desktop.add_base_icons(args)
|
||||||
|
@ -10,6 +10,6 @@
|
|||||||
--]]
|
--]]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
desktop = require("freedesktop.desktop"),
|
desktop = require('freedesktop.desktop'),
|
||||||
menu = require("freedesktop.menu")
|
menu = require('freedesktop.menu'),
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
--[[
|
--[[
|
||||||
|
|
||||||
Awesome-Freedesktop
|
Awesome-Freedesktop
|
||||||
@ -12,15 +11,15 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local Gio = require("lgi").Gio
|
local Gio = require('lgi').Gio
|
||||||
local awful_menu = require("awful.menu")
|
local awful_menu = require('awful.menu')
|
||||||
local menu_gen = require("menubar.menu_gen")
|
local menu_gen = require('menubar.menu_gen')
|
||||||
local menu_utils = require("menubar.utils")
|
local menu_utils = require('menubar.utils')
|
||||||
|
|
||||||
local io, pairs, string, table, os = io, pairs, string, table, os
|
local io, pairs, string, table, os = io, pairs, string, table, os
|
||||||
|
|
||||||
-- Expecting a wm_name of awesome omits too many applications and tools
|
-- Expecting a wm_name of awesome omits too many applications and tools
|
||||||
menu_utils.wm_name = ""
|
menu_utils.wm_name = ''
|
||||||
|
|
||||||
-- Menu
|
-- Menu
|
||||||
-- freedesktop.menu
|
-- freedesktop.menu
|
||||||
@ -30,7 +29,7 @@ local menu = {}
|
|||||||
-- @tparam string path The directory path
|
-- @tparam string path The directory path
|
||||||
-- @treturn boolean True if path exists and is a directory
|
-- @treturn boolean True if path exists and is a directory
|
||||||
function menu.is_dir(path)
|
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
|
end
|
||||||
|
|
||||||
-- Remove non existent paths in order to avoid issues
|
-- Remove non existent paths in order to avoid issues
|
||||||
@ -93,14 +92,18 @@ function menu.build(args)
|
|||||||
table.remove(result, i)
|
table.remove(result, i)
|
||||||
else
|
else
|
||||||
--Sort entries alphabetically (by name)
|
--Sort entries alphabetically (by name)
|
||||||
table.sort(v[2], function (a, b) return string.byte(a[1]) < string.byte(b[1]) end)
|
table.sort(v[2], function(a, b)
|
||||||
|
return string.byte(a[1]) < string.byte(b[1])
|
||||||
|
end)
|
||||||
-- Replace category name with nice name
|
-- Replace category name with nice name
|
||||||
v[1] = menu_gen.all_categories[v[1]].name
|
v[1] = menu_gen.all_categories[v[1]].name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Sort categories alphabetically also
|
-- Sort categories alphabetically also
|
||||||
table.sort(result, function(a, b) return string.byte(a[1]) < string.byte(b[1]) end)
|
table.sort(result, function(a, b)
|
||||||
|
return string.byte(a[1]) < string.byte(b[1])
|
||||||
|
end)
|
||||||
|
|
||||||
-- Add menu item to hold the generated menu
|
-- Add menu item to hold the generated menu
|
||||||
if sub_menu then
|
if sub_menu then
|
||||||
@ -108,8 +111,12 @@ function menu.build(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Add items to menu
|
-- Add items to menu
|
||||||
for _, v in pairs(result) do _menu:add(v) end
|
for _, v in pairs(result) do
|
||||||
for _, v in pairs(after) do _menu:add(v) end
|
_menu:add(v)
|
||||||
|
end
|
||||||
|
for _, v in pairs(after) do
|
||||||
|
_menu:add(v)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Hold the menu in the module
|
-- Hold the menu in the module
|
||||||
|
@ -5,11 +5,10 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local spawn = require("awful.spawn")
|
local spawn = require('awful.spawn')
|
||||||
local timer = require("gears.timer")
|
local timer = require('gears.timer')
|
||||||
local debug = require("debug")
|
local debug = require('debug')
|
||||||
local io = { lines = io.lines,
|
local io = { lines = io.lines, open = io.open }
|
||||||
open = io.open }
|
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local rawget = rawget
|
local rawget = rawget
|
||||||
local tsort = table.sort
|
local tsort = table.sort
|
||||||
@ -19,7 +18,7 @@ local unpack = unpack or table.unpack -- lua 5.1 retro-compatibility
|
|||||||
-- lain.helpers
|
-- lain.helpers
|
||||||
local helpers = {}
|
local helpers = {}
|
||||||
|
|
||||||
helpers.lain_dir = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
|
helpers.lain_dir = debug.getinfo(1, 'S').source:match([[^@(.*/).*$]])
|
||||||
helpers.icons_dir = helpers.lain_dir .. 'icons/'
|
helpers.icons_dir = helpers.lain_dir .. 'icons/'
|
||||||
helpers.scripts_dir = helpers.lain_dir .. 'scripts/'
|
helpers.scripts_dir = helpers.lain_dir .. 'scripts/'
|
||||||
|
|
||||||
@ -35,8 +34,10 @@ end
|
|||||||
|
|
||||||
-- check if the file exists and is readable
|
-- check if the file exists and is readable
|
||||||
function helpers.file_exists(path)
|
function helpers.file_exists(path)
|
||||||
local file = io.open(path, "rb")
|
local file = io.open(path, 'rb')
|
||||||
if file then file:close() end
|
if file then
|
||||||
|
file:close()
|
||||||
|
end
|
||||||
return file ~= nil
|
return file ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -62,9 +63,9 @@ end
|
|||||||
|
|
||||||
-- get first line of a file
|
-- get first line of a file
|
||||||
function helpers.first_line(path)
|
function helpers.first_line(path)
|
||||||
local file, first = io.open(path, "rb"), nil
|
local file, first = io.open(path, 'rb'), nil
|
||||||
if file then
|
if file then
|
||||||
first = file:read("*l")
|
first = file:read('*l')
|
||||||
file:close()
|
file:close()
|
||||||
end
|
end
|
||||||
return first
|
return first
|
||||||
@ -73,7 +74,9 @@ end
|
|||||||
-- get first non empty line from a file
|
-- get first non empty line from a file
|
||||||
function helpers.first_nonempty_line(path)
|
function helpers.first_nonempty_line(path)
|
||||||
for line in io.lines(path) do
|
for line in io.lines(path) do
|
||||||
if #line then return line end
|
if #line then
|
||||||
|
return line
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@ -85,15 +88,17 @@ end
|
|||||||
helpers.timer_table = {}
|
helpers.timer_table = {}
|
||||||
|
|
||||||
function helpers.newtimer(name, timeout, fun, nostart, stoppable)
|
function helpers.newtimer(name, timeout, fun, nostart, stoppable)
|
||||||
if not name or #name == 0 then return end
|
if not name or #name == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
name = (stoppable and name) or timeout
|
name = (stoppable and name) or timeout
|
||||||
if not helpers.timer_table[name] then
|
if not helpers.timer_table[name] then
|
||||||
helpers.timer_table[name] = timer({ timeout = timeout })
|
helpers.timer_table[name] = timer({ timeout = timeout })
|
||||||
helpers.timer_table[name]:start()
|
helpers.timer_table[name]:start()
|
||||||
end
|
end
|
||||||
helpers.timer_table[name]:connect_signal("timeout", fun)
|
helpers.timer_table[name]:connect_signal('timeout', fun)
|
||||||
if not nostart then
|
if not nostart then
|
||||||
helpers.timer_table[name]:emit_signal("timeout")
|
helpers.timer_table[name]:emit_signal('timeout')
|
||||||
end
|
end
|
||||||
return stoppable and helpers.timer_table[name]
|
return stoppable and helpers.timer_table[name]
|
||||||
end
|
end
|
||||||
@ -107,16 +112,14 @@ end
|
|||||||
-- @param callback function to execute on cmd output
|
-- @param callback function to execute on cmd output
|
||||||
-- @return cmd PID
|
-- @return cmd PID
|
||||||
function helpers.async(cmd, callback)
|
function helpers.async(cmd, callback)
|
||||||
return spawn.easy_async(cmd,
|
return spawn.easy_async(cmd, function(stdout, _, _, exit_code)
|
||||||
function (stdout, _, _, exit_code)
|
|
||||||
callback(stdout, exit_code)
|
callback(stdout, exit_code)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- like above, but call spawn.easy_async with a shell
|
-- like above, but call spawn.easy_async with a shell
|
||||||
function helpers.async_with_shell(cmd, callback)
|
function helpers.async_with_shell(cmd, callback)
|
||||||
return spawn.easy_async_with_shell(cmd,
|
return spawn.easy_async_with_shell(cmd, function(stdout, _, _, exit_code)
|
||||||
function (stdout, _, _, exit_code)
|
|
||||||
callback(stdout, exit_code)
|
callback(stdout, exit_code)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -162,7 +165,9 @@ end
|
|||||||
function helpers.spairs(t)
|
function helpers.spairs(t)
|
||||||
-- collect the keys
|
-- collect the keys
|
||||||
local keys = {}
|
local keys = {}
|
||||||
for k in pairs(t) do keys[#keys+1] = k end
|
for k in pairs(t) do
|
||||||
|
keys[#keys + 1] = k
|
||||||
|
end
|
||||||
|
|
||||||
tsort(keys)
|
tsort(keys)
|
||||||
|
|
||||||
@ -188,7 +193,9 @@ end
|
|||||||
|
|
||||||
-- create the powerset of a given set
|
-- create the powerset of a given set
|
||||||
function helpers.powerset(s)
|
function helpers.powerset(s)
|
||||||
if not s then return {} end
|
if not s then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
local t = { {} }
|
local t = { {} }
|
||||||
for i = 1, #s do
|
for i = 1, #s do
|
||||||
for j = 1, #t do
|
for j = 1, #t do
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
--]]
|
--]]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
layout = require("lain.layout"),
|
layout = require('lain.layout'),
|
||||||
util = require("lain.util"),
|
util = require('lain.util'),
|
||||||
widget = require("lain.widget")
|
widget = require('lain.widget'),
|
||||||
}
|
}
|
||||||
|
@ -11,19 +11,19 @@ local floor = math.floor
|
|||||||
local screen = screen
|
local screen = screen
|
||||||
|
|
||||||
local cascade = {
|
local cascade = {
|
||||||
name = "cascade",
|
name = 'cascade',
|
||||||
nmaster = 0,
|
nmaster = 0,
|
||||||
offset_x = 32,
|
offset_x = 32,
|
||||||
offset_y = 8,
|
offset_y = 8,
|
||||||
tile = {
|
tile = {
|
||||||
name = "cascadetile",
|
name = 'cascadetile',
|
||||||
nmaster = 0,
|
nmaster = 0,
|
||||||
ncol = 0,
|
ncol = 0,
|
||||||
mwfact = 0,
|
mwfact = 0,
|
||||||
offset_x = 5,
|
offset_x = 5,
|
||||||
offset_y = 32,
|
offset_y = 32,
|
||||||
extra_padding = 0
|
extra_padding = 0,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
local function do_cascade(p, tiling)
|
local function do_cascade(p, tiling)
|
||||||
@ -31,7 +31,9 @@ local function do_cascade(p, tiling)
|
|||||||
local wa = p.workarea
|
local wa = p.workarea
|
||||||
local cls = p.clients
|
local cls = p.clients
|
||||||
|
|
||||||
if #cls == 0 then return end
|
if #cls == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if not tiling then
|
if not tiling then
|
||||||
-- Cascade windows.
|
-- Cascade windows.
|
||||||
@ -62,8 +64,12 @@ local function do_cascade(p, tiling)
|
|||||||
g.width = wa.width - current_offset_x
|
g.width = wa.width - current_offset_x
|
||||||
g.height = wa.height - current_offset_y
|
g.height = wa.height - current_offset_y
|
||||||
|
|
||||||
if g.width < 1 then g.width = 1 end
|
if g.width < 1 then
|
||||||
if g.height < 1 then g.height = 1 end
|
g.width = 1
|
||||||
|
end
|
||||||
|
if g.height < 1 then
|
||||||
|
g.height = 1
|
||||||
|
end
|
||||||
|
|
||||||
p.geometries[c] = g
|
p.geometries[c] = g
|
||||||
end
|
end
|
||||||
@ -109,7 +115,9 @@ local function do_cascade(p, tiling)
|
|||||||
local current_offset_x = cascade.tile.offset_x * (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)
|
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.
|
-- Main column, fixed width and height.
|
||||||
local c = cls[1]
|
local c = cls[1]
|
||||||
@ -136,13 +144,19 @@ local function do_cascade(p, tiling)
|
|||||||
g.x = wa.x
|
g.x = wa.x
|
||||||
g.y = wa.y
|
g.y = wa.y
|
||||||
|
|
||||||
if g.width < 1 then g.width = 1 end
|
if g.width < 1 then
|
||||||
if g.height < 1 then g.height = 1 end
|
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.
|
-- Remaining clients stacked in slave column, new ones on top.
|
||||||
if #cls <= 1 then return end
|
if #cls <= 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
for i = 2, #cls do
|
for i = 2, #cls do
|
||||||
c = cls[i]
|
c = cls[i]
|
||||||
g = {}
|
g = {}
|
||||||
@ -153,8 +167,12 @@ local function do_cascade(p, tiling)
|
|||||||
g.x = wa.x + mainwid + (how_many - (i - 1)) * cascade.tile.offset_x
|
g.x = wa.x + mainwid + (how_many - (i - 1)) * cascade.tile.offset_x
|
||||||
g.y = wa.y + (i - 2) * cascade.tile.offset_y
|
g.y = wa.y + (i - 2) * cascade.tile.offset_y
|
||||||
|
|
||||||
if g.width < 1 then g.width = 1 end
|
if g.width < 1 then
|
||||||
if g.height < 1 then g.height = 1 end
|
g.width = 1
|
||||||
|
end
|
||||||
|
if g.height < 1 then
|
||||||
|
g.height = 1
|
||||||
|
end
|
||||||
|
|
||||||
p.geometries[c] = g
|
p.geometries[c] = g
|
||||||
end
|
end
|
||||||
|
@ -17,8 +17,8 @@ local mousegrabber = mousegrabber
|
|||||||
local screen = screen
|
local screen = screen
|
||||||
|
|
||||||
local centerwork = {
|
local centerwork = {
|
||||||
name = "centerwork",
|
name = 'centerwork',
|
||||||
horizontal = { name = "centerworkh" }
|
horizontal = { name = 'centerworkh' },
|
||||||
}
|
}
|
||||||
|
|
||||||
local function arrange(p, layout)
|
local function arrange(p, layout)
|
||||||
@ -26,7 +26,9 @@ local function arrange(p, layout)
|
|||||||
local wa = p.workarea
|
local wa = p.workarea
|
||||||
local cls = p.clients
|
local cls = p.clients
|
||||||
|
|
||||||
if #cls == 0 then return end
|
if #cls == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local g = {}
|
local g = {}
|
||||||
|
|
||||||
@ -45,9 +47,13 @@ local function arrange(p, layout)
|
|||||||
|
|
||||||
local slaveFirstDim, slaveSecondDim = 0, 0
|
local slaveFirstDim, slaveSecondDim = 0, 0
|
||||||
|
|
||||||
if layout.name == "centerwork" then -- vertical
|
if layout.name == 'centerwork' then -- vertical
|
||||||
if nbrFirstSlaves > 0 then slaveFirstDim = floor(wa.height / nbrFirstSlaves) end
|
if nbrFirstSlaves > 0 then
|
||||||
if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.height / nbrSecondSlaves) end
|
slaveFirstDim = floor(wa.height / nbrFirstSlaves)
|
||||||
|
end
|
||||||
|
if nbrSecondSlaves > 0 then
|
||||||
|
slaveSecondDim = floor(wa.height / nbrSecondSlaves)
|
||||||
|
end
|
||||||
|
|
||||||
g.height = wa.height
|
g.height = wa.height
|
||||||
g.width = mainwid
|
g.width = mainwid
|
||||||
@ -55,8 +61,12 @@ local function arrange(p, layout)
|
|||||||
g.x = wa.x + slaveLwid
|
g.x = wa.x + slaveLwid
|
||||||
g.y = wa.y
|
g.y = wa.y
|
||||||
else -- horizontal
|
else -- horizontal
|
||||||
if nbrFirstSlaves > 0 then slaveFirstDim = floor(wa.width / nbrFirstSlaves) end
|
if nbrFirstSlaves > 0 then
|
||||||
if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.width / nbrSecondSlaves) end
|
slaveFirstDim = floor(wa.width / nbrFirstSlaves)
|
||||||
|
end
|
||||||
|
if nbrSecondSlaves > 0 then
|
||||||
|
slaveSecondDim = floor(wa.width / nbrSecondSlaves)
|
||||||
|
end
|
||||||
|
|
||||||
g.height = mainhei
|
g.height = mainhei
|
||||||
g.width = wa.width
|
g.width = wa.width
|
||||||
@ -71,14 +81,16 @@ local function arrange(p, layout)
|
|||||||
p.geometries[cls[1]] = g
|
p.geometries[cls[1]] = g
|
||||||
|
|
||||||
-- Auxiliary clients
|
-- Auxiliary clients
|
||||||
if #cls <= 1 then return end
|
if #cls <= 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
for i = 2, #cls do
|
for i = 2, #cls do
|
||||||
g = {}
|
g = {}
|
||||||
local idxChecker, dimToAssign
|
local idxChecker, dimToAssign
|
||||||
|
|
||||||
local rowIndex = floor(i / 2)
|
local rowIndex = floor(i / 2)
|
||||||
|
|
||||||
if layout.name == "centerwork" then
|
if layout.name == 'centerwork' then
|
||||||
if i % 2 == 0 then -- left slave
|
if i % 2 == 0 then -- left slave
|
||||||
g.x = wa.x
|
g.x = wa.x
|
||||||
g.y = wa.y + (rowIndex - 1) * slaveFirstDim
|
g.y = wa.y + (rowIndex - 1) * slaveFirstDim
|
||||||
@ -134,22 +146,22 @@ local function mouse_resize_handler(c, _, _, _, orientation)
|
|||||||
local mwfact = c.screen.selected_tag.master_width_factor
|
local mwfact = c.screen.selected_tag.master_width_factor
|
||||||
local g = c:geometry()
|
local g = c:geometry()
|
||||||
local offset = 0
|
local offset = 0
|
||||||
local cursor = "cross"
|
local cursor = 'cross'
|
||||||
|
|
||||||
local corner_coords
|
local corner_coords
|
||||||
|
|
||||||
if orientation == 'vertical' then
|
if orientation == 'vertical' then
|
||||||
if g.height + 15 >= wa.height then
|
if g.height + 15 >= wa.height then
|
||||||
offset = g.height * .5
|
offset = g.height * 0.5
|
||||||
cursor = "sb_h_double_arrow"
|
cursor = 'sb_h_double_arrow'
|
||||||
elseif g.y + g.height + 15 <= wa.y + wa.height then
|
elseif g.y + g.height + 15 <= wa.y + wa.height then
|
||||||
offset = g.height
|
offset = g.height
|
||||||
end
|
end
|
||||||
corner_coords = { x = wa.x + wa.width * (1 - mwfact) / 2, y = g.y + offset }
|
corner_coords = { x = wa.x + wa.width * (1 - mwfact) / 2, y = g.y + offset }
|
||||||
else
|
else
|
||||||
if g.width + 15 >= wa.width then
|
if g.width + 15 >= wa.width then
|
||||||
offset = g.width * .5
|
offset = g.width * 0.5
|
||||||
cursor = "sb_v_double_arrow"
|
cursor = 'sb_v_double_arrow'
|
||||||
elseif g.x + g.width + 15 <= wa.x + wa.width then
|
elseif g.x + g.width + 15 <= wa.x + wa.width then
|
||||||
offset = g.width
|
offset = g.width
|
||||||
end
|
end
|
||||||
@ -161,7 +173,9 @@ local function mouse_resize_handler(c, _, _, _, orientation)
|
|||||||
local prev_coords = {}
|
local prev_coords = {}
|
||||||
|
|
||||||
mousegrabber.run(function(m)
|
mousegrabber.run(function(m)
|
||||||
if not c.valid then return false end
|
if not c.valid then
|
||||||
|
return false
|
||||||
|
end
|
||||||
for _, v in ipairs(m.buttons) do
|
for _, v in ipairs(m.buttons) do
|
||||||
if v then
|
if v then
|
||||||
prev_coords = { x = m.x, y = m.y }
|
prev_coords = { x = m.x, y = m.y }
|
||||||
@ -195,13 +209,12 @@ 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
|
end
|
||||||
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Make focus.byidx and swap.byidx behave more consistently with other layouts.
|
Make focus.byidx and swap.byidx behave more consistently with other layouts.
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local gears = require("gears")
|
local gears = require('gears')
|
||||||
local client = client
|
local client = client
|
||||||
|
|
||||||
local function compare_position(a, b)
|
local function compare_position(a, b)
|
||||||
@ -217,7 +230,9 @@ local function clients_by_position()
|
|||||||
if this then
|
if this then
|
||||||
local sorted = {}
|
local sorted = {}
|
||||||
for _, c in ipairs(client.focus.first_tag:clients()) do
|
for _, c in ipairs(client.focus.first_tag:clients()) do
|
||||||
if not c.minimized then sorted[#sorted+1] = c end
|
if not c.minimized then
|
||||||
|
sorted[#sorted + 1] = c
|
||||||
|
end
|
||||||
end
|
end
|
||||||
table.sort(sorted, compare_position)
|
table.sort(sorted, compare_position)
|
||||||
|
|
||||||
@ -236,12 +251,11 @@ local function clients_by_position()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function in_centerwork()
|
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
|
end
|
||||||
|
|
||||||
centerwork.focus = {}
|
centerwork.focus = {}
|
||||||
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Drop in replacements for awful.client.focus.byidx and awful.client.swap.byidx
|
Drop in replacements for awful.client.focus.byidx and awful.client.swap.byidx
|
||||||
that behaves consistently with other layouts.
|
that behaves consistently with other layouts.
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local wrequire = require("lain.helpers").wrequire
|
local wrequire = require('lain.helpers').wrequire
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
local layout = { _NAME = "lain.layout" }
|
local layout = { _NAME = 'lain.layout' }
|
||||||
|
|
||||||
return setmetatable(layout, { __index = wrequire })
|
return setmetatable(layout, { __index = wrequire })
|
||||||
|
@ -12,25 +12,31 @@ local math = math
|
|||||||
local screen = screen
|
local screen = screen
|
||||||
local tonumber = tonumber
|
local tonumber = tonumber
|
||||||
|
|
||||||
local termfair = { name = "termfair" }
|
local termfair = { name = 'termfair' }
|
||||||
termfair.center = { name = "centerfair" }
|
termfair.center = { name = 'centerfair' }
|
||||||
termfair.stable = { name = "stablefair" }
|
termfair.stable = { name = 'stablefair' }
|
||||||
|
|
||||||
local function do_fair(p, orientation)
|
local function do_fair(p, orientation)
|
||||||
local t = p.tag or screen[p.screen].selected_tag
|
local t = p.tag or screen[p.screen].selected_tag
|
||||||
local wa = p.workarea
|
local wa = p.workarea
|
||||||
local cls = p.clients
|
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.
|
-- How many vertical columns? Read from nmaster on the tag.
|
||||||
local num_x = tonumber(termfair.nmaster) or t.master_count
|
local num_x = tonumber(termfair.nmaster) or t.master_count
|
||||||
local ncol = tonumber(termfair.ncol) or t.column_count
|
local ncol = tonumber(termfair.ncol) or t.column_count
|
||||||
if num_x <= 2 then num_x = 2 end
|
if num_x <= 2 then
|
||||||
if ncol <= 1 then ncol = 1 end
|
num_x = 2
|
||||||
|
end
|
||||||
|
if ncol <= 1 then
|
||||||
|
ncol = 1
|
||||||
|
end
|
||||||
local width = math.floor(wa.width / num_x)
|
local width = math.floor(wa.width / num_x)
|
||||||
|
|
||||||
if orientation == "west" then
|
if orientation == 'west' then
|
||||||
-- Layout with fixed number of vertical columns (read from nmaster).
|
-- Layout with fixed number of vertical columns (read from nmaster).
|
||||||
-- New windows align from left to right. When a row is full, a new
|
-- New windows align from left to right. When a row is full, a new
|
||||||
-- one above it is created. Like this:
|
-- one above it is created. Like this:
|
||||||
@ -87,8 +93,12 @@ local function do_fair(p, orientation)
|
|||||||
g.x = wa.x + this_x * width
|
g.x = wa.x + this_x * width
|
||||||
g.y = wa.y + this_y * height
|
g.y = wa.y + this_y * height
|
||||||
|
|
||||||
if g.width < 1 then g.width = 1 end
|
if g.width < 1 then
|
||||||
if g.height < 1 then g.height = 1 end
|
g.width = 1
|
||||||
|
end
|
||||||
|
if g.height < 1 then
|
||||||
|
g.height = 1
|
||||||
|
end
|
||||||
|
|
||||||
p.geometries[c] = g
|
p.geometries[c] = g
|
||||||
|
|
||||||
@ -107,7 +117,7 @@ local function do_fair(p, orientation)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif orientation == "stable" then
|
elseif orientation == 'stable' then
|
||||||
-- Layout with fixed number of vertical columns (read from nmaster).
|
-- Layout with fixed number of vertical columns (read from nmaster).
|
||||||
-- New windows align from left to right. When a row is full, a new
|
-- New windows align from left to right. When a row is full, a new
|
||||||
-- one below it is created. Like this:
|
-- one below it is created. Like this:
|
||||||
@ -152,12 +162,16 @@ local function do_fair(p, orientation)
|
|||||||
g.x = wa.x + this_x * width
|
g.x = wa.x + this_x * width
|
||||||
g.y = wa.y + this_y * height
|
g.y = wa.y + this_y * height
|
||||||
|
|
||||||
if g.width < 1 then g.width = 1 end
|
if g.width < 1 then
|
||||||
if g.height < 1 then g.height = 1 end
|
g.width = 1
|
||||||
|
end
|
||||||
|
if g.height < 1 then
|
||||||
|
g.height = 1
|
||||||
|
end
|
||||||
|
|
||||||
p.geometries[c] = g
|
p.geometries[c] = g
|
||||||
end
|
end
|
||||||
elseif orientation == "center" then
|
elseif orientation == 'center' then
|
||||||
-- Layout with fixed number of vertical columns (read from nmaster).
|
-- Layout with fixed number of vertical columns (read from nmaster).
|
||||||
-- Cols are centerded until there is nmaster columns, then windows
|
-- Cols are centerded until there is nmaster columns, then windows
|
||||||
-- are stacked in the slave columns, with at most ncol clients per
|
-- are stacked in the slave columns, with at most ncol clients per
|
||||||
@ -185,8 +199,12 @@ local function do_fair(p, orientation)
|
|||||||
local g = { y = wa.y }
|
local g = { y = wa.y }
|
||||||
g.width = width
|
g.width = width
|
||||||
g.height = wa.height
|
g.height = wa.height
|
||||||
if g.width < 1 then g.width = 1 end
|
if g.width < 1 then
|
||||||
if g.height < 1 then g.height = 1 end
|
g.width = 1
|
||||||
|
end
|
||||||
|
if g.height < 1 then
|
||||||
|
g.height = 1
|
||||||
|
end
|
||||||
g.x = offset_x + (i - 1) * width
|
g.x = offset_x + (i - 1) * width
|
||||||
p.geometries[cls[i]] = g
|
p.geometries[cls[i]] = g
|
||||||
end
|
end
|
||||||
@ -196,8 +214,12 @@ local function do_fair(p, orientation)
|
|||||||
local g = {}
|
local g = {}
|
||||||
g.width = wa.width - (num_x - 1) * width
|
g.width = wa.width - (num_x - 1) * width
|
||||||
g.height = wa.height
|
g.height = wa.height
|
||||||
if g.width < 1 then g.width = 1 end
|
if g.width < 1 then
|
||||||
if g.height < 1 then g.height = 1 end
|
g.width = 1
|
||||||
|
end
|
||||||
|
if g.height < 1 then
|
||||||
|
g.height = 1
|
||||||
|
end
|
||||||
g.x = wa.x
|
g.x = wa.x
|
||||||
g.y = wa.y
|
g.y = wa.y
|
||||||
p.geometries[cls[1]] = g
|
p.geometries[cls[1]] = g
|
||||||
@ -246,8 +268,12 @@ local function do_fair(p, orientation)
|
|||||||
g.y = wy
|
g.y = wy
|
||||||
g.height = height
|
g.height = height
|
||||||
g.width = width
|
g.width = width
|
||||||
if g.width < 1 then g.width = 1 end
|
if g.width < 1 then
|
||||||
if g.height < 1 then g.height = 1 end
|
g.width = 1
|
||||||
|
end
|
||||||
|
if g.height < 1 then
|
||||||
|
g.height = 1
|
||||||
|
end
|
||||||
p.geometries[cls[nclient]] = g
|
p.geometries[cls[nclient]] = g
|
||||||
nclient = nclient + 1
|
nclient = nclient + 1
|
||||||
wy = wy + height
|
wy = wy + height
|
||||||
@ -257,8 +283,12 @@ local function do_fair(p, orientation)
|
|||||||
g.y = wy
|
g.y = wy
|
||||||
g.height = wa.height - (num_y[i] - 1) * height
|
g.height = wa.height - (num_y[i] - 1) * height
|
||||||
g.width = width
|
g.width = width
|
||||||
if g.width < 1 then g.width = 1 end
|
if g.width < 1 then
|
||||||
if g.height < 1 then g.height = 1 end
|
g.width = 1
|
||||||
|
end
|
||||||
|
if g.height < 1 then
|
||||||
|
g.height = 1
|
||||||
|
end
|
||||||
p.geometries[cls[nclient]] = g
|
p.geometries[cls[nclient]] = g
|
||||||
nclient = nclient + 1
|
nclient = nclient + 1
|
||||||
wx = wx + width
|
wx = wx + width
|
||||||
@ -268,15 +298,15 @@ local function do_fair(p, orientation)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function termfair.center.arrange(p)
|
function termfair.center.arrange(p)
|
||||||
return do_fair(p, "center")
|
return do_fair(p, 'center')
|
||||||
end
|
end
|
||||||
|
|
||||||
function termfair.stable.arrange(p)
|
function termfair.stable.arrange(p)
|
||||||
return do_fair(p, "stable")
|
return do_fair(p, 'stable')
|
||||||
end
|
end
|
||||||
|
|
||||||
function termfair.arrange(p)
|
function termfair.arrange(p)
|
||||||
return do_fair(p, "west")
|
return do_fair(p, 'west')
|
||||||
end
|
end
|
||||||
|
|
||||||
return termfair
|
return termfair
|
||||||
|
@ -47,12 +47,11 @@ local pairs, type, tostring, tonumber, getmetatable, setmetatable =
|
|||||||
local error, require, pcall, select = error, require, pcall, select
|
local error, require, pcall, select = error, require, pcall, select
|
||||||
local floor, huge = math.floor, math.huge
|
local floor, huge = math.floor, math.huge
|
||||||
local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat =
|
local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat =
|
||||||
string.rep, string.gsub, string.sub, string.byte, string.char,
|
string.rep, string.gsub, string.sub, string.byte, string.char, string.find, string.len, string.format
|
||||||
string.find, string.len, string.format
|
|
||||||
local strmatch = string.match
|
local strmatch = string.match
|
||||||
local concat = table.concat
|
local concat = table.concat
|
||||||
|
|
||||||
local json = { version = "dkjson 2.6" }
|
local json = { version = 'dkjson 2.6' }
|
||||||
|
|
||||||
local jsonlpeg = {}
|
local jsonlpeg = {}
|
||||||
|
|
||||||
@ -69,12 +68,16 @@ _ENV = nil -- blocking globals in Lua 5.2 and later
|
|||||||
pcall(function()
|
pcall(function()
|
||||||
-- Enable access to blocked metatables.
|
-- Enable access to blocked metatables.
|
||||||
-- Don't worry, this module doesn't change anything in them.
|
-- Don't worry, this module doesn't change anything in them.
|
||||||
local debmeta = require "debug".getmetatable
|
local debmeta = require('debug').getmetatable
|
||||||
if debmeta then getmetatable = debmeta end
|
if debmeta then
|
||||||
|
getmetatable = debmeta
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
json.null = setmetatable({}, {
|
json.null = setmetatable({}, {
|
||||||
__tojson = function () return "null" end
|
__tojson = function()
|
||||||
|
return 'null'
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
local function isarray(tbl)
|
local function isarray(tbl)
|
||||||
@ -102,8 +105,13 @@ local function isarray (tbl)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local escapecodes = {
|
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 function escapeutf8(uchar)
|
||||||
@ -122,17 +130,17 @@ local function escapeutf8 (uchar)
|
|||||||
elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then
|
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
|
value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80
|
||||||
else
|
else
|
||||||
return ""
|
return ''
|
||||||
end
|
end
|
||||||
if value <= 0xffff then
|
if value <= 0xffff then
|
||||||
return strformat ("\\u%.4x", value)
|
return strformat('\\u%.4x', value)
|
||||||
elseif value <= 0x10ffff then
|
elseif value <= 0x10ffff then
|
||||||
-- encode as UTF-16 surrogate pair
|
-- encode as UTF-16 surrogate pair
|
||||||
value = value - 0x10000
|
value = value - 0x10000
|
||||||
local highsur, lowsur = 0xD800 + floor(value / 0x400), 0xDC00 + (value % 0x400)
|
local highsur, lowsur = 0xD800 + floor(value / 0x400), 0xDC00 + (value % 0x400)
|
||||||
return strformat ("\\u%.4x\\u%.4x", highsur, lowsur)
|
return strformat('\\u%.4x\\u%.4x', highsur, lowsur)
|
||||||
else
|
else
|
||||||
return ""
|
return ''
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -149,18 +157,18 @@ end
|
|||||||
|
|
||||||
local function quotestring(value)
|
local function quotestring(value)
|
||||||
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
|
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
|
||||||
value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
|
value = fsub(value, '[%z\1-\31"\\\127]', escapeutf8)
|
||||||
if strfind (value, "[\194\216\220\225\226\239]") then
|
if strfind(value, '[\194\216\220\225\226\239]') then
|
||||||
value = fsub (value, "\194[\128-\159\173]", escapeutf8)
|
value = fsub(value, '\194[\128-\159\173]', escapeutf8)
|
||||||
value = fsub (value, "\216[\128-\132]", escapeutf8)
|
value = fsub(value, '\216[\128-\132]', escapeutf8)
|
||||||
value = fsub (value, "\220\143", escapeutf8)
|
value = fsub(value, '\220\143', escapeutf8)
|
||||||
value = fsub (value, "\225\158[\180\181]", escapeutf8)
|
value = fsub(value, '\225\158[\180\181]', escapeutf8)
|
||||||
value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8)
|
value = fsub(value, '\226\128[\140-\143\168-\175]', escapeutf8)
|
||||||
value = fsub (value, "\226\129[\160-\175]", escapeutf8)
|
value = fsub(value, '\226\129[\160-\175]', escapeutf8)
|
||||||
value = fsub (value, "\239\187\191", escapeutf8)
|
value = fsub(value, '\239\187\191', escapeutf8)
|
||||||
value = fsub (value, "\239\191[\176-\191]", escapeutf8)
|
value = fsub(value, '\239\191[\176-\191]', escapeutf8)
|
||||||
end
|
end
|
||||||
return "\"" .. value .. "\""
|
return '"' .. value .. '"'
|
||||||
end
|
end
|
||||||
json.quotestring = quotestring
|
json.quotestring = quotestring
|
||||||
|
|
||||||
@ -177,37 +185,36 @@ end
|
|||||||
local decpoint, numfilter
|
local decpoint, numfilter
|
||||||
|
|
||||||
local function updatedecpoint()
|
local function updatedecpoint()
|
||||||
decpoint = strmatch(tostring(0.5), "([^05+])")
|
decpoint = strmatch(tostring(0.5), '([^05+])')
|
||||||
-- build a filter that can be used to remove group separators
|
-- build a filter that can be used to remove group separators
|
||||||
numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+"
|
numfilter = '[^0-9%-%+eE' .. gsub(decpoint, '[%^%$%(%)%%%.%[%]%*%+%-%?]', '%%%0') .. ']+'
|
||||||
end
|
end
|
||||||
|
|
||||||
updatedecpoint()
|
updatedecpoint()
|
||||||
|
|
||||||
local function num2str(num)
|
local function num2str(num)
|
||||||
return replace(fsub(tostring(num), numfilter, ""), decpoint, ".")
|
return replace(fsub(tostring(num), numfilter, ''), decpoint, '.')
|
||||||
end
|
end
|
||||||
|
|
||||||
local function str2num(str)
|
local function str2num(str)
|
||||||
local num = tonumber(replace(str, ".", decpoint))
|
local num = tonumber(replace(str, '.', decpoint))
|
||||||
if not num then
|
if not num then
|
||||||
updatedecpoint()
|
updatedecpoint()
|
||||||
num = tonumber(replace(str, ".", decpoint))
|
num = tonumber(replace(str, '.', decpoint))
|
||||||
end
|
end
|
||||||
return num
|
return num
|
||||||
end
|
end
|
||||||
|
|
||||||
local function addnewline2(level, buffer, buflen)
|
local function addnewline2(level, buffer, buflen)
|
||||||
buffer[buflen+1] = "\n"
|
buffer[buflen + 1] = '\n'
|
||||||
buffer[buflen+2] = strrep (" ", level)
|
buffer[buflen + 2] = strrep(' ', level)
|
||||||
buflen = buflen + 2
|
buflen = buflen + 2
|
||||||
return buflen
|
return buflen
|
||||||
end
|
end
|
||||||
|
|
||||||
function json.addnewline(state)
|
function json.addnewline(state)
|
||||||
if state.indent then
|
if state.indent then
|
||||||
state.bufferlen = addnewline2 (state.level or 0,
|
state.bufferlen = addnewline2(state.level or 0, state.buffer, state.bufferlen or #state.buffer)
|
||||||
state.buffer, state.bufferlen or #(state.buffer))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -220,13 +227,13 @@ local function addpair (key, value, prev, indent, level, buffer, buflen, tables,
|
|||||||
end
|
end
|
||||||
if prev then
|
if prev then
|
||||||
buflen = buflen + 1
|
buflen = buflen + 1
|
||||||
buffer[buflen] = ","
|
buffer[buflen] = ','
|
||||||
end
|
end
|
||||||
if indent then
|
if indent then
|
||||||
buflen = addnewline2(level, buffer, buflen)
|
buflen = addnewline2(level, buffer, buflen)
|
||||||
end
|
end
|
||||||
buffer[buflen + 1] = quotestring(key)
|
buffer[buflen + 1] = quotestring(key)
|
||||||
buffer[buflen+2] = ":"
|
buffer[buflen + 2] = ':'
|
||||||
return encode2(value, indent, level, buffer, buflen + 2, tables, globalorder, state)
|
return encode2(value, indent, level, buffer, buflen + 2, tables, globalorder, state)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -247,13 +254,15 @@ local function exception(reason, value, state, buffer, buflen, defaultmessage)
|
|||||||
else
|
else
|
||||||
state.bufferlen = buflen
|
state.bufferlen = buflen
|
||||||
local ret, msg = handler(reason, value, state, defaultmessage)
|
local ret, msg = handler(reason, value, state, defaultmessage)
|
||||||
if not ret then return nil, msg or defaultmessage end
|
if not ret then
|
||||||
|
return nil, msg or defaultmessage
|
||||||
|
end
|
||||||
return appendcustom(ret, buffer, state)
|
return appendcustom(ret, buffer, state)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function json.encodeexception(_reason, _value, _state, defaultmessage)
|
function json.encodeexception(_reason, _value, _state, defaultmessage)
|
||||||
return quotestring("<" .. defaultmessage .. ">")
|
return quotestring('<' .. defaultmessage .. '>')
|
||||||
end
|
end
|
||||||
|
|
||||||
encode2 = function(value, indent, level, buffer, buflen, tables, globalorder, state)
|
encode2 = function(value, indent, level, buffer, buflen, tables, globalorder, state)
|
||||||
@ -268,17 +277,19 @@ encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, s
|
|||||||
tables[value] = true
|
tables[value] = true
|
||||||
state.bufferlen = buflen
|
state.bufferlen = buflen
|
||||||
local ret, msg = valtojson(value, state)
|
local ret, msg = valtojson(value, state)
|
||||||
if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end
|
if not ret then
|
||||||
|
return exception('custom encoder failed', value, state, buffer, buflen, msg)
|
||||||
|
end
|
||||||
tables[value] = nil
|
tables[value] = nil
|
||||||
buflen = appendcustom(ret, buffer, state)
|
buflen = appendcustom(ret, buffer, state)
|
||||||
elseif value == nil then
|
elseif value == nil then
|
||||||
buflen = buflen + 1
|
buflen = buflen + 1
|
||||||
buffer[buflen] = "null"
|
buffer[buflen] = 'null'
|
||||||
elseif valtype == 'number' then
|
elseif valtype == 'number' then
|
||||||
local s
|
local s
|
||||||
if value ~= value or value >= huge or -value >= huge then
|
if value ~= value or value >= huge or -value >= huge then
|
||||||
-- This is the behaviour of the original JSON implementation.
|
-- This is the behaviour of the original JSON implementation.
|
||||||
s = "null"
|
s = 'null'
|
||||||
else
|
else
|
||||||
s = num2str(value)
|
s = num2str(value)
|
||||||
end
|
end
|
||||||
@ -286,7 +297,7 @@ encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, s
|
|||||||
buffer[buflen] = s
|
buffer[buflen] = s
|
||||||
elseif valtype == 'boolean' then
|
elseif valtype == 'boolean' then
|
||||||
buflen = buflen + 1
|
buflen = buflen + 1
|
||||||
buffer[buflen] = value and "true" or "false"
|
buffer[buflen] = value and 'true' or 'false'
|
||||||
elseif valtype == 'string' then
|
elseif valtype == 'string' then
|
||||||
buflen = buflen + 1
|
buflen = buflen + 1
|
||||||
buffer[buflen] = quotestring(value)
|
buffer[buflen] = quotestring(value)
|
||||||
@ -303,21 +314,23 @@ encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, s
|
|||||||
local msg
|
local msg
|
||||||
if isa then -- JSON array
|
if isa then -- JSON array
|
||||||
buflen = buflen + 1
|
buflen = buflen + 1
|
||||||
buffer[buflen] = "["
|
buffer[buflen] = '['
|
||||||
for i = 1, n do
|
for i = 1, n do
|
||||||
buflen, msg = encode2(value[i], indent, level, buffer, buflen, tables, globalorder, state)
|
buflen, msg = encode2(value[i], indent, level, buffer, buflen, tables, globalorder, state)
|
||||||
if not buflen then return nil, msg end
|
if not buflen then
|
||||||
|
return nil, msg
|
||||||
|
end
|
||||||
if i < n then
|
if i < n then
|
||||||
buflen = buflen + 1
|
buflen = buflen + 1
|
||||||
buffer[buflen] = ","
|
buffer[buflen] = ','
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
buflen = buflen + 1
|
buflen = buflen + 1
|
||||||
buffer[buflen] = "]"
|
buffer[buflen] = ']'
|
||||||
else -- JSON object
|
else -- JSON object
|
||||||
local prev = false
|
local prev = false
|
||||||
buflen = buflen + 1
|
buflen = buflen + 1
|
||||||
buffer[buflen] = "{"
|
buffer[buflen] = '{'
|
||||||
local order = valmeta and valmeta.__jsonorder or globalorder
|
local order = valmeta and valmeta.__jsonorder or globalorder
|
||||||
if order then
|
if order then
|
||||||
local used = {}
|
local used = {}
|
||||||
@ -334,14 +347,18 @@ encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, s
|
|||||||
for k, v in pairs(value) do
|
for k, v in pairs(value) do
|
||||||
if not used[k] then
|
if not used[k] then
|
||||||
buflen, msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
|
buflen, msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
|
||||||
if not buflen then return nil, msg end
|
if not buflen then
|
||||||
|
return nil, msg
|
||||||
|
end
|
||||||
prev = true -- add a seperator before the next element
|
prev = true -- add a seperator before the next element
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else -- unordered
|
else -- unordered
|
||||||
for k, v in pairs(value) do
|
for k, v in pairs(value) do
|
||||||
buflen, msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
|
buflen, msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
|
||||||
if not buflen then return nil, msg end
|
if not buflen then
|
||||||
|
return nil, msg
|
||||||
|
end
|
||||||
prev = true -- add a seperator before the next element
|
prev = true -- add a seperator before the next element
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -349,12 +366,18 @@ encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, s
|
|||||||
buflen = addnewline2(level - 1, buffer, buflen)
|
buflen = addnewline2(level - 1, buffer, buflen)
|
||||||
end
|
end
|
||||||
buflen = buflen + 1
|
buflen = buflen + 1
|
||||||
buffer[buflen] = "}"
|
buffer[buflen] = '}'
|
||||||
end
|
end
|
||||||
tables[value] = nil
|
tables[value] = nil
|
||||||
else
|
else
|
||||||
return exception ('unsupported type', value, state, buffer, buflen,
|
return exception(
|
||||||
"type '" .. valtype .. "' is not supported by JSON.")
|
'unsupported type',
|
||||||
|
value,
|
||||||
|
state,
|
||||||
|
buffer,
|
||||||
|
buflen,
|
||||||
|
"type '" .. valtype .. "' is not supported by JSON."
|
||||||
|
)
|
||||||
end
|
end
|
||||||
return buflen
|
return buflen
|
||||||
end
|
end
|
||||||
@ -365,8 +388,16 @@ function json.encode (value, state)
|
|||||||
local buffer = oldbuffer or {}
|
local buffer = oldbuffer or {}
|
||||||
state.buffer = buffer
|
state.buffer = buffer
|
||||||
updatedecpoint()
|
updatedecpoint()
|
||||||
local ret, msg = encode2 (value, state.indent, state.level or 0,
|
local ret, msg = encode2(
|
||||||
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state)
|
value,
|
||||||
|
state.indent,
|
||||||
|
state.level or 0,
|
||||||
|
buffer,
|
||||||
|
state.bufferlen or 0,
|
||||||
|
state.tables or {},
|
||||||
|
state.keyorder,
|
||||||
|
state
|
||||||
|
)
|
||||||
if not ret then
|
if not ret then
|
||||||
error(msg, 2)
|
error(msg, 2)
|
||||||
elseif oldbuffer == buffer then
|
elseif oldbuffer == buffer then
|
||||||
@ -382,7 +413,7 @@ end
|
|||||||
local function loc(str, where)
|
local function loc(str, where)
|
||||||
local line, pos, linepos = 1, 1, 0
|
local line, pos, linepos = 1, 1, 0
|
||||||
while true do
|
while true do
|
||||||
pos = strfind (str, "\n", pos, true)
|
pos = strfind(str, '\n', pos, true)
|
||||||
if pos and pos < where then
|
if pos and pos < where then
|
||||||
line = line + 1
|
line = line + 1
|
||||||
linepos = pos
|
linepos = pos
|
||||||
@ -391,27 +422,33 @@ local function loc (str, where)
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return "line " .. line .. ", column " .. (where - linepos)
|
return 'line ' .. line .. ', column ' .. (where - linepos)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function unterminated(str, what, where)
|
local function unterminated(str, what, where)
|
||||||
return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
|
return nil, strlen(str) + 1, 'unterminated ' .. what .. ' at ' .. loc(str, where)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function scanwhite(str, pos)
|
local function scanwhite(str, pos)
|
||||||
while true do
|
while true do
|
||||||
pos = strfind (str, "%S", pos)
|
pos = strfind(str, '%S', pos)
|
||||||
if not pos then return nil end
|
if not pos then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
local sub2 = strsub(str, pos, pos + 1)
|
local sub2 = strsub(str, pos, pos + 1)
|
||||||
if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then
|
if sub2 == '\239\187' and strsub(str, pos + 2, pos + 2) == '\191' then
|
||||||
-- UTF-8 Byte Order Mark
|
-- UTF-8 Byte Order Mark
|
||||||
pos = pos + 3
|
pos = pos + 3
|
||||||
elseif sub2 == "//" then
|
elseif sub2 == '//' then
|
||||||
pos = strfind (str, "[\n\r]", pos + 2)
|
pos = strfind(str, '[\n\r]', pos + 2)
|
||||||
if not pos then return nil end
|
if not pos then
|
||||||
elseif sub2 == "/*" then
|
return nil
|
||||||
pos = strfind (str, "*/", pos + 2)
|
end
|
||||||
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
|
pos = pos + 2
|
||||||
else
|
else
|
||||||
return pos
|
return pos
|
||||||
@ -420,8 +457,14 @@ local function scanwhite (str, pos)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local escapechars = {
|
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)
|
local function unichar(value)
|
||||||
@ -430,17 +473,16 @@ local function unichar (value)
|
|||||||
elseif value <= 0x007f then
|
elseif value <= 0x007f then
|
||||||
return strchar(value)
|
return strchar(value)
|
||||||
elseif value <= 0x07ff then
|
elseif value <= 0x07ff then
|
||||||
return strchar (0xc0 + floor(value/0x40),
|
return strchar(0xc0 + floor(value / 0x40), 0x80 + (floor(value) % 0x40))
|
||||||
0x80 + (floor(value) % 0x40))
|
|
||||||
elseif value <= 0xffff then
|
elseif value <= 0xffff then
|
||||||
return strchar (0xe0 + floor(value/0x1000),
|
return strchar(0xe0 + floor(value / 0x1000), 0x80 + (floor(value / 0x40) % 0x40), 0x80 + (floor(value) % 0x40))
|
||||||
0x80 + (floor(value/0x40) % 0x40),
|
|
||||||
0x80 + (floor(value) % 0x40))
|
|
||||||
elseif value <= 0x10ffff then
|
elseif value <= 0x10ffff then
|
||||||
return strchar (0xf0 + floor(value/0x40000),
|
return strchar(
|
||||||
|
0xf0 + floor(value / 0x40000),
|
||||||
0x80 + (floor(value / 0x1000) % 0x40),
|
0x80 + (floor(value / 0x1000) % 0x40),
|
||||||
0x80 + (floor(value / 0x40) % 0x40),
|
0x80 + (floor(value / 0x40) % 0x40),
|
||||||
0x80 + (floor(value) % 0x40))
|
0x80 + (floor(value) % 0x40)
|
||||||
|
)
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@ -450,28 +492,28 @@ local function scanstring (str, pos)
|
|||||||
local lastpos = pos + 1
|
local lastpos = pos + 1
|
||||||
local buffer, n = {}, 0
|
local buffer, n = {}, 0
|
||||||
while true do
|
while true do
|
||||||
local nextpos = strfind (str, "[\"\\]", lastpos)
|
local nextpos = strfind(str, '["\\]', lastpos)
|
||||||
if not nextpos then
|
if not nextpos then
|
||||||
return unterminated (str, "string", pos)
|
return unterminated(str, 'string', pos)
|
||||||
end
|
end
|
||||||
if nextpos > lastpos then
|
if nextpos > lastpos then
|
||||||
n = n + 1
|
n = n + 1
|
||||||
buffer[n] = strsub(str, lastpos, nextpos - 1)
|
buffer[n] = strsub(str, lastpos, nextpos - 1)
|
||||||
end
|
end
|
||||||
if strsub (str, nextpos, nextpos) == "\"" then
|
if strsub(str, nextpos, nextpos) == '"' then
|
||||||
lastpos = nextpos + 1
|
lastpos = nextpos + 1
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
local escchar = strsub(str, nextpos + 1, nextpos + 1)
|
local escchar = strsub(str, nextpos + 1, nextpos + 1)
|
||||||
local value
|
local value
|
||||||
if escchar == "u" then
|
if escchar == 'u' then
|
||||||
value = tonumber(strsub(str, nextpos + 2, nextpos + 5), 16)
|
value = tonumber(strsub(str, nextpos + 2, nextpos + 5), 16)
|
||||||
if value then
|
if value then
|
||||||
local value2
|
local value2
|
||||||
if 0xD800 <= value and value <= 0xDBff then
|
if 0xD800 <= value and value <= 0xDBff then
|
||||||
-- we have the high surrogate of UTF-16. Check if there is a
|
-- we have the high surrogate of UTF-16. Check if there is a
|
||||||
-- low surrogate escaped nearby to combine them.
|
-- low surrogate escaped nearby to combine them.
|
||||||
if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then
|
if strsub(str, nextpos + 6, nextpos + 7) == '\\u' then
|
||||||
value2 = tonumber(strsub(str, nextpos + 8, nextpos + 11), 16)
|
value2 = tonumber(strsub(str, nextpos + 8, nextpos + 11), 16)
|
||||||
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
|
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
|
||||||
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
|
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
|
||||||
@ -503,7 +545,7 @@ local function scanstring (str, pos)
|
|||||||
elseif n > 1 then
|
elseif n > 1 then
|
||||||
return concat(buffer), lastpos
|
return concat(buffer), lastpos
|
||||||
else
|
else
|
||||||
return "", lastpos
|
return '', lastpos
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -519,35 +561,47 @@ local function scantable (what, closechar, str, startpos, nullval, objectmeta, a
|
|||||||
end
|
end
|
||||||
while true do
|
while true do
|
||||||
pos = scanwhite(str, pos)
|
pos = scanwhite(str, pos)
|
||||||
if not pos then return unterminated (str, what, startpos) end
|
if not pos then
|
||||||
|
return unterminated(str, what, startpos)
|
||||||
|
end
|
||||||
local char = strsub(str, pos, pos)
|
local char = strsub(str, pos, pos)
|
||||||
if char == closechar then
|
if char == closechar then
|
||||||
return tbl, pos + 1
|
return tbl, pos + 1
|
||||||
end
|
end
|
||||||
local val1, err
|
local val1, err
|
||||||
val1, pos, err = scanvalue(str, pos, nullval, objectmeta, arraymeta)
|
val1, pos, err = scanvalue(str, pos, nullval, objectmeta, arraymeta)
|
||||||
if err then return nil, pos, err end
|
if err then
|
||||||
|
return nil, pos, err
|
||||||
|
end
|
||||||
pos = scanwhite(str, pos)
|
pos = scanwhite(str, pos)
|
||||||
if not pos then return unterminated (str, what, startpos) end
|
if not pos then
|
||||||
|
return unterminated(str, what, startpos)
|
||||||
|
end
|
||||||
char = strsub(str, pos, pos)
|
char = strsub(str, pos, pos)
|
||||||
if char == ":" then
|
if char == ':' then
|
||||||
if val1 == nil then
|
if val1 == nil then
|
||||||
return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
|
return nil, pos, 'cannot use nil as table index (at ' .. loc(str, pos) .. ')'
|
||||||
end
|
end
|
||||||
pos = scanwhite(str, pos + 1)
|
pos = scanwhite(str, pos + 1)
|
||||||
if not pos then return unterminated (str, what, startpos) end
|
if not pos then
|
||||||
|
return unterminated(str, what, startpos)
|
||||||
|
end
|
||||||
local val2
|
local val2
|
||||||
val2, pos, err = scanvalue(str, pos, nullval, objectmeta, arraymeta)
|
val2, pos, err = scanvalue(str, pos, nullval, objectmeta, arraymeta)
|
||||||
if err then return nil, pos, err end
|
if err then
|
||||||
|
return nil, pos, err
|
||||||
|
end
|
||||||
tbl[val1] = val2
|
tbl[val1] = val2
|
||||||
pos = scanwhite(str, pos)
|
pos = scanwhite(str, pos)
|
||||||
if not pos then return unterminated (str, what, startpos) end
|
if not pos then
|
||||||
|
return unterminated(str, what, startpos)
|
||||||
|
end
|
||||||
char = strsub(str, pos, pos)
|
char = strsub(str, pos, pos)
|
||||||
else
|
else
|
||||||
n = n + 1
|
n = n + 1
|
||||||
tbl[n] = val1
|
tbl[n] = val1
|
||||||
end
|
end
|
||||||
if char == "," then
|
if char == ',' then
|
||||||
pos = pos + 1
|
pos = pos + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -557,40 +611,40 @@ scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
|
|||||||
pos = pos or 1
|
pos = pos or 1
|
||||||
pos = scanwhite(str, pos)
|
pos = scanwhite(str, pos)
|
||||||
if not pos then
|
if not pos then
|
||||||
return nil, strlen (str) + 1, "no valid JSON value (reached the end)"
|
return nil, strlen(str) + 1, 'no valid JSON value (reached the end)'
|
||||||
end
|
end
|
||||||
local char = strsub(str, pos, pos)
|
local char = strsub(str, pos, pos)
|
||||||
if char == "{" then
|
if char == '{' then
|
||||||
return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta)
|
return scantable('object', '}', str, pos, nullval, objectmeta, arraymeta)
|
||||||
elseif char == "[" then
|
elseif char == '[' then
|
||||||
return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta)
|
return scantable('array', ']', str, pos, nullval, objectmeta, arraymeta)
|
||||||
elseif char == "\"" then
|
elseif char == '"' then
|
||||||
return scanstring(str, pos)
|
return scanstring(str, pos)
|
||||||
else
|
else
|
||||||
local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos)
|
local pstart, pend = strfind(str, '^%-?[%d%.]+[eE]?[%+%-]?%d*', pos)
|
||||||
if pstart then
|
if pstart then
|
||||||
local number = str2num(strsub(str, pstart, pend))
|
local number = str2num(strsub(str, pstart, pend))
|
||||||
if number then
|
if number then
|
||||||
return number, pend + 1
|
return number, pend + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
pstart, pend = strfind (str, "^%a%w*", pos)
|
pstart, pend = strfind(str, '^%a%w*', pos)
|
||||||
if pstart then
|
if pstart then
|
||||||
local name = strsub(str, pstart, pend)
|
local name = strsub(str, pstart, pend)
|
||||||
if name == "true" then
|
if name == 'true' then
|
||||||
return true, pend + 1
|
return true, pend + 1
|
||||||
elseif name == "false" then
|
elseif name == 'false' then
|
||||||
return false, pend + 1
|
return false, pend + 1
|
||||||
elseif name == "null" then
|
elseif name == 'null' then
|
||||||
return nullval, pend + 1
|
return nullval, pend + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil, pos, "no valid JSON value at " .. loc (str, pos)
|
return nil, pos, 'no valid JSON value at ' .. loc(str, pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function optionalmetatables(...)
|
local function optionalmetatables(...)
|
||||||
if select("#", ...) > 0 then
|
if select('#', ...) > 0 then
|
||||||
return ...
|
return ...
|
||||||
else
|
else
|
||||||
return { __jsontype = 'object' }, { __jsontype = 'array' }
|
return { __jsontype = 'object' }, { __jsontype = 'array' }
|
||||||
@ -603,10 +657,10 @@ function json.decode (str, pos, nullval, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function json.use_lpeg()
|
function json.use_lpeg()
|
||||||
local g = require ("lpeg")
|
local g = require('lpeg')
|
||||||
|
|
||||||
if g.version() == "0.11" then
|
if g.version() == '0.11' then
|
||||||
error "due to a bug in LPeg 0.11, it cannot be used for JSON matching"
|
error('due to a bug in LPeg 0.11, it cannot be used for JSON matching')
|
||||||
end
|
end
|
||||||
|
|
||||||
local pegmatch = g.match
|
local pegmatch = g.match
|
||||||
@ -614,7 +668,7 @@ function json.use_lpeg ()
|
|||||||
|
|
||||||
local function ErrorCall(str, pos, msg, state)
|
local function ErrorCall(str, pos, msg, state)
|
||||||
if not state.msg then
|
if not state.msg then
|
||||||
state.msg = msg .. " at " .. loc (str, pos)
|
state.msg = msg .. ' at ' .. loc(str, pos)
|
||||||
state.pos = pos
|
state.pos = pos
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
@ -625,20 +679,20 @@ function json.use_lpeg ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function ErrorUnterminatedCall(str, pos, what, state)
|
local function ErrorUnterminatedCall(str, pos, what, state)
|
||||||
return ErrorCall (str, pos - 1, "unterminated " .. what, state)
|
return ErrorCall(str, pos - 1, 'unterminated ' .. what, state)
|
||||||
end
|
end
|
||||||
|
|
||||||
local SingleLineComment = P"//" * (1 - S"\n\r")^0
|
local SingleLineComment = P('//') * (1 - S('\n\r')) ^ 0
|
||||||
local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/"
|
local MultiLineComment = P('/*') * (1 - P('*/')) ^ 0 * P('*/')
|
||||||
local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0
|
local Space = (S(' \n\r\t') + P('\239\187\191') + SingleLineComment + MultiLineComment) ^ 0
|
||||||
|
|
||||||
local function ErrUnterminated(what)
|
local function ErrUnterminated(what)
|
||||||
return g.Cmt(g.Cc(what) * g.Carg(2), ErrorUnterminatedCall)
|
return g.Cmt(g.Cc(what) * g.Carg(2), ErrorUnterminatedCall)
|
||||||
end
|
end
|
||||||
|
|
||||||
local PlainChar = 1 - S"\"\\\n\r"
|
local PlainChar = 1 - S('"\\\n\r')
|
||||||
local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars
|
local EscapeSequence = (P('\\') * g.C(S('"\\/bfnrt') + Err('unsupported escape sequence'))) / escapechars
|
||||||
local HexDigit = R("09", "af", "AF")
|
local HexDigit = R('09', 'af', 'AF')
|
||||||
local function UTF16Surrogate(_match, _pos, high, low)
|
local function UTF16Surrogate(_match, _pos, high, low)
|
||||||
high, low = tonumber(high, 16), tonumber(low, 16)
|
high, low = tonumber(high, 16), tonumber(low, 16)
|
||||||
if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then
|
if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then
|
||||||
@ -650,15 +704,15 @@ function json.use_lpeg ()
|
|||||||
local function UTF16BMP(hex)
|
local function UTF16BMP(hex)
|
||||||
return unichar(tonumber(hex, 16))
|
return unichar(tonumber(hex, 16))
|
||||||
end
|
end
|
||||||
local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit))
|
local U16Sequence = (P('\\u') * g.C(HexDigit * HexDigit * HexDigit * HexDigit))
|
||||||
local UnicodeEscape = g.Cmt(U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence / UTF16BMP
|
local UnicodeEscape = g.Cmt(U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence / UTF16BMP
|
||||||
local Char = UnicodeEscape + EscapeSequence + PlainChar
|
local Char = UnicodeEscape + EscapeSequence + PlainChar
|
||||||
local String = P"\"" * (g.Cs (Char ^ 0) * P"\"" + ErrUnterminated "string")
|
local String = P('"') * (g.Cs(Char ^ 0) * P('"') + ErrUnterminated('string'))
|
||||||
local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0))
|
local Integer = P('-') ^ -1 * (P('0') + (R('19') * R('09') ^ 0))
|
||||||
local Fractal = P"." * R"09"^0
|
local Fractal = P('.') * R('09') ^ 0
|
||||||
local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1
|
local Exponent = (S('eE')) * (S('+-')) ^ -1 * R('09') ^ 1
|
||||||
local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num
|
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 Constant = P('true') * g.Cc(true) + P('false') * g.Cc(false) + P('null') * g.Carg(1)
|
||||||
local SimpleValue = Number + String + Constant
|
local SimpleValue = Number + String + Constant
|
||||||
local ArrayContent, ObjectContent
|
local ArrayContent, ObjectContent
|
||||||
|
|
||||||
@ -672,7 +726,7 @@ function json.use_lpeg ()
|
|||||||
repeat
|
repeat
|
||||||
obj, cont, npos = pegmatch(ArrayContent, str, pos, nullval, state)
|
obj, cont, npos = pegmatch(ArrayContent, str, pos, nullval, state)
|
||||||
if cont == 'end' then
|
if cont == 'end' then
|
||||||
return ErrorUnterminatedCall (str, start, "array", state)
|
return ErrorUnterminatedCall(str, start, 'array', state)
|
||||||
end
|
end
|
||||||
pos = npos
|
pos = npos
|
||||||
if cont == 'cont' or cont == 'last' then
|
if cont == 'cont' or cont == 'last' then
|
||||||
@ -691,7 +745,7 @@ function json.use_lpeg ()
|
|||||||
repeat
|
repeat
|
||||||
key, obj, cont, npos = pegmatch(ObjectContent, str, pos, nullval, state)
|
key, obj, cont, npos = pegmatch(ObjectContent, str, pos, nullval, state)
|
||||||
if cont == 'end' then
|
if cont == 'end' then
|
||||||
return ErrorUnterminatedCall (str, start, "object", state)
|
return ErrorUnterminatedCall(str, start, 'object', state)
|
||||||
end
|
end
|
||||||
pos = npos
|
pos = npos
|
||||||
if cont == 'cont' or cont == 'last' then
|
if cont == 'cont' or cont == 'last' then
|
||||||
@ -701,16 +755,23 @@ function json.use_lpeg ()
|
|||||||
return pos, setmetatable(t, state.objectmeta)
|
return pos, setmetatable(t, state.objectmeta)
|
||||||
end
|
end
|
||||||
|
|
||||||
local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray)
|
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 Object = P('{') * g.Cmt(g.Carg(1) * g.Carg(2), parseobject)
|
||||||
local Value = Space * (Array + Object + SimpleValue)
|
local Value = Space * (Array + Object + SimpleValue)
|
||||||
local ExpectedValue = Value + Space * Err "value expected"
|
local ExpectedValue = Value + Space * Err('value expected')
|
||||||
local ExpectedKey = String + Err "key expected"
|
local ExpectedKey = String + Err('key expected')
|
||||||
local End = P(-1) * g.Cc'end'
|
local End = P(-1) * g.Cc('end')
|
||||||
local ErrInvalid = Err "invalid JSON"
|
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()
|
ArrayContent = (
|
||||||
local Pair = g.Cg (Space * ExpectedKey * Space * (P":" + Err "colon expected") * ExpectedValue)
|
Value * Space * (P(',') * g.Cc('cont') + P(']') * g.Cc('last') + End + ErrInvalid)
|
||||||
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()
|
+ 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 DecodeValue = ExpectedValue * g.Cp()
|
||||||
|
|
||||||
jsonlpeg.version = json.version
|
jsonlpeg.version = json.version
|
||||||
@ -733,7 +794,9 @@ function json.use_lpeg ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- cache result of this function:
|
-- cache result of this function:
|
||||||
json.use_lpeg = function () return jsonlpeg end
|
json.use_lpeg = function()
|
||||||
|
return jsonlpeg
|
||||||
|
end
|
||||||
jsonlpeg.use_lpeg = json.use_lpeg
|
jsonlpeg.use_lpeg = json.use_lpeg
|
||||||
|
|
||||||
return jsonlpeg
|
return jsonlpeg
|
||||||
@ -744,4 +807,3 @@ if always_use_lpeg then
|
|||||||
end
|
end
|
||||||
|
|
||||||
return json
|
return json
|
||||||
|
|
||||||
|
@ -11,24 +11,26 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local sqrt = math.sqrt
|
local sqrt = math.sqrt
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local client = client
|
local client = client
|
||||||
local tonumber = tonumber
|
local tonumber = tonumber
|
||||||
local wrequire = require("lain.helpers").wrequire
|
local wrequire = require('lain.helpers').wrequire
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
-- Lain utilities submodule
|
-- Lain utilities submodule
|
||||||
-- lain.util
|
-- lain.util
|
||||||
local util = { _NAME = "lain.util" }
|
local util = { _NAME = 'lain.util' }
|
||||||
|
|
||||||
-- Like awful.menu.clients, but only show clients of currently selected tags
|
-- Like awful.menu.clients, but only show clients of currently selected tags
|
||||||
function util.menu_clients_current_tags(menu, args)
|
function util.menu_clients_current_tags(menu, args)
|
||||||
-- List of currently selected tags.
|
-- List of currently selected tags.
|
||||||
local cls_tags = awful.screen.focused().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.
|
-- Final list of menu items.
|
||||||
local cls_t = {}
|
local cls_t = {}
|
||||||
@ -40,22 +42,28 @@ function util.menu_clients_current_tags(menu, args)
|
|||||||
local cls = t:clients()
|
local cls = t:clients()
|
||||||
|
|
||||||
for _, c in pairs(cls) do
|
for _, c in pairs(cls) do
|
||||||
cls_t[#cls_t + 1] = { awful.util.escape(c.name) or "",
|
cls_t[#cls_t + 1] = {
|
||||||
|
awful.util.escape(c.name) or '',
|
||||||
function()
|
function()
|
||||||
c.minimized = false
|
c.minimized = false
|
||||||
client.focus = c
|
client.focus = c
|
||||||
c:raise()
|
c:raise()
|
||||||
end,
|
end,
|
||||||
c.icon }
|
c.icon,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- No clients? Then quit.
|
-- No clients? Then quit.
|
||||||
if #cls_t <= 0 then return nil end
|
if #cls_t <= 0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
-- menu may contain some predefined values, otherwise start with a
|
-- menu may contain some predefined values, otherwise start with a
|
||||||
-- fresh menu.
|
-- fresh menu.
|
||||||
if not menu then menu = {} end
|
if not menu then
|
||||||
|
menu = {}
|
||||||
|
end
|
||||||
|
|
||||||
-- Set the list of items and show the menu.
|
-- Set the list of items and show the menu.
|
||||||
menu.items = cls_t
|
menu.items = cls_t
|
||||||
@ -79,7 +87,9 @@ end
|
|||||||
-- https://github.com/lcpz/lain/issues/195
|
-- https://github.com/lcpz/lain/issues/195
|
||||||
function util.mc(c, width_f, height_f)
|
function util.mc(c, width_f, height_f)
|
||||||
c = c or util.magnified_client
|
c = c or util.magnified_client
|
||||||
if not c then return end
|
if not c then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
c.floating = true
|
c.floating = true
|
||||||
local s = awful.screen.focused()
|
local s = awful.screen.focused()
|
||||||
@ -91,7 +101,9 @@ function util.mc(c, width_f, height_f)
|
|||||||
g.x = mg.x + (mg.width - g.width) / 2
|
g.x = mg.x + (mg.width - g.width) / 2
|
||||||
g.y = mg.y + (mg.height - g.height) / 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
|
end
|
||||||
|
|
||||||
-- Non-empty tag browsing
|
-- Non-empty tag browsing
|
||||||
@ -133,29 +145,35 @@ end
|
|||||||
|
|
||||||
-- Add a new tag
|
-- Add a new tag
|
||||||
function util.add_tag(layout)
|
function util.add_tag(layout)
|
||||||
awful.prompt.run {
|
awful.prompt.run({
|
||||||
prompt = "New tag name: ",
|
prompt = 'New tag name: ',
|
||||||
textbox = awful.screen.focused().mypromptbox.widget,
|
textbox = awful.screen.focused().mypromptbox.widget,
|
||||||
exe_callback = function(name)
|
exe_callback = function(name)
|
||||||
if not name or #name == 0 then return end
|
if not name or #name == 0 then
|
||||||
awful.tag.add(name, { screen = awful.screen.focused(), layout = layout or awful.layout.suit.tile }):view_only()
|
return
|
||||||
end
|
end
|
||||||
}
|
awful.tag
|
||||||
|
.add(name, { screen = awful.screen.focused(), layout = layout or awful.layout.suit.tile })
|
||||||
|
:view_only()
|
||||||
|
end,
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Rename current tag
|
-- Rename current tag
|
||||||
function util.rename_tag()
|
function util.rename_tag()
|
||||||
awful.prompt.run {
|
awful.prompt.run({
|
||||||
prompt = "Rename tag: ",
|
prompt = 'Rename tag: ',
|
||||||
textbox = awful.screen.focused().mypromptbox.widget,
|
textbox = awful.screen.focused().mypromptbox.widget,
|
||||||
exe_callback = function(new_name)
|
exe_callback = function(new_name)
|
||||||
if not new_name or #new_name == 0 then return end
|
if not new_name or #new_name == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
local t = awful.screen.focused().selected_tag
|
local t = awful.screen.focused().selected_tag
|
||||||
if t then
|
if t then
|
||||||
t.name = new_name
|
t.name = new_name
|
||||||
end
|
end
|
||||||
end
|
end,
|
||||||
}
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Move current tag
|
-- Move current tag
|
||||||
@ -173,7 +191,9 @@ end
|
|||||||
-- Any rule set on the tag shall be broken
|
-- Any rule set on the tag shall be broken
|
||||||
function util.delete_tag()
|
function util.delete_tag()
|
||||||
local t = awful.screen.focused().selected_tag
|
local t = awful.screen.focused().selected_tag
|
||||||
if not t then return end
|
if not t then
|
||||||
|
return
|
||||||
|
end
|
||||||
t:delete()
|
t:delete()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -15,13 +15,27 @@ local setmetatable = setmetatable
|
|||||||
local markup = { fg = {}, bg = {} }
|
local markup = { fg = {}, bg = {} }
|
||||||
|
|
||||||
-- Convenience tags
|
-- Convenience tags
|
||||||
function markup.bold(text) return format("<b>%s</b>", text) end
|
function markup.bold(text)
|
||||||
function markup.italic(text) return format("<i>%s</i>", text) end
|
return format('<b>%s</b>', text)
|
||||||
function markup.strike(text) return format("<s>%s</s>", text) end
|
end
|
||||||
function markup.underline(text) return format("<u>%s</u>", text) end
|
function markup.italic(text)
|
||||||
function markup.monospace(text) return format("<tt>%s</tt>", text) end
|
return format('<i>%s</i>', text)
|
||||||
function markup.big(text) return format("<big>%s</big>", text) end
|
end
|
||||||
function markup.small(text) return format("<small>%s</small>", text) end
|
function markup.strike(text)
|
||||||
|
return format('<s>%s</s>', text)
|
||||||
|
end
|
||||||
|
function markup.underline(text)
|
||||||
|
return format('<u>%s</u>', text)
|
||||||
|
end
|
||||||
|
function markup.monospace(text)
|
||||||
|
return format('<tt>%s</tt>', text)
|
||||||
|
end
|
||||||
|
function markup.big(text)
|
||||||
|
return format('<big>%s</big>', text)
|
||||||
|
end
|
||||||
|
function markup.small(text)
|
||||||
|
return format('<small>%s</small>', text)
|
||||||
|
end
|
||||||
|
|
||||||
-- Set the font
|
-- Set the font
|
||||||
function markup.font(font, text)
|
function markup.font(font, text)
|
||||||
@ -59,8 +73,20 @@ function markup.fontcolor(font, fg, bg, text)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- link markup.{fg,bg}(...) calls to markup.{fg,bg}.color(...)
|
-- link markup.{fg,bg}(...) calls to markup.{fg,bg}.color(...)
|
||||||
setmetatable(markup.fg, { __call = function(_, ...) return markup.fg.color(...) end })
|
setmetatable(markup.fg, {
|
||||||
setmetatable(markup.bg, { __call = function(_, ...) return markup.bg.color(...) end })
|
__call = function(_, ...)
|
||||||
|
return markup.fg.color(...)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
setmetatable(markup.bg, {
|
||||||
|
__call = function(_, ...)
|
||||||
|
return markup.bg.color(...)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
-- link markup(...) calls to markup.fg.color(...)
|
-- 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,
|
||||||
|
})
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
-- Menu iterator with Naughty notifications
|
-- Menu iterator with Naughty notifications
|
||||||
-- lain.util.menu_iterator
|
-- lain.util.menu_iterator
|
||||||
|
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local atable = require("awful.util").table
|
local atable = require('awful.util').table
|
||||||
local assert = assert
|
local assert = assert
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local tconcat = table.concat
|
local tconcat = table.concat
|
||||||
@ -27,7 +27,9 @@ local function naughty_destroy_callback(reason)
|
|||||||
if actions then
|
if actions then
|
||||||
for _, action in pairs(actions) do
|
for _, action in pairs(actions) do
|
||||||
-- don't try to call nil callbacks
|
-- don't try to call nil callbacks
|
||||||
if action then action() end
|
if action then
|
||||||
|
action()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
state.index = nil
|
state.index = nil
|
||||||
end
|
end
|
||||||
@ -56,7 +58,7 @@ local function iterate(menu, timeout, icon)
|
|||||||
state.index = state.index + 1
|
state.index = state.index + 1
|
||||||
|
|
||||||
if not next then
|
if not next then
|
||||||
label = "Cancel"
|
label = 'Cancel'
|
||||||
state.index = nil
|
state.index = nil
|
||||||
else
|
else
|
||||||
label, _ = unpack(next)
|
label, _ = unpack(next)
|
||||||
@ -68,7 +70,7 @@ local function iterate(menu, timeout, icon)
|
|||||||
timeout = timeout,
|
timeout = timeout,
|
||||||
screen = mouse.screen,
|
screen = mouse.screen,
|
||||||
replaces_id = state.cid,
|
replaces_id = state.cid,
|
||||||
destroy = naughty_destroy_callback
|
destroy = naughty_destroy_callback,
|
||||||
}).id
|
}).id
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -101,7 +103,8 @@ local function menu(args)
|
|||||||
local rejected_cb = args.rejected_cb
|
local rejected_cb = args.rejected_cb
|
||||||
local extra_choices = args.extra_choices or {}
|
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
|
for _, c in pairs(extra_choices) do
|
||||||
ch_combinations = atable.join(ch_combinations, { { c[1] } })
|
ch_combinations = atable.join(ch_combinations, { { c[1] } })
|
||||||
@ -116,14 +119,18 @@ local function menu(args)
|
|||||||
-- selected choices
|
-- selected choices
|
||||||
for _, ch in pairs(c) do
|
for _, ch in pairs(c) do
|
||||||
if atable.hasitem(choices, ch) then
|
if atable.hasitem(choices, ch) then
|
||||||
cbs[#cbs + 1] = selected_cb and function() selected_cb(ch) end or nil
|
cbs[#cbs + 1] = selected_cb and function()
|
||||||
|
selected_cb(ch)
|
||||||
|
end or nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- rejected choices
|
-- rejected choices
|
||||||
for _, ch in pairs(choices) do
|
for _, ch in pairs(choices) do
|
||||||
if not atable.hasitem(c, ch) and atable.hasitem(choices, ch) then
|
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
|
cbs[#cbs + 1] = rejected_cb and function()
|
||||||
|
rejected_cb(ch)
|
||||||
|
end or nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -134,7 +141,7 @@ local function menu(args)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
m[#m + 1] = { name .. ": " .. tconcat(c, " + "), cbs }
|
m[#m + 1] = { name .. ': ' .. tconcat(c, ' + '), cbs }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local capi = { client = client }
|
local capi = { client = client }
|
||||||
local math = math
|
local math = math
|
||||||
local string = string
|
local string = string
|
||||||
@ -22,12 +22,15 @@ local quake = {}
|
|||||||
-- run into problems with focus.
|
-- run into problems with focus.
|
||||||
|
|
||||||
function quake:display()
|
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
|
-- First, we locate the client
|
||||||
local client = nil
|
local client = nil
|
||||||
local i = 0
|
local i = 0
|
||||||
for c in awful.client.iterate(function (c)
|
for c in
|
||||||
|
awful.client.iterate(function(c)
|
||||||
-- c.name may be changed!
|
-- c.name may be changed!
|
||||||
return c.instance == self.name
|
return c.instance == self.name
|
||||||
end)
|
end)
|
||||||
@ -46,12 +49,13 @@ function quake:display()
|
|||||||
end
|
end
|
||||||
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
|
if not client then
|
||||||
-- The client does not exist, we spawn it
|
-- The client does not exist, we spawn it
|
||||||
local cmd = string.format("%s %s %s", self.app,
|
local cmd = string.format('%s %s %s', self.app, string.format(self.argname, self.name), self.extra)
|
||||||
string.format(self.argname, self.name), self.extra)
|
|
||||||
awful.spawn(cmd, { tag = self.screen.selected_tag })
|
awful.spawn(cmd, { tag = self.screen.selected_tag })
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -71,7 +75,9 @@ function quake:display()
|
|||||||
client.skip_taskbar = true
|
client.skip_taskbar = true
|
||||||
|
|
||||||
-- Additional user settings
|
-- Additional user settings
|
||||||
if self.settings then self.settings(client) end
|
if self.settings then
|
||||||
|
self.settings(client)
|
||||||
|
end
|
||||||
|
|
||||||
-- Toggle display
|
-- Toggle display
|
||||||
if self.visible then
|
if self.visible then
|
||||||
@ -108,22 +114,36 @@ function quake:compute_size()
|
|||||||
geom = screen[self.screen.index].geometry
|
geom = screen[self.screen.index].geometry
|
||||||
end
|
end
|
||||||
local width, height = self.width, self.height
|
local width, height = self.width, self.height
|
||||||
if width <= 1 then width = math.floor(geom.width * width) - 2 * self.border end
|
if width <= 1 then
|
||||||
if height <= 1 then height = math.floor(geom.height * height) end
|
width = math.floor(geom.width * width) - 2 * self.border
|
||||||
|
end
|
||||||
|
if height <= 1 then
|
||||||
|
height = math.floor(geom.height * height)
|
||||||
|
end
|
||||||
local x, y
|
local x, y
|
||||||
if self.horiz == "left" then x = geom.x
|
if self.horiz == 'left' then
|
||||||
elseif self.horiz == "right" then x = geom.width + geom.x - width
|
x = geom.x
|
||||||
else x = geom.x + (geom.width - width)/2 end
|
elseif self.horiz == 'right' then
|
||||||
if self.vert == "top" then y = geom.y
|
x = geom.width + geom.x - width
|
||||||
elseif self.vert == "bottom" then y = geom.height + geom.y - height
|
else
|
||||||
else y = geom.y + (geom.height - height)/2 end
|
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 }
|
self.geometry[self.screen.index] = { x = x, y = y, width = width, height = height }
|
||||||
end
|
end
|
||||||
return self.geometry[self.screen.index]
|
return self.geometry[self.screen.index]
|
||||||
end
|
end
|
||||||
|
|
||||||
function quake:toggle()
|
function quake:toggle()
|
||||||
if self.followtag then self.screen = awful.screen.focused() end
|
if self.followtag then
|
||||||
|
self.screen = awful.screen.focused()
|
||||||
|
end
|
||||||
local current_tag = self.screen.selected_tag
|
local current_tag = self.screen.selected_tag
|
||||||
if current_tag and self.last_tag ~= current_tag and self.visible then
|
if current_tag and self.last_tag ~= current_tag and self.visible then
|
||||||
local c = self:display()
|
local c = self:display()
|
||||||
@ -139,10 +159,10 @@ end
|
|||||||
function quake.new(conf)
|
function quake.new(conf)
|
||||||
conf = conf or {}
|
conf = conf or {}
|
||||||
|
|
||||||
conf.app = conf.app or "xterm" -- application to spawn
|
conf.app = conf.app or 'xterm' -- application to spawn
|
||||||
conf.name = conf.name or "QuakeDD" -- window name
|
conf.name = conf.name or 'QuakeDD' -- window name
|
||||||
conf.argname = conf.argname or "-name %s" -- how to specify window name
|
conf.argname = conf.argname or '-name %s' -- how to specify window name
|
||||||
conf.extra = conf.extra or "" -- extra arguments
|
conf.extra = conf.extra or '' -- extra arguments
|
||||||
conf.border = conf.border or 1 -- client border width
|
conf.border = conf.border or 1 -- client border width
|
||||||
conf.visible = conf.visible or false -- initially not visible
|
conf.visible = conf.visible or false -- initially not visible
|
||||||
conf.followtag = conf.followtag or false -- spawn on currently focused screen
|
conf.followtag = conf.followtag or false -- spawn on currently focused screen
|
||||||
@ -153,8 +173,8 @@ function quake.new(conf)
|
|||||||
-- If width or height <= 1 this is a proportion of the workspace
|
-- If width or height <= 1 this is a proportion of the workspace
|
||||||
conf.height = conf.height or 0.25 -- height
|
conf.height = conf.height or 0.25 -- height
|
||||||
conf.width = conf.width or 1 -- width
|
conf.width = conf.width or 1 -- width
|
||||||
conf.vert = conf.vert or "top" -- top, bottom or center
|
conf.vert = conf.vert or 'top' -- top, bottom or center
|
||||||
conf.horiz = conf.horiz or "left" -- left, right or center
|
conf.horiz = conf.horiz or 'left' -- left, right or center
|
||||||
conf.geometry = {} -- internal use
|
conf.geometry = {} -- internal use
|
||||||
|
|
||||||
conf.maximized = false
|
conf.maximized = false
|
||||||
@ -162,12 +182,12 @@ function quake.new(conf)
|
|||||||
|
|
||||||
local dropdown = setmetatable(conf, { __index = quake })
|
local dropdown = setmetatable(conf, { __index = quake })
|
||||||
|
|
||||||
capi.client.connect_signal("manage", function(c)
|
capi.client.connect_signal('manage', function(c)
|
||||||
if c.instance == dropdown.name and c.screen == dropdown.screen then
|
if c.instance == dropdown.name and c.screen == dropdown.screen then
|
||||||
dropdown:display()
|
dropdown:display()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
capi.client.connect_signal("unmanage", function(c)
|
capi.client.connect_signal('unmanage', function(c)
|
||||||
if c.instance == dropdown.name and c.screen == dropdown.screen then
|
if c.instance == dropdown.name and c.screen == dropdown.screen then
|
||||||
dropdown.visible = false
|
dropdown.visible = false
|
||||||
end
|
end
|
||||||
@ -176,4 +196,8 @@ function quake.new(conf)
|
|||||||
return dropdown
|
return dropdown
|
||||||
end
|
end
|
||||||
|
|
||||||
return setmetatable(quake, { __call = function(_, ...) return quake.new(...) end })
|
return setmetatable(quake, {
|
||||||
|
__call = function(_, ...)
|
||||||
|
return quake.new(...)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local gears = require("gears")
|
local gears = require('gears')
|
||||||
local beautiful = require("beautiful")
|
local beautiful = require('beautiful')
|
||||||
|
|
||||||
-- Lain Cairo separators util submodule
|
-- Lain Cairo separators util submodule
|
||||||
-- lain.util.separators
|
-- lain.util.separators
|
||||||
@ -29,11 +29,11 @@ function separators.arrow_right(col1, col2)
|
|||||||
widget.update = function(_, _)
|
widget.update = function(_, _)
|
||||||
widget.col1 = col1
|
widget.col1 = col1
|
||||||
widget.col2 = col2
|
widget.col2 = col2
|
||||||
widget:emit_signal("widget::redraw_needed")
|
widget:emit_signal('widget::redraw_needed')
|
||||||
end
|
end
|
||||||
|
|
||||||
widget.draw = function(_, _, cr, width, height)
|
widget.draw = function(_, _, cr, width, height)
|
||||||
if widget.col2 ~= "alpha" then
|
if widget.col2 ~= 'alpha' then
|
||||||
cr:set_source_rgba(gears.color.parse_color(widget.col2))
|
cr:set_source_rgba(gears.color.parse_color(widget.col2))
|
||||||
cr:new_path()
|
cr:new_path()
|
||||||
cr:move_to(0, 0)
|
cr:move_to(0, 0)
|
||||||
@ -50,7 +50,7 @@ function separators.arrow_right(col1, col2)
|
|||||||
cr:fill()
|
cr:fill()
|
||||||
end
|
end
|
||||||
|
|
||||||
if widget.col1 ~= "alpha" then
|
if widget.col1 ~= 'alpha' then
|
||||||
cr:set_source_rgba(gears.color.parse_color(widget.col1))
|
cr:set_source_rgba(gears.color.parse_color(widget.col1))
|
||||||
cr:new_path()
|
cr:new_path()
|
||||||
cr:move_to(0, 0)
|
cr:move_to(0, 0)
|
||||||
@ -77,11 +77,11 @@ function separators.arrow_left(col1, col2)
|
|||||||
widget.update = function(c1, c2)
|
widget.update = function(c1, c2)
|
||||||
widget.col1 = c1
|
widget.col1 = c1
|
||||||
widget.col2 = c2
|
widget.col2 = c2
|
||||||
widget:emit_signal("widget::redraw_needed")
|
widget:emit_signal('widget::redraw_needed')
|
||||||
end
|
end
|
||||||
|
|
||||||
widget.draw = function(_, _, cr, width, height)
|
widget.draw = function(_, _, cr, width, height)
|
||||||
if widget.col1 ~= "alpha" then
|
if widget.col1 ~= 'alpha' then
|
||||||
cr:set_source_rgba(gears.color.parse_color(widget.col1))
|
cr:set_source_rgba(gears.color.parse_color(widget.col1))
|
||||||
cr:new_path()
|
cr:new_path()
|
||||||
cr:move_to(width, 0)
|
cr:move_to(width, 0)
|
||||||
@ -98,7 +98,7 @@ function separators.arrow_left(col1, col2)
|
|||||||
cr:fill()
|
cr:fill()
|
||||||
end
|
end
|
||||||
|
|
||||||
if widget.col2 ~= "alpha" then
|
if widget.col2 ~= 'alpha' then
|
||||||
cr:new_path()
|
cr:new_path()
|
||||||
cr:move_to(width, 0)
|
cr:move_to(width, 0)
|
||||||
cr:line_to(0, height / 2)
|
cr:line_to(0, height / 2)
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local shell = require("awful.util").shell
|
local shell = require('awful.util').shell
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local string = string
|
local string = string
|
||||||
|
|
||||||
-- ALSA volume
|
-- ALSA volume
|
||||||
@ -20,22 +20,25 @@ local function factory(args)
|
|||||||
local timeout = args.timeout or 5
|
local timeout = args.timeout or 5
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
alsa.cmd = args.cmd or "amixer"
|
alsa.cmd = args.cmd or 'amixer'
|
||||||
alsa.channel = args.channel or "Master"
|
alsa.channel = args.channel or 'Master'
|
||||||
alsa.togglechannel = args.togglechannel
|
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
|
if alsa.togglechannel then
|
||||||
format_cmd = { shell, "-c", string.format("%s get %s; %s get %s",
|
format_cmd = {
|
||||||
alsa.cmd, alsa.channel, alsa.cmd, alsa.togglechannel) }
|
shell,
|
||||||
|
'-c',
|
||||||
|
string.format('%s get %s; %s get %s', alsa.cmd, alsa.channel, alsa.cmd, alsa.togglechannel),
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
alsa.last = {}
|
alsa.last = {}
|
||||||
|
|
||||||
function alsa.update()
|
function alsa.update()
|
||||||
helpers.async(format_cmd, function(mixer)
|
helpers.async(format_cmd, function(mixer)
|
||||||
local l,s = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
|
local l, s = string.match(mixer, '([%d]+)%%.*%[([%l]*)')
|
||||||
l = tonumber(l)
|
l = tonumber(l)
|
||||||
if alsa.last.level ~= l or alsa.last.status ~= s then
|
if alsa.last.level ~= l or alsa.last.status ~= s then
|
||||||
volume_now = { level = l, status = s }
|
volume_now = { level = l, status = s }
|
||||||
@ -46,7 +49,7 @@ local function factory(args)
|
|||||||
end)
|
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
|
end
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local math = math
|
local math = math
|
||||||
local string = string
|
local string = string
|
||||||
local type = type
|
local type = type
|
||||||
@ -21,13 +21,13 @@ local tonumber = tonumber
|
|||||||
local function factory(args)
|
local function factory(args)
|
||||||
local alsabar = {
|
local alsabar = {
|
||||||
colors = {
|
colors = {
|
||||||
background = "#000000",
|
background = '#000000',
|
||||||
mute = "#EB8F8F",
|
mute = '#EB8F8F',
|
||||||
unmute = "#A4CE8A"
|
unmute = '#A4CE8A',
|
||||||
},
|
},
|
||||||
|
|
||||||
_current_level = 0,
|
_current_level = 0,
|
||||||
_playback = "off"
|
_playback = 'off',
|
||||||
}
|
}
|
||||||
|
|
||||||
args = args or {}
|
args = args or {}
|
||||||
@ -39,30 +39,33 @@ local function factory(args)
|
|||||||
local margins = args.margins or 1
|
local margins = args.margins or 1
|
||||||
local ticks = args.ticks or false
|
local ticks = args.ticks or false
|
||||||
local ticks_size = args.ticks_size or 7
|
local ticks_size = args.ticks_size or 7
|
||||||
local tick = args.tick or "|"
|
local tick = args.tick or '|'
|
||||||
local tick_pre = args.tick_pre or "["
|
local tick_pre = args.tick_pre or '['
|
||||||
local tick_post = args.tick_post or "]"
|
local tick_post = args.tick_post or ']'
|
||||||
local tick_none = args.tick_none or " "
|
local tick_none = args.tick_none or ' '
|
||||||
|
|
||||||
alsabar.cmd = args.cmd or "amixer"
|
alsabar.cmd = args.cmd or 'amixer'
|
||||||
alsabar.channel = args.channel or "Master"
|
alsabar.channel = args.channel or 'Master'
|
||||||
alsabar.togglechannel = args.togglechannel
|
alsabar.togglechannel = args.togglechannel
|
||||||
alsabar.colors = args.colors or alsabar.colors
|
alsabar.colors = args.colors or alsabar.colors
|
||||||
alsabar.followtag = args.followtag or false
|
alsabar.followtag = args.followtag or false
|
||||||
alsabar.notification_preset = args.notification_preset
|
alsabar.notification_preset = args.notification_preset
|
||||||
|
|
||||||
if not alsabar.notification_preset then
|
if not alsabar.notification_preset then
|
||||||
alsabar.notification_preset = { font = "Monospace 10" }
|
alsabar.notification_preset = { font = 'Monospace 10' }
|
||||||
end
|
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
|
if alsabar.togglechannel then
|
||||||
format_cmd = { awful.util.shell, "-c", string.format("%s get %s; %s get %s",
|
format_cmd = {
|
||||||
alsabar.cmd, alsabar.channel, alsabar.cmd, alsabar.togglechannel) }
|
awful.util.shell,
|
||||||
|
'-c',
|
||||||
|
string.format('%s get %s; %s get %s', alsabar.cmd, alsabar.channel, alsabar.cmd, alsabar.togglechannel),
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
alsabar.bar = wibox.widget {
|
alsabar.bar = wibox.widget({
|
||||||
color = alsabar.colors.unmute,
|
color = alsabar.colors.unmute,
|
||||||
background_color = alsabar.colors.background,
|
background_color = alsabar.colors.background,
|
||||||
forced_height = height,
|
forced_height = height,
|
||||||
@ -71,38 +74,42 @@ local function factory(args)
|
|||||||
paddings = margins,
|
paddings = margins,
|
||||||
ticks = ticks,
|
ticks = ticks,
|
||||||
ticks_size = ticks_size,
|
ticks_size = ticks_size,
|
||||||
widget = wibox.widget.progressbar
|
widget = wibox.widget.progressbar,
|
||||||
}
|
})
|
||||||
|
|
||||||
alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
|
alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
|
||||||
|
|
||||||
function alsabar.update(callback)
|
function alsabar.update(callback)
|
||||||
helpers.async(format_cmd, function(mixer)
|
helpers.async(format_cmd, function(mixer)
|
||||||
local vol, playback = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
|
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
|
if vol ~= alsabar._current_level or playback ~= alsabar._playback then
|
||||||
alsabar._current_level = tonumber(vol)
|
alsabar._current_level = tonumber(vol)
|
||||||
alsabar.bar:set_value(alsabar._current_level / 100)
|
alsabar.bar:set_value(alsabar._current_level / 100)
|
||||||
if alsabar._current_level == 0 or playback == "off" then
|
if alsabar._current_level == 0 or playback == 'off' then
|
||||||
alsabar._playback = playback
|
alsabar._playback = playback
|
||||||
alsabar.tooltip:set_text("[Muted]")
|
alsabar.tooltip:set_text('[Muted]')
|
||||||
alsabar.bar.color = alsabar.colors.mute
|
alsabar.bar.color = alsabar.colors.mute
|
||||||
else
|
else
|
||||||
alsabar._playback = "on"
|
alsabar._playback = 'on'
|
||||||
alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, vol))
|
alsabar.tooltip:set_text(string.format('%s: %s', alsabar.channel, vol))
|
||||||
alsabar.bar.color = alsabar.colors.unmute
|
alsabar.bar.color = alsabar.colors.unmute
|
||||||
end
|
end
|
||||||
|
|
||||||
volume_now = {
|
volume_now = {
|
||||||
level = alsabar._current_level,
|
level = alsabar._current_level,
|
||||||
status = alsabar._playback
|
status = alsabar._playback,
|
||||||
}
|
}
|
||||||
|
|
||||||
settings()
|
settings()
|
||||||
|
|
||||||
if type(callback) == "function" then callback() end
|
if type(callback) == 'function' then
|
||||||
|
callback()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -111,10 +118,10 @@ local function factory(args)
|
|||||||
alsabar.update(function()
|
alsabar.update(function()
|
||||||
local preset = alsabar.notification_preset
|
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
|
if alsabar._playback == 'off' then
|
||||||
preset.title = preset.title .. " Muted"
|
preset.title = preset.title .. ' Muted'
|
||||||
end
|
end
|
||||||
|
|
||||||
-- tot is the maximum number of ticks to display in the notification
|
-- tot is the maximum number of ticks to display in the notification
|
||||||
@ -125,7 +132,7 @@ local function factory(args)
|
|||||||
-- if we can grab mywibox, tot is defined as its height if
|
-- if we can grab mywibox, tot is defined as its height if
|
||||||
-- horizontal, or width otherwise
|
-- horizontal, or width otherwise
|
||||||
if wib then
|
if wib then
|
||||||
if wib.position == "left" or wib.position == "right" then
|
if wib.position == 'left' or wib.position == 'right' then
|
||||||
tot = wib.width
|
tot = wib.width
|
||||||
else
|
else
|
||||||
tot = wib.height
|
tot = wib.height
|
||||||
@ -137,28 +144,27 @@ local function factory(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local int = math.modf((alsabar._current_level / 100) * tot)
|
local int = math.modf((alsabar._current_level / 100) * tot)
|
||||||
preset.text = string.format(
|
preset.text =
|
||||||
"%s%s%s%s",
|
string.format('%s%s%s%s', tick_pre, string.rep(tick, int), string.rep(tick_none, tot - int), tick_post)
|
||||||
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
|
if not alsabar.notification then
|
||||||
alsabar.notification = naughty.notify {
|
alsabar.notification = naughty.notify({
|
||||||
preset = preset,
|
preset = preset,
|
||||||
destroy = function() alsabar.notification = nil end
|
destroy = function()
|
||||||
}
|
alsabar.notification = nil
|
||||||
|
end,
|
||||||
|
})
|
||||||
else
|
else
|
||||||
naughty.replace_text(alsabar.notification, preset.title, preset.text)
|
naughty.replace_text(alsabar.notification, preset.title, preset.text)
|
||||||
end
|
end
|
||||||
end)
|
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
|
end
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local fs = require("gears.filesystem")
|
local fs = require('gears.filesystem')
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local math = math
|
local math = math
|
||||||
local string = string
|
local string = string
|
||||||
local ipairs = ipairs
|
local ipairs = ipairs
|
||||||
@ -19,10 +19,10 @@ local tonumber = tonumber
|
|||||||
-- lain.widget.bat
|
-- lain.widget.bat
|
||||||
|
|
||||||
local function factory(args)
|
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
|
if not fs.is_dir(pspath) then
|
||||||
naughty.notify { text = "lain.widget.bat: invalid power supply path", timeout = 0 }
|
naughty.notify({ text = 'lain.widget.bat: invalid power supply path', timeout = 0 })
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -30,64 +30,66 @@ local function factory(args)
|
|||||||
|
|
||||||
local bat = { widget = args.widget or wibox.widget.textbox() }
|
local bat = { widget = args.widget or wibox.widget.textbox() }
|
||||||
local timeout = args.timeout or 30
|
local timeout = args.timeout or 30
|
||||||
local notify = args.notify or "on"
|
local notify = args.notify or 'on'
|
||||||
local full_notify = args.full_notify or notify
|
local full_notify = args.full_notify or notify
|
||||||
local n_perc = args.n_perc or { 5, 15 }
|
local n_perc = args.n_perc or { 5, 15 }
|
||||||
local batteries = args.batteries or (args.battery and { args.battery }) or {}
|
local batteries = args.batteries or (args.battery and { args.battery }) or {}
|
||||||
local ac = args.ac or "AC0"
|
local ac = args.ac or 'AC0'
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
function bat.get_batteries()
|
function bat.get_batteries()
|
||||||
helpers.line_callback("ls -1 " .. pspath, function(line)
|
helpers.line_callback('ls -1 ' .. pspath, function(line)
|
||||||
local bstr = string.match(line, "BAT%w+")
|
local bstr = string.match(line, 'BAT%w+')
|
||||||
if bstr then
|
if bstr then
|
||||||
batteries[#batteries + 1] = bstr
|
batteries[#batteries + 1] = bstr
|
||||||
else
|
else
|
||||||
ac = string.match(line, "A%w+") or ac
|
ac = string.match(line, 'A%w+') or ac
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
if #batteries == 0 then bat.get_batteries() end
|
if #batteries == 0 then
|
||||||
|
bat.get_batteries()
|
||||||
|
end
|
||||||
|
|
||||||
bat_notification_critical_preset = {
|
bat_notification_critical_preset = {
|
||||||
title = "Battery exhausted",
|
title = 'Battery exhausted',
|
||||||
text = "Shutdown imminent",
|
text = 'Shutdown imminent',
|
||||||
timeout = 15,
|
timeout = 15,
|
||||||
fg = "#000000",
|
fg = '#000000',
|
||||||
bg = "#FFFFFF"
|
bg = '#FFFFFF',
|
||||||
}
|
}
|
||||||
|
|
||||||
bat_notification_low_preset = {
|
bat_notification_low_preset = {
|
||||||
title = "Battery low",
|
title = 'Battery low',
|
||||||
text = "Plug the cable!",
|
text = 'Plug the cable!',
|
||||||
timeout = 15,
|
timeout = 15,
|
||||||
fg = "#202020",
|
fg = '#202020',
|
||||||
bg = "#CDCDCD"
|
bg = '#CDCDCD',
|
||||||
}
|
}
|
||||||
|
|
||||||
bat_notification_charged_preset = {
|
bat_notification_charged_preset = {
|
||||||
title = "Battery full",
|
title = 'Battery full',
|
||||||
text = "You can unplug the cable",
|
text = 'You can unplug the cable',
|
||||||
timeout = 15,
|
timeout = 15,
|
||||||
fg = "#202020",
|
fg = '#202020',
|
||||||
bg = "#CDCDCD"
|
bg = '#CDCDCD',
|
||||||
}
|
}
|
||||||
|
|
||||||
bat_now = {
|
bat_now = {
|
||||||
status = "N/A",
|
status = 'N/A',
|
||||||
ac_status = "N/A",
|
ac_status = 'N/A',
|
||||||
perc = "N/A",
|
perc = 'N/A',
|
||||||
time = "N/A",
|
time = 'N/A',
|
||||||
watt = "N/A",
|
watt = 'N/A',
|
||||||
capacity = "N/A"
|
capacity = 'N/A',
|
||||||
}
|
}
|
||||||
|
|
||||||
bat_now.n_status = {}
|
bat_now.n_status = {}
|
||||||
bat_now.n_perc = {}
|
bat_now.n_perc = {}
|
||||||
bat_now.n_capacity = {}
|
bat_now.n_capacity = {}
|
||||||
for i = 1, #batteries do
|
for i = 1, #batteries do
|
||||||
bat_now.n_status[i] = "N/A"
|
bat_now.n_status[i] = 'N/A'
|
||||||
bat_now.n_perc[i] = 0
|
bat_now.n_perc[i] = 0
|
||||||
bat_now.n_capacity[i] = 0
|
bat_now.n_capacity[i] = 0
|
||||||
end
|
end
|
||||||
@ -108,28 +110,27 @@ local function factory(args)
|
|||||||
|
|
||||||
for i, battery in ipairs(batteries) do
|
for i, battery in ipairs(batteries) do
|
||||||
local bstr = pspath .. battery
|
local bstr = pspath .. battery
|
||||||
local present = helpers.first_line(bstr .. "/present")
|
local present = helpers.first_line(bstr .. '/present')
|
||||||
|
|
||||||
if tonumber(present) == 1 then
|
if tonumber(present) == 1 then
|
||||||
-- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW]
|
-- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW]
|
||||||
local rate_current = tonumber(helpers.first_line(bstr .. "/current_now"))
|
local rate_current = tonumber(helpers.first_line(bstr .. '/current_now'))
|
||||||
local rate_voltage = tonumber(helpers.first_line(bstr .. "/voltage_now"))
|
local rate_voltage = tonumber(helpers.first_line(bstr .. '/voltage_now'))
|
||||||
local rate_power = tonumber(helpers.first_line(bstr .. "/power_now"))
|
local rate_power = tonumber(helpers.first_line(bstr .. '/power_now'))
|
||||||
local charge_full = tonumber(helpers.first_line(bstr .. "/charge_full"))
|
local charge_full = tonumber(helpers.first_line(bstr .. '/charge_full'))
|
||||||
local charge_design = tonumber(helpers.first_line(bstr .. "/charge_full_design"))
|
local charge_design = tonumber(helpers.first_line(bstr .. '/charge_full_design'))
|
||||||
|
|
||||||
-- energy_now(P)[uWh], charge_now(I)[uAh]
|
-- energy_now(P)[uWh], charge_now(I)[uAh]
|
||||||
local energy_now = tonumber(helpers.first_line(bstr .. "/energy_now") or
|
local energy_now =
|
||||||
helpers.first_line(bstr .. "/charge_now"))
|
tonumber(helpers.first_line(bstr .. '/energy_now') or helpers.first_line(bstr .. '/charge_now'))
|
||||||
|
|
||||||
-- energy_full(P)[uWh], charge_full(I)[uAh]
|
-- energy_full(P)[uWh], charge_full(I)[uAh]
|
||||||
local energy_full = tonumber(helpers.first_line(bstr .. "/energy_full") or
|
local energy_full = tonumber(helpers.first_line(bstr .. '/energy_full') or charge_full)
|
||||||
charge_full)
|
|
||||||
|
|
||||||
local energy_percentage = tonumber(helpers.first_line(bstr .. "/capacity")) or
|
local energy_percentage = tonumber(helpers.first_line(bstr .. '/capacity'))
|
||||||
math.floor((energy_now / energy_full) * 100)
|
or math.floor((energy_now / energy_full) * 100)
|
||||||
|
|
||||||
bat_now.n_status[i] = helpers.first_line(bstr .. "/status") or "N/A"
|
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_perc[i] = energy_percentage or bat_now.n_perc[i]
|
||||||
|
|
||||||
if not charge_design or charge_design == 0 then
|
if not charge_design or charge_design == 0 then
|
||||||
@ -155,28 +156,28 @@ local function factory(args)
|
|||||||
-- "Full", "Unknown" or "Charging". When the laptop is not plugged in,
|
-- "Full", "Unknown" or "Charging". When the laptop is not plugged in,
|
||||||
-- one or more of the batteries may be full, but only one battery
|
-- one or more of the batteries may be full, but only one battery
|
||||||
-- discharging suffices to set global status to "Discharging".
|
-- discharging suffices to set global status to "Discharging".
|
||||||
bat_now.status = bat_now.n_status[1] or "N/A"
|
bat_now.status = bat_now.n_status[1] or 'N/A'
|
||||||
for _, status in ipairs(bat_now.n_status) do
|
for _, status in ipairs(bat_now.n_status) do
|
||||||
if status == "Discharging" or status == "Charging" then
|
if status == 'Discharging' or status == 'Charging' then
|
||||||
bat_now.status = status
|
bat_now.status = status
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
bat_now.ac_status = tonumber(helpers.first_line(string.format("%s%s/online", pspath, ac))) or "N/A"
|
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 ~= 'N/A' then
|
||||||
if bat_now.status ~= "Full" and sum_rate_power == 0 and bat_now.ac_status == 1 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.perc = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100))
|
||||||
bat_now.time = "00:00"
|
bat_now.time = '00:00'
|
||||||
bat_now.watt = 0
|
bat_now.watt = 0
|
||||||
|
|
||||||
-- update {perc,time,watt} iff battery not full and rate > 0
|
-- update {perc,time,watt} iff battery not full and rate > 0
|
||||||
elseif bat_now.status ~= "Full" then
|
elseif bat_now.status ~= 'Full' then
|
||||||
local rate_time = 0
|
local rate_time = 0
|
||||||
-- Calculate time and watt if rates are greater then 0
|
-- Calculate time and watt if rates are greater then 0
|
||||||
if (sum_rate_power > 0 or sum_rate_current > 0) then
|
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
|
local div = (sum_rate_power > 0 and sum_rate_power) or sum_rate_current
|
||||||
|
|
||||||
if bat_now.status == "Charging" then
|
if bat_now.status == 'Charging' then
|
||||||
rate_time = (sum_energy_full - sum_energy_now) / div
|
rate_time = (sum_energy_full - sum_energy_now) / div
|
||||||
else -- Discharging
|
else -- Discharging
|
||||||
rate_time = sum_energy_now / div
|
rate_time = sum_energy_now / div
|
||||||
@ -191,11 +192,11 @@ local function factory(args)
|
|||||||
local hours = math.floor(rate_time)
|
local hours = math.floor(rate_time)
|
||||||
local minutes = math.floor((rate_time - hours) * 60)
|
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.perc = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100))
|
||||||
bat_now.time = string.format("%02d:%02d", hours, minutes)
|
bat_now.time = string.format('%02d:%02d', hours, minutes)
|
||||||
bat_now.watt = tonumber(string.format("%.2f", sum_rate_energy / 1e6))
|
bat_now.watt = tonumber(string.format('%.2f', sum_rate_energy / 1e6))
|
||||||
elseif bat_now.status == "Full" then
|
elseif bat_now.status == 'Full' then
|
||||||
bat_now.perc = 100
|
bat_now.perc = 100
|
||||||
bat_now.time = "00:00"
|
bat_now.time = '00:00'
|
||||||
bat_now.watt = 0
|
bat_now.watt = 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -204,31 +205,31 @@ local function factory(args)
|
|||||||
settings()
|
settings()
|
||||||
|
|
||||||
-- notifications for critical, low, and full levels
|
-- notifications for critical, low, and full levels
|
||||||
if notify == "on" then
|
if notify == 'on' then
|
||||||
if bat_now.status == "Discharging" then
|
if bat_now.status == 'Discharging' then
|
||||||
if tonumber(bat_now.perc) <= n_perc[1] then
|
if tonumber(bat_now.perc) <= n_perc[1] then
|
||||||
bat.id = naughty.notify({
|
bat.id = naughty.notify({
|
||||||
preset = bat_notification_critical_preset,
|
preset = bat_notification_critical_preset,
|
||||||
replaces_id = bat.id
|
replaces_id = bat.id,
|
||||||
}).id
|
}).id
|
||||||
elseif tonumber(bat_now.perc) <= n_perc[2] then
|
elseif tonumber(bat_now.perc) <= n_perc[2] then
|
||||||
bat.id = naughty.notify({
|
bat.id = naughty.notify({
|
||||||
preset = bat_notification_low_preset,
|
preset = bat_notification_low_preset,
|
||||||
replaces_id = bat.id
|
replaces_id = bat.id,
|
||||||
}).id
|
}).id
|
||||||
end
|
end
|
||||||
fullnotification = false
|
fullnotification = false
|
||||||
elseif bat_now.status == "Full" and full_notify == "on" and not fullnotification then
|
elseif bat_now.status == 'Full' and full_notify == 'on' and not fullnotification then
|
||||||
bat.id = naughty.notify({
|
bat.id = naughty.notify({
|
||||||
preset = bat_notification_charged_preset,
|
preset = bat_notification_charged_preset,
|
||||||
replaces_id = bat.id
|
replaces_id = bat.id,
|
||||||
}).id
|
}).id
|
||||||
fullnotification = true
|
fullnotification = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer("batteries", timeout, bat.update)
|
helpers.newtimer('batteries', timeout, bat.update)
|
||||||
|
|
||||||
return bat
|
return bat
|
||||||
end
|
end
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local markup = require("lain.util.markup")
|
local markup = require('lain.util.markup')
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local floor = math.floor
|
local floor = math.floor
|
||||||
local os = os
|
local os = os
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
@ -28,24 +28,28 @@ local function factory(args)
|
|||||||
week_start = args.week_start or 2,
|
week_start = args.week_start or 2,
|
||||||
three = args.three or false,
|
three = args.three or false,
|
||||||
followtag = args.followtag or false,
|
followtag = args.followtag or false,
|
||||||
week_number = args.week_number or "none",
|
week_number = args.week_number or 'none',
|
||||||
week_number_format = args.week_number_format or args.week_number == "left" and "%3d | " or "| %-3d",
|
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/",
|
icons = args.icons or helpers.icons_dir .. 'cal/white/',
|
||||||
notification_preset = args.notification_preset or {
|
notification_preset = args.notification_preset or {
|
||||||
font = "Monospace 10", fg = "#FFFFFF", bg = "#000000"
|
font = 'Monospace 10',
|
||||||
}
|
fg = '#FFFFFF',
|
||||||
|
bg = '#000000',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function cal.get_week_number(m, st_day, x)
|
function cal.get_week_number(m, st_day, x)
|
||||||
local date = os.date("*t", m)
|
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 {
|
local display_time = os.time({
|
||||||
year = date.year, month = date.month, day = date.day + 7 * week_step
|
year = date.year,
|
||||||
}
|
month = date.month,
|
||||||
|
day = date.day + 7 * week_step,
|
||||||
|
})
|
||||||
|
|
||||||
return string.format(cal.week_number_format, os.date("%V", display_time))
|
return string.format(cal.week_number_format, os.date('%V', display_time))
|
||||||
end
|
end
|
||||||
|
|
||||||
function cal.sum_week_days(x, y)
|
function cal.sum_week_days(x, y)
|
||||||
@ -53,55 +57,70 @@ local function factory(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function cal.build(month, year)
|
function cal.build(month, year)
|
||||||
local current_month, current_year = tonumber(os.date("%m")), tonumber(os.date("%Y"))
|
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 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 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 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 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 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)) }
|
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
|
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 }))
|
notifytable[#notifytable + 1] = string.format(
|
||||||
|
'%3s ',
|
||||||
|
os.date('%a', os.time({ year = 2006, month = 1, day = day_num + cal.week_start }))
|
||||||
|
)
|
||||||
end
|
end
|
||||||
notifytable[#notifytable] = string.format("%s\n%s", notifytable[#notifytable]:sub(1, -2), string.rep(" ", st_day*4))
|
notifytable[#notifytable] =
|
||||||
|
string.format('%s\n%s', notifytable[#notifytable]:sub(1, -2), string.rep(' ', st_day * 4))
|
||||||
local strx
|
local strx
|
||||||
for x = 1, mth_days do
|
for x = 1, mth_days do
|
||||||
strx = x
|
strx = x
|
||||||
if x == today then
|
if x == today then
|
||||||
if x < 10 then x = " " .. x end
|
if x < 10 then
|
||||||
strx = markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. " ")
|
x = ' ' .. x
|
||||||
end
|
end
|
||||||
strx = string.format("%s%s", string.rep(" ", 3 - tostring(x):len()), strx)
|
strx = markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. ' ')
|
||||||
notifytable[#notifytable+1] = string.format("%-4s%s", strx, (x+st_day)%7==0 and x ~= mth_days and "\n" or "")
|
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
|
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
|
cal.month, cal.year = d.month, d.year
|
||||||
|
|
||||||
if cal.week_number ~= "none" then
|
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 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())
|
local head_prepend = string.rep(' ', tostring(string.format(cal.week_number_format, 0)):len())
|
||||||
|
|
||||||
if cal.week_number == "left" then
|
if cal.week_number == 'left' then
|
||||||
notifytable[1] = head_prepend .. notifytable[1] -- month-year row
|
notifytable[1] = head_prepend .. notifytable[1] -- month-year row
|
||||||
notifytable[2] = head_prepend .. notifytable[2] -- weekdays 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
|
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
|
for x = 10, #notifytable do
|
||||||
if cal.sum_week_days(st_day, x) == 2 then
|
if cal.sum_week_days(st_day, x) == 2 then
|
||||||
notifytable[x] = cal.get_week_number(m, st_day, x) .. notifytable[x]
|
notifytable[x] = cal.get_week_number(m, st_day, x) .. notifytable[x]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif cal.week_number == "right" then
|
elseif cal.week_number == 'right' then
|
||||||
notifytable[8] = notifytable[8]:gsub("\n", head_prepend .. "\n") -- weekdays row
|
notifytable[8] = notifytable[8]:gsub('\n', head_prepend .. '\n') -- weekdays row
|
||||||
for x = 9, #notifytable do
|
for x = 9, #notifytable do
|
||||||
if cal.sum_week_days(st_day, x) == 1 then
|
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")
|
notifytable[x] = notifytable[x]:gsub('\n', cal.get_week_number(m, st_day, x - 7) .. '\n')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- last week of the month
|
-- last week of the month
|
||||||
local end_days = cal.sum_week_days(st_day, mth_days)
|
local end_days = cal.sum_week_days(st_day, mth_days)
|
||||||
if end_days ~= 0 then end_days = 7 - end_days end
|
if end_days ~= 0 then
|
||||||
notifytable[#notifytable] = notifytable[#notifytable] .. string.rep(" ", 4 * end_days) .. cal.get_week_number(m, st_day, mth_days + end_days)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -110,8 +129,8 @@ local function factory(args)
|
|||||||
|
|
||||||
function cal.getdate(month, year, offset)
|
function cal.getdate(month, year, offset)
|
||||||
if not month or not year then
|
if not month or not year then
|
||||||
month = tonumber(os.date("%m"))
|
month = tonumber(os.date('%m'))
|
||||||
year = tonumber(os.date("%Y"))
|
year = tonumber(os.date('%Y'))
|
||||||
end
|
end
|
||||||
|
|
||||||
month = month + offset
|
month = month + offset
|
||||||
@ -130,7 +149,9 @@ local function factory(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function cal.hide()
|
function cal.hide()
|
||||||
if not cal.notification then return end
|
if not cal.notification then
|
||||||
|
return
|
||||||
|
end
|
||||||
naughty.destroy(cal.notification)
|
naughty.destroy(cal.notification)
|
||||||
cal.notification = nil
|
cal.notification = nil
|
||||||
end
|
end
|
||||||
@ -142,9 +163,12 @@ local function factory(args)
|
|||||||
local current_month, current_year = cal.month, cal.year
|
local current_month, current_year = cal.month, cal.year
|
||||||
local prev_month, prev_year = cal.getdate(cal.month, cal.year, -1)
|
local prev_month, prev_year = cal.getdate(cal.month, cal.year, -1)
|
||||||
local next_month, next_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",
|
text = string.format(
|
||||||
tconcat(cal.build(prev_month, prev_year)), text,
|
'%s\n\n%s\n\n%s',
|
||||||
tconcat(cal.build(next_month, next_year)))
|
tconcat(cal.build(prev_month, prev_year)),
|
||||||
|
text,
|
||||||
|
tconcat(cal.build(next_month, next_year))
|
||||||
|
)
|
||||||
cal.month, cal.year = current_month, current_year
|
cal.month, cal.year = current_month, current_year
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -154,36 +178,47 @@ local function factory(args)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
cal.notification = naughty.notify {
|
cal.notification = naughty.notify({
|
||||||
preset = cal.notification_preset,
|
preset = cal.notification_preset,
|
||||||
screen = cal.followtag and awful.screen.focused() or scr or 1,
|
screen = cal.followtag and awful.screen.focused() or scr or 1,
|
||||||
icon = cal.icon,
|
icon = cal.icon,
|
||||||
timeout = type(seconds) == "number" and seconds or cal.notification_preset.timeout or 5,
|
timeout = type(seconds) == 'number' and seconds or cal.notification_preset.timeout or 5,
|
||||||
text = text
|
text = text,
|
||||||
}
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function cal.hover_on() cal.show(0) end
|
function cal.hover_on()
|
||||||
|
cal.show(0)
|
||||||
|
end
|
||||||
function cal.move(offset)
|
function cal.move(offset)
|
||||||
offset = offset or 0
|
offset = offset or 0
|
||||||
cal.month, cal.year = cal.getdate(cal.month, cal.year, offset)
|
cal.month, cal.year = cal.getdate(cal.month, cal.year, offset)
|
||||||
cal.show(0, cal.month, cal.year)
|
cal.show(0, cal.month, cal.year)
|
||||||
end
|
end
|
||||||
function cal.prev() cal.move(-1) end
|
function cal.prev()
|
||||||
function cal.next() cal.move( 1) end
|
cal.move(-1)
|
||||||
|
end
|
||||||
|
function cal.next()
|
||||||
|
cal.move(1)
|
||||||
|
end
|
||||||
|
|
||||||
function cal.attach(widget)
|
function cal.attach(widget)
|
||||||
widget:connect_signal("mouse::enter", cal.hover_on)
|
widget:connect_signal('mouse::enter', cal.hover_on)
|
||||||
widget:connect_signal("mouse::leave", cal.hide)
|
widget:connect_signal('mouse::leave', cal.hide)
|
||||||
widget:buttons(awful.util.table.join(
|
widget:buttons(
|
||||||
|
awful.util.table.join(
|
||||||
awful.button({}, 1, cal.prev),
|
awful.button({}, 1, cal.prev),
|
||||||
awful.button({}, 3, cal.next),
|
awful.button({}, 3, cal.next),
|
||||||
awful.button({}, 2, cal.hover_on),
|
awful.button({}, 2, cal.hover_on),
|
||||||
awful.button({}, 5, cal.prev),
|
awful.button({}, 5, cal.prev),
|
||||||
awful.button({}, 4, cal.next)))
|
awful.button({}, 4, cal.next)
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
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
|
end
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local wrequire = require("lain.helpers").wrequire
|
local wrequire = require('lain.helpers').wrequire
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
local widget = { _NAME = "lain.widget.contrib" }
|
local widget = { _NAME = 'lain.widget.contrib' }
|
||||||
|
|
||||||
return setmetatable(widget, { __index = wrequire })
|
return setmetatable(widget, { __index = wrequire })
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local shell = require("awful.util").shell
|
local shell = require('awful.util').shell
|
||||||
local focused = require("awful.screen").focused
|
local focused = require('awful.screen').focused
|
||||||
local escape_f = require("awful.util").escape
|
local escape_f = require('awful.util').escape
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local os = os
|
local os = os
|
||||||
local string = string
|
local string = string
|
||||||
|
|
||||||
@ -22,52 +22,61 @@ local function factory(args)
|
|||||||
|
|
||||||
local moc = { widget = args.widget or wibox.widget.textbox() }
|
local moc = { widget = args.widget or wibox.widget.textbox() }
|
||||||
local timeout = args.timeout or 2
|
local timeout = args.timeout or 2
|
||||||
local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
|
local music_dir = args.music_dir or os.getenv('HOME') .. '/Music'
|
||||||
local cover_pattern = args.cover_pattern or "*\\.(jpg|jpeg|png|gif)$"
|
local cover_pattern = args.cover_pattern or '*\\.(jpg|jpeg|png|gif)$'
|
||||||
local cover_size = args.cover_size or 100
|
local cover_size = args.cover_size or 100
|
||||||
local default_art = args.default_art or ""
|
local default_art = args.default_art or ''
|
||||||
local followtag = args.followtag or false
|
local followtag = args.followtag or false
|
||||||
local settings = args.settings or function() end
|
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()
|
function moc.update()
|
||||||
helpers.async("mocp -i", function(f)
|
helpers.async('mocp -i', function(f)
|
||||||
moc_now = {
|
moc_now = {
|
||||||
state = "N/A",
|
state = 'N/A',
|
||||||
file = "N/A",
|
file = 'N/A',
|
||||||
artist = "N/A",
|
artist = 'N/A',
|
||||||
title = "N/A",
|
title = 'N/A',
|
||||||
album = "N/A",
|
album = 'N/A',
|
||||||
elapsed = "N/A",
|
elapsed = 'N/A',
|
||||||
total = "N/A"
|
total = 'N/A',
|
||||||
}
|
}
|
||||||
|
|
||||||
for line in string.gmatch(f, "[^\n]+") do
|
for line in string.gmatch(f, '[^\n]+') do
|
||||||
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
|
for k, v in string.gmatch(line, '([%w]+):[%s](.*)$') do
|
||||||
if k == "State" then moc_now.state = v
|
if k == 'State' then
|
||||||
elseif k == "File" then moc_now.file = v
|
moc_now.state = v
|
||||||
elseif k == "Artist" then moc_now.artist = escape_f(v)
|
elseif k == 'File' then
|
||||||
elseif k == "SongTitle" then moc_now.title = escape_f(v)
|
moc_now.file = v
|
||||||
elseif k == "Album" then moc_now.album = escape_f(v)
|
elseif k == 'Artist' then
|
||||||
elseif k == "CurrentTime" then moc_now.elapsed = escape_f(v)
|
moc_now.artist = escape_f(v)
|
||||||
elseif k == "TotalTime" then moc_now.total = 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
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
moc_notification_preset.text = string.format("%s (%s) - %s\n%s", moc_now.artist,
|
moc_notification_preset.text =
|
||||||
moc_now.album, moc_now.total, moc_now.title)
|
string.format('%s (%s) - %s\n%s', moc_now.artist, moc_now.album, moc_now.total, moc_now.title)
|
||||||
widget = moc.widget
|
widget = moc.widget
|
||||||
settings()
|
settings()
|
||||||
|
|
||||||
if moc_now.state == "PLAY" then
|
if moc_now.state == 'PLAY' then
|
||||||
if moc_now.title ~= helpers.get_map("current moc track") then
|
if moc_now.title ~= helpers.get_map('current moc track') then
|
||||||
helpers.set_map("current moc track", moc_now.title)
|
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 = {
|
local common = {
|
||||||
preset = moc_notification_preset,
|
preset = moc_notification_preset,
|
||||||
@ -76,20 +85,21 @@ local function factory(args)
|
|||||||
replaces_id = moc.id,
|
replaces_id = moc.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
local path = string.format("%s/%s", music_dir, string.match(moc_now.file, ".*/"))
|
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)
|
local cover =
|
||||||
helpers.async({ shell, "-c", cover }, function(current_icon)
|
string.format("find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'", path, cover_pattern)
|
||||||
common.icon = current_icon:gsub("\n", "")
|
helpers.async({ shell, '-c', cover }, function(current_icon)
|
||||||
|
common.icon = current_icon:gsub('\n', '')
|
||||||
moc.id = naughty.notify(common).id
|
moc.id = naughty.notify(common).id
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
elseif moc_now.state ~= "PAUSE" then
|
elseif moc_now.state ~= 'PAUSE' then
|
||||||
helpers.set_map("current moc track", nil)
|
helpers.set_map('current moc track', nil)
|
||||||
end
|
end
|
||||||
end)
|
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
|
end
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local async = require("lain.helpers").async
|
local async = require('lain.helpers').async
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local execute = os.execute
|
local execute = os.execute
|
||||||
local type = type
|
local type = type
|
||||||
|
|
||||||
@ -16,20 +16,20 @@ local type = type
|
|||||||
local redshift = { active = false, pid = nil }
|
local redshift = { active = false, pid = nil }
|
||||||
|
|
||||||
function redshift.start()
|
function redshift.start()
|
||||||
execute("pkill redshift")
|
execute('pkill redshift')
|
||||||
awful.spawn.with_shell("redshift -x") -- clear adjustments
|
awful.spawn.with_shell('redshift -x') -- clear adjustments
|
||||||
redshift.pid = awful.spawn.with_shell("redshift")
|
redshift.pid = awful.spawn.with_shell('redshift')
|
||||||
redshift.active = true
|
redshift.active = true
|
||||||
if type(redshift.update_fun) == "function" then
|
if type(redshift.update_fun) == 'function' then
|
||||||
redshift.update_fun(redshift.active)
|
redshift.update_fun(redshift.active)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function redshift.toggle()
|
function redshift.toggle()
|
||||||
async({ awful.util.shell, "-c", string.format("ps -p %d -o pid=", redshift.pid) }, function(f)
|
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
|
if f and #f > 0 then -- redshift is running
|
||||||
-- Sending -USR1 toggles redshift (See project website)
|
-- Sending -USR1 toggles redshift (See project website)
|
||||||
execute("pkill -USR1 redshift")
|
execute('pkill -USR1 redshift')
|
||||||
redshift.active = not redshift.active
|
redshift.active = not redshift.active
|
||||||
else -- not started or killed, (re)start it
|
else -- not started or killed, (re)start it
|
||||||
redshift.start()
|
redshift.start()
|
||||||
@ -45,9 +45,13 @@ end
|
|||||||
-- Use it to update widget text or icons on status change.
|
-- Use it to update widget text or icons on status change.
|
||||||
function redshift.attach(widget, fun)
|
function redshift.attach(widget, fun)
|
||||||
redshift.update_fun = fun or function() end
|
redshift.update_fun = fun or function() end
|
||||||
if not redshift.pid then redshift.start() end
|
if not redshift.pid then
|
||||||
|
redshift.start()
|
||||||
|
end
|
||||||
if widget then
|
if widget then
|
||||||
widget:buttons(awful.util.table.join(awful.button({}, 1, function () redshift.toggle() end)))
|
widget:buttons(awful.util.table.join(awful.button({}, 1, function()
|
||||||
|
redshift.toggle()
|
||||||
|
end)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local markup = require("lain.util").markup
|
local markup = require('lain.util').markup
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local mouse = mouse
|
local mouse = mouse
|
||||||
|
|
||||||
-- Taskwarrior notification
|
-- Taskwarrior notification
|
||||||
@ -16,7 +16,9 @@ local mouse = mouse
|
|||||||
local task = {}
|
local task = {}
|
||||||
|
|
||||||
function task.hide()
|
function task.hide()
|
||||||
if not task.notification then return end
|
if not task.notification then
|
||||||
|
return
|
||||||
|
end
|
||||||
naughty.destroy(task.notification)
|
naughty.destroy(task.notification)
|
||||||
task.notification = nil
|
task.notification = nil
|
||||||
end
|
end
|
||||||
@ -24,7 +26,7 @@ end
|
|||||||
function task.show(scr)
|
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)
|
helpers.async({ awful.util.shell, '-c', task.show_cmd }, function(f)
|
||||||
local widget_focused = true
|
local widget_focused = true
|
||||||
|
|
||||||
if mouse.current_widgets then
|
if mouse.current_widgets then
|
||||||
@ -39,53 +41,55 @@ function task.show(scr)
|
|||||||
|
|
||||||
if widget_focused then
|
if widget_focused then
|
||||||
task.hide()
|
task.hide()
|
||||||
task.notification = naughty.notify {
|
task.notification = naughty.notify({
|
||||||
preset = task.notification_preset,
|
preset = task.notification_preset,
|
||||||
title = "task next",
|
title = 'task next',
|
||||||
text = markup.font(task.notification_preset.font,
|
text = markup.font(task.notification_preset.font, awful.util.escape(f:gsub('\n*$', ''))),
|
||||||
awful.util.escape(f:gsub("\n*$", "")))
|
})
|
||||||
}
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function task.prompt()
|
function task.prompt()
|
||||||
awful.prompt.run {
|
awful.prompt.run({
|
||||||
prompt = task.prompt_text,
|
prompt = task.prompt_text,
|
||||||
textbox = awful.screen.focused().mypromptbox.widget,
|
textbox = awful.screen.focused().mypromptbox.widget,
|
||||||
exe_callback = function(t)
|
exe_callback = function(t)
|
||||||
helpers.async(t, function(f)
|
helpers.async(t, function(f)
|
||||||
naughty.notify {
|
naughty.notify({
|
||||||
preset = task.notification_preset,
|
preset = task.notification_preset,
|
||||||
title = t,
|
title = t,
|
||||||
text = markup.font(task.notification_preset.font,
|
text = markup.font(task.notification_preset.font, awful.util.escape(f:gsub('\n*$', ''))),
|
||||||
awful.util.escape(f:gsub("\n*$", "")))
|
})
|
||||||
}
|
|
||||||
end)
|
end)
|
||||||
end,
|
end,
|
||||||
history_path = awful.util.getdir("cache") .. "/history_task"
|
history_path = awful.util.getdir('cache') .. '/history_task',
|
||||||
}
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function task.attach(widget, args)
|
function task.attach(widget, args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
task.show_cmd = args.show_cmd or "task next"
|
task.show_cmd = args.show_cmd or 'task next'
|
||||||
task.prompt_text = args.prompt_text or "Enter task command: "
|
task.prompt_text = args.prompt_text or 'Enter task command: '
|
||||||
task.followtag = args.followtag or false
|
task.followtag = args.followtag or false
|
||||||
task.notification_preset = args.notification_preset
|
task.notification_preset = args.notification_preset
|
||||||
task.widget = widget
|
task.widget = widget
|
||||||
|
|
||||||
if not task.notification_preset then
|
if not task.notification_preset then
|
||||||
task.notification_preset = {
|
task.notification_preset = {
|
||||||
font = "Monospace 10",
|
font = 'Monospace 10',
|
||||||
icon = helpers.icons_dir .. "/taskwarrior.png"
|
icon = helpers.icons_dir .. '/taskwarrior.png',
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
if widget then
|
if widget then
|
||||||
widget:connect_signal("mouse::enter", function () task.show() end)
|
widget:connect_signal('mouse::enter', function()
|
||||||
widget:connect_signal("mouse::leave", function () task.hide() end)
|
task.show()
|
||||||
|
end)
|
||||||
|
widget:connect_signal('mouse::leave', function()
|
||||||
|
task.hide()
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local focused = require("awful.screen").focused
|
local focused = require('awful.screen').focused
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local string = string
|
local string = string
|
||||||
local type = type
|
local type = type
|
||||||
|
|
||||||
@ -19,77 +19,92 @@ local type = type
|
|||||||
|
|
||||||
local function factory(apipath)
|
local function factory(apipath)
|
||||||
local tp_smapi = {
|
local tp_smapi = {
|
||||||
path = apipath or "/sys/devices/platform/smapi"
|
path = apipath or '/sys/devices/platform/smapi',
|
||||||
}
|
}
|
||||||
|
|
||||||
function tp_smapi.get(batid, feature)
|
function tp_smapi.get(batid, feature)
|
||||||
return helpers.first_line(string.format("%s/%s/%s", tp_smapi.path, batid or "BAT0", feature or ""))
|
return helpers.first_line(string.format('%s/%s/%s', tp_smapi.path, batid or 'BAT0', feature or ''))
|
||||||
end
|
end
|
||||||
|
|
||||||
function tp_smapi.installed(batid)
|
function tp_smapi.installed(batid)
|
||||||
return tp_smapi.get(batid, "installed") == "1"
|
return tp_smapi.get(batid, 'installed') == '1'
|
||||||
end
|
end
|
||||||
|
|
||||||
function tp_smapi.status(batid)
|
function tp_smapi.status(batid)
|
||||||
return tp_smapi.get(batid, "state")
|
return tp_smapi.get(batid, 'state')
|
||||||
end
|
end
|
||||||
|
|
||||||
function tp_smapi.percentage(batid)
|
function tp_smapi.percentage(batid)
|
||||||
return tp_smapi.get(batid, "remaining_percent")
|
return tp_smapi.get(batid, 'remaining_percent')
|
||||||
end
|
end
|
||||||
|
|
||||||
-- either running or charging time
|
-- either running or charging time
|
||||||
function tp_smapi.time(batid)
|
function tp_smapi.time(batid)
|
||||||
local status = tp_smapi.status(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")
|
local mins_left = tp_smapi.get(
|
||||||
if not string.find(mins_left, "^%d+") then return "N/A" end
|
batid,
|
||||||
return string.format("%02d:%02d", math.floor(mins_left / 60), mins_left % 60) -- HH:mm
|
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
|
end
|
||||||
|
|
||||||
function tp_smapi.hide()
|
function tp_smapi.hide()
|
||||||
if not tp_smapi.notification then return end
|
if not tp_smapi.notification then
|
||||||
|
return
|
||||||
|
end
|
||||||
naughty.destroy(tp_smapi.notification)
|
naughty.destroy(tp_smapi.notification)
|
||||||
tp_smapi.notification = nil
|
tp_smapi.notification = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function tp_smapi.show(batid, seconds, scr)
|
function tp_smapi.show(batid, seconds, scr)
|
||||||
if not tp_smapi.installed(batid) then return end
|
if not tp_smapi.installed(batid) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local mfgr = tp_smapi.get(batid, "manufacturer") or "no_mfgr"
|
local mfgr = tp_smapi.get(batid, 'manufacturer') or 'no_mfgr'
|
||||||
local model = tp_smapi.get(batid, "model") or "no_model"
|
local model = tp_smapi.get(batid, 'model') or 'no_model'
|
||||||
local chem = tp_smapi.get(batid, "chemistry") or "no_chem"
|
local chem = tp_smapi.get(batid, 'chemistry') or 'no_chem'
|
||||||
local status = tp_smapi.get(batid, "state")
|
local status = tp_smapi.get(batid, 'state')
|
||||||
local time = tp_smapi.time(batid)
|
local time = tp_smapi.time(batid)
|
||||||
local msg
|
local msg
|
||||||
|
|
||||||
if status and status ~= "idle" then
|
if status and status ~= 'idle' then
|
||||||
msg = string.format("[%s] %s %s", status, time ~= "N/A" and time or "unknown remaining time",
|
msg = string.format(
|
||||||
string.lower(status):gsub(" ", ""):gsub("\n", "") == "charging" and " until charged" or " remaining")
|
'[%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
|
else
|
||||||
msg = "On AC power"
|
msg = 'On AC power'
|
||||||
end
|
end
|
||||||
|
|
||||||
tp_smapi.hide()
|
tp_smapi.hide()
|
||||||
tp_smapi.notification = naughty.notify {
|
tp_smapi.notification = naughty.notify({
|
||||||
title = string.format("%s: %s %s (%s)", batid, mfgr, model, chem),
|
title = string.format('%s: %s %s (%s)', batid, mfgr, model, chem),
|
||||||
text = msg,
|
text = msg,
|
||||||
timeout = type(seconds) == "number" and seconds or 0,
|
timeout = type(seconds) == 'number' and seconds or 0,
|
||||||
screen = scr or focused()
|
screen = scr or focused(),
|
||||||
}
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function tp_smapi.create_widget(args)
|
function tp_smapi.create_widget(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
local pspath = args.pspath or "/sys/class/power_supply/"
|
local pspath = args.pspath or '/sys/class/power_supply/'
|
||||||
local batteries = args.batteries or (args.battery and { args.battery }) or {}
|
local batteries = args.batteries or (args.battery and { args.battery }) or {}
|
||||||
local timeout = args.timeout or 30
|
local timeout = args.timeout or 30
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
if #batteries == 0 then
|
if #batteries == 0 then
|
||||||
helpers.line_callback("ls -1 " .. pspath, function(line)
|
helpers.line_callback('ls -1 ' .. pspath, function(line)
|
||||||
local bstr = string.match(line, "BAT%w+")
|
local bstr = string.match(line, 'BAT%w+')
|
||||||
if bstr then batteries[#batteries + 1] = bstr end
|
if bstr then
|
||||||
|
batteries[#batteries + 1] = bstr
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -97,21 +112,23 @@ local function factory(apipath)
|
|||||||
|
|
||||||
for _, battery in ipairs(batteries) do
|
for _, battery in ipairs(batteries) do
|
||||||
if not tp_smapi.installed(battery) then
|
if not tp_smapi.installed(battery) then
|
||||||
naughty.notify {
|
naughty.notify({
|
||||||
preset = naughty.config.critical,
|
preset = naughty.config.critical,
|
||||||
title = "tp_smapi: error while creating widget",
|
title = 'tp_smapi: error while creating widget',
|
||||||
text = string.format("battery %s is not installed", battery)
|
text = string.format('battery %s is not installed', battery),
|
||||||
}
|
})
|
||||||
all_batteries_installed = false
|
all_batteries_installed = false
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not all_batteries_installed then return end
|
if not all_batteries_installed then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
tpbat = {
|
tpbat = {
|
||||||
batteries = batteries,
|
batteries = batteries,
|
||||||
widget = args.widget or wibox.widget.textbox()
|
widget = args.widget or wibox.widget.textbox(),
|
||||||
}
|
}
|
||||||
|
|
||||||
function tpbat.update()
|
function tpbat.update()
|
||||||
@ -119,15 +136,15 @@ local function factory(apipath)
|
|||||||
n_status = {},
|
n_status = {},
|
||||||
n_perc = {},
|
n_perc = {},
|
||||||
n_time = {},
|
n_time = {},
|
||||||
status = "N/A"
|
status = 'N/A',
|
||||||
}
|
}
|
||||||
|
|
||||||
for i = 1, #batteries do
|
for i = 1, #batteries do
|
||||||
tpbat_now.n_status[i] = tp_smapi.status(batteries[i]) or "N/A"
|
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_perc[i] = tp_smapi.percentage(batteries[i])
|
||||||
tpbat_now.n_time[i] = tp_smapi.time(batteries[i]) or "N/A"
|
tpbat_now.n_time[i] = tp_smapi.time(batteries[i]) or 'N/A'
|
||||||
|
|
||||||
if not tpbat_now.n_status[i]:lower():match("full") then
|
if not tpbat_now.n_status[i]:lower():match('full') then
|
||||||
tpbat_now.status = tpbat_now.n_status[i]
|
tpbat_now.status = tpbat_now.n_status[i]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -136,7 +153,7 @@ local function factory(apipath)
|
|||||||
settings()
|
settings()
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer("thinkpad-batteries", timeout, tpbat.update)
|
helpers.newtimer('thinkpad-batteries', timeout, tpbat.update)
|
||||||
|
|
||||||
return tpbat
|
return tpbat
|
||||||
end
|
end
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local math = math
|
local math = math
|
||||||
local string = string
|
local string = string
|
||||||
|
|
||||||
@ -25,15 +25,14 @@ local function factory(args)
|
|||||||
-- Read the amount of time the CPUs have spent performing
|
-- Read the amount of time the CPUs have spent performing
|
||||||
-- different kinds of work. Read the first line of /proc/stat
|
-- different kinds of work. Read the first line of /proc/stat
|
||||||
-- which is the sum of all CPUs.
|
-- which is the sum of all CPUs.
|
||||||
for index,time in pairs(helpers.lines_match("cpu","/proc/stat")) do
|
for index, time in pairs(helpers.lines_match('cpu', '/proc/stat')) do
|
||||||
local coreid = index - 1
|
local coreid = index - 1
|
||||||
local core = cpu.core[coreid] or
|
local core = cpu.core[coreid] or { last_active = 0, last_total = 0, usage = 0 }
|
||||||
{ last_active = 0 , last_total = 0, usage = 0 }
|
|
||||||
local at = 1
|
local at = 1
|
||||||
local idle = 0
|
local idle = 0
|
||||||
local total = 0
|
local total = 0
|
||||||
|
|
||||||
for field in string.gmatch(time, "[%s]+([^%s]+)") do
|
for field in string.gmatch(time, '[%s]+([^%s]+)') do
|
||||||
-- 4 = idle, 5 = ioWait. Essentially, the CPUs have done
|
-- 4 = idle, 5 = ioWait. Essentially, the CPUs have done
|
||||||
-- nothing during these times.
|
-- nothing during these times.
|
||||||
if at == 4 or at == 5 then
|
if at == 4 or at == 5 then
|
||||||
@ -67,7 +66,7 @@ local function factory(args)
|
|||||||
settings()
|
settings()
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer("cpu", timeout, cpu.update)
|
helpers.newtimer('cpu', timeout, cpu.update)
|
||||||
|
|
||||||
return cpu
|
return cpu
|
||||||
end
|
end
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local Gio = require("lgi").Gio
|
local Gio = require('lgi').Gio
|
||||||
local focused = require("awful.screen").focused
|
local focused = require('awful.screen').focused
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local gears = require("gears")
|
local gears = require('gears')
|
||||||
local math = math
|
local math = math
|
||||||
local string = string
|
local string = string
|
||||||
local tconcat = table.concat
|
local tconcat = table.concat
|
||||||
@ -20,7 +20,7 @@ local type = type
|
|||||||
local query_size = Gio.FILE_ATTRIBUTE_FILESYSTEM_SIZE
|
local query_size = Gio.FILE_ATTRIBUTE_FILESYSTEM_SIZE
|
||||||
local query_free = Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE
|
local query_free = Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE
|
||||||
local query_used = Gio.FILE_ATTRIBUTE_FILESYSTEM_USED
|
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
|
-- File systems info
|
||||||
-- lain.widget.fs
|
-- lain.widget.fs
|
||||||
@ -31,14 +31,21 @@ local function factory(args)
|
|||||||
local fs = {
|
local fs = {
|
||||||
widget = args.widget or wibox.widget.textbox(),
|
widget = args.widget or wibox.widget.textbox(),
|
||||||
units = {
|
units = {
|
||||||
[1] = "Kb", [2] = "Mb", [3] = "Gb",
|
[1] = 'Kb',
|
||||||
[4] = "Tb", [5] = "Pb", [6] = "Eb",
|
[2] = 'Mb',
|
||||||
[7] = "Zb", [8] = "Yb"
|
[3] = 'Gb',
|
||||||
}
|
[4] = 'Tb',
|
||||||
|
[5] = 'Pb',
|
||||||
|
[6] = 'Eb',
|
||||||
|
[7] = 'Zb',
|
||||||
|
[8] = 'Yb',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function fs.hide()
|
function fs.hide()
|
||||||
if not fs.notification then return end
|
if not fs.notification then
|
||||||
|
return
|
||||||
|
end
|
||||||
naughty.destroy(fs.notification)
|
naughty.destroy(fs.notification)
|
||||||
fs.notification = nil
|
fs.notification = nil
|
||||||
end
|
end
|
||||||
@ -47,17 +54,17 @@ local function factory(args)
|
|||||||
fs.hide()
|
fs.hide()
|
||||||
fs.update(function()
|
fs.update(function()
|
||||||
fs.notification_preset.screen = fs.followtag and focused() or scr or 1
|
fs.notification_preset.screen = fs.followtag and focused() or scr or 1
|
||||||
fs.notification = naughty.notify {
|
fs.notification = naughty.notify({
|
||||||
preset = fs.notification_preset,
|
preset = fs.notification_preset,
|
||||||
timeout = type(seconds) == "number" and seconds or 5
|
timeout = type(seconds) == 'number' and seconds or 5,
|
||||||
}
|
})
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local timeout = args.timeout or 600
|
local timeout = args.timeout or 600
|
||||||
local partition = args.partition
|
local partition = args.partition
|
||||||
local threshold = args.threshold or 99
|
local threshold = args.threshold or 99
|
||||||
local showpopup = args.showpopup or "on"
|
local showpopup = args.showpopup or 'on'
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
fs.followtag = args.followtag or false
|
fs.followtag = args.followtag or false
|
||||||
@ -65,9 +72,9 @@ local function factory(args)
|
|||||||
|
|
||||||
if not fs.notification_preset then
|
if not fs.notification_preset then
|
||||||
fs.notification_preset = {
|
fs.notification_preset = {
|
||||||
font = "Monospace 10",
|
font = 'Monospace 10',
|
||||||
fg = "#FFFFFF",
|
fg = '#FFFFFF',
|
||||||
bg = "#000000"
|
bg = '#000000',
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -94,7 +101,7 @@ local function factory(args)
|
|||||||
percentage = math.floor(100 * used / size), -- used percentage
|
percentage = math.floor(100 * used / size), -- used percentage
|
||||||
size = size / math.pow(1024, units),
|
size = size / math.pow(1024, units),
|
||||||
used = used / math.pow(1024, units),
|
used = used / math.pow(1024, units),
|
||||||
free = free / math.pow(1024, units)
|
free = free / math.pow(1024, units),
|
||||||
}
|
}
|
||||||
|
|
||||||
if fs_now[path].percentage > 0 then -- don't notify unused file systems
|
if fs_now[path].percentage > 0 then -- don't notify unused file systems
|
||||||
@ -113,22 +120,29 @@ local function factory(args)
|
|||||||
|
|
||||||
if partition and fs_now[partition] and fs_now[partition].percentage >= threshold then
|
if partition and fs_now[partition] and fs_now[partition].percentage >= threshold then
|
||||||
if not helpers.get_map(partition) then
|
if not helpers.get_map(partition) then
|
||||||
naughty.notify {
|
naughty.notify({
|
||||||
preset = naughty.config.presets.critical,
|
preset = naughty.config.presets.critical,
|
||||||
title = "Warning",
|
title = 'Warning',
|
||||||
text = string.format("%s is above %d%% (%d%%)", partition, threshold, fs_now[partition].percentage)
|
text = string.format('%s is above %d%% (%d%%)', partition, threshold, fs_now[partition].percentage),
|
||||||
}
|
})
|
||||||
helpers.set_map(partition, true)
|
helpers.set_map(partition, true)
|
||||||
else
|
else
|
||||||
helpers.set_map(partition, false)
|
helpers.set_map(partition, false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local fmt = "%-" .. tostring(pathlen) .. "s %4s\t%6s\t%6s\n"
|
local fmt = '%-' .. tostring(pathlen) .. 's %4s\t%6s\t%6s\n'
|
||||||
local notifytable = { [1] = string.format(fmt, "path", "used", "free", "size") }
|
local notifytable = { [1] = string.format(fmt, 'path', 'used', 'free', 'size') }
|
||||||
fmt = "\n%-" .. tostring(pathlen) .. "s %3s%%\t%6.2f\t%6.2f %s"
|
fmt = '\n%-' .. tostring(pathlen) .. 's %3s%%\t%6.2f\t%6.2f %s'
|
||||||
for _, path in ipairs(notifypaths) do
|
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)
|
notifytable[#notifytable + 1] = string.format(
|
||||||
|
fmt,
|
||||||
|
path,
|
||||||
|
fs_now[path].percentage,
|
||||||
|
fs_now[path].free,
|
||||||
|
fs_now[path].size,
|
||||||
|
fs_now[path].units
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
fs.notification_preset.text = tconcat(notifytable)
|
fs.notification_preset.text = tconcat(notifytable)
|
||||||
@ -137,18 +151,22 @@ local function factory(args)
|
|||||||
function fs.update(callback)
|
function fs.update(callback)
|
||||||
Gio.Async.start(gears.protected_call.call)(function()
|
Gio.Async.start(gears.protected_call.call)(function()
|
||||||
update_synced()
|
update_synced()
|
||||||
if type(callback) == "function" and callback then
|
if type(callback) == 'function' and callback then
|
||||||
callback()
|
callback()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
if showpopup == "on" then
|
if showpopup == 'on' then
|
||||||
fs.widget:connect_signal('mouse::enter', function () fs.show(0) end)
|
fs.widget:connect_signal('mouse::enter', function()
|
||||||
fs.widget:connect_signal('mouse::leave', function () fs.hide() end)
|
fs.show(0)
|
||||||
|
end)
|
||||||
|
fs.widget:connect_signal('mouse::leave', function()
|
||||||
|
fs.hide()
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer(partition or "fs", timeout, fs.update)
|
helpers.newtimer(partition or 'fs', timeout, fs.update)
|
||||||
|
|
||||||
return fs
|
return fs
|
||||||
end
|
end
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local string = string
|
local string = string
|
||||||
local type = type
|
local type = type
|
||||||
local tonumber = tonumber
|
local tonumber = tonumber
|
||||||
@ -28,30 +28,34 @@ local function factory(args)
|
|||||||
local pwdtimeout = args.pwdtimeout or 10
|
local pwdtimeout = args.pwdtimeout or 10
|
||||||
local is_plain = args.is_plain or false
|
local is_plain = args.is_plain or false
|
||||||
local followtag = args.followtag or false
|
local followtag = args.followtag or false
|
||||||
local notify = args.notify or "on"
|
local notify = args.notify or 'on'
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
local head_command = "curl --connect-timeout 3 -fsm 3"
|
local head_command = 'curl --connect-timeout 3 -fsm 3'
|
||||||
local request = "-X 'STATUS INBOX (MESSAGES RECENT UNSEEN)'"
|
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 = {
|
mail_notification_preset = {
|
||||||
icon = helpers.icons_dir .. "mail.png",
|
icon = helpers.icons_dir .. 'mail.png',
|
||||||
position = "top_left"
|
position = 'top_left',
|
||||||
}
|
}
|
||||||
|
|
||||||
helpers.set_map(mail, 0)
|
helpers.set_map(mail, 0)
|
||||||
|
|
||||||
if not is_plain then
|
if not is_plain then
|
||||||
if type(password) == "string" or type(password) == "table" then
|
if type(password) == 'string' or type(password) == 'table' then
|
||||||
helpers.async(password, function(f) password = f:gsub("\n", "") end)
|
helpers.async(password, function(f)
|
||||||
elseif type(password) == "function" then
|
password = f:gsub('\n', '')
|
||||||
imap.pwdtimer = helpers.newtimer(mail .. "-password", pwdtimeout, function()
|
end)
|
||||||
|
elseif type(password) == 'function' then
|
||||||
|
imap.pwdtimer = helpers.newtimer(mail .. '-password', pwdtimeout, function()
|
||||||
local retrieved_password, try_again = password()
|
local retrieved_password, try_again = password()
|
||||||
if not try_again then
|
if not try_again then
|
||||||
imap.pwdtimer:stop() -- stop trying to retrieve
|
imap.pwdtimer:stop() -- stop trying to retrieve
|
||||||
password = retrieved_password or "" -- failsafe
|
password = retrieved_password or '' -- failsafe
|
||||||
end
|
end
|
||||||
end, true, true)
|
end, true, true)
|
||||||
end
|
end
|
||||||
@ -59,31 +63,48 @@ local function factory(args)
|
|||||||
|
|
||||||
function imap.update()
|
function imap.update()
|
||||||
-- do not update if the password has not been retrieved yet
|
-- do not update if the password has not been retrieved yet
|
||||||
if type(password) ~= "string" then return end
|
if type(password) ~= 'string' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:'%s' %s -k",
|
local curl = string.format(
|
||||||
head_command, server, port, mail, password, request)
|
"%s --url imaps://%s:%s/INBOX -u %s:'%s' %s -k",
|
||||||
|
head_command,
|
||||||
|
server,
|
||||||
|
port,
|
||||||
|
mail,
|
||||||
|
password,
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
helpers.async(curl, function(f)
|
helpers.async(curl, function(f)
|
||||||
imap_now = { ["MESSAGES"] = 0, ["RECENT"] = 0, ["UNSEEN"] = 0 }
|
imap_now = { ['MESSAGES'] = 0, ['RECENT'] = 0, ['UNSEEN'] = 0 }
|
||||||
|
|
||||||
for s,d in f:gmatch("(%w+)%s+(%d+)") do imap_now[s] = tonumber(d) end
|
for s, d in f:gmatch('(%w+)%s+(%d+)') do
|
||||||
mailcount = imap_now["UNSEEN"] -- backwards compatibility
|
imap_now[s] = tonumber(d)
|
||||||
|
end
|
||||||
|
mailcount = imap_now['UNSEEN'] -- backwards compatibility
|
||||||
widget = imap.widget
|
widget = imap.widget
|
||||||
|
|
||||||
settings()
|
settings()
|
||||||
|
|
||||||
if notify == "on" and mailcount and mailcount >= 1 and mailcount > helpers.get_map(mail) then
|
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
|
if followtag then
|
||||||
naughty.notify {
|
mail_notification_preset.screen = awful.screen.focused()
|
||||||
|
end
|
||||||
|
naughty.notify({
|
||||||
preset = mail_notification_preset,
|
preset = mail_notification_preset,
|
||||||
text = string.format("%s has <b>%d</b> new message%s", mail, mailcount, mailcount == 1 and "" or "s")
|
text = string.format(
|
||||||
}
|
'%s has <b>%d</b> new message%s',
|
||||||
|
mail,
|
||||||
|
mailcount,
|
||||||
|
mailcount == 1 and '' or 's'
|
||||||
|
),
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.set_map(mail, imap_now["UNSEEN"])
|
helpers.set_map(mail, imap_now['UNSEEN'])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
imap.timer = helpers.newtimer(mail, timeout, imap.update, true, true)
|
imap.timer = helpers.newtimer(mail, timeout, imap.update, true, true)
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local wrequire = require("lain.helpers").wrequire
|
local wrequire = require('lain.helpers').wrequire
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
local widget = { _NAME = "lain.widget" }
|
local widget = { _NAME = 'lain.widget' }
|
||||||
|
|
||||||
return setmetatable(widget, { __index = wrequire })
|
return setmetatable(widget, { __index = wrequire })
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local gmatch, lines, floor = string.gmatch, io.lines, math.floor
|
local gmatch, lines, floor = string.gmatch, io.lines, math.floor
|
||||||
|
|
||||||
-- Memory usage (ignoring caches)
|
-- Memory usage (ignoring caches)
|
||||||
@ -22,15 +22,22 @@ local function factory(args)
|
|||||||
|
|
||||||
function mem.update()
|
function mem.update()
|
||||||
mem_now = {}
|
mem_now = {}
|
||||||
for line in lines("/proc/meminfo") do
|
for line in lines('/proc/meminfo') do
|
||||||
for k, v in gmatch(line, "([%a]+):[%s]+([%d]+).+") do
|
for k, v in gmatch(line, '([%a]+):[%s]+([%d]+).+') do
|
||||||
if k == "MemTotal" then mem_now.total = floor(v / 1024 + 0.5)
|
if k == 'MemTotal' then
|
||||||
elseif k == "MemFree" then mem_now.free = floor(v / 1024 + 0.5)
|
mem_now.total = floor(v / 1024 + 0.5)
|
||||||
elseif k == "Buffers" then mem_now.buf = floor(v / 1024 + 0.5)
|
elseif k == 'MemFree' then
|
||||||
elseif k == "Cached" then mem_now.cache = floor(v / 1024 + 0.5)
|
mem_now.free = floor(v / 1024 + 0.5)
|
||||||
elseif k == "SwapTotal" then mem_now.swap = floor(v / 1024 + 0.5)
|
elseif k == 'Buffers' then
|
||||||
elseif k == "SwapFree" then mem_now.swapf = floor(v / 1024 + 0.5)
|
mem_now.buf = floor(v / 1024 + 0.5)
|
||||||
elseif k == "SReclaimable" then mem_now.srec = 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
|
end
|
||||||
end
|
end
|
||||||
@ -43,7 +50,7 @@ local function factory(args)
|
|||||||
settings()
|
settings()
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer("mem", timeout, mem.update)
|
helpers.newtimer('mem', timeout, mem.update)
|
||||||
|
|
||||||
return mem
|
return mem
|
||||||
end
|
end
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local shell = require("awful.util").shell
|
local shell = require('awful.util').shell
|
||||||
local escape_f = require("awful.util").escape
|
local escape_f = require('awful.util').escape
|
||||||
local focused = require("awful.screen").focused
|
local focused = require('awful.screen').focused
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local os = os
|
local os = os
|
||||||
local string = string
|
local string = string
|
||||||
|
|
||||||
@ -23,111 +23,135 @@ local function factory(args)
|
|||||||
|
|
||||||
local mpd = { widget = args.widget or wibox.widget.textbox() }
|
local mpd = { widget = args.widget or wibox.widget.textbox() }
|
||||||
local timeout = args.timeout or 2
|
local timeout = args.timeout or 2
|
||||||
local password = (args.password and #args.password > 0 and string.format("password %s\\n", args.password)) or ""
|
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 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 port = args.port or os.getenv('MPD_PORT') or '6600'
|
||||||
local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
|
local music_dir = args.music_dir or os.getenv('HOME') .. '/Music'
|
||||||
local cover_pattern = args.cover_pattern or "*\\.(jpg|jpeg|png|gif)$"
|
local cover_pattern = args.cover_pattern or '*\\.(jpg|jpeg|png|gif)$'
|
||||||
local cover_size = args.cover_size or 100
|
local cover_size = args.cover_size or 100
|
||||||
local default_art = args.default_art
|
local default_art = args.default_art
|
||||||
local notify = args.notify or "on"
|
local notify = args.notify or 'on'
|
||||||
local followtag = args.followtag or false
|
local followtag = args.followtag or false
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
local mpdh = string.format("telnet://%s:%s", host, port)
|
local mpdh = string.format('telnet://%s:%s', host, port)
|
||||||
local echo = string.format("printf \"%sstatus\\ncurrentsong\\nclose\\n\"", password)
|
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 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()
|
function mpd.update()
|
||||||
helpers.async({ shell, "-c", cmd }, function(f)
|
helpers.async({ shell, '-c', cmd }, function(f)
|
||||||
mpd_now = {
|
mpd_now = {
|
||||||
random_mode = false,
|
random_mode = false,
|
||||||
single_mode = false,
|
single_mode = false,
|
||||||
repeat_mode = false,
|
repeat_mode = false,
|
||||||
consume_mode = false,
|
consume_mode = false,
|
||||||
pls_pos = "N/A",
|
pls_pos = 'N/A',
|
||||||
pls_len = "N/A",
|
pls_len = 'N/A',
|
||||||
state = "N/A",
|
state = 'N/A',
|
||||||
file = "N/A",
|
file = 'N/A',
|
||||||
name = "N/A",
|
name = 'N/A',
|
||||||
artist = "N/A",
|
artist = 'N/A',
|
||||||
title = "N/A",
|
title = 'N/A',
|
||||||
album = "N/A",
|
album = 'N/A',
|
||||||
genre = "N/A",
|
genre = 'N/A',
|
||||||
track = "N/A",
|
track = 'N/A',
|
||||||
date = "N/A",
|
date = 'N/A',
|
||||||
time = "N/A",
|
time = 'N/A',
|
||||||
elapsed = "N/A",
|
elapsed = 'N/A',
|
||||||
volume = "N/A"
|
volume = 'N/A',
|
||||||
}
|
}
|
||||||
|
|
||||||
for line in string.gmatch(f, "[^\n]+") do
|
for line in string.gmatch(f, '[^\n]+') do
|
||||||
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
|
for k, v in string.gmatch(line, '([%w]+):[%s](.*)$') do
|
||||||
if k == "state" then mpd_now.state = v
|
if k == 'state' then
|
||||||
elseif k == "file" then mpd_now.file = v
|
mpd_now.state = v
|
||||||
elseif k == "Name" then mpd_now.name = escape_f(v)
|
elseif k == 'file' then
|
||||||
elseif k == "Artist" then mpd_now.artist = escape_f(v)
|
mpd_now.file = v
|
||||||
elseif k == "Title" then mpd_now.title = escape_f(v)
|
elseif k == 'Name' then
|
||||||
elseif k == "Album" then mpd_now.album = escape_f(v)
|
mpd_now.name = escape_f(v)
|
||||||
elseif k == "Genre" then mpd_now.genre = escape_f(v)
|
elseif k == 'Artist' then
|
||||||
elseif k == "Track" then mpd_now.track = escape_f(v)
|
mpd_now.artist = escape_f(v)
|
||||||
elseif k == "Date" then mpd_now.date = escape_f(v)
|
elseif k == 'Title' then
|
||||||
elseif k == "Time" then mpd_now.time = v
|
mpd_now.title = escape_f(v)
|
||||||
elseif k == "elapsed" then mpd_now.elapsed = string.match(v, "%d+")
|
elseif k == 'Album' then
|
||||||
elseif k == "song" then mpd_now.pls_pos = v
|
mpd_now.album = escape_f(v)
|
||||||
elseif k == "playlistlength" then mpd_now.pls_len = v
|
elseif k == 'Genre' then
|
||||||
elseif k == "repeat" then mpd_now.repeat_mode = v ~= "0"
|
mpd_now.genre = escape_f(v)
|
||||||
elseif k == "single" then mpd_now.single_mode = v ~= "0"
|
elseif k == 'Track' then
|
||||||
elseif k == "random" then mpd_now.random_mode = v ~= "0"
|
mpd_now.track = escape_f(v)
|
||||||
elseif k == "consume" then mpd_now.consume_mode = v ~= "0"
|
elseif k == 'Date' then
|
||||||
elseif k == "volume" then mpd_now.volume = v
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist,
|
mpd_notification_preset.text =
|
||||||
mpd_now.album, mpd_now.date, mpd_now.title)
|
string.format('%s (%s) - %s\n%s', mpd_now.artist, mpd_now.album, mpd_now.date, mpd_now.title)
|
||||||
widget = mpd.widget
|
widget = mpd.widget
|
||||||
settings()
|
settings()
|
||||||
|
|
||||||
if mpd_now.state == "play" then
|
if mpd_now.state == 'play' then
|
||||||
if notify == "on" and mpd_now.title ~= helpers.get_map("current mpd track") then
|
if notify == 'on' and mpd_now.title ~= helpers.get_map('current mpd track') then
|
||||||
helpers.set_map("current mpd track", mpd_now.title)
|
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 = {
|
local common = {
|
||||||
preset = mpd_notification_preset,
|
preset = mpd_notification_preset,
|
||||||
icon = default_art,
|
icon = default_art,
|
||||||
icon_size = cover_size,
|
icon_size = cover_size,
|
||||||
replaces_id = mpd.id
|
replaces_id = mpd.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
if not string.match(mpd_now.file, "http.*://") then -- local file instead of http stream
|
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 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'",
|
local cover = string.format(
|
||||||
path:gsub("'", "'\\''"), cover_pattern)
|
"find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'",
|
||||||
helpers.async({ shell, "-c", cover }, function(current_icon)
|
path:gsub("'", "'\\''"),
|
||||||
common.icon = current_icon:gsub("\n", "")
|
cover_pattern
|
||||||
if #common.icon == 0 then common.icon = nil end
|
)
|
||||||
|
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
|
mpd.id = naughty.notify(common).id
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
mpd.id = naughty.notify(common).id
|
mpd.id = naughty.notify(common).id
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
elseif mpd_now.state ~= "pause" then
|
elseif mpd_now.state ~= 'pause' then
|
||||||
helpers.set_map("current mpd track", nil)
|
helpers.set_map('current mpd track', nil)
|
||||||
end
|
end
|
||||||
end)
|
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
|
end
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local string = string
|
local string = string
|
||||||
|
|
||||||
-- Network infos
|
-- Network infos
|
||||||
@ -20,25 +20,29 @@ local function factory(args)
|
|||||||
local net = { widget = args.widget or wibox.widget.textbox(), devices = {} }
|
local net = { widget = args.widget or wibox.widget.textbox(), devices = {} }
|
||||||
local timeout = args.timeout or 2
|
local timeout = args.timeout or 2
|
||||||
local units = args.units or 1024 -- KB
|
local units = args.units or 1024 -- KB
|
||||||
local notify = args.notify or "on"
|
local notify = args.notify or 'on'
|
||||||
local wifi_state = args.wifi_state or "off"
|
local wifi_state = args.wifi_state or 'off'
|
||||||
local eth_state = args.eth_state or "off"
|
local eth_state = args.eth_state or 'off'
|
||||||
local screen = args.screen or 1
|
local screen = args.screen or 1
|
||||||
local format = args.format or "%.1f"
|
local format = args.format or '%.1f'
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
-- Compatibility with old API where iface was a string corresponding to 1 interface
|
-- 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
|
net.iface = (
|
||||||
(type(args.iface) == "table" and args.iface)) or {}
|
args.iface and (type(args.iface) == 'string' and { args.iface })
|
||||||
|
or (type(args.iface) == 'table' and args.iface)
|
||||||
|
) or {}
|
||||||
|
|
||||||
function net.get_devices()
|
function net.get_devices()
|
||||||
net.iface = {} -- reset at every call
|
net.iface = {} -- reset at every call
|
||||||
helpers.line_callback("ip link", function(line)
|
helpers.line_callback('ip link', function(line)
|
||||||
net.iface[#net.iface + 1] = not string.match(line, "LOOPBACK") and string.match(line, "(%w+): <") or nil
|
net.iface[#net.iface + 1] = not string.match(line, 'LOOPBACK') and string.match(line, '(%w+): <') or nil
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
if #net.iface == 0 then net.get_devices() end
|
if #net.iface == 0 then
|
||||||
|
net.get_devices()
|
||||||
|
end
|
||||||
|
|
||||||
function net.update()
|
function net.update()
|
||||||
-- These are the totals over all specified interfaces
|
-- These are the totals over all specified interfaces
|
||||||
@ -46,17 +50,17 @@ local function factory(args)
|
|||||||
devices = {},
|
devices = {},
|
||||||
-- Bytes since last iteration
|
-- Bytes since last iteration
|
||||||
sent = 0,
|
sent = 0,
|
||||||
received = 0
|
received = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dev in ipairs(net.iface) do
|
for _, dev in ipairs(net.iface) do
|
||||||
local dev_now = {}
|
local dev_now = {}
|
||||||
local dev_before = net.devices[dev] or { last_t = 0, last_r = 0 }
|
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_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)
|
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.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.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.sent = (now_t - dev_before.last_t) / timeout / units
|
||||||
dev_now.received = (now_r - dev_before.last_r) / timeout / units
|
dev_now.received = (now_r - dev_before.last_r) / timeout / units
|
||||||
@ -70,16 +74,23 @@ local function factory(args)
|
|||||||
dev_now.last_t = now_t
|
dev_now.last_t = now_t
|
||||||
dev_now.last_r = now_r
|
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
|
if
|
||||||
|
wifi_state == 'on'
|
||||||
|
and helpers.first_line(string.format('/sys/class/net/%s/uevent', dev)) == 'DEVTYPE=wlan'
|
||||||
|
then
|
||||||
dev_now.wifi = true
|
dev_now.wifi = true
|
||||||
if string.match(dev_now.carrier, "1") then
|
if string.match(dev_now.carrier, '1') then
|
||||||
dev_now.signal = tonumber(string.match(helpers.lines_from("/proc/net/wireless")[3], "(%-%d+%.)")) or nil
|
dev_now.signal = tonumber(string.match(helpers.lines_from('/proc/net/wireless')[3], '(%-%d+%.)'))
|
||||||
|
or nil
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
dev_now.wifi = false
|
dev_now.wifi = false
|
||||||
end
|
end
|
||||||
|
|
||||||
if eth_state == "on" and helpers.first_line(string.format("/sys/class/net/%s/uevent", dev)) ~= "DEVTYPE=wlan" then
|
if
|
||||||
|
eth_state == 'on'
|
||||||
|
and helpers.first_line(string.format('/sys/class/net/%s/uevent', dev)) ~= 'DEVTYPE=wlan'
|
||||||
|
then
|
||||||
dev_now.ethernet = true
|
dev_now.ethernet = true
|
||||||
else
|
else
|
||||||
dev_now.ethernet = false
|
dev_now.ethernet = false
|
||||||
@ -88,15 +99,15 @@ local function factory(args)
|
|||||||
net.devices[dev] = dev_now
|
net.devices[dev] = dev_now
|
||||||
|
|
||||||
-- Notify only once when connection is lost
|
-- Notify only once when connection is lost
|
||||||
if string.match(dev_now.carrier, "0") and notify == "on" and helpers.get_map(dev) then
|
if string.match(dev_now.carrier, '0') and notify == 'on' and helpers.get_map(dev) then
|
||||||
naughty.notify {
|
naughty.notify({
|
||||||
title = dev,
|
title = dev,
|
||||||
text = "No carrier",
|
text = 'No carrier',
|
||||||
icon = helpers.icons_dir .. "no_net.png",
|
icon = helpers.icons_dir .. 'no_net.png',
|
||||||
screen = screen
|
screen = screen,
|
||||||
}
|
})
|
||||||
helpers.set_map(dev, false)
|
helpers.set_map(dev, false)
|
||||||
elseif string.match(dev_now.carrier, "1") then
|
elseif string.match(dev_now.carrier, '1') then
|
||||||
helpers.set_map(dev, true)
|
helpers.set_map(dev, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -114,7 +125,7 @@ local function factory(args)
|
|||||||
settings()
|
settings()
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer("network", timeout, net.update)
|
helpers.newtimer('network', timeout, net.update)
|
||||||
|
|
||||||
return net
|
return net
|
||||||
end
|
end
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local shell = require("awful.util").shell
|
local shell = require('awful.util').shell
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local string = string
|
local string = string
|
||||||
local type = type
|
local type = type
|
||||||
|
|
||||||
@ -17,40 +17,42 @@ local type = type
|
|||||||
local function factory(args)
|
local function factory(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
local pulse = { widget = args.widget or wibox.widget.textbox(), device = "N/A" }
|
local pulse = { widget = args.widget or wibox.widget.textbox(), device = 'N/A' }
|
||||||
local timeout = args.timeout or 5
|
local timeout = args.timeout or 5
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
pulse.devicetype = args.devicetype or "sink"
|
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.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()
|
function pulse.update()
|
||||||
helpers.async({ shell, "-c", type(pulse.cmd) == "string" and pulse.cmd or pulse.cmd() },
|
helpers.async({ shell, '-c', type(pulse.cmd) == 'string' and pulse.cmd or pulse.cmd() }, function(s)
|
||||||
function(s)
|
|
||||||
volume_now = {
|
volume_now = {
|
||||||
index = string.match(s, "index: (%S+)") or "N/A",
|
index = string.match(s, 'index: (%S+)') or 'N/A',
|
||||||
device = string.match(s, "device.string = \"(%S+)\"") or "N/A",
|
device = string.match(s, 'device.string = "(%S+)"') or 'N/A',
|
||||||
muted = string.match(s, "muted: (%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
|
local ch = 1
|
||||||
volume_now.channel = {}
|
volume_now.channel = {}
|
||||||
for v in string.gmatch(s, ":.-(%d+)%%") do
|
for v in string.gmatch(s, ':.-(%d+)%%') do
|
||||||
volume_now.channel[ch] = v
|
volume_now.channel[ch] = v
|
||||||
ch = ch + 1
|
ch = ch + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
volume_now.left = volume_now.channel[1] or "N/A"
|
volume_now.left = volume_now.channel[1] or 'N/A'
|
||||||
volume_now.right = volume_now.channel[2] or "N/A"
|
volume_now.right = volume_now.channel[2] or 'N/A'
|
||||||
|
|
||||||
widget = pulse.widget
|
widget = pulse.widget
|
||||||
settings()
|
settings()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer("pulse", timeout, pulse.update)
|
helpers.newtimer('pulse', timeout, pulse.update)
|
||||||
|
|
||||||
return pulse
|
return pulse
|
||||||
end
|
end
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local awful = require("awful")
|
local awful = require('awful')
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local math = math
|
local math = math
|
||||||
local string = string
|
local string = string
|
||||||
local type = type
|
local type = type
|
||||||
@ -21,15 +21,15 @@ local tonumber = tonumber
|
|||||||
local function factory(args)
|
local function factory(args)
|
||||||
local pulsebar = {
|
local pulsebar = {
|
||||||
colors = {
|
colors = {
|
||||||
background = "#000000",
|
background = '#000000',
|
||||||
mute_background = "#000000",
|
mute_background = '#000000',
|
||||||
mute = "#EB8F8F",
|
mute = '#EB8F8F',
|
||||||
unmute = "#A4CE8A"
|
unmute = '#A4CE8A',
|
||||||
},
|
},
|
||||||
|
|
||||||
_current_level = 0,
|
_current_level = 0,
|
||||||
_mute = "no",
|
_mute = 'no',
|
||||||
device = "N/A"
|
device = 'N/A',
|
||||||
}
|
}
|
||||||
|
|
||||||
args = args or {}
|
args = args or {}
|
||||||
@ -42,24 +42,27 @@ local function factory(args)
|
|||||||
local paddings = args.paddings or 1
|
local paddings = args.paddings or 1
|
||||||
local ticks = args.ticks or false
|
local ticks = args.ticks or false
|
||||||
local ticks_size = args.ticks_size or 7
|
local ticks_size = args.ticks_size or 7
|
||||||
local tick = args.tick or "|"
|
local tick = args.tick or '|'
|
||||||
local tick_pre = args.tick_pre or "["
|
local tick_pre = args.tick_pre or '['
|
||||||
local tick_post = args.tick_post or "]"
|
local tick_post = args.tick_post or ']'
|
||||||
local tick_none = args.tick_none or " "
|
local tick_none = args.tick_none or ' '
|
||||||
|
|
||||||
pulsebar.colors = args.colors or pulsebar.colors
|
pulsebar.colors = args.colors or pulsebar.colors
|
||||||
pulsebar.followtag = args.followtag or false
|
pulsebar.followtag = args.followtag or false
|
||||||
pulsebar.notification_preset = args.notification_preset
|
pulsebar.notification_preset = args.notification_preset
|
||||||
pulsebar.devicetype = args.devicetype or "sink"
|
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.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
|
if not pulsebar.notification_preset then
|
||||||
pulsebar.notification_preset = {
|
pulsebar.notification_preset = {
|
||||||
font = "Monospace 10"
|
font = 'Monospace 10',
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
pulsebar.bar = wibox.widget {
|
pulsebar.bar = wibox.widget({
|
||||||
color = pulsebar.colors.unmute,
|
color = pulsebar.colors.unmute,
|
||||||
background_color = pulsebar.colors.background,
|
background_color = pulsebar.colors.background,
|
||||||
forced_height = height,
|
forced_height = height,
|
||||||
@ -69,66 +72,74 @@ local function factory(args)
|
|||||||
ticks = ticks,
|
ticks = ticks,
|
||||||
ticks_size = ticks_size,
|
ticks_size = ticks_size,
|
||||||
widget = wibox.widget.progressbar,
|
widget = wibox.widget.progressbar,
|
||||||
}
|
})
|
||||||
|
|
||||||
pulsebar.tooltip = awful.tooltip({ objects = { pulsebar.bar } })
|
pulsebar.tooltip = awful.tooltip({ objects = { pulsebar.bar } })
|
||||||
|
|
||||||
function pulsebar.update(callback)
|
function pulsebar.update(callback)
|
||||||
helpers.async({ awful.util.shell, "-c", type(pulsebar.cmd) == "string" and pulsebar.cmd or pulsebar.cmd() },
|
helpers.async(
|
||||||
|
{ awful.util.shell, '-c', type(pulsebar.cmd) == 'string' and pulsebar.cmd or pulsebar.cmd() },
|
||||||
function(s)
|
function(s)
|
||||||
volume_now = {
|
volume_now = {
|
||||||
index = string.match(s, "index: (%S+)") or "N/A",
|
index = string.match(s, 'index: (%S+)') or 'N/A',
|
||||||
device = string.match(s, "device.string = \"(%S+)\"") or "N/A",
|
device = string.match(s, 'device.string = "(%S+)"') or 'N/A',
|
||||||
muted = string.match(s, "muted: (%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
|
local ch = 1
|
||||||
volume_now.channel = {}
|
volume_now.channel = {}
|
||||||
for v in string.gmatch(s, ":.-(%d+)%%") do
|
for v in string.gmatch(s, ':.-(%d+)%%') do
|
||||||
volume_now.channel[ch] = v
|
volume_now.channel[ch] = v
|
||||||
ch = ch + 1
|
ch = ch + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
volume_now.left = volume_now.channel[1] or "N/A"
|
volume_now.left = volume_now.channel[1] or 'N/A'
|
||||||
volume_now.right = volume_now.channel[2] or "N/A"
|
volume_now.right = volume_now.channel[2] or 'N/A'
|
||||||
|
|
||||||
local volu = volume_now.left
|
local volu = volume_now.left
|
||||||
local mute = volume_now.muted
|
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
|
if volu ~= pulsebar._current_level or mute ~= pulsebar._mute then
|
||||||
pulsebar._current_level = tonumber(volu)
|
pulsebar._current_level = tonumber(volu)
|
||||||
pulsebar.bar:set_value(pulsebar._current_level / 100)
|
pulsebar.bar:set_value(pulsebar._current_level / 100)
|
||||||
if pulsebar._current_level == 0 or mute == "yes" then
|
if pulsebar._current_level == 0 or mute == 'yes' then
|
||||||
pulsebar._mute = mute
|
pulsebar._mute = mute
|
||||||
pulsebar.tooltip:set_text ("[muted]")
|
pulsebar.tooltip:set_text('[muted]')
|
||||||
pulsebar.bar.color = pulsebar.colors.mute
|
pulsebar.bar.color = pulsebar.colors.mute
|
||||||
pulsebar.bar.background_color = pulsebar.colors.mute_background
|
pulsebar.bar.background_color = pulsebar.colors.mute_background
|
||||||
else
|
else
|
||||||
pulsebar._mute = "no"
|
pulsebar._mute = 'no'
|
||||||
pulsebar.tooltip:set_text(string.format("%s %s: %s", pulsebar.devicetype, pulsebar.device, volu))
|
pulsebar.tooltip:set_text(
|
||||||
|
string.format('%s %s: %s', pulsebar.devicetype, pulsebar.device, volu)
|
||||||
|
)
|
||||||
pulsebar.bar.color = pulsebar.colors.unmute
|
pulsebar.bar.color = pulsebar.colors.unmute
|
||||||
pulsebar.bar.background_color = pulsebar.colors.background
|
pulsebar.bar.background_color = pulsebar.colors.background
|
||||||
end
|
end
|
||||||
|
|
||||||
settings()
|
settings()
|
||||||
|
|
||||||
if type(callback) == "function" then callback() end
|
if type(callback) == 'function' then
|
||||||
|
callback()
|
||||||
end
|
end
|
||||||
end)
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function pulsebar.notify()
|
function pulsebar.notify()
|
||||||
pulsebar.update(function()
|
pulsebar.update(function()
|
||||||
local preset = pulsebar.notification_preset
|
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
|
if pulsebar._mute == 'yes' then
|
||||||
preset.title = preset.title .. " muted"
|
preset.title = preset.title .. ' muted'
|
||||||
end
|
end
|
||||||
|
|
||||||
-- tot is the maximum number of ticks to display in the notification
|
-- tot is the maximum number of ticks to display in the notification
|
||||||
@ -138,7 +149,7 @@ local function factory(args)
|
|||||||
-- if we can grab mywibox, tot is defined as its height if
|
-- if we can grab mywibox, tot is defined as its height if
|
||||||
-- horizontal, or width otherwise
|
-- horizontal, or width otherwise
|
||||||
if wib then
|
if wib then
|
||||||
if wib.position == "left" or wib.position == "right" then
|
if wib.position == 'left' or wib.position == 'right' then
|
||||||
tot = wib.width
|
tot = wib.width
|
||||||
else
|
else
|
||||||
tot = wib.height
|
tot = wib.height
|
||||||
@ -146,28 +157,27 @@ local function factory(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local int = math.modf((pulsebar._current_level / 100) * tot)
|
local int = math.modf((pulsebar._current_level / 100) * tot)
|
||||||
preset.text = string.format(
|
preset.text =
|
||||||
"%s%s%s%s",
|
string.format('%s%s%s%s', tick_pre, string.rep(tick, int), string.rep(tick_none, tot - int), tick_post)
|
||||||
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
|
if not pulsebar.notification then
|
||||||
pulsebar.notification = naughty.notify {
|
pulsebar.notification = naughty.notify({
|
||||||
preset = preset,
|
preset = preset,
|
||||||
destroy = function() pulsebar.notification = nil end
|
destroy = function()
|
||||||
}
|
pulsebar.notification = nil
|
||||||
|
end,
|
||||||
|
})
|
||||||
else
|
else
|
||||||
naughty.replace_text(pulsebar.notification, preset.title, preset.text)
|
naughty.replace_text(pulsebar.notification, preset.title, preset.text)
|
||||||
end
|
end
|
||||||
end)
|
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
|
end
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local open, match = io.open, string.match
|
local open, match = io.open, string.match
|
||||||
|
|
||||||
-- System load
|
-- System load
|
||||||
@ -21,17 +21,17 @@ local function factory(args)
|
|||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
function sysload.update()
|
function sysload.update()
|
||||||
local f = open("/proc/loadavg")
|
local f = open('/proc/loadavg')
|
||||||
local ret = f:read("*all")
|
local ret = f:read('*all')
|
||||||
f:close()
|
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
|
widget = sysload.widget
|
||||||
settings()
|
settings()
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer("sysload", timeout, sysload.update)
|
helpers.newtimer('sysload', timeout, sysload.update)
|
||||||
|
|
||||||
return sysload
|
return sysload
|
||||||
end
|
end
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local tonumber = tonumber
|
local tonumber = tonumber
|
||||||
|
|
||||||
-- {thermal,core} temperature info
|
-- {thermal,core} temperature info
|
||||||
@ -17,15 +17,15 @@ local function factory(args)
|
|||||||
|
|
||||||
local temp = { widget = args.widget or wibox.widget.textbox() }
|
local temp = { widget = args.widget or wibox.widget.textbox() }
|
||||||
local timeout = args.timeout or 30
|
local timeout = args.timeout or 30
|
||||||
local tempfile = args.tempfile or "/sys/devices/virtual/thermal/thermal_zone0/temp"
|
local tempfile = args.tempfile or '/sys/devices/virtual/thermal/thermal_zone0/temp'
|
||||||
local format = args.format or "%.1f"
|
local format = args.format or '%.1f'
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
function temp.update()
|
function temp.update()
|
||||||
helpers.async({"find", "/sys/devices", "-type", "f", "-name", "*temp*"}, function(f)
|
helpers.async({ 'find', '/sys/devices', '-type', 'f', '-name', '*temp*' }, function(f)
|
||||||
temp_now = {}
|
temp_now = {}
|
||||||
local temp_fl, temp_value
|
local temp_fl, temp_value
|
||||||
for t in f:gmatch("[^\n]+") do
|
for t in f:gmatch('[^\n]+') do
|
||||||
temp_fl = helpers.first_line(t)
|
temp_fl = helpers.first_line(t)
|
||||||
if temp_fl then
|
if temp_fl then
|
||||||
temp_value = tonumber(temp_fl)
|
temp_value = tonumber(temp_fl)
|
||||||
@ -35,14 +35,14 @@ local function factory(args)
|
|||||||
if temp_now[tempfile] then
|
if temp_now[tempfile] then
|
||||||
coretemp_now = string.format(format, temp_now[tempfile])
|
coretemp_now = string.format(format, temp_now[tempfile])
|
||||||
else
|
else
|
||||||
coretemp_now = "N/A"
|
coretemp_now = 'N/A'
|
||||||
end
|
end
|
||||||
widget = temp.widget
|
widget = temp.widget
|
||||||
settings()
|
settings()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer("thermal", timeout, temp.update)
|
helpers.newtimer('thermal', timeout, temp.update)
|
||||||
|
|
||||||
return temp
|
return temp
|
||||||
end
|
end
|
||||||
|
@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local helpers = require("lain.helpers")
|
local helpers = require('lain.helpers')
|
||||||
local json = require("lain.util").dkjson
|
local json = require('lain.util').dkjson
|
||||||
local focused = require("awful.screen").focused
|
local focused = require('awful.screen').focused
|
||||||
local naughty = require("naughty")
|
local naughty = require('naughty')
|
||||||
local wibox = require("wibox")
|
local wibox = require('wibox')
|
||||||
local math = math
|
local math = math
|
||||||
local os = os
|
local os = os
|
||||||
local string = string
|
local string = string
|
||||||
@ -26,28 +26,30 @@ local function factory(args)
|
|||||||
local weather = { widget = args.widget or wibox.widget.textbox() }
|
local weather = { widget = args.widget or wibox.widget.textbox() }
|
||||||
local APPID = args.APPID -- mandatory
|
local APPID = args.APPID -- mandatory
|
||||||
local timeout = args.timeout or 60 * 15 -- 15 min
|
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 current_call = args.current_call
|
||||||
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'"
|
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 city_id = args.city_id or 0 -- placeholder
|
||||||
local units = args.units or "metric"
|
local units = args.units or 'metric'
|
||||||
local lang = args.lang or "en"
|
local lang = args.lang or 'en'
|
||||||
local cnt = args.cnt or 5
|
local cnt = args.cnt or 5
|
||||||
local icons_path = args.icons_path or helpers.icons_dir .. "openweathermap/"
|
local icons_path = args.icons_path or helpers.icons_dir .. 'openweathermap/'
|
||||||
local notification_preset = args.notification_preset or {}
|
local notification_preset = args.notification_preset or {}
|
||||||
local notification_text_fun = args.notification_text_fun or
|
local notification_text_fun = args.notification_text_fun
|
||||||
function (wn)
|
or function(wn)
|
||||||
local day = os.date("%a %d", wn["dt"])
|
local day = os.date('%a %d', wn['dt'])
|
||||||
local temp = math.floor(wn["main"]["temp"])
|
local temp = math.floor(wn['main']['temp'])
|
||||||
local desc = wn["weather"][1]["description"]
|
local desc = wn['weather'][1]['description']
|
||||||
return string.format("<b>%s</b>: %s, %d ", day, desc, temp)
|
return string.format('<b>%s</b>: %s, %d ', day, desc, temp)
|
||||||
end
|
end
|
||||||
local weather_na_markup = args.weather_na_markup or " N/A "
|
local weather_na_markup = args.weather_na_markup or ' N/A '
|
||||||
local followtag = args.followtag or false
|
local followtag = args.followtag or false
|
||||||
local showpopup = args.showpopup or "on"
|
local showpopup = args.showpopup or 'on'
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
weather.widget:set_markup(weather_na_markup)
|
weather.widget:set_markup(weather_na_markup)
|
||||||
weather.icon_path = icons_path .. "na.png"
|
weather.icon_path = icons_path .. 'na.png'
|
||||||
weather.icon = wibox.widget.imagebox(weather.icon_path)
|
weather.icon = wibox.widget.imagebox(weather.icon_path)
|
||||||
|
|
||||||
function weather.show(seconds)
|
function weather.show(seconds)
|
||||||
@ -62,12 +64,12 @@ local function factory(args)
|
|||||||
weather.forecast_update()
|
weather.forecast_update()
|
||||||
end
|
end
|
||||||
|
|
||||||
weather.notification = naughty.notify {
|
weather.notification = naughty.notify({
|
||||||
preset = notification_preset,
|
preset = notification_preset,
|
||||||
text = weather.notification_text,
|
text = weather.notification_text,
|
||||||
icon = weather.icon_path,
|
icon = weather.icon_path,
|
||||||
timeout = type(seconds) == "number" and seconds or notification_preset.timeout
|
timeout = type(seconds) == 'number' and seconds or notification_preset.timeout,
|
||||||
}
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function weather.hide()
|
function weather.hide()
|
||||||
@ -78,10 +80,10 @@ local function factory(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function weather.attach(obj)
|
function weather.attach(obj)
|
||||||
obj:connect_signal("mouse::enter", function()
|
obj:connect_signal('mouse::enter', function()
|
||||||
weather.show(0)
|
weather.show(0)
|
||||||
end)
|
end)
|
||||||
obj:connect_signal("mouse::leave", function()
|
obj:connect_signal('mouse::leave', function()
|
||||||
weather.hide()
|
weather.hide()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -92,13 +94,13 @@ local function factory(args)
|
|||||||
local err
|
local err
|
||||||
weather_now, _, err = json.decode(f, 1, nil)
|
weather_now, _, err = json.decode(f, 1, nil)
|
||||||
|
|
||||||
if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then
|
if not err and type(weather_now) == 'table' and tonumber(weather_now['cod']) == 200 then
|
||||||
weather.notification_text = ""
|
weather.notification_text = ''
|
||||||
for i = 1, weather_now["cnt"], math.floor(weather_now["cnt"] / cnt) do
|
for i = 1, weather_now['cnt'], math.floor(weather_now['cnt'] / cnt) do
|
||||||
weather.notification_text = weather.notification_text ..
|
weather.notification_text = weather.notification_text
|
||||||
notification_text_fun(weather_now["list"][i])
|
.. notification_text_fun(weather_now['list'][i])
|
||||||
if i < weather_now["cnt"] then
|
if i < weather_now['cnt'] then
|
||||||
weather.notification_text = weather.notification_text .. "\n"
|
weather.notification_text = weather.notification_text .. '\n'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -111,23 +113,23 @@ local function factory(args)
|
|||||||
local err
|
local err
|
||||||
weather_now, _, err = json.decode(f, 1, nil)
|
weather_now, _, err = json.decode(f, 1, nil)
|
||||||
|
|
||||||
if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then
|
if not err and type(weather_now) == 'table' and tonumber(weather_now['cod']) == 200 then
|
||||||
local sunrise = tonumber(weather_now["sys"]["sunrise"])
|
local sunrise = tonumber(weather_now['sys']['sunrise'])
|
||||||
local sunset = tonumber(weather_now["sys"]["sunset"])
|
local sunset = tonumber(weather_now['sys']['sunset'])
|
||||||
local icon = weather_now["weather"][1]["icon"]
|
local icon = weather_now['weather'][1]['icon']
|
||||||
local loc_now = os.time()
|
local loc_now = os.time()
|
||||||
|
|
||||||
if sunrise <= loc_now and loc_now <= sunset then
|
if sunrise <= loc_now and loc_now <= sunset then
|
||||||
icon = string.gsub(icon, "n", "d")
|
icon = string.gsub(icon, 'n', 'd')
|
||||||
else
|
else
|
||||||
icon = string.gsub(icon, "d", "n")
|
icon = string.gsub(icon, 'd', 'n')
|
||||||
end
|
end
|
||||||
|
|
||||||
weather.icon_path = icons_path .. icon .. ".png"
|
weather.icon_path = icons_path .. icon .. '.png'
|
||||||
widget = weather.widget
|
widget = weather.widget
|
||||||
settings()
|
settings()
|
||||||
else
|
else
|
||||||
weather.icon_path = icons_path .. "na.png"
|
weather.icon_path = icons_path .. 'na.png'
|
||||||
weather.widget:set_markup(weather_na_markup)
|
weather.widget:set_markup(weather_na_markup)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -135,10 +137,13 @@ local function factory(args)
|
|||||||
end)
|
end)
|
||||||
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 = 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_forecast =
|
||||||
|
helpers.newtimer('weather_forecast-' .. city_id, timeout, weather.forecast_update, false, true)
|
||||||
|
|
||||||
return weather
|
return weather
|
||||||
end
|
end
|
||||||
|
@ -10,13 +10,29 @@ local lain = require('lain')
|
|||||||
local awful = require('awful')
|
local awful = require('awful')
|
||||||
local wibox = require('wibox')
|
local wibox = require('wibox')
|
||||||
local dpi = require('beautiful.xresources').apply_dpi
|
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 os = os
|
||||||
local my_table = awful.util.table or gears.table -- 4.{0,1} compatibility
|
local my_table = awful.util.table or gears.table -- 4.{0,1} compatibility
|
||||||
|
|
||||||
local theme = {}
|
local theme = {}
|
||||||
theme.confdir = os.getenv('HOME') .. '/.config/awesome/'
|
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.font = 'Terminus 8'
|
||||||
theme.menu_bg_normal = '#000000'
|
theme.menu_bg_normal = '#000000'
|
||||||
theme.menu_bg_focus = '#000000'
|
theme.menu_bg_focus = '#000000'
|
||||||
@ -146,29 +162,39 @@ local cpu = lain.widget.cpu({
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local optional = {}
|
||||||
|
|
||||||
-- Coretemp
|
-- Coretemp
|
||||||
--[[local tempicon = wibox.widget.imagebox(theme.widget_temp)
|
if settings['show_temp'] == true then
|
||||||
|
local tempicon = wibox.widget.imagebox(theme.widget_temp)
|
||||||
local temp = lain.widget.temp({
|
local temp = lain.widget.temp({
|
||||||
settings = function()
|
settings = function()
|
||||||
widget:set_markup(markup.fontfg(theme.font, "#f1af5f", coretemp_now .. "°C "))
|
-- 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
|
end
|
||||||
})]]
|
|
||||||
--
|
|
||||||
|
|
||||||
-- Battery
|
-- Battery
|
||||||
--[[local baticon = wibox.widget.imagebox(theme.widget_batt)
|
if settings['show_battery'] == true then
|
||||||
|
local baticon = wibox.widget.imagebox(theme.widget_batt)
|
||||||
local bat = lain.widget.bat({
|
local bat = lain.widget.bat({
|
||||||
settings = function()
|
settings = function()
|
||||||
local perc = bat_now.perc ~= "N/A" and bat_now.perc .. "%" or bat_now.perc
|
-- 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
|
if bat_now.ac_status == 1 then
|
||||||
perc = perc .. " plug"
|
perc = perc .. ' plug'
|
||||||
end
|
end
|
||||||
|
|
||||||
widget:set_markup(markup.fontfg(theme.font, theme.fg_normal, perc .. " "))
|
widget:set_markup(markup.fontfg(theme.font, theme.fg_normal, perc .. ' '))
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
table.insert(optional, baticon)
|
||||||
|
table.insert(optional, bat)
|
||||||
end
|
end
|
||||||
})]]
|
|
||||||
--
|
|
||||||
|
|
||||||
-- ALSA volume
|
-- ALSA volume
|
||||||
local volicon = wibox.widget.imagebox(theme.widget_vol)
|
local volicon = wibox.widget.imagebox(theme.widget_vol)
|
||||||
@ -331,6 +357,7 @@ function theme.at_screen_connect(s)
|
|||||||
},
|
},
|
||||||
s.mytasklist, -- Middle widget
|
s.mytasklist, -- Middle widget
|
||||||
--nil,
|
--nil,
|
||||||
|
gears.table.join(
|
||||||
{ -- Right widgets
|
{ -- Right widgets
|
||||||
layout = wibox.layout.fixed.horizontal,
|
layout = wibox.layout.fixed.horizontal,
|
||||||
wibox.widget.systray(),
|
wibox.widget.systray(),
|
||||||
@ -360,15 +387,13 @@ function theme.at_screen_connect(s)
|
|||||||
cpu.widget,
|
cpu.widget,
|
||||||
fsicon,
|
fsicon,
|
||||||
theme.fs.widget,
|
theme.fs.widget,
|
||||||
--weathericon,
|
},
|
||||||
--theme.weather.widget,
|
optional,
|
||||||
--tempicon,
|
{
|
||||||
--temp.widget,
|
|
||||||
--baticon,
|
|
||||||
--bat.widget,
|
|
||||||
clockicon,
|
clockicon,
|
||||||
mytextclock,
|
mytextclock,
|
||||||
},
|
}
|
||||||
|
),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
BIN
awesome/wall2.png
Normal file
BIN
awesome/wall2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 MiB |
Loading…
Reference in New Issue
Block a user