Added settings.lua
This commit is contained in:
		@@ -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 },
 | 
				
			||||||
@@ -60,9 +60,11 @@ desktop.current_pos = {}
 | 
				
			|||||||
-- @return iterator on input pipe
 | 
					-- @return iterator on input pipe
 | 
				
			||||||
local function pipelines(...)
 | 
					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,13 +105,13 @@ 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))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		icon_container = wibox(common)
 | 
							icon_container = wibox(common)
 | 
				
			||||||
		icon_container:set_widget(icon)
 | 
							icon_container:set_widget(icon)
 | 
				
			||||||
@@ -116,19 +123,19 @@ function desktop.add_single_icon(args, label, icon, onclick)
 | 
				
			|||||||
	if label then
 | 
						if label then
 | 
				
			||||||
		common.width = args.labelsize.width
 | 
							common.width = args.labelsize.width
 | 
				
			||||||
		common.height = args.labelsize.height
 | 
							common.height = args.labelsize.height
 | 
				
			||||||
        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)
 | 
				
			||||||
		caption_container:set_widget(caption)
 | 
							caption_container:set_widget(caption)
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
@@ -143,7 +150,7 @@ end
 | 
				
			|||||||
-- Adds base icons (This PC, Trash, etc) to desktop
 | 
					-- Adds base icons (This PC, Trash, etc) to desktop
 | 
				
			||||||
-- @param args settings from desktop.add_icons
 | 
					-- @param args settings from desktop.add_icons
 | 
				
			||||||
function desktop.add_base_icons(args)
 | 
					function desktop.add_base_icons(args)
 | 
				
			||||||
    for _,base in ipairs(args.baseicons) do
 | 
						for _, base in ipairs(args.baseicons) do
 | 
				
			||||||
		desktop.add_single_icon(args, base.label, utils.lookup_icon(base.icon), function()
 | 
							desktop.add_single_icon(args, base.label, utils.lookup_icon(base.icon), function()
 | 
				
			||||||
			awful.spawn(string.format("%s '%s'", args.open_with, base.onclick))
 | 
								awful.spawn(string.format("%s '%s'", args.open_with, base.onclick))
 | 
				
			||||||
		end)
 | 
							end)
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -196,22 +207,22 @@ end
 | 
				
			|||||||
-- @return files table with found entries
 | 
					-- @return files table with found entries
 | 
				
			||||||
function desktop.parse_dirs_and_files(dir)
 | 
					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,12 +29,12 @@ 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
 | 
				
			||||||
local existent_paths = {}
 | 
					local existent_paths = {}
 | 
				
			||||||
for k,v in pairs(menu_gen.all_menu_dirs) do
 | 
					for k, v in pairs(menu_gen.all_menu_dirs) do
 | 
				
			||||||
	if menu.is_dir(v) then
 | 
						if menu.is_dir(v) then
 | 
				
			||||||
		table.insert(existent_paths, v)
 | 
							table.insert(existent_paths, v)
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
@@ -46,7 +45,7 @@ menu_gen.all_menu_dirs = existent_paths
 | 
				
			|||||||
-- @param tab a given table
 | 
					-- @param tab a given table
 | 
				
			||||||
-- @param val the element to search for
 | 
					-- @param val the element to search for
 | 
				
			||||||
-- @return true if the given string is found within the search table; otherwise, false if not
 | 
					-- @return true if the given string is found within the search table; otherwise, false if not
 | 
				
			||||||
function menu.has_value (tab, val)
 | 
					function menu.has_value(tab, val)
 | 
				
			||||||
	for index, value in pairs(tab) do
 | 
						for index, value in pairs(tab) do
 | 
				
			||||||
		if val:find(value) then
 | 
							if val:find(value) then
 | 
				
			||||||
			return true
 | 
								return true
 | 
				
			||||||
@@ -93,23 +92,31 @@ 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
 | 
				
			||||||
            result = {{sub_menu, result}}
 | 
								result = { { sub_menu, result } }
 | 
				
			||||||
		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
 | 
				
			||||||
@@ -124,7 +127,7 @@ end
 | 
				
			|||||||
-- run a command and execute a function on its output line by line
 | 
					-- run a command and execute a function on its output line by line
 | 
				
			||||||
