diff --git a/README.rst b/README.rst index 422b786..c0eef21 100644 --- a/README.rst +++ b/README.rst @@ -28,7 +28,7 @@ If you want to create a pull request, make sure that: - Your code fits with the general style of the module. In particular, you should use the same indentation pattern that the code uses, and also avoid adding space at the ends of lines. -- Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions to or using lain.helpers_. If something is unclear, or you can not write it in such a way that it will be clear, explain it with a comment. +- Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions to or using lina.helpers_. If something is unclear, or you can not write it in such a way that it will be clear, explina it with a comment. - You test your changes before submitting to make sure that your code works and does not break other parts of the module. diff --git a/helpers.lua b/helpers.lua index ef9e08b..231a79b 100644 --- a/helpers.lua +++ b/helpers.lua @@ -15,13 +15,13 @@ local rawget = rawget local tsort = table.sort local unpack = unpack or table.unpack -- lua 5.1 retro-compatibility --- Lain helper functions for internal use --- lain.helpers +-- Lina helper functions for internal use +-- lina.helpers local helpers = {} -helpers.lain_dir = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]] -helpers.icons_dir = helpers.lain_dir .. 'icons/' -helpers.scripts_dir = helpers.lain_dir .. 'scripts/' +helpers.lina_dir = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]] +helpers.icons_dir = helpers.lina_dir .. 'icons/' +helpers.scripts_dir = helpers.lina_dir .. 'scripts/' -- {{{ Modules loader diff --git a/init.lua b/init.lua index 321d063..95899e7 100644 --- a/init.lua +++ b/init.lua @@ -1,6 +1,6 @@ --[[ - Lain + Lina Layouts, widgets and utilities for Awesome WM Licensed under GNU General Public License v2 diff --git a/layout/init.lua b/layout/init.lua index 6478b06..0bcd0fc 100644 --- a/layout/init.lua +++ b/layout/init.lua @@ -1,6 +1,6 @@ --[[ - Lain + Lina Layouts, widgets and utilities for Awesome WM Layouts section @@ -11,9 +11,9 @@ --]] -local wrequire = require("lain.helpers").wrequire +local wrequire = require("lina.helpers").wrequire local setmetatable = setmetatable -local layout = { _NAME = "lain.layout" } +local layout = { _NAME = "lina.layout" } return setmetatable(layout, { __index = wrequire }) diff --git a/util/dkjson.lua b/util/dkjson.lua index 61cccb9..62ed58e 100644 --- a/util/dkjson.lua +++ b/util/dkjson.lua @@ -1,7 +1,7 @@ -- Module options: local always_use_lpeg = false local register_global_module_table = false -local global_module_name = 'json' +local global_module_name = "json" --[==[ @@ -43,12 +43,11 @@ SOFTWARE. -- global dependencies: local pairs, type, tostring, tonumber, getmetatable, setmetatable = - pairs, type, tostring, tonumber, getmetatable, setmetatable + pairs, type, tostring, tonumber, getmetatable, setmetatable local error, require, pcall, select = error, require, pcall, select local floor, huge = math.floor, math.huge local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat = - string.rep, string.gsub, string.sub, string.byte, string.char, - string.find, string.len, string.format + string.rep, string.gsub, string.sub, string.byte, string.char, string.find, string.len, string.format local strmatch = string.match local concat = table.concat @@ -57,691 +56,754 @@ local json = { version = "dkjson 2.6" } local jsonlpeg = {} if register_global_module_table then - if always_use_lpeg then - _G[global_module_name] = jsonlpeg - else - _G[global_module_name] = json - end + if always_use_lpeg then + _G[global_module_name] = jsonlpeg + else + _G[global_module_name] = json + end end _ENV = nil -- blocking globals in Lua 5.2 and later -pcall (function() - -- Enable access to blocked metatables. - -- Don't worry, this module doesn't change anything in them. - local debmeta = require "debug".getmetatable - if debmeta then getmetatable = debmeta end +pcall(function() + -- Enable access to blocked metatables. + -- Don't worry, this module doesn't change anything in them. + local debmeta = require("debug").getmetatable + if debmeta then + getmetatable = debmeta + end end) -json.null = setmetatable ({}, { - __tojson = function () return "null" end +json.null = setmetatable({}, { + __tojson = function() + return "null" + end, }) -local function isarray (tbl) - local max, n, arraylen = 0, 0, 0 - for k,v in pairs (tbl) do - if k == 'n' and type(v) == 'number' then - arraylen = v - if v > max then - max = v - end - else - if type(k) ~= 'number' or k < 1 or floor(k) ~= k then - return false - end - if k > max then - max = k - end - n = n + 1 - end - end - if max > 10 and max > arraylen and max > n * 2 then - return false -- don't create an array with too many holes - end - return true, max +local function isarray(tbl) + local max, n, arraylen = 0, 0, 0 + for k, v in pairs(tbl) do + if k == "n" and type(v) == "number" then + arraylen = v + if v > max then + max = v + end + else + if type(k) ~= "number" or k < 1 or floor(k) ~= k then + return false + end + if k > max then + max = k + end + n = n + 1 + end + end + if max > 10 and max > arraylen and max > n * 2 then + return false -- don't create an array with too many holes + end + return true, max end local escapecodes = { - ["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f", - ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t" + ['"'] = '\\"', + ["\\"] = "\\\\", + ["\b"] = "\\b", + ["\f"] = "\\f", + ["\n"] = "\\n", + ["\r"] = "\\r", + ["\t"] = "\\t", } -local function escapeutf8 (uchar) - local value = escapecodes[uchar] - if value then - return value - end - local a, b, c, d = strbyte (uchar, 1, 4) - a, b, c, d = a or 0, b or 0, c or 0, d or 0 - if a <= 0x7f then - value = a - elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then - value = (a - 0xc0) * 0x40 + b - 0x80 - elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then - value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80 - elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then - value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80 - else - return "" - end - if value <= 0xffff then - return strformat ("\\u%.4x", value) - elseif value <= 0x10ffff then - -- encode as UTF-16 surrogate pair - value = value - 0x10000 - local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400) - return strformat ("\\u%.4x\\u%.4x", highsur, lowsur) - else - return "" - end +local function escapeutf8(uchar) + local value = escapecodes[uchar] + if value then + return value + end + local a, b, c, d = strbyte(uchar, 1, 4) + a, b, c, d = a or 0, b or 0, c or 0, d or 0 + if a <= 0x7f then + value = a + elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then + value = (a - 0xc0) * 0x40 + b - 0x80 + elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then + value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80 + elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then + value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80 + else + return "" + end + if value <= 0xffff then + return strformat("\\u%.4x", value) + elseif value <= 0x10ffff then + -- encode as UTF-16 surrogate pair + value = value - 0x10000 + local highsur, lowsur = 0xD800 + floor(value / 0x400), 0xDC00 + (value % 0x400) + return strformat("\\u%.4x\\u%.4x", highsur, lowsur) + else + return "" + end end -local function fsub (str, pattern, repl) - -- gsub always builds a new string in a buffer, even when no match - -- exists. First using find should be more efficient when most strings - -- don't contain the pattern. - if strfind (str, pattern) then - return gsub (str, pattern, repl) - else - return str - end +local function fsub(str, pattern, repl) + -- gsub always builds a new string in a buffer, even when no match + -- exists. First using find should be more efficient when most strings + -- don't contain the pattern. + if strfind(str, pattern) then + return gsub(str, pattern, repl) + else + return str + end end -local function quotestring (value) - -- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js - value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8) - if strfind (value, "[\194\216\220\225\226\239]") then - value = fsub (value, "\194[\128-\159\173]", escapeutf8) - value = fsub (value, "\216[\128-\132]", escapeutf8) - value = fsub (value, "\220\143", escapeutf8) - value = fsub (value, "\225\158[\180\181]", escapeutf8) - value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8) - value = fsub (value, "\226\129[\160-\175]", escapeutf8) - value = fsub (value, "\239\187\191", escapeutf8) - value = fsub (value, "\239\191[\176-\191]", escapeutf8) - end - return "\"" .. value .. "\"" +local function quotestring(value) + -- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js + value = fsub(value, '[%z\1-\31"\\\127]', escapeutf8) + if strfind(value, "[\194\216\220\225\226\239]") then + value = fsub(value, "\194[\128-\159\173]", escapeutf8) + value = fsub(value, "\216[\128-\132]", escapeutf8) + value = fsub(value, "\220\143", escapeutf8) + value = fsub(value, "\225\158[\180\181]", escapeutf8) + value = fsub(value, "\226\128[\140-\143\168-\175]", escapeutf8) + value = fsub(value, "\226\129[\160-\175]", escapeutf8) + value = fsub(value, "\239\187\191", escapeutf8) + value = fsub(value, "\239\191[\176-\191]", escapeutf8) + end + return '"' .. value .. '"' end json.quotestring = quotestring local function replace(str, o, n) - local i, j = strfind (str, o, 1, true) - if i then - return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1) - else - return str - end + local i, j = strfind(str, o, 1, true) + if i then + return strsub(str, 1, i - 1) .. n .. strsub(str, j + 1, -1) + else + return str + end end -- locale independent num2str and str2num functions local decpoint, numfilter -local function updatedecpoint () - decpoint = strmatch(tostring(0.5), "([^05+])") - -- build a filter that can be used to remove group separators - numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+" +local function updatedecpoint() + decpoint = strmatch(tostring(0.5), "([^05+])") + -- build a filter that can be used to remove group separators + numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+" end updatedecpoint() -local function num2str (num) - return replace(fsub(tostring(num), numfilter, ""), decpoint, ".") +local function num2str(num) + return replace(fsub(tostring(num), numfilter, ""), decpoint, ".") end -local function str2num (str) - local num = tonumber(replace(str, ".", decpoint)) - if not num then - updatedecpoint() - num = tonumber(replace(str, ".", decpoint)) - end - return num +local function str2num(str) + local num = tonumber(replace(str, ".", decpoint)) + if not num then + updatedecpoint() + num = tonumber(replace(str, ".", decpoint)) + end + return num end -local function addnewline2 (level, buffer, buflen) - buffer[buflen+1] = "\n" - buffer[buflen+2] = strrep (" ", level) - buflen = buflen + 2 - return buflen +local function addnewline2(level, buffer, buflen) + buffer[buflen + 1] = "\n" + buffer[buflen + 2] = strrep(" ", level) + buflen = buflen + 2 + return buflen end -function json.addnewline (state) - if state.indent then - state.bufferlen = addnewline2 (state.level or 0, - state.buffer, state.bufferlen or #(state.buffer)) - end +function json.addnewline(state) + if state.indent then + state.bufferlen = addnewline2(state.level or 0, state.buffer, state.bufferlen or #state.buffer) + end end local encode2 -- forward declaration -local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state) - local kt = type (key) - if kt ~= 'string' and kt ~= 'number' then - return nil, "type '" .. kt .. "' is not supported as a key by JSON." - end - if prev then - buflen = buflen + 1 - buffer[buflen] = "," - end - if indent then - buflen = addnewline2 (level, buffer, buflen) - end - buffer[buflen+1] = quotestring (key) - buffer[buflen+2] = ":" - return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state) +local function addpair(key, value, prev, indent, level, buffer, buflen, tables, globalorder, state) + local kt = type(key) + if kt ~= "string" and kt ~= "number" then + return nil, "type '" .. kt .. "' is not supported as a key by JSON." + end + if prev then + buflen = buflen + 1 + buffer[buflen] = "," + end + if indent then + buflen = addnewline2(level, buffer, buflen) + end + buffer[buflen + 1] = quotestring(key) + buffer[buflen + 2] = ":" + return encode2(value, indent, level, buffer, buflen + 2, tables, globalorder, state) end local function appendcustom(res, buffer, state) - local buflen = state.bufferlen - if type (res) == 'string' then - buflen = buflen + 1 - buffer[buflen] = res - end - return buflen + local buflen = state.bufferlen + if type(res) == "string" then + buflen = buflen + 1 + buffer[buflen] = res + end + return buflen end local function exception(reason, value, state, buffer, buflen, defaultmessage) - defaultmessage = defaultmessage or reason - local handler = state.exception - if not handler then - return nil, defaultmessage - else - state.bufferlen = buflen - local ret, msg = handler (reason, value, state, defaultmessage) - if not ret then return nil, msg or defaultmessage end - return appendcustom(ret, buffer, state) - end + defaultmessage = defaultmessage or reason + local handler = state.exception + if not handler then + return nil, defaultmessage + else + state.bufferlen = buflen + local ret, msg = handler(reason, value, state, defaultmessage) + if not ret then + return nil, msg or defaultmessage + end + return appendcustom(ret, buffer, state) + end end function json.encodeexception(_reason, _value, _state, defaultmessage) - return quotestring("<" .. defaultmessage .. ">") + return quotestring("<" .. defaultmessage .. ">") end -encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state) - local valtype = type (value) - local valmeta = getmetatable (value) - valmeta = type (valmeta) == 'table' and valmeta -- only tables - local valtojson = valmeta and valmeta.__tojson - if valtojson then - if tables[value] then - return exception('reference cycle', value, state, buffer, buflen) - end - tables[value] = true - state.bufferlen = buflen - local ret, msg = valtojson (value, state) - if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end - tables[value] = nil - buflen = appendcustom(ret, buffer, state) - elseif value == nil then - buflen = buflen + 1 - buffer[buflen] = "null" - elseif valtype == 'number' then - local s - if value ~= value or value >= huge or -value >= huge then - -- This is the behaviour of the original JSON implementation. - s = "null" - else - s = num2str (value) - end - buflen = buflen + 1 - buffer[buflen] = s - elseif valtype == 'boolean' then - buflen = buflen + 1 - buffer[buflen] = value and "true" or "false" - elseif valtype == 'string' then - buflen = buflen + 1 - buffer[buflen] = quotestring (value) - elseif valtype == 'table' then - if tables[value] then - return exception('reference cycle', value, state, buffer, buflen) - end - tables[value] = true - level = level + 1 - local isa, n = isarray (value) - if n == 0 and valmeta and valmeta.__jsontype == 'object' then - isa = false - end - local msg - if isa then -- JSON array - buflen = buflen + 1 - buffer[buflen] = "[" - for i = 1, n do - buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state) - if not buflen then return nil, msg end - if i < n then - buflen = buflen + 1 - buffer[buflen] = "," - end - end - buflen = buflen + 1 - buffer[buflen] = "]" - else -- JSON object - local prev = false - buflen = buflen + 1 - buffer[buflen] = "{" - local order = valmeta and valmeta.__jsonorder or globalorder - if order then - local used = {} - n = #order - for i = 1, n do - local k = order[i] - local v = value[k] - if v ~= nil then - used[k] = true - buflen, _msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) - prev = true -- add a seperator before the next element - end - end - for k,v in pairs (value) do - if not used[k] then - buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) - if not buflen then return nil, msg end - prev = true -- add a seperator before the next element - end - end - else -- unordered - for k,v in pairs (value) do - buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) - if not buflen then return nil, msg end - prev = true -- add a seperator before the next element - end - end - if indent then - buflen = addnewline2 (level - 1, buffer, buflen) - end - buflen = buflen + 1 - buffer[buflen] = "}" - end - tables[value] = nil - else - return exception ('unsupported type', value, state, buffer, buflen, - "type '" .. valtype .. "' is not supported by JSON.") - end - return buflen +encode2 = function(value, indent, level, buffer, buflen, tables, globalorder, state) + local valtype = type(value) + local valmeta = getmetatable(value) + valmeta = type(valmeta) == "table" and valmeta -- only tables + local valtojson = valmeta and valmeta.__tojson + if valtojson then + if tables[value] then + return exception("reference cycle", value, state, buffer, buflen) + end + tables[value] = true + state.bufferlen = buflen + local ret, msg = valtojson(value, state) + if not ret then + return exception("custom encoder failed", value, state, buffer, buflen, msg) + end + tables[value] = nil + buflen = appendcustom(ret, buffer, state) + elseif value == nil then + buflen = buflen + 1 + buffer[buflen] = "null" + elseif valtype == "number" then + local s + if value ~= value or value >= huge or -value >= huge then + -- This is the behaviour of the original JSON implementation. + s = "null" + else + s = num2str(value) + end + buflen = buflen + 1 + buffer[buflen] = s + elseif valtype == "boolean" then + buflen = buflen + 1 + buffer[buflen] = value and "true" or "false" + elseif valtype == "string" then + buflen = buflen + 1 + buffer[buflen] = quotestring(value) + elseif valtype == "table" then + if tables[value] then + return exception("reference cycle", value, state, buffer, buflen) + end + tables[value] = true + level = level + 1 + local isa, n = isarray(value) + if n == 0 and valmeta and valmeta.__jsontype == "object" then + isa = false + end + local msg + if isa then -- JSON array + buflen = buflen + 1 + buffer[buflen] = "[" + for i = 1, n do + buflen, msg = encode2(value[i], indent, level, buffer, buflen, tables, globalorder, state) + if not buflen then + return nil, msg + end + if i < n then + buflen = buflen + 1 + buffer[buflen] = "," + end + end + buflen = buflen + 1 + buffer[buflen] = "]" + else -- JSON object + local prev = false + buflen = buflen + 1 + buffer[buflen] = "{" + local order = valmeta and valmeta.__jsonorder or globalorder + if order then + local used = {} + n = #order + for i = 1, n do + local k = order[i] + local v = value[k] + if v ~= nil then + used[k] = true + buflen, _msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) + prev = true -- add a seperator before the next element + end + end + for k, v in pairs(value) do + if not used[k] then + buflen, msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) + if not buflen then + return nil, msg + end + prev = true -- add a seperator before the next element + end + end + else -- unordered + for k, v in pairs(value) do + buflen, msg = addpair(k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) + if not buflen then + return nil, msg + end + prev = true -- add a seperator before the next element + end + end + if indent then + buflen = addnewline2(level - 1, buffer, buflen) + end + buflen = buflen + 1 + buffer[buflen] = "}" + end + tables[value] = nil + else + return exception( + "unsupported type", + value, + state, + buffer, + buflen, + "type '" .. valtype .. "' is not supported by JSON." + ) + end + return buflen end -function json.encode (value, state) - state = state or {} - local oldbuffer = state.buffer - local buffer = oldbuffer or {} - state.buffer = buffer - updatedecpoint() - local ret, msg = encode2 (value, state.indent, state.level or 0, - buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state) - if not ret then - error (msg, 2) - elseif oldbuffer == buffer then - state.bufferlen = ret - return true - else - state.bufferlen = nil - state.buffer = nil - return concat (buffer) - end +function json.encode(value, state) + state = state or {} + local oldbuffer = state.buffer + local buffer = oldbuffer or {} + state.buffer = buffer + updatedecpoint() + local ret, msg = encode2( + value, + state.indent, + state.level or 0, + buffer, + state.bufferlen or 0, + state.tables or {}, + state.keyorder, + state + ) + if not ret then + error(msg, 2) + elseif oldbuffer == buffer then + state.bufferlen = ret + return true + else + state.bufferlen = nil + state.buffer = nil + return concat(buffer) + end end -local function loc (str, where) - local line, pos, linepos = 1, 1, 0 - while true do - pos = strfind (str, "\n", pos, true) - if pos and pos < where then - line = line + 1 - linepos = pos - pos = pos + 1 - else - break - end - end - return "line " .. line .. ", column " .. (where - linepos) +local function loc(str, where) + local line, pos, linepos = 1, 1, 0 + while true do + pos = strfind(str, "\n", pos, true) + if pos and pos < where then + line = line + 1 + linepos = pos + pos = pos + 1 + else + break + end + end + return "line " .. line .. ", column " .. (where - linepos) end -local function unterminated (str, what, where) - return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where) +local function unterminated(str, what, where) + return nil, strlen(str) + 1, "unterminated " .. what .. " at " .. loc(str, where) end -local function scanwhite (str, pos) - while true do - pos = strfind (str, "%S", pos) - if not pos then return nil end - local sub2 = strsub (str, pos, pos + 1) - if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then - -- UTF-8 Byte Order Mark - pos = pos + 3 - elseif sub2 == "//" then - pos = strfind (str, "[\n\r]", pos + 2) - if not pos then return nil end - elseif sub2 == "/*" then - pos = strfind (str, "*/", pos + 2) - if not pos then return nil end - pos = pos + 2 - else - return pos - end - end +local function scanwhite(str, pos) + while true do + pos = strfind(str, "%S", pos) + if not pos then + return nil + end + local sub2 = strsub(str, pos, pos + 1) + if sub2 == "\239\187" and strsub(str, pos + 2, pos + 2) == "\191" then + -- UTF-8 Byte Order Mark + pos = pos + 3 + elseif sub2 == "//" then + pos = strfind(str, "[\n\r]", pos + 2) + if not pos then + return nil + end + elseif sub2 == "/*" then + pos = strfind(str, "*/", pos + 2) + if not pos then + return nil + end + pos = pos + 2 + else + return pos + end + end end local escapechars = { - ["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f", - ["n"] = "\n", ["r"] = "\r", ["t"] = "\t" + ['"'] = '"', + ["\\"] = "\\", + ["/"] = "/", + ["b"] = "\b", + ["f"] = "\f", + ["n"] = "\n", + ["r"] = "\r", + ["t"] = "\t", } -local function unichar (value) - if value < 0 then - return nil - elseif value <= 0x007f then - return strchar (value) - elseif value <= 0x07ff then - return strchar (0xc0 + floor(value/0x40), - 0x80 + (floor(value) % 0x40)) - elseif value <= 0xffff then - return strchar (0xe0 + floor(value/0x1000), - 0x80 + (floor(value/0x40) % 0x40), - 0x80 + (floor(value) % 0x40)) - elseif value <= 0x10ffff then - return strchar (0xf0 + floor(value/0x40000), - 0x80 + (floor(value/0x1000) % 0x40), - 0x80 + (floor(value/0x40) % 0x40), - 0x80 + (floor(value) % 0x40)) - else - return nil - end +local function unichar(value) + if value < 0 then + return nil + elseif value <= 0x007f then + return strchar(value) + elseif value <= 0x07ff then + return strchar(0xc0 + floor(value / 0x40), 0x80 + (floor(value) % 0x40)) + elseif value <= 0xffff then + return strchar(0xe0 + floor(value / 0x1000), 0x80 + (floor(value / 0x40) % 0x40), 0x80 + (floor(value) % 0x40)) + elseif value <= 0x10ffff then + return strchar( + 0xf0 + floor(value / 0x40000), + 0x80 + (floor(value / 0x1000) % 0x40), + 0x80 + (floor(value / 0x40) % 0x40), + 0x80 + (floor(value) % 0x40) + ) + else + return nil + end end -local function scanstring (str, pos) - local lastpos = pos + 1 - local buffer, n = {}, 0 - while true do - local nextpos = strfind (str, "[\"\\]", lastpos) - if not nextpos then - return unterminated (str, "string", pos) - end - if nextpos > lastpos then - n = n + 1 - buffer[n] = strsub (str, lastpos, nextpos - 1) - end - if strsub (str, nextpos, nextpos) == "\"" then - lastpos = nextpos + 1 - break - else - local escchar = strsub (str, nextpos + 1, nextpos + 1) - local value - if escchar == "u" then - value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16) - if value then - local value2 - if 0xD800 <= value and value <= 0xDBff then - -- we have the high surrogate of UTF-16. Check if there is a - -- low surrogate escaped nearby to combine them. - if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then - value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16) - if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then - value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000 - else - value2 = nil -- in case it was out of range for a low surrogate - end - end - end - value = value and unichar (value) - if value then - if value2 then - lastpos = nextpos + 12 - else - lastpos = nextpos + 6 - end - end - end - end - if not value then - value = escapechars[escchar] or escchar - lastpos = nextpos + 2 - end - n = n + 1 - buffer[n] = value - end - end - if n == 1 then - return buffer[1], lastpos - elseif n > 1 then - return concat (buffer), lastpos - else - return "", lastpos - end +local function scanstring(str, pos) + local lastpos = pos + 1 + local buffer, n = {}, 0 + while true do + local nextpos = strfind(str, '["\\]', lastpos) + if not nextpos then + return unterminated(str, "string", pos) + end + if nextpos > lastpos then + n = n + 1 + buffer[n] = strsub(str, lastpos, nextpos - 1) + end + if strsub(str, nextpos, nextpos) == '"' then + lastpos = nextpos + 1 + break + else + local escchar = strsub(str, nextpos + 1, nextpos + 1) + local value + if escchar == "u" then + value = tonumber(strsub(str, nextpos + 2, nextpos + 5), 16) + if value then + local value2 + if 0xD800 <= value and value <= 0xDBff then + -- we have the high surrogate of UTF-16. Check if there is a + -- low surrogate escaped nearby to combine them. + if strsub(str, nextpos + 6, nextpos + 7) == "\\u" then + value2 = tonumber(strsub(str, nextpos + 8, nextpos + 11), 16) + if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then + value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000 + else + value2 = nil -- in case it was out of range for a low surrogate + end + end + end + value = value and unichar(value) + if value then + if value2 then + lastpos = nextpos + 12 + else + lastpos = nextpos + 6 + end + end + end + end + if not value then + value = escapechars[escchar] or escchar + lastpos = nextpos + 2 + end + n = n + 1 + buffer[n] = value + end + end + if n == 1 then + return buffer[1], lastpos + elseif n > 1 then + return concat(buffer), lastpos + else + return "", lastpos + end end local scanvalue -- forward declaration -local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta) - local tbl, n = {}, 0 - local pos = startpos + 1 - if what == 'object' then - setmetatable (tbl, objectmeta) - else - setmetatable (tbl, arraymeta) - end - while true do - pos = scanwhite (str, pos) - if not pos then return unterminated (str, what, startpos) end - local char = strsub (str, pos, pos) - if char == closechar then - return tbl, pos + 1 - end - local val1, err - val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta) - if err then return nil, pos, err end - pos = scanwhite (str, pos) - if not pos then return unterminated (str, what, startpos) end - char = strsub (str, pos, pos) - if char == ":" then - if val1 == nil then - return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")" - end - pos = scanwhite (str, pos + 1) - if not pos then return unterminated (str, what, startpos) end - local val2 - val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta) - if err then return nil, pos, err end - tbl[val1] = val2 - pos = scanwhite (str, pos) - if not pos then return unterminated (str, what, startpos) end - char = strsub (str, pos, pos) - else - n = n + 1 - tbl[n] = val1 - end - if char == "," then - pos = pos + 1 - end - end +local function scantable(what, closechar, str, startpos, nullval, objectmeta, arraymeta) + local tbl, n = {}, 0 + local pos = startpos + 1 + if what == "object" then + setmetatable(tbl, objectmeta) + else + setmetatable(tbl, arraymeta) + end + while true do + pos = scanwhite(str, pos) + if not pos then + return unterminated(str, what, startpos) + end + local char = strsub(str, pos, pos) + if char == closechar then + return tbl, pos + 1 + end + local val1, err + val1, pos, err = scanvalue(str, pos, nullval, objectmeta, arraymeta) + if err then + return nil, pos, err + end + pos = scanwhite(str, pos) + if not pos then + return unterminated(str, what, startpos) + end + char = strsub(str, pos, pos) + if char == ":" then + if val1 == nil then + return nil, pos, "cannot use nil as table index (at " .. loc(str, pos) .. ")" + end + pos = scanwhite(str, pos + 1) + if not pos then + return unterminated(str, what, startpos) + end + local val2 + val2, pos, err = scanvalue(str, pos, nullval, objectmeta, arraymeta) + if err then + return nil, pos, err + end + tbl[val1] = val2 + pos = scanwhite(str, pos) + if not pos then + return unterminated(str, what, startpos) + end + char = strsub(str, pos, pos) + else + n = n + 1 + tbl[n] = val1 + end + if char == "," then + pos = pos + 1 + end + end end -scanvalue = function (str, pos, nullval, objectmeta, arraymeta) - pos = pos or 1 - pos = scanwhite (str, pos) - if not pos then - return nil, strlen (str) + 1, "no valid JSON value (reached the end)" - end - local char = strsub (str, pos, pos) - if char == "{" then - return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta) - elseif char == "[" then - return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta) - elseif char == "\"" then - return scanstring (str, pos) - else - local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos) - if pstart then - local number = str2num (strsub (str, pstart, pend)) - if number then - return number, pend + 1 - end - end - pstart, pend = strfind (str, "^%a%w*", pos) - if pstart then - local name = strsub (str, pstart, pend) - if name == "true" then - return true, pend + 1 - elseif name == "false" then - return false, pend + 1 - elseif name == "null" then - return nullval, pend + 1 - end - end - return nil, pos, "no valid JSON value at " .. loc (str, pos) - end +scanvalue = function(str, pos, nullval, objectmeta, arraymeta) + pos = pos or 1 + pos = scanwhite(str, pos) + if not pos then + return nil, strlen(str) + 1, "no valid JSON value (reached the end)" + end + local char = strsub(str, pos, pos) + if char == "{" then + return scantable("object", "}", str, pos, nullval, objectmeta, arraymeta) + elseif char == "[" then + return scantable("array", "]", str, pos, nullval, objectmeta, arraymeta) + elseif char == '"' then + return scanstring(str, pos) + else + local pstart, pend = strfind(str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos) + if pstart then + local number = str2num(strsub(str, pstart, pend)) + if number then + return number, pend + 1 + end + end + pstart, pend = strfind(str, "^%a%w*", pos) + if pstart then + local name = strsub(str, pstart, pend) + if name == "true" then + return true, pend + 1 + elseif name == "false" then + return false, pend + 1 + elseif name == "null" then + return nullval, pend + 1 + end + end + return nil, pos, "no valid JSON value at " .. loc(str, pos) + end end local function optionalmetatables(...) - if select("#", ...) > 0 then - return ... - else - return {__jsontype = 'object'}, {__jsontype = 'array'} - end + if select("#", ...) > 0 then + return ... + else + return { __jsontype = "object" }, { __jsontype = "array" } + end end -function json.decode (str, pos, nullval, ...) - local objectmeta, arraymeta = optionalmetatables(...) - return scanvalue (str, pos, nullval, objectmeta, arraymeta) +function json.decode(str, pos, nullval, ...) + local objectmeta, arraymeta = optionalmetatables(...) + return scanvalue(str, pos, nullval, objectmeta, arraymeta) end -function json.use_lpeg () - local g = require ("lpeg") +function json.use_lpeg() + local g = require("lpeg") - if g.version() == "0.11" then - error "due to a bug in LPeg 0.11, it cannot be used for JSON matching" - end + if g.version() == "0.11" then + error("due to a bug in LPeg 0.11, it cannot be used for JSON matching") + end - local pegmatch = g.match - local P, S, R = g.P, g.S, g.R + local pegmatch = g.match + local P, S, R = g.P, g.S, g.R - local function ErrorCall (str, pos, msg, state) - if not state.msg then - state.msg = msg .. " at " .. loc (str, pos) - state.pos = pos - end - return false - end + local function ErrorCall(str, pos, msg, state) + if not state.msg then + state.msg = msg .. " at " .. loc(str, pos) + state.pos = pos + end + return false + end - local function Err (msg) - return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall) - end + local function Err(msg) + return g.Cmt(g.Cc(msg) * g.Carg(2), ErrorCall) + end - local function ErrorUnterminatedCall (str, pos, what, state) - return ErrorCall (str, pos - 1, "unterminated " .. what, state) - end + local function ErrorUnterminatedCall(str, pos, what, state) + return ErrorCall(str, pos - 1, "unterminated " .. what, state) + end - local SingleLineComment = P"//" * (1 - S"\n\r")^0 - local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/" - local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0 + local SingleLineComment = P("//") * (1 - S("\n\r")) ^ 0 + local MultiLineComment = P("/*") * (1 - P("*/")) ^ 0 * P("*/") + local Space = (S(" \n\r\t") + P("\239\187\191") + SingleLineComment + MultiLineComment) ^ 0 - local function ErrUnterminated (what) - return g.Cmt (g.Cc (what) * g.Carg (2), ErrorUnterminatedCall) - end + local function ErrUnterminated(what) + return g.Cmt(g.Cc(what) * g.Carg(2), ErrorUnterminatedCall) + end - local PlainChar = 1 - S"\"\\\n\r" - local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars - local HexDigit = R("09", "af", "AF") - local function UTF16Surrogate (_match, _pos, high, low) - high, low = tonumber (high, 16), tonumber (low, 16) - if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then - return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000) - else - return false - end - end - local function UTF16BMP (hex) - return unichar (tonumber (hex, 16)) - end - local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit)) - local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP - local Char = UnicodeEscape + EscapeSequence + PlainChar - local String = P"\"" * (g.Cs (Char ^ 0) * P"\"" + ErrUnterminated "string") - local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0)) - local Fractal = P"." * R"09"^0 - local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1 - local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num - local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1) - local SimpleValue = Number + String + Constant - local ArrayContent, ObjectContent + local PlainChar = 1 - S('"\\\n\r') + local EscapeSequence = (P("\\") * g.C(S('"\\/bfnrt') + Err("unsupported escape sequence"))) / escapechars + local HexDigit = R("09", "af", "AF") + local function UTF16Surrogate(_match, _pos, high, low) + high, low = tonumber(high, 16), tonumber(low, 16) + if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then + return true, unichar((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000) + else + return false + end + end + local function UTF16BMP(hex) + return unichar(tonumber(hex, 16)) + end + local U16Sequence = (P("\\u") * g.C(HexDigit * HexDigit * HexDigit * HexDigit)) + local UnicodeEscape = g.Cmt(U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence / UTF16BMP + local Char = UnicodeEscape + EscapeSequence + PlainChar + local String = P('"') * (g.Cs(Char ^ 0) * P('"') + ErrUnterminated("string")) + local Integer = P("-") ^ -1 * (P("0") + (R("19") * R("09") ^ 0)) + local Fractal = P(".") * R("09") ^ 0 + local Exponent = (S("eE")) * (S("+-")) ^ -1 * R("09") ^ 1 + local Number = (Integer * Fractal ^ -1 * Exponent ^ -1) / str2num + local Constant = P("true") * g.Cc(true) + P("false") * g.Cc(false) + P("null") * g.Carg(1) + local SimpleValue = Number + String + Constant + local ArrayContent, ObjectContent - -- The functions parsearray and parseobject parse only a single value/pair - -- at a time and store them directly to avoid hitting the LPeg limits. - local function parsearray (str, pos, nullval, state) - local obj, cont - local start = pos - local npos - local t, nt = {}, 0 - repeat - obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state) - if cont == 'end' then - return ErrorUnterminatedCall (str, start, "array", state) - end - pos = npos - if cont == 'cont' or cont == 'last' then - nt = nt + 1 - t[nt] = obj - end - until cont ~= 'cont' - return pos, setmetatable (t, state.arraymeta) - end + -- The functions parsearray and parseobject parse only a single value/pair + -- at a time and store them directly to avoid hitting the LPeg limits. + local function parsearray(str, pos, nullval, state) + local obj, cont + local start = pos + local npos + local t, nt = {}, 0 + repeat + obj, cont, npos = pegmatch(ArrayContent, str, pos, nullval, state) + if cont == "end" then + return ErrorUnterminatedCall(str, start, "array", state) + end + pos = npos + if cont == "cont" or cont == "last" then + nt = nt + 1 + t[nt] = obj + end + until cont ~= "cont" + return pos, setmetatable(t, state.arraymeta) + end - local function parseobject (str, pos, nullval, state) - local obj, key, cont - local start = pos - local npos - local t = {} - repeat - key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state) - if cont == 'end' then - return ErrorUnterminatedCall (str, start, "object", state) - end - pos = npos - if cont == 'cont' or cont == 'last' then - t[key] = obj - end - until cont ~= 'cont' - return pos, setmetatable (t, state.objectmeta) - end + local function parseobject(str, pos, nullval, state) + local obj, key, cont + local start = pos + local npos + local t = {} + repeat + key, obj, cont, npos = pegmatch(ObjectContent, str, pos, nullval, state) + if cont == "end" then + return ErrorUnterminatedCall(str, start, "object", state) + end + pos = npos + if cont == "cont" or cont == "last" then + t[key] = obj + end + until cont ~= "cont" + return pos, setmetatable(t, state.objectmeta) + end - local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) - local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) - local Value = Space * (Array + Object + SimpleValue) - local ExpectedValue = Value + Space * Err "value expected" - local ExpectedKey = String + Err "key expected" - local End = P(-1) * g.Cc'end' - local ErrInvalid = Err "invalid JSON" - ArrayContent = (Value * Space * (P"," * g.Cc'cont' + P"]" * g.Cc'last'+ End + ErrInvalid) + g.Cc(nil) * (P"]" * g.Cc'empty' + End + ErrInvalid)) * g.Cp() - local Pair = g.Cg (Space * ExpectedKey * Space * (P":" + Err "colon expected") * ExpectedValue) - ObjectContent = (g.Cc(nil) * g.Cc(nil) * P"}" * g.Cc'empty' + End + (Pair * Space * (P"," * g.Cc'cont' + P"}" * g.Cc'last' + End + ErrInvalid) + ErrInvalid)) * g.Cp() - local DecodeValue = ExpectedValue * g.Cp () + local Array = P("[") * g.Cmt(g.Carg(1) * g.Carg(2), parsearray) + local Object = P("{") * g.Cmt(g.Carg(1) * g.Carg(2), parseobject) + local Value = Space * (Array + Object + SimpleValue) + local ExpectedValue = Value + Space * Err("value expected") + local ExpectedKey = String + Err("key expected") + local End = P(-1) * g.Cc("end") + local ErrInvalid = Err("invalid JSON") + ArrayContent = ( + Value * Space * (P(",") * g.Cc("cont") + P("]") * g.Cc("last") + End + ErrInvalid) + + g.Cc(nil) * (P("]") * g.Cc("empty") + End + ErrInvalid) + ) * g.Cp() + local Pair = g.Cg(Space * ExpectedKey * Space * (P(":") + Err("colon expected")) * ExpectedValue) + ObjectContent = ( + g.Cc(nil) * g.Cc(nil) * P("}") * g.Cc("empty") + + End + + (Pair * Space * (P(",") * g.Cc("cont") + P("}") * g.Cc("last") + End + ErrInvalid) + ErrInvalid) + ) * g.Cp() + local DecodeValue = ExpectedValue * g.Cp() - jsonlpeg.version = json.version - jsonlpeg.encode = json.encode - jsonlpeg.null = json.null - jsonlpeg.quotestring = json.quotestring - jsonlpeg.addnewline = json.addnewline - jsonlpeg.encodeexception = json.encodeexception - jsonlpeg.using_lpeg = true + jsonlpeg.version = json.version + jsonlpeg.encode = json.encode + jsonlpeg.null = json.null + jsonlpeg.quotestring = json.quotestring + jsonlpeg.addnewline = json.addnewline + jsonlpeg.encodeexception = json.encodeexception + jsonlpeg.using_lpeg = true - function jsonlpeg.decode (str, pos, nullval, ...) - local state = {} - state.objectmeta, state.arraymeta = optionalmetatables(...) - local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state) - if state.msg then - return nil, state.pos, state.msg - else - return obj, retpos - end - end + function jsonlpeg.decode(str, pos, nullval, ...) + local state = {} + state.objectmeta, state.arraymeta = optionalmetatables(...) + local obj, retpos = pegmatch(DecodeValue, str, pos, nullval, state) + if state.msg then + return nil, state.pos, state.msg + else + return obj, retpos + end + end - -- cache result of this function: - json.use_lpeg = function () return jsonlpeg end - jsonlpeg.use_lpeg = json.use_lpeg + -- cache result of this function: + json.use_lpeg = function() + return jsonlpeg + end + jsonlpeg.use_lpeg = json.use_lpeg - return jsonlpeg + return jsonlpeg end if always_use_lpeg then - return json.use_lpeg() + return json.use_lpeg() end return json - diff --git a/util/init.lua b/util/init.lua index 426d250..c5a0853 100644 --- a/util/init.lua +++ b/util/init.lua @@ -1,6 +1,6 @@ --[[ - Lain + Lina Layouts, widgets and utilities for Awesome WM Utilities section @@ -11,180 +11,200 @@ --]] -local awful = require("awful") -local sqrt = math.sqrt -local pairs = pairs -local client = client -local tonumber = tonumber -local wrequire = require("lina.helpers").wrequire +local awful = require("awful") +local sqrt = math.sqrt +local pairs = pairs +local client = client +local tonumber = tonumber +local wrequire = require("lina.helpers").wrequire local setmetatable = setmetatable --- Lain utilities submodule --- lain.util -local util = { _NAME = "lain.util" } +-- Lina utilities submodule +-- lina.util +local util = { _NAME = "lina.util" } -- Like awful.menu.clients, but only show clients of currently selected tags function util.menu_clients_current_tags(menu, args) - -- List of currently selected tags. - local cls_tags = awful.screen.focused().selected_tags + -- List of currently selected tags. + local cls_tags = awful.screen.focused().selected_tags - if cls_tags == nil then return nil end + if cls_tags == nil then + return nil + end - -- Final list of menu items. - local cls_t = {} + -- Final list of menu items. + local cls_t = {} - -- For each selected tag get all clients of that tag and add them to - -- the menu. A click on a menu item will raise that client. - for i = 1,#cls_tags do - local t = cls_tags[i] - local cls = t:clients() + -- For each selected tag get all clients of that tag and add them to + -- the menu. A click on a menu item will raise that client. + for i = 1, #cls_tags do + local t = cls_tags[i] + local cls = t:clients() - for _, c in pairs(cls) do - cls_t[#cls_t + 1] = { awful.util.escape(c.name) or "", - function () - c.minimized = false - client.focus = c - c:raise() - end, - c.icon } - end - end + for _, c in pairs(cls) do + cls_t[#cls_t + 1] = { + awful.util.escape(c.name) or "", + function() + c.minimized = false + client.focus = c + c:raise() + end, + c.icon, + } + end + end - -- No clients? Then quit. - if #cls_t <= 0 then return nil end + -- No clients? Then quit. + if #cls_t <= 0 then + return nil + end - -- menu may contain some predefined values, otherwise start with a - -- fresh menu. - if not menu then menu = {} end + -- menu may contain some predefined values, otherwise start with a + -- fresh menu. + if not menu then + menu = {} + end - -- Set the list of items and show the menu. - menu.items = cls_t - local m = awful.menu(menu) - m:show(args) + -- Set the list of items and show the menu. + menu.items = cls_t + local m = awful.menu(menu) + m:show(args) - return m + return m end -- Magnify a client: set it to "float" and resize it. function util.magnify_client(c, width_f, height_f) - if c and not c.floating then - util.magnified_client = c - util.mc(c, width_f, height_f) - else - util.magnified_client = nil - c.floating = false - end + if c and not c.floating then + util.magnified_client = c + util.mc(c, width_f, height_f) + else + util.magnified_client = nil + c.floating = false + end end -- https://github.com/lcpz/lain/issues/195 function util.mc(c, width_f, height_f) - c = c or util.magnified_client - if not c then return end + c = c or util.magnified_client + if not c then + return + end - c.floating = true - local s = awful.screen.focused() - local mg = s.workarea - local g = {} - local mwfact = width_f or s.selected_tag.master_width_factor or 0.5 - g.width = sqrt(mwfact) * mg.width - g.height = sqrt(height_f or mwfact) * mg.height - g.x = mg.x + (mg.width - g.width) / 2 - g.y = mg.y + (mg.height - g.height) / 2 + c.floating = true + local s = awful.screen.focused() + local mg = s.workarea + local g = {} + local mwfact = width_f or s.selected_tag.master_width_factor or 0.5 + g.width = sqrt(mwfact) * mg.width + g.height = sqrt(height_f or mwfact) * mg.height + g.x = mg.x + (mg.width - g.width) / 2 + g.y = mg.y + (mg.height - g.height) / 2 - if c then c:geometry(g) end -- if c is still a valid object + if c then + c:geometry(g) + end -- if c is still a valid object end -- Non-empty tag browsing -- direction in {-1, 1} <-> {previous, next} non-empty tag -function util.tag_view_nonempty(direction,sc) - direction = direction or 1 - local s = sc or awful.screen.focused() - local tags = s.tags - local sel = s.selected_tag +function util.tag_view_nonempty(direction, sc) + direction = direction or 1 + local s = sc or awful.screen.focused() + local tags = s.tags + local sel = s.selected_tag - local i = sel.index - repeat - i = i + direction + local i = sel.index + repeat + i = i + direction - -- Wrap around when we reach one of the bounds - if i > #tags then - i = i - #tags - end - if i < 1 then - i = i + #tags - end + -- Wrap around when we reach one of the bounds + if i > #tags then + i = i - #tags + end + if i < 1 then + i = i + #tags + end - local t = tags[i] + local t = tags[i] - -- Stop when we get back to where we started - if t == sel then - break - end + -- Stop when we get back to where we started + if t == sel then + break + end - -- If it's The One, view it. - if #t:clients() > 0 then - t:view_only() - return - end - until false + -- If it's The One, view it. + if #t:clients() > 0 then + t:view_only() + return + end + until false end -- {{{ Dynamic tagging -- Add a new tag function util.add_tag(layout) - awful.prompt.run { - prompt = "New tag name: ", - textbox = awful.screen.focused().mypromptbox.widget, - exe_callback = function(name) - if not name or #name == 0 then return end - awful.tag.add(name, { screen = awful.screen.focused(), layout = layout or awful.layout.suit.tile }):view_only() - end - } + awful.prompt.run({ + prompt = "New tag name: ", + textbox = awful.screen.focused().mypromptbox.widget, + exe_callback = function(name) + if not name or #name == 0 then + return + end + awful.tag + .add(name, { screen = awful.screen.focused(), layout = layout or awful.layout.suit.tile }) + :view_only() + end, + }) end -- Rename current tag function util.rename_tag() - awful.prompt.run { - prompt = "Rename tag: ", - textbox = awful.screen.focused().mypromptbox.widget, - exe_callback = function(new_name) - if not new_name or #new_name == 0 then return end - local t = awful.screen.focused().selected_tag - if t then - t.name = new_name - end - end - } + awful.prompt.run({ + prompt = "Rename tag: ", + textbox = awful.screen.focused().mypromptbox.widget, + exe_callback = function(new_name) + if not new_name or #new_name == 0 then + return + end + local t = awful.screen.focused().selected_tag + if t then + t.name = new_name + end + end, + }) end -- Move current tag -- pos in {-1, 1} <-> {previous, next} tag position function util.move_tag(pos) - local tag = awful.screen.focused().selected_tag - if tonumber(pos) <= -1 then - awful.tag.move(tag.index - 1, tag) - else - awful.tag.move(tag.index + 1, tag) - end + local tag = awful.screen.focused().selected_tag + if tonumber(pos) <= -1 then + awful.tag.move(tag.index - 1, tag) + else + awful.tag.move(tag.index + 1, tag) + end end -- Delete current tag -- Any rule set on the tag shall be broken function util.delete_tag() - local t = awful.screen.focused().selected_tag - if not t then return end - t:delete() + local t = awful.screen.focused().selected_tag + if not t then + return + end + t:delete() end -- }}} -- On the fly useless gaps change function util.useless_gaps_resize(thatmuch, s, t) - local scr = s or awful.screen.focused() - local tag = t or scr.selected_tag - tag.gap = tag.gap + tonumber(thatmuch) - awful.layout.arrange(scr) + local scr = s or awful.screen.focused() + local tag = t or scr.selected_tag + tag.gap = tag.gap + tonumber(thatmuch) + awful.layout.arrange(scr) end return setmetatable(util, { __index = wrequire }) diff --git a/util/markup.lua b/util/markup.lua index 63f9486..16ad892 100644 --- a/util/markup.lua +++ b/util/markup.lua @@ -10,8 +10,8 @@ local format = string.format local setmetatable = setmetatable --- Lain markup util submodule --- lain.util.markup +-- Lina markup util submodule +-- lina.util.markup local markup = { fg = {}, bg = {} } -- Convenience tags diff --git a/util/menu_iterator.lua b/util/menu_iterator.lua index d457473..c09ff41 100644 --- a/util/menu_iterator.lua +++ b/util/menu_iterator.lua @@ -8,10 +8,10 @@ --]] -- Menu iterator with Naughty notifications --- lain.util.menu_iterator +-- lina.util.menu_iterator local naughty = require("naughty") -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local atable = require("awful.util").table local assert = assert local pairs = pairs diff --git a/util/separators.lua b/util/separators.lua index 04402bb..880539d 100644 --- a/util/separators.lua +++ b/util/separators.lua @@ -10,8 +10,8 @@ local wibox = require("wibox") local gears = require("gears") local beautiful = require("beautiful") --- Lain Cairo separators util submodule --- lain.util.separators +-- Lina Cairo separators util submodule +-- lina.util.separators local separators = { height = beautiful.separators_height or 0, width = beautiful.separators_width or 9 } -- [[ Arrow diff --git a/widget/alsa.lua b/widget/alsa.lua index 202dc98..d8151e9 100644 --- a/widget/alsa.lua +++ b/widget/alsa.lua @@ -6,13 +6,13 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local shell = require("awful.util").shell local wibox = require("wibox") local string = string -- ALSA volume --- lain.widget.alsa +-- lina.widget.alsa local function factory(args) args = args or {} diff --git a/widget/alsabar.lua b/widget/alsabar.lua index 8e8cd3a..789160d 100644 --- a/widget/alsabar.lua +++ b/widget/alsabar.lua @@ -6,7 +6,7 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local awful = require("awful") local naughty = require("naughty") local wibox = require("wibox") @@ -16,7 +16,7 @@ local type = type local tonumber = tonumber -- ALSA volume bar --- lain.widget.alsabar +-- lina.widget.alsabar local function factory(args) local alsabar = { diff --git a/widget/bat.lua b/widget/bat.lua index 260f4b9..9e66d1c 100644 --- a/widget/bat.lua +++ b/widget/bat.lua @@ -6,7 +6,7 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local fs = require("gears.filesystem") local naughty = require("naughty") local wibox = require("wibox") @@ -16,13 +16,13 @@ local ipairs = ipairs local tonumber = tonumber -- Battery infos --- lain.widget.bat +-- lina.widget.bat local function factory(args) local pspath = args.pspath or "/sys/class/power_supply/" if not fs.is_dir(pspath) then - naughty.notify { text = "lain.widget.bat: invalid power supply path", timeout = 0 } + naughty.notify { text = "lina.widget.bat: invalid power supply path", timeout = 0 } return end diff --git a/widget/cal.lua b/widget/cal.lua index 97dced8..16ab112 100644 --- a/widget/cal.lua +++ b/widget/cal.lua @@ -5,8 +5,8 @@ --]] -local helpers = require("lain.helpers") -local markup = require("lain.util.markup") +local helpers = require("lina.helpers") +local markup = require("lina.util.markup") local awful = require("awful") local naughty = require("naughty") local floor = math.floor @@ -19,7 +19,7 @@ local tonumber = tonumber local tostring = tostring -- Calendar notification --- lain.widget.cal +-- lina.widget.cal local function factory(args) args = args or {} diff --git a/widget/contrib/init.lua b/widget/contrib/init.lua index 9e863a5..20b86b7 100644 --- a/widget/contrib/init.lua +++ b/widget/contrib/init.lua @@ -1,6 +1,6 @@ --[[ - Lain + Lina Layouts, widgets and utilities for Awesome WM Users contributed widgets section @@ -10,9 +10,9 @@ --]] -local wrequire = require("lain.helpers").wrequire +local wrequire = require("lina.helpers").wrequire local setmetatable = setmetatable -local widget = { _NAME = "lain.widget.contrib" } +local widget = { _NAME = "lina.widget.contrib" } return setmetatable(widget, { __index = wrequire }) diff --git a/widget/contrib/moc.lua b/widget/contrib/moc.lua index ad6452e..7186ddc 100644 --- a/widget/contrib/moc.lua +++ b/widget/contrib/moc.lua @@ -5,7 +5,7 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local shell = require("awful.util").shell local focused = require("awful.screen").focused local escape_f = require("awful.util").escape @@ -15,7 +15,7 @@ local os = os local string = string -- MOC audio player --- lain.widget.contrib.moc +-- lina.widget.contrib.moc local function factory(args) args = args or {} diff --git a/widget/contrib/redshift.lua b/widget/contrib/redshift.lua index d91d941..56615de 100644 --- a/widget/contrib/redshift.lua +++ b/widget/contrib/redshift.lua @@ -6,13 +6,13 @@ --]] -local async = require("lain.helpers").async +local async = require("lina.helpers").async local awful = require("awful") local execute = os.execute local type = type -- Redshift --- lain.widget.contrib.redshift +-- lina.widget.contrib.redshift local redshift = { active = false, pid = nil } function redshift.start() diff --git a/widget/contrib/task.lua b/widget/contrib/task.lua index 2311996..f42cef5 100644 --- a/widget/contrib/task.lua +++ b/widget/contrib/task.lua @@ -5,14 +5,14 @@ --]] -local helpers = require("lain.helpers") -local markup = require("lain.util").markup +local helpers = require("lina.helpers") +local markup = require("lina.util").markup local awful = require("awful") local naughty = require("naughty") local mouse = mouse -- Taskwarrior notification --- lain.widget.contrib.task +-- lina.widget.contrib.task local task = {} function task.hide() diff --git a/widget/contrib/tp_smapi.lua b/widget/contrib/tp_smapi.lua index 87c5e51..23c4dff 100644 --- a/widget/contrib/tp_smapi.lua +++ b/widget/contrib/tp_smapi.lua @@ -6,7 +6,7 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local focused = require("awful.screen").focused local naughty = require("naughty") local wibox = require("wibox") @@ -15,7 +15,7 @@ local type = type -- ThinkPad battery infos and widget creator -- http://www.thinkwiki.org/wiki/Tp_smapi --- lain.widget.contrib.tp_smapi +-- lina.widget.contrib.tp_smapi local function factory(apipath) local tp_smapi = { diff --git a/widget/cpu.lua b/widget/cpu.lua index 6c51115..2a8c60a 100644 --- a/widget/cpu.lua +++ b/widget/cpu.lua @@ -6,13 +6,13 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local wibox = require("wibox") local math = math local string = string -- CPU usage --- lain.widget.cpu +-- lina.widget.cpu local function factory(args) args = args or {} diff --git a/widget/fs.lua b/widget/fs.lua index b3a2dad..39732d7 100644 --- a/widget/fs.lua +++ b/widget/fs.lua @@ -7,7 +7,7 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local Gio = require("lgi").Gio local focused = require("awful.screen").focused local wibox = require("wibox") @@ -23,7 +23,7 @@ local query_used = Gio.FILE_ATTRIBUTE_FILESYSTEM_USED local query = query_size .. "," .. query_free .. "," .. query_used -- File systems info --- lain.widget.fs +-- lina.widget.fs local function factory(args) args = args or {} diff --git a/widget/imap.lua b/widget/imap.lua index e3f7baa..50ae486 100644 --- a/widget/imap.lua +++ b/widget/imap.lua @@ -5,90 +5,111 @@ --]] -local helpers = require("lain.helpers") -local naughty = require("naughty") -local wibox = require("wibox") -local awful = require("awful") -local string = string -local type = type +local helpers = require("lina.helpers") +local naughty = require("naughty") +local wibox = require("wibox") +local awful = require("awful") +local string = string +local type = type local tonumber = tonumber -- Mail IMAP check --- lain.widget.imap +-- lina.widget.imap local function factory(args) - args = args or {} + args = args or {} - local imap = { widget = args.widget or wibox.widget.textbox() } - local server = args.server - local mail = args.mail - local password = args.password - local port = args.port or 993 - local timeout = args.timeout or 60 - local pwdtimeout = args.pwdtimeout or 10 - local is_plain = args.is_plain or false - local followtag = args.followtag or false - local notify = args.notify or "on" - local settings = args.settings or function() end + local imap = { widget = args.widget or wibox.widget.textbox() } + local server = args.server + local mail = args.mail + local password = args.password + local port = args.port or 993 + local timeout = args.timeout or 60 + local pwdtimeout = args.pwdtimeout or 10 + local is_plain = args.is_plain or false + local followtag = args.followtag or false + local notify = args.notify or "on" + local settings = args.settings or function() end - local head_command = "curl --connect-timeout 3 -fsm 3" - local request = "-X 'STATUS INBOX (MESSAGES RECENT UNSEEN)'" + local head_command = "curl --connect-timeout 3 -fsm 3" + local request = "-X 'STATUS INBOX (MESSAGES RECENT UNSEEN)'" - if not server or not mail or not password then return end + if not server or not mail or not password then + return + end - mail_notification_preset = { - icon = helpers.icons_dir .. "mail.png", - position = "top_left" - } + mail_notification_preset = { + icon = helpers.icons_dir .. "mail.png", + position = "top_left", + } - helpers.set_map(mail, 0) + helpers.set_map(mail, 0) - if not is_plain then - if type(password) == "string" or type(password) == "table" then - helpers.async(password, function(f) password = f:gsub("\n", "") end) - elseif type(password) == "function" then - imap.pwdtimer = helpers.newtimer(mail .. "-password", pwdtimeout, function() - local retrieved_password, try_again = password() - if not try_again then - imap.pwdtimer:stop() -- stop trying to retrieve - password = retrieved_password or "" -- failsafe - end - end, true, true) - end - end + if not is_plain then + if type(password) == "string" or type(password) == "table" then + helpers.async(password, function(f) + password = f:gsub("\n", "") + end) + elseif type(password) == "function" then + imap.pwdtimer = helpers.newtimer(mail .. "-password", pwdtimeout, function() + local retrieved_password, try_again = password() + if not try_again then + imap.pwdtimer:stop() -- stop trying to retrieve + password = retrieved_password or "" -- failsafe + end + end, true, true) + end + end - function imap.update() - -- do not update if the password has not been retrieved yet - if type(password) ~= "string" then return end + function imap.update() + -- do not update if the password has not been retrieved yet + if type(password) ~= "string" then + return + end - local curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:'%s' %s -k", - head_command, server, port, mail, password, request) + local curl = string.format( + "%s --url imaps://%s:%s/INBOX -u %s:'%s' %s -k", + head_command, + server, + port, + mail, + password, + request + ) - helpers.async(curl, function(f) - imap_now = { ["MESSAGES"] = 0, ["RECENT"] = 0, ["UNSEEN"] = 0 } + helpers.async(curl, function(f) + imap_now = { ["MESSAGES"] = 0, ["RECENT"] = 0, ["UNSEEN"] = 0 } - for s,d in f:gmatch("(%w+)%s+(%d+)") do imap_now[s] = tonumber(d) end - mailcount = imap_now["UNSEEN"] -- backwards compatibility - widget = imap.widget + for s, d in f:gmatch("(%w+)%s+(%d+)") do + imap_now[s] = tonumber(d) + end + mailcount = imap_now["UNSEEN"] -- backwards compatibility + widget = imap.widget - settings() + settings() - if notify == "on" and mailcount and mailcount >= 1 and mailcount > helpers.get_map(mail) then - if followtag then mail_notification_preset.screen = awful.screen.focused() end - naughty.notify { - preset = mail_notification_preset, - text = string.format("%s has %d new message%s", mail, mailcount, mailcount == 1 and "" or "s") - } - end + if notify == "on" and mailcount and mailcount >= 1 and mailcount > helpers.get_map(mail) then + if followtag then + mail_notification_preset.screen = awful.screen.focused() + end + naughty.notify({ + preset = mail_notification_preset, + text = string.format( + "%s has %d new message%s", + mail, + mailcount, + mailcount == 1 and "" or "s" + ), + }) + end - helpers.set_map(mail, imap_now["UNSEEN"]) - end) + helpers.set_map(mail, imap_now["UNSEEN"]) + end) + end - end + imap.timer = helpers.newtimer(mail, timeout, imap.update, true, true) - imap.timer = helpers.newtimer(mail, timeout, imap.update, true, true) - - return imap + return imap end return factory diff --git a/widget/init.lua b/widget/init.lua index 57b86bb..1c7832b 100644 --- a/widget/init.lua +++ b/widget/init.lua @@ -1,6 +1,6 @@ --[[ - Lain + Lina Layouts, widgets and utilities for Awesome WM Widgets section @@ -11,9 +11,9 @@ --]] -local wrequire = require("lain.helpers").wrequire +local wrequire = require("lina.helpers").wrequire local setmetatable = setmetatable -local widget = { _NAME = "lain.widget" } +local widget = { _NAME = "lina.widget" } return setmetatable(widget, { __index = wrequire }) diff --git a/widget/mem.lua b/widget/mem.lua index 0318494..4bac5c1 100644 --- a/widget/mem.lua +++ b/widget/mem.lua @@ -6,12 +6,12 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local wibox = require("wibox") local gmatch, lines, floor = string.gmatch, io.lines, math.floor -- Memory usage (ignoring caches) --- lain.widget.mem +-- lina.widget.mem local function factory(args) args = args or {} diff --git a/widget/mpd.lua b/widget/mpd.lua index 55d3649..5e434a6 100644 --- a/widget/mpd.lua +++ b/widget/mpd.lua @@ -6,7 +6,7 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local shell = require("awful.util").shell local escape_f = require("awful.util").escape local focused = require("awful.screen").focused @@ -16,7 +16,7 @@ local os = os local string = string -- MPD infos --- lain.widget.mpd +-- lina.widget.mpd local function factory(args) args = args or {} diff --git a/widget/net.lua b/widget/net.lua index 9b7b165..5b18290 100644 --- a/widget/net.lua +++ b/widget/net.lua @@ -6,13 +6,13 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local naughty = require("naughty") local wibox = require("wibox") local string = string -- Network infos --- lain.widget.net +-- lina.widget.net local function factory(args) args = args or {} diff --git a/widget/pulse.lua b/widget/pulse.lua index 69f4d70..75c376f 100644 --- a/widget/pulse.lua +++ b/widget/pulse.lua @@ -5,14 +5,14 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local shell = require("awful.util").shell local wibox = require("wibox") local string = string local type = type -- PulseAudio volume --- lain.widget.pulse +-- lina.widget.pulse local function factory(args) args = args or {} diff --git a/widget/pulsebar.lua b/widget/pulsebar.lua index 19e73b9..5d8a3f2 100644 --- a/widget/pulsebar.lua +++ b/widget/pulsebar.lua @@ -6,7 +6,7 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local awful = require("awful") local naughty = require("naughty") local wibox = require("wibox") @@ -16,7 +16,7 @@ local type = type local tonumber = tonumber -- PulseAudio volume bar --- lain.widget.pulsebar +-- lina.widget.pulsebar local function factory(args) local pulsebar = { diff --git a/widget/sysload.lua b/widget/sysload.lua index 7260524..e94a47c 100644 --- a/widget/sysload.lua +++ b/widget/sysload.lua @@ -6,12 +6,12 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local wibox = require("wibox") local open, match = io.open, string.match -- System load --- lain.widget.sysload +-- lina.widget.sysload local function factory(args) args = args or {} diff --git a/widget/temp.lua b/widget/temp.lua index 99f8700..8137d6c 100644 --- a/widget/temp.lua +++ b/widget/temp.lua @@ -5,12 +5,12 @@ --]] -local helpers = require("lain.helpers") +local helpers = require("lina.helpers") local wibox = require("wibox") local tonumber = tonumber -- {thermal,core} temperature info --- lain.widget.temp +-- lina.widget.temp local function factory(args) args = args or {} diff --git a/widget/weather.lua b/widget/weather.lua index 93028b5..821f1bd 100644 --- a/widget/weather.lua +++ b/widget/weather.lua @@ -5,8 +5,8 @@ --]] -local helpers = require("lain.helpers") -local json = require("lain.util").dkjson +local helpers = require("lina.helpers") +local json = require("lina.util").dkjson local focused = require("awful.screen").focused local naughty = require("naughty") local wibox = require("wibox") @@ -18,7 +18,7 @@ local tonumber = tonumber -- OpenWeatherMap -- current weather and X-days forecast --- lain.widget.weather +-- lina.widget.weather local function factory(args) args = args or {}