function helpers.line_callback(cmd, callback)
 | 
					function helpers.line_callback(cmd, callback)
 | 
				
			||||||
	return spawn.with_line_callback(cmd, {
 | 
						return spawn.with_line_callback(cmd, {
 | 
				
			||||||
        stdout = function (line)
 | 
							stdout = function(line)
 | 
				
			||||||
			callback(line)
 | 
								callback(line)
 | 
				
			||||||
		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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -180,19 +185,21 @@ end
 | 
				
			|||||||
-- example: the trivial partition set of {a, b, c}, is {{a}, {b}, {c}}
 | 
					-- example: the trivial partition set of {a, b, c}, is {{a}, {b}, {c}}
 | 
				
			||||||
function helpers.trivial_partition_set(set)
 | 
					function helpers.trivial_partition_set(set)
 | 
				
			||||||
	local ss = {}
 | 
						local ss = {}
 | 
				
			||||||
    for _,e in pairs(set) do
 | 
						for _, e in pairs(set) do
 | 
				
			||||||
        ss[#ss+1] = {e}
 | 
							ss[#ss + 1] = { e }
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
	return ss
 | 
						return ss
 | 
				
			||||||
end
 | 
					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
 | 
				
			||||||
    local t = {{}}
 | 
							return {}
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
						local t = { {} }
 | 
				
			||||||
	for i = 1, #s do
 | 
						for i = 1, #s do
 | 
				
			||||||
		for j = 1, #t do
 | 
							for j = 1, #t do
 | 
				
			||||||
            t[#t+1] = {s[i],unpack(t[j])}
 | 
								t[#t + 1] = { s[i], unpack(t[j]) }
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
	return t
 | 
						return t
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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.
 | 
				
			||||||
@@ -53,7 +55,7 @@ local function do_cascade(p, tiling)
 | 
				
			|||||||
		local current_offset_y = cascade.offset_y * (how_many - 1)
 | 
							local current_offset_y = cascade.offset_y * (how_many - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		-- Iterate.
 | 
							-- Iterate.
 | 
				
			||||||
        for i = 1,#cls,1 do
 | 
							for i = 1, #cls, 1 do
 | 
				
			||||||
			local c = cls[i]
 | 
								local c = cls[i]
 | 
				
			||||||
			local g = {}
 | 
								local g = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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,14 +144,20 @@ 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
 | 
				
			||||||
        for i = 2,#cls do
 | 
								return
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
							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
 | 
				
			||||||
    local width = math.floor(wa.width/num_x)
 | 
						end
 | 
				
			||||||
 | 
						if ncol <= 1 then
 | 
				
			||||||
 | 
							ncol = 1
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
						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:
 | 
				
			||||||
@@ -50,7 +56,7 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
		--   +---+---+---+      +---+---+---+      +---+---+---+
 | 
							--   +---+---+---+      +---+---+---+      +---+---+---+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local num_y = math.max(math.ceil(#cls / num_x), ncol)
 | 
							local num_y = math.max(math.ceil(#cls / num_x), ncol)
 | 
				
			||||||
        local height    = math.floor(wa.height/num_y)
 | 
							local height = math.floor(wa.height / num_y)
 | 
				
			||||||
		local cur_num_x = num_x
 | 
							local cur_num_x = num_x
 | 
				
			||||||
		local at_x = 0
 | 
							local at_x = 0
 | 
				
			||||||
		local at_y = 0
 | 
							local at_y = 0
 | 
				
			||||||
@@ -64,7 +70,7 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
		end
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		-- Iterate in reversed order.
 | 
							-- Iterate in reversed order.
 | 
				
			||||||
        for i = #cls,1,-1 do
 | 
							for i = #cls, 1, -1 do
 | 
				
			||||||
			-- Get x and y position.
 | 
								-- Get x and y position.
 | 
				
			||||||
			local c = cls[i]
 | 
								local c = cls[i]
 | 
				
			||||||
			local this_x = cur_num_x - at_x - 1
 | 
								local this_x = cur_num_x - at_x - 1
 | 
				
			||||||
@@ -73,22 +79,26 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
			-- Calculate geometry.
 | 
								-- Calculate geometry.
 | 
				
			||||||
			local g = {}
 | 
								local g = {}
 | 
				
			||||||
			if this_x == (num_x - 1) then
 | 
								if this_x == (num_x - 1) then
 | 
				
			||||||
                g.width = wa.width - (num_x - 1)*width
 | 
									g.width = wa.width - (num_x - 1) * width
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				g.width = width
 | 
									g.width = width
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if this_y == (num_y - 1) then
 | 
								if this_y == (num_y - 1) then
 | 
				
			||||||
                g.height = wa.height - (num_y - 1)*height
 | 
									g.height = wa.height - (num_y - 1) * height
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				g.height = height
 | 
									g.height = height
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            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:
 | 
				
			||||||
@@ -127,9 +137,9 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
		--   +---+---+---+  ->  +---+---+---+  ->  +---+---+---+
 | 
							--   +---+---+---+  ->  +---+---+---+  ->  +---+---+---+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local num_y = math.max(math.ceil(#cls / num_x), ncol)
 | 
							local num_y = math.max(math.ceil(#cls / num_x), ncol)
 | 
				
			||||||
        local height    = math.floor(wa.height/num_y)
 | 
							local height = math.floor(wa.height / num_y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for i = #cls,1,-1 do
 | 
							for i = #cls, 1, -1 do
 | 
				
			||||||
			-- Get x and y position.
 | 
								-- Get x and y position.
 | 
				
			||||||
			local c = cls[i]
 | 
								local c = cls[i]
 | 
				
			||||||
			local this_x = (i - 1) % num_x
 | 
								local this_x = (i - 1) % num_x
 | 
				
			||||||
@@ -138,26 +148,30 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
			-- Calculate geometry.
 | 
								-- Calculate geometry.
 | 
				
			||||||
			local g = {}
 | 
								local g = {}
 | 
				
			||||||
			if this_x == (num_x - 1) then
 | 
								if this_x == (num_x - 1) then
 | 
				
			||||||
                g.width = wa.width - (num_x - 1)*width
 | 
									g.width = wa.width - (num_x - 1) * width
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				g.width = width
 | 
									g.width = width
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if this_y == (num_y - 1) then
 | 
								if this_y == (num_y - 1) then
 | 
				
			||||||
                g.height = wa.height - (num_y - 1)*height
 | 
									g.height = wa.height - (num_y - 1) * height
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				g.height = height
 | 
									g.height = height
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            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
 | 
				
			||||||
@@ -180,13 +194,17 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if #cls < num_x then
 | 
							if #cls < num_x then
 | 
				
			||||||
			-- Less clients than the number of columns, let's center it!
 | 
								-- Less clients than the number of columns, let's center it!
 | 
				
			||||||
            local offset_x = wa.x + (wa.width - #cls*width) / 2
 | 
								local offset_x = wa.x + (wa.width - #cls * width) / 2
 | 
				
			||||||
			for i = 1, #cls do
 | 
								for i = 1, #cls do
 | 
				
			||||||
				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
 | 
				
			||||||
@@ -194,10 +212,14 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
			-- More clients than the number of columns, let's arrange it!
 | 
								-- More clients than the number of columns, let's arrange it!
 | 
				
			||||||
			-- Master client deserves a special treatement
 | 
								-- Master client deserves a special treatement
 | 
				
			||||||
			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
 | 
				
			||||||
@@ -206,30 +228,30 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			-- Compute distribution of clients among columns
 | 
								-- Compute distribution of clients among columns
 | 
				
			||||||
			local num_y = {}
 | 
								local num_y = {}
 | 
				
			||||||
            local remaining_clients = #cls-1
 | 
								local remaining_clients = #cls - 1
 | 
				
			||||||
            local ncol_min = math.ceil(remaining_clients/(num_x-1))
 | 
								local ncol_min = math.ceil(remaining_clients / (num_x - 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ncol >= ncol_min then
 | 
								if ncol >= ncol_min then
 | 
				
			||||||
                for i = (num_x-1), 1, -1 do
 | 
									for i = (num_x - 1), 1, -1 do
 | 
				
			||||||
                    if (remaining_clients-i+1) < ncol then
 | 
										if (remaining_clients - i + 1) < ncol then
 | 
				
			||||||
                        num_y[i] = remaining_clients-i + 1
 | 
											num_y[i] = remaining_clients - i + 1
 | 
				
			||||||
					else
 | 
										else
 | 
				
			||||||
						num_y[i] = ncol
 | 
											num_y[i] = ncol
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
					remaining_clients = remaining_clients - num_y[i]
 | 
										remaining_clients = remaining_clients - num_y[i]
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
                local rem = remaining_clients % (num_x-1)
 | 
									local rem = remaining_clients % (num_x - 1)
 | 
				
			||||||
				if rem == 0 then
 | 
									if rem == 0 then
 | 
				
			||||||
                    for i = 1, num_x-1 do
 | 
										for i = 1, num_x - 1 do
 | 
				
			||||||
						num_y[i] = ncol_min
 | 
											num_y[i] = ncol_min
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
                    for i = 1, num_x-1 do
 | 
										for i = 1, num_x - 1 do
 | 
				
			||||||
						num_y[i] = ncol_min - 1
 | 
											num_y[i] = ncol_min - 1
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
                    for i = 0, rem-1 do
 | 
										for i = 0, rem - 1 do
 | 
				
			||||||
                        num_y[num_x-1-i] = num_y[num_x-1-i] + 1
 | 
											num_y[num_x - 1 - i] = num_y[num_x - 1 - i] + 1
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
@@ -237,17 +259,21 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
			-- Compute geometry of the other clients
 | 
								-- Compute geometry of the other clients
 | 
				
			||||||
			local nclient = 2 -- we start with the 2nd client
 | 
								local nclient = 2 -- we start with the 2nd client
 | 
				
			||||||
			local wx = g.x + g.width
 | 
								local wx = g.x + g.width
 | 
				
			||||||
            for i = 1, (num_x-1) do
 | 
								for i = 1, (num_x - 1) do
 | 
				
			||||||
				local height = math.floor(wa.height / num_y[i])
 | 
									local height = math.floor(wa.height / num_y[i])
 | 
				
			||||||
				local wy = wa.y
 | 
									local wy = wa.y
 | 
				
			||||||
                for _ = 0, (num_y[i]-2) do
 | 
									for _ = 0, (num_y[i] - 2) do
 | 
				
			||||||
					g = {}
 | 
										g = {}
 | 
				
			||||||
					g.x = wx
 | 
										g.x = wx
 | 
				
			||||||
					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
 | 
				
			||||||
@@ -255,10 +281,14 @@ local function do_fair(p, orientation)
 | 
				
			|||||||
				g = {}
 | 
									g = {}
 | 
				
			||||||
				g.x = wx
 | 
									g.x = wx
 | 
				
			||||||
				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 = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,20 +65,24 @@ end
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
_ENV = nil -- blocking globals in Lua 5.2 and later
 | 
					_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)
 | 
				
			||||||
	local max, n, arraylen = 0, 0, 0
 | 
						local max, n, arraylen = 0, 0, 0
 | 
				
			||||||
  for k,v in pairs (tbl) do
 | 
						for k, v in pairs(tbl) do
 | 
				
			||||||
		if k == 'n' and type(v) == 'number' then
 | 
							if k == 'n' and type(v) == 'number' then
 | 
				
			||||||
			arraylen = v
 | 
								arraylen = v
 | 
				
			||||||
			if v > max then
 | 
								if v > max then
 | 
				
			||||||
@@ -102,16 +105,21 @@ 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)
 | 
				
			||||||
	local value = escapecodes[uchar]
 | 
						local value = escapecodes[uchar]
 | 
				
			||||||
	if value then
 | 
						if value then
 | 
				
			||||||
		return value
 | 
							return value
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
  local a, b, c, d = strbyte (uchar, 1, 4)
 | 
						local a, b, c, d = strbyte(uchar, 1, 4)
 | 
				
			||||||
	a, b, c, d = a or 0, b or 0, c or 0, d or 0
 | 
						a, b, c, d = a or 0, b or 0, c or 0, d or 0
 | 
				
			||||||
	if a <= 0x7f then
 | 
						if a <= 0x7f then
 | 
				
			||||||
		value = a
 | 
							value = a
 | 
				
			||||||
@@ -122,52 +130,52 @@ 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function fsub (str, pattern, repl)
 | 
					local function fsub(str, pattern, repl)
 | 
				
			||||||
	-- gsub always builds a new string in a buffer, even when no match
 | 
						-- gsub always builds a new string in a buffer, even when no match
 | 
				
			||||||
	-- exists. First using find should be more efficient when most strings
 | 
						-- exists. First using find should be more efficient when most strings
 | 
				
			||||||
	-- don't contain the pattern.
 | 
						-- don't contain the pattern.
 | 
				
			||||||
  if strfind (str, pattern) then
 | 
						if strfind(str, pattern) then
 | 
				
			||||||
    return gsub (str, pattern, repl)
 | 
							return gsub(str, pattern, repl)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return str
 | 
							return str
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
end
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function replace(str, o, n)
 | 
					local function replace(str, o, n)
 | 
				
			||||||
  local i, j = strfind (str, o, 1, true)
 | 
						local i, j = strfind(str, o, 1, true)
 | 
				
			||||||
	if i then
 | 
						if i then
 | 
				
			||||||
    return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1)
 | 
							return strsub(str, 1, i - 1) .. n .. strsub(str, j + 1, -1)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return str
 | 
							return str
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
@@ -176,63 +184,62 @@ end
 | 
				
			|||||||
-- locale independent num2str and str2num functions
 | 
					-- locale independent num2str and str2num functions
 | 
				
			||||||
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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local encode2 -- forward declaration
 | 
					local encode2 -- forward declaration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state)
 | 
					local function addpair(key, value, prev, indent, level, buffer, buflen, tables, globalorder, state)
 | 
				
			||||||
  local kt = type (key)
 | 
						local kt = type(key)
 | 
				
			||||||
	if kt ~= 'string' and kt ~= 'number' then
 | 
						if kt ~= 'string' and kt ~= 'number' then
 | 
				
			||||||
		return nil, "type '" .. kt .. "' is not supported as a key by JSON."
 | 
							return nil, "type '" .. kt .. "' is not supported as a key by JSON."
 | 
				
			||||||
	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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function appendcustom(res, buffer, state)
 | 
					local function appendcustom(res, buffer, state)
 | 
				
			||||||
	local buflen = state.bufferlen
 | 
						local buflen = state.bufferlen
 | 
				
			||||||
  if type (res) == 'string' then
 | 
						if type(res) == 'string' then
 | 
				
			||||||
		buflen = buflen + 1
 | 
							buflen = buflen + 1
 | 
				
			||||||
		buffer[buflen] = res
 | 
							buffer[buflen] = res
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
@@ -246,20 +253,22 @@ local function exception(reason, value, state, buffer, buflen, defaultmessage)
 | 
				
			|||||||
		return nil, defaultmessage
 | 
							return nil, 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)
 | 
				
			||||||
  local valtype = type (value)
 | 
						local valtype = type(value)
 | 
				
			||||||
  local valmeta = getmetatable (value)
 | 
						local valmeta = getmetatable(value)
 | 
				
			||||||
  valmeta = type (valmeta) == 'table' and valmeta -- only tables
 | 
						valmeta = type(valmeta) == 'table' and valmeta -- only tables
 | 
				
			||||||
	local valtojson = valmeta and valmeta.__tojson
 | 
						local valtojson = valmeta and valmeta.__tojson
 | 
				
			||||||
	if valtojson then
 | 
						if valtojson then
 | 
				
			||||||
		if tables[value] then
 | 
							if tables[value] then
 | 
				
			||||||
@@ -267,57 +276,61 @@ encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, s
 | 
				
			|||||||
		end
 | 
							end
 | 
				
			||||||
		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
 | 
				
			||||||
		buflen = buflen + 1
 | 
							buflen = buflen + 1
 | 
				
			||||||
		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)
 | 
				
			||||||
	elseif valtype == 'table' then
 | 
						elseif valtype == 'table' then
 | 
				
			||||||
		if tables[value] then
 | 
							if tables[value] then
 | 
				
			||||||
			return exception('reference cycle', value, state, buffer, buflen)
 | 
								return exception('reference cycle', value, state, buffer, buflen)
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
		tables[value] = true
 | 
							tables[value] = true
 | 
				
			||||||
		level = level + 1
 | 
							level = level + 1
 | 
				
			||||||
    local isa, n = isarray (value)
 | 
							local isa, n = isarray(value)
 | 
				
			||||||
		if n == 0 and valmeta and valmeta.__jsontype == 'object' then
 | 
							if n == 0 and valmeta and valmeta.__jsontype == 'object' then
 | 
				
			||||||
			isa = false
 | 
								isa = false
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
		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 = {}
 | 
				
			||||||
@@ -327,62 +340,80 @@ encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, s
 | 
				
			|||||||
					local v = value[k]
 | 
										local v = value[k]
 | 
				
			||||||
					if v ~= nil then
 | 
										if v ~= nil then
 | 
				
			||||||
						used[k] = true
 | 
											used[k] = true
 | 
				
			||||||
            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)
 | 
				
			||||||
						prev = true -- add a seperator before the next element
 | 
											prev = true -- add a seperator before the next element
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
        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
 | 
				
			||||||
			if indent then
 | 
								if indent then
 | 
				
			||||||
        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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function json.encode (value, state)
 | 
					function json.encode(value, state)
 | 
				
			||||||
	state = state or {}
 | 
						state = state or {}
 | 
				
			||||||
	local oldbuffer = state.buffer
 | 
						local oldbuffer = state.buffer
 | 
				
			||||||
	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
 | 
				
			||||||
		state.bufferlen = ret
 | 
							state.bufferlen = ret
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		state.bufferlen = nil
 | 
							state.bufferlen = nil
 | 
				
			||||||
		state.buffer = nil
 | 
							state.buffer = nil
 | 
				
			||||||
    return concat (buffer)
 | 
							return concat(buffer)
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
end
 | 
					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
 | 
				
			||||||
    local sub2 = strsub (str, pos, pos + 1)
 | 
								return nil
 | 
				
			||||||
    if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then
 | 
							end
 | 
				
			||||||
 | 
							local sub2 = strsub(str, pos, pos + 1)
 | 
				
			||||||
 | 
							if sub2 == '\239\187' and strsub(str, pos + 2, pos + 2) == '\191' then
 | 
				
			||||||
			-- UTF-8 Byte Order Mark
 | 
								-- 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,59 +457,64 @@ 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)
 | 
				
			||||||
	if value < 0 then
 | 
						if value < 0 then
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	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(
 | 
				
			||||||
                    0x80 + (floor(value/0x1000) % 0x40),
 | 
								0xf0 + floor(value / 0x40000),
 | 
				
			||||||
                    0x80 + (floor(value/0x40) % 0x40),
 | 
								0x80 + (floor(value / 0x1000) % 0x40),
 | 
				
			||||||
                    0x80 + (floor(value) % 0x40))
 | 
								0x80 + (floor(value / 0x40) % 0x40),
 | 
				
			||||||
 | 
								0x80 + (floor(value) % 0x40)
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function scanstring (str, pos)
 | 
					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
 | 
				
			||||||
							else
 | 
												else
 | 
				
			||||||
@@ -480,7 +522,7 @@ local function scanstring (str, pos)
 | 
				
			|||||||
							end
 | 
												end
 | 
				
			||||||
						end
 | 
											end
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
          value = value and unichar (value)
 | 
										value = value and unichar(value)
 | 
				
			||||||
					if value then
 | 
										if value then
 | 
				
			||||||
						if value2 then
 | 
											if value2 then
 | 
				
			||||||
							lastpos = nextpos + 12
 | 
												lastpos = nextpos + 12
 | 
				
			||||||
@@ -501,178 +543,190 @@ local function scanstring (str, pos)
 | 
				
			|||||||
	if n == 1 then
 | 
						if n == 1 then
 | 
				
			||||||
		return buffer[1], lastpos
 | 
							return buffer[1], lastpos
 | 
				
			||||||
	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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local scanvalue -- forward declaration
 | 
					local scanvalue -- forward declaration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta)
 | 
					local function scantable(what, closechar, str, startpos, nullval, objectmeta, arraymeta)
 | 
				
			||||||
	local tbl, n = {}, 0
 | 
						local tbl, n = {}, 0
 | 
				
			||||||
	local pos = startpos + 1
 | 
						local pos = startpos + 1
 | 
				
			||||||
	if what == 'object' then
 | 
						if what == 'object' then
 | 
				
			||||||
    setmetatable (tbl, objectmeta)
 | 
							setmetatable(tbl, objectmeta)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
    setmetatable (tbl, arraymeta)
 | 
							setmetatable(tbl, arraymeta)
 | 
				
			||||||
	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
 | 
				
			||||||
    local char = strsub (str, pos, pos)
 | 
								return unterminated(str, what, startpos)
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
							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
 | 
				
			||||||
    pos = scanwhite (str, pos)
 | 
								return nil, pos, err
 | 
				
			||||||
    if not pos then return unterminated (str, what, startpos) end
 | 
							end
 | 
				
			||||||
    char = strsub (str, pos, pos)
 | 
							pos = scanwhite(str, pos)
 | 
				
			||||||
    if char == ":" then
 | 
							if not pos then
 | 
				
			||||||
      if val1 == nil then
 | 
								return unterminated(str, what, startpos)
 | 
				
			||||||
        return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
 | 
							end
 | 
				
			||||||
 | 
							char = strsub(str, pos, pos)
 | 
				
			||||||
 | 
							if char == ':' then
 | 
				
			||||||
 | 
								if val1 == nil then
 | 
				
			||||||
 | 
									return nil, pos, 'cannot use nil as table index (at ' .. loc(str, pos) .. ')'
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
								pos = scanwhite(str, pos + 1)
 | 
				
			||||||
 | 
								if not pos then
 | 
				
			||||||
 | 
									return unterminated(str, what, startpos)
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
      pos = scanwhite (str, pos + 1)
 | 
					 | 
				
			||||||
      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
 | 
				
			||||||
      char = strsub (str, pos, pos)
 | 
									return unterminated(str, what, startpos)
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
								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
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
 | 
					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' }
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function json.decode (str, pos, nullval, ...)
 | 
					function json.decode(str, pos, nullval, ...)
 | 
				
			||||||
	local objectmeta, arraymeta = optionalmetatables(...)
 | 
						local objectmeta, arraymeta = optionalmetatables(...)
 | 
				
			||||||
  return scanvalue (str, pos, nullval, objectmeta, arraymeta)
 | 
						return scanvalue(str, pos, nullval, objectmeta, arraymeta)
 | 
				
			||||||
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
 | 
				
			||||||
	local P, S, R = g.P, g.S, g.R
 | 
						local P, S, R = g.P, g.S, g.R
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  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
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local function Err (msg)
 | 
						local function Err(msg)
 | 
				
			||||||
    return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall)
 | 
							return g.Cmt(g.Cc(msg) * g.Carg(2), ErrorCall)
 | 
				
			||||||
	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
 | 
				
			||||||
      return true, unichar ((high - 0xD800)  * 0x400 + (low - 0xDC00) + 0x10000)
 | 
								return true, unichar((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			return false
 | 
								return false
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
  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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	-- The functions parsearray and parseobject parse only a single value/pair
 | 
						-- The functions parsearray and parseobject parse only a single value/pair
 | 
				
			||||||
	-- at a time and store them directly to avoid hitting the LPeg limits.
 | 
						-- at a time and store them directly to avoid hitting the LPeg limits.
 | 
				
			||||||
  local function parsearray (str, pos, nullval, state)
 | 
						local function parsearray(str, pos, nullval, state)
 | 
				
			||||||
		local obj, cont
 | 
							local obj, cont
 | 
				
			||||||
		local start = pos
 | 
							local start = pos
 | 
				
			||||||
		local npos
 | 
							local npos
 | 
				
			||||||
		local t, nt = {}, 0
 | 
							local t, nt = {}, 0
 | 
				
			||||||
		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
 | 
				
			||||||
@@ -680,38 +734,45 @@ function json.use_lpeg ()
 | 
				
			|||||||
				t[nt] = obj
 | 
									t[nt] = obj
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		until cont ~= 'cont'
 | 
							until cont ~= 'cont'
 | 
				
			||||||
    return pos, setmetatable (t, state.arraymeta)
 | 
							return pos, setmetatable(t, state.arraymeta)
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local function parseobject (str, pos, nullval, state)
 | 
						local function parseobject(str, pos, nullval, state)
 | 
				
			||||||
		local obj, key, cont
 | 
							local obj, key, cont
 | 
				
			||||||
		local start = pos
 | 
							local start = pos
 | 
				
			||||||
		local npos
 | 
							local npos
 | 
				
			||||||
		local t = {}
 | 
							local t = {}
 | 
				
			||||||
		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
 | 
				
			||||||
				t[key] = obj
 | 
									t[key] = obj
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
		until cont ~= 'cont'
 | 
							until cont ~= 'cont'
 | 
				
			||||||
    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)
 | 
				
			||||||
  local DecodeValue = ExpectedValue * g.Cp ()
 | 
						) * g.Cp()
 | 
				
			||||||
 | 
						local Pair = g.Cg(Space * ExpectedKey * Space * (P(':') + Err('colon expected')) * ExpectedValue)
 | 
				
			||||||
 | 
						ObjectContent = (
 | 
				
			||||||
 | 
							g.Cc(nil) * g.Cc(nil) * P('}') * g.Cc('empty')
 | 
				
			||||||
 | 
							+ End
 | 
				
			||||||
 | 
							+ (Pair * Space * (P(',') * g.Cc('cont') + P('}') * g.Cc('last') + End + ErrInvalid) + ErrInvalid)
 | 
				
			||||||
 | 
						) * g.Cp()
 | 
				
			||||||
 | 
						local DecodeValue = ExpectedValue * g.Cp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	jsonlpeg.version = json.version
 | 
						jsonlpeg.version = json.version
 | 
				
			||||||
	jsonlpeg.encode = json.encode
 | 
						jsonlpeg.encode = json.encode
 | 
				
			||||||
@@ -721,10 +782,10 @@ function json.use_lpeg ()
 | 
				
			|||||||
	jsonlpeg.encodeexception = json.encodeexception
 | 
						jsonlpeg.encodeexception = json.encodeexception
 | 
				
			||||||
	jsonlpeg.using_lpeg = true
 | 
						jsonlpeg.using_lpeg = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function jsonlpeg.decode (str, pos, nullval, ...)
 | 
						function jsonlpeg.decode(str, pos, nullval, ...)
 | 
				
			||||||
		local state = {}
 | 
							local state = {}
 | 
				
			||||||
		state.objectmeta, state.arraymeta = optionalmetatables(...)
 | 
							state.objectmeta, state.arraymeta = optionalmetatables(...)
 | 
				
			||||||
    local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state)
 | 
							local obj, retpos = pegmatch(DecodeValue, str, pos, nullval, state)
 | 
				
			||||||
		if state.msg then
 | 
							if state.msg then
 | 
				
			||||||
			return nil, state.pos, state.msg
 | 
								return nil, state.pos, state.msg
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
@@ -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,51 +11,59 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
--]]
 | 
					--]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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 = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	-- For each selected tag get all clients of that tag and add them to
 | 
						-- For each selected tag get all clients of that tag and add them to
 | 
				
			||||||
	-- the menu. A click on a menu item will raise that client.
 | 
						-- the menu. A click on a menu item will raise that client.
 | 
				
			||||||
    for i = 1,#cls_tags do
 | 
						for i = 1, #cls_tags do
 | 
				
			||||||
		local t = cls_tags[i]
 | 
							local t = cls_tags[i]
 | 
				
			||||||
		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] = {
 | 
				
			||||||
                                  function ()
 | 
									awful.util.escape(c.name) or '',
 | 
				
			||||||
 | 
									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,12 +101,14 @@ 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
 | 
				
			||||||
-- direction in {-1, 1} <-> {previous, next} non-empty tag
 | 
					-- direction in {-1, 1} <-> {previous, next} non-empty tag
 | 
				
			||||||
function util.tag_view_nonempty(direction,sc)
 | 
					function util.tag_view_nonempty(direction, sc)
 | 
				
			||||||
	direction = direction or 1
 | 
						direction = direction or 1
 | 
				
			||||||
	local s = sc or awful.screen.focused()
 | 
						local s = sc or awful.screen.focused()
 | 
				
			||||||
	local tags = s.tags
 | 
						local tags = s.tags
 | 
				
			||||||
@@ -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
 | 
				
			||||||
@@ -25,9 +25,11 @@ local function naughty_destroy_callback(reason)
 | 
				
			|||||||
	if reason == closed.expired or reason == closed.dismissedByUser then
 | 
						if reason == closed.expired or reason == closed.dismissedByUser then
 | 
				
			||||||
		local actions = state.index and state.menu[state.index - 1][2]
 | 
							local actions = state.index and state.menu[state.index - 1][2]
 | 
				
			||||||
		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,40 +103,45 @@ 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] } })
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local m = {} -- the menu
 | 
						local m = {} -- the menu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for _,c in pairs(ch_combinations) do
 | 
						for _, c in pairs(ch_combinations) do
 | 
				
			||||||
		if #c > 0 then
 | 
							if #c > 0 then
 | 
				
			||||||
			local cbs = {}
 | 
								local cbs = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			-- 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			-- add user extra choices (like the choice "None" for example)
 | 
								-- add user extra choices (like the choice "None" for example)
 | 
				
			||||||
            for _,x in pairs(extra_choices) do
 | 
								for _, x in pairs(extra_choices) do
 | 
				
			||||||
				if x[1] == c[1] then
 | 
									if x[1] == c[1] then
 | 
				
			||||||
					cbs[#cbs + 1] = x[2]
 | 
										cbs[#cbs + 1] = x[2]
 | 
				
			||||||
				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
 | 
				
			||||||
@@ -80,7 +86,7 @@ function quake:display()
 | 
				
			|||||||
		client.fullscreen = self.fullscreen
 | 
							client.fullscreen = self.fullscreen
 | 
				
			||||||
		client:raise()
 | 
							client:raise()
 | 
				
			||||||
		self.last_tag = self.screen.selected_tag
 | 
							self.last_tag = self.screen.selected_tag
 | 
				
			||||||
        client:tags({self.screen.selected_tag})
 | 
							client:tags({ self.screen.selected_tag })
 | 
				
			||||||
		capi.client.focus = client
 | 
							capi.client.focus = client
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		self.maximized = maximized
 | 
							self.maximized = maximized
 | 
				
			||||||
@@ -108,25 +114,39 @@ 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()
 | 
				
			||||||
		if c then
 | 
							if c then
 | 
				
			||||||
			c:move_to_tag(current_tag)
 | 
								c:move_to_tag(current_tag)
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
@@ -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,32 +29,32 @@ 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)
 | 
				
			||||||
            cr:line_to(width, height/2)
 | 
								cr:line_to(width, height / 2)
 | 
				
			||||||
			cr:line_to(width, 0)
 | 
								cr:line_to(width, 0)
 | 
				
			||||||
			cr:close_path()
 | 
								cr:close_path()
 | 
				
			||||||
			cr:fill()
 | 
								cr:fill()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			cr:new_path()
 | 
								cr:new_path()
 | 
				
			||||||
			cr:move_to(0, height)
 | 
								cr:move_to(0, height)
 | 
				
			||||||
            cr:line_to(width, height/2)
 | 
								cr:line_to(width, height / 2)
 | 
				
			||||||
			cr:line_to(width, height)
 | 
								cr:line_to(width, height)
 | 
				
			||||||
			cr:close_path()
 | 
								cr:close_path()
 | 
				
			||||||
			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)
 | 
				
			||||||
            cr:line_to(width, height/2)
 | 
								cr:line_to(width, height / 2)
 | 
				
			||||||
			cr:line_to(0, height)
 | 
								cr:line_to(0, height)
 | 
				
			||||||
			cr:close_path()
 | 
								cr:close_path()
 | 
				
			||||||
			cr:fill()
 | 
								cr:fill()
 | 
				
			||||||
@@ -77,31 +77,31 @@ 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)
 | 
				
			||||||
            cr:line_to(0, height/2)
 | 
								cr:line_to(0, height / 2)
 | 
				
			||||||
			cr:line_to(0, 0)
 | 
								cr:line_to(0, 0)
 | 
				
			||||||
			cr:close_path()
 | 
								cr:close_path()
 | 
				
			||||||
			cr:fill()
 | 
								cr:fill()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			cr:new_path()
 | 
								cr:new_path()
 | 
				
			||||||
			cr:move_to(width, height)
 | 
								cr:move_to(width, height)
 | 
				
			||||||
            cr:line_to(0, height/2)
 | 
								cr:line_to(0, height / 2)
 | 
				
			||||||
			cr:line_to(0, height)
 | 
								cr:line_to(0, height)
 | 
				
			||||||
			cr:close_path()
 | 
								cr:close_path()
 | 
				
			||||||
			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)
 | 
				
			||||||
			cr:line_to(width, height)
 | 
								cr:line_to(width, height)
 | 
				
			||||||
			cr:close_path()
 | 
								cr:close_path()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
@@ -184,18 +185,18 @@ local function factory(args)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					if 0 < rate_time and rate_time < 0.01 then -- check for magnitude discrepancies (#199)
 | 
										if 0 < rate_time and rate_time < 0.01 then -- check for magnitude discrepancies (#199)
 | 
				
			||||||
						rate_time_magnitude = math.abs(math.floor(math.log10(rate_time)))
 | 
											rate_time_magnitude = math.abs(math.floor(math.log10(rate_time)))
 | 
				
			||||||
                        rate_time = rate_time * 10^(rate_time_magnitude - 2)
 | 
											rate_time = rate_time * 10 ^ (rate_time_magnitude - 2)
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				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,12 +26,12 @@ 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
 | 
				
			||||||
			widget_focused = false
 | 
								widget_focused = false
 | 
				
			||||||
            for _,v in ipairs(mouse.current_widgets) do
 | 
								for _, v in ipairs(mouse.current_widgets) do
 | 
				
			||||||
				if task.widget == v then
 | 
									if task.widget == v then
 | 
				
			||||||
					widget_focused = true
 | 
										widget_focused = true
 | 
				
			||||||
					break
 | 
										break
 | 
				
			||||||
@@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,18 +94,18 @@ local function factory(args)
 | 
				
			|||||||
				local free = info:get_attribute_uint64(query_free)
 | 
									local free = info:get_attribute_uint64(query_free)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if size > 0 then
 | 
									if size > 0 then
 | 
				
			||||||
                    local units = math.floor(math.log(size)/math.log(1024))
 | 
										local units = math.floor(math.log(size) / math.log(1024))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					fs_now[path] = {
 | 
										fs_now[path] = {
 | 
				
			||||||
						units = fs.units[units],
 | 
											units = fs.units[units],
 | 
				
			||||||
						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
 | 
				
			||||||
                        notifypaths[#notifypaths+1] = path
 | 
											notifypaths[#notifypaths + 1] = path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						if #path > pathlen then
 | 
											if #path > pathlen then
 | 
				
			||||||
							pathlen = #path
 | 
												pathlen = #path
 | 
				
			||||||
@@ -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,32 +17,32 @@ 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)
 | 
				
			||||||
                    temp_now[t] = temp_value and temp_value/1e3 or temp_fl
 | 
										temp_now[t] = temp_value and temp_value / 1e3 or temp_fl
 | 
				
			||||||
				end
 | 
									end
 | 
				
			||||||
			end
 | 
								end
 | 
				
			||||||
			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 temp = lain.widget.temp({
 | 
						local tempicon = wibox.widget.imagebox(theme.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
 | 
				
			||||||
    end
 | 
								widget:set_markup(markup.fontfg(theme.font, '#f1af5f', coretemp_now .. '°C '))
 | 
				
			||||||
})]]
 | 
							end,
 | 
				
			||||||
--
 | 
						})
 | 
				
			||||||
 | 
						table.insert(optional, tempicon)
 | 
				
			||||||
 | 
						table.insert(optional, temp)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- Battery
 | 
					-- Battery
 | 
				
			||||||
--[[local baticon = wibox.widget.imagebox(theme.widget_batt)
 | 
					if settings['show_battery'] == true then
 | 
				
			||||||
local bat = lain.widget.bat({
 | 
						local baticon = wibox.widget.imagebox(theme.widget_batt)
 | 
				
			||||||
 | 
						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
 | 
							end,
 | 
				
			||||||
})]]
 | 
						})
 | 
				
			||||||
--
 | 
						table.insert(optional, baticon)
 | 
				
			||||||
 | 
						table.insert(optional, bat)
 | 
				
			||||||
 | 
					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  | 
		Reference in New Issue
	
	Block a user