Initial commit
This commit is contained in:
		
							
								
								
									
										747
									
								
								.config/awesome/lain/util/dkjson.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										747
									
								
								.config/awesome/lain/util/dkjson.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,747 @@
 | 
			
		||||
-- Module options:
 | 
			
		||||
local always_use_lpeg = false
 | 
			
		||||
local register_global_module_table = false
 | 
			
		||||
local global_module_name = 'json'
 | 
			
		||||
 | 
			
		||||
--[==[
 | 
			
		||||
 | 
			
		||||
David Kolf's JSON module for Lua 5.1 - 5.4
 | 
			
		||||
 | 
			
		||||
Version 2.6
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
For the documentation see the corresponding readme.txt or visit
 | 
			
		||||
<http://dkolf.de/src/dkjson-lua.fsl/>.
 | 
			
		||||
 | 
			
		||||
You can contact the author by sending an e-mail to 'david' at the
 | 
			
		||||
domain 'dkolf.de'.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2010-2021 David Heiko Kolf
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining
 | 
			
		||||
a copy of this software and associated documentation files (the
 | 
			
		||||
"Software"), to deal in the Software without restriction, including
 | 
			
		||||
without limitation the rights to use, copy, modify, merge, publish,
 | 
			
		||||
distribute, sublicense, and/or sell copies of the Software, and to
 | 
			
		||||
permit persons to whom the Software is furnished to do so, subject to
 | 
			
		||||
the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be
 | 
			
		||||
included in all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
			
		||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
			
		||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
 | 
			
		||||
--]==]
 | 
			
		||||
 | 
			
		||||
-- global dependencies:
 | 
			
		||||
local 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
 | 
			
		||||
local strmatch = string.match
 | 
			
		||||
local concat = table.concat
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local escapecodes = {
 | 
			
		||||
  ["\""] = "\\\"", ["\\"] = "\\\\", ["\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
 | 
			
		||||
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 .. "\""
 | 
			
		||||
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
 | 
			
		||||
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") .. "]+"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
updatedecpoint()
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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)
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function json.encodeexception(_reason, _value, _state, 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
 | 
			
		||||
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)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local escapechars = {
 | 
			
		||||
  ["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["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
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
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")
 | 
			
		||||
 | 
			
		||||
  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 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 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 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
 | 
			
		||||
 | 
			
		||||
  -- 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 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
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
 | 
			
		||||
  return jsonlpeg
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if always_use_lpeg then
 | 
			
		||||
  return json.use_lpeg()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return json
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										190
									
								
								.config/awesome/lain/util/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								.config/awesome/lain/util/init.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,190 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Lain
 | 
			
		||||
     Layouts, widgets and utilities for Awesome WM
 | 
			
		||||
 | 
			
		||||
     Utilities section
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013,      Luca CPZ
 | 
			
		||||
      * (c) 2010-2012, Peter Hofmann
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local awful        = require("awful")
 | 
			
		||||
local sqrt         = math.sqrt
 | 
			
		||||
local pairs        = pairs
 | 
			
		||||
local client       = client
 | 
			
		||||
local tonumber     = tonumber
 | 
			
		||||
local wrequire     = require("lain.helpers").wrequire
 | 
			
		||||
local setmetatable = setmetatable
 | 
			
		||||
 | 
			
		||||
-- Lain utilities submodule
 | 
			
		||||
-- lain.util
 | 
			
		||||
local util = { _NAME = "lain.util" }
 | 
			
		||||
 | 
			
		||||
-- 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
 | 
			
		||||
 | 
			
		||||
    if cls_tags == nil then return nil end
 | 
			
		||||
 | 
			
		||||
    -- 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 _, 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
 | 
			
		||||
 | 
			
		||||
    -- 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)
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
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.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
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
        local t = tags[i]
 | 
			
		||||
 | 
			
		||||
        -- 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
 | 
			
		||||
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
 | 
			
		||||
    }
 | 
			
		||||
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
 | 
			
		||||
    }
 | 
			
		||||
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
 | 
			
		||||
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()
 | 
			
		||||
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)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return setmetatable(util, { __index = wrequire })
 | 
			
		||||
							
								
								
									
										66
									
								
								.config/awesome/lain/util/markup.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								.config/awesome/lain/util/markup.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under MIT License
 | 
			
		||||
      * (c) 2013, Luca CPZ
 | 
			
		||||
      * (c) 2009, Uli Schlachter
 | 
			
		||||
      * (c) 2009, Majic
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local format = string.format
 | 
			
		||||
local setmetatable = setmetatable
 | 
			
		||||
 | 
			
		||||
-- Lain markup util submodule
 | 
			
		||||
-- lain.util.markup
 | 
			
		||||
local markup = { fg = {}, bg = {} }
 | 
			
		||||
 | 
			
		||||
-- Convenience tags
 | 
			
		||||
function markup.bold(text)      return format("<b>%s</b>",         text) end
 | 
			
		||||
function markup.italic(text)    return format("<i>%s</i>",         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
 | 
			
		||||
function markup.font(font, text)
 | 
			
		||||
    return format("<span font='%s'>%s</span>", font, text)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Set the foreground
 | 
			
		||||
function markup.fg.color(color, text)
 | 
			
		||||
    return format("<span foreground='%s'>%s</span>", color, text)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Set the background
 | 
			
		||||
function markup.bg.color(color, text)
 | 
			
		||||
    return format("<span background='%s'>%s</span>", color, text)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Set foreground and background
 | 
			
		||||
function markup.color(fg, bg, text)
 | 
			
		||||
    return format("<span foreground='%s' background='%s'>%s</span>", fg, bg, text)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Set font and foreground
 | 
			
		||||
function markup.fontfg(font, fg, text)
 | 
			
		||||
    return format("<span font='%s' foreground='%s'>%s</span>", font, fg, text)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Set font and background
 | 
			
		||||
function markup.fontbg(font, bg, text)
 | 
			
		||||
    return format("<span font='%s' background='%s'>%s</span>", font, bg, text)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Set font, foreground and background
 | 
			
		||||
function markup.fontcolor(font, fg, bg, text)
 | 
			
		||||
    return format("<span font='%s' foreground='%s' background='%s'>%s</span>", font, fg, bg, text)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- link markup.{fg,bg}(...) calls to markup.{fg,bg}.color(...)
 | 
			
		||||
setmetatable(markup.fg, { __call = function(_, ...) return markup.fg.color(...) end })
 | 
			
		||||
setmetatable(markup.bg, { __call = function(_, ...) return markup.bg.color(...) end })
 | 
			
		||||
 | 
			
		||||
-- link markup(...) calls to markup.fg.color(...)
 | 
			
		||||
return setmetatable(markup, { __call = function(_, ...) return markup.fg.color(...) end })
 | 
			
		||||
							
								
								
									
										144
									
								
								.config/awesome/lain/util/menu_iterator.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								.config/awesome/lain/util/menu_iterator.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2017, Simon Désaulniers <sim.desaulniers@gmail.com>
 | 
			
		||||
      * (c) 2017, Uli Schlachter
 | 
			
		||||
      * (c) 2017, Jeferson Siqueira <jefersonlsiq@gmail.com>
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
-- Menu iterator with Naughty notifications
 | 
			
		||||
-- lain.util.menu_iterator
 | 
			
		||||
 | 
			
		||||
local naughty = require("naughty")
 | 
			
		||||
local helpers = require("lain.helpers")
 | 
			
		||||
local atable  = require("awful.util").table
 | 
			
		||||
local assert  = assert
 | 
			
		||||
local pairs   = pairs
 | 
			
		||||
local tconcat = table.concat
 | 
			
		||||
local unpack = unpack or table.unpack -- lua 5.1 retro-compatibility
 | 
			
		||||
 | 
			
		||||
local state = { cid = nil }
 | 
			
		||||
 | 
			
		||||
local function naughty_destroy_callback(reason)
 | 
			
		||||
    local closed = naughty.notificationClosedReason
 | 
			
		||||
    if reason == closed.expired or reason == closed.dismissedByUser then
 | 
			
		||||
        local actions = state.index and state.menu[state.index - 1][2]
 | 
			
		||||
        if actions then
 | 
			
		||||
            for _,action in pairs(actions) do
 | 
			
		||||
                -- don't try to call nil callbacks
 | 
			
		||||
                if action then action() end
 | 
			
		||||
            end
 | 
			
		||||
            state.index = nil
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Iterates over a menu.
 | 
			
		||||
-- After the timeout, callbacks associated to the last visited choice are
 | 
			
		||||
-- executed. Inputs:
 | 
			
		||||
-- * menu:    a list of {label, {callbacks}} pairs
 | 
			
		||||
-- * timeout: time to wait before confirming the menu selection
 | 
			
		||||
-- * icon:    icon to display in the notification of the chosen label
 | 
			
		||||
local function iterate(menu, timeout, icon)
 | 
			
		||||
    timeout = timeout or 4 -- default timeout for each menu entry
 | 
			
		||||
    icon    = icon or nil  -- icon to display on the menu
 | 
			
		||||
 | 
			
		||||
    -- Build the list of choices
 | 
			
		||||
    if not state.index then
 | 
			
		||||
        state.menu = menu
 | 
			
		||||
        state.index = 1
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    -- Select one and display the appropriate notification
 | 
			
		||||
    local label
 | 
			
		||||
    local next = state.menu[state.index]
 | 
			
		||||
    state.index = state.index + 1
 | 
			
		||||
 | 
			
		||||
    if not next then
 | 
			
		||||
        label = "Cancel"
 | 
			
		||||
        state.index = nil
 | 
			
		||||
    else
 | 
			
		||||
        label, _ = unpack(next)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    state.cid = naughty.notify({
 | 
			
		||||
        text        = label,
 | 
			
		||||
        icon        = icon,
 | 
			
		||||
        timeout     = timeout,
 | 
			
		||||
        screen      = mouse.screen,
 | 
			
		||||
        replaces_id = state.cid,
 | 
			
		||||
        destroy     = naughty_destroy_callback
 | 
			
		||||
    }).id
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Generates a menu compatible with the first argument of `iterate` function and
 | 
			
		||||
-- suitable for the following cases:
 | 
			
		||||
-- * all possible choices individually (partition of singletons);
 | 
			
		||||
-- * all possible subsets of the set of choices (powerset).
 | 
			
		||||
--
 | 
			
		||||
-- Inputs:
 | 
			
		||||
-- * args: an array containing the following members:
 | 
			
		||||
--   * choices:       Array of choices (string) on which the menu will be
 | 
			
		||||
--                    generated.
 | 
			
		||||
--   * name:          Displayed name of the menu (in the form "name: choices").
 | 
			
		||||
--   * selected_cb:   Callback to execute for each selected choice. Takes
 | 
			
		||||
--                    the choice as a string argument. Can be `nil` (no action
 | 
			
		||||
--                    to execute).
 | 
			
		||||
--   * rejected_cb:   Callback to execute for each rejected choice (possible
 | 
			
		||||
--                    choices which are not selected). Takes the choice as a
 | 
			
		||||
--                    string argument. Can be `nil` (no action to execute).
 | 
			
		||||
--   * extra_choices: An array of extra { choice_str, callback_fun } pairs to be
 | 
			
		||||
--                    added to the menu. Each callback_fun can be `nil`.
 | 
			
		||||
--   * combination:   The combination of choices to generate. Possible values:
 | 
			
		||||
--                    "powerset" and "single" (default).
 | 
			
		||||
-- Output:
 | 
			
		||||
-- * m: menu to be iterated over.
 | 
			
		||||
local function menu(args)
 | 
			
		||||
    local choices       = assert(args.choices or args[1])
 | 
			
		||||
    local name          = assert(args.name or args[2])
 | 
			
		||||
    local selected_cb   = args.selected_cb
 | 
			
		||||
    local rejected_cb   = args.rejected_cb
 | 
			
		||||
    local extra_choices = args.extra_choices or {}
 | 
			
		||||
 | 
			
		||||
    local ch_combinations = args.combination == "powerset" and helpers.powerset(choices) or helpers.trivial_partition_set(choices)
 | 
			
		||||
 | 
			
		||||
    for _, c in pairs(extra_choices) do
 | 
			
		||||
        ch_combinations = atable.join(ch_combinations, {{c[1]}})
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local m = {} -- the menu
 | 
			
		||||
 | 
			
		||||
    for _,c in pairs(ch_combinations) do
 | 
			
		||||
        if #c > 0 then
 | 
			
		||||
            local cbs = {}
 | 
			
		||||
 | 
			
		||||
            -- selected choices
 | 
			
		||||
            for _,ch in pairs(c) do
 | 
			
		||||
                if atable.hasitem(choices, ch) then
 | 
			
		||||
                    cbs[#cbs + 1] = selected_cb and function() selected_cb(ch) end or nil
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            -- rejected choices
 | 
			
		||||
            for _,ch in pairs(choices) do
 | 
			
		||||
                if not atable.hasitem(c, ch) and atable.hasitem(choices, ch) then
 | 
			
		||||
                    cbs[#cbs + 1] = rejected_cb and function() rejected_cb(ch) end or nil
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            -- add user extra choices (like the choice "None" for example)
 | 
			
		||||
            for _,x in pairs(extra_choices) do
 | 
			
		||||
                if x[1] == c[1] then
 | 
			
		||||
                    cbs[#cbs + 1] = x[2]
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            m[#m + 1] = { name .. ": " .. tconcat(c, " + "), cbs }
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return m
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return { iterate = iterate, menu = menu }
 | 
			
		||||
							
								
								
									
										179
									
								
								.config/awesome/lain/util/quake.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								.config/awesome/lain/util/quake.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2016, Luca CPZ
 | 
			
		||||
      * (c) 2015, unknown
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local awful        = require("awful")
 | 
			
		||||
local capi         = { client = client }
 | 
			
		||||
local math         = math
 | 
			
		||||
local string       = string
 | 
			
		||||
local pairs        = pairs
 | 
			
		||||
local screen       = screen
 | 
			
		||||
local setmetatable = setmetatable
 | 
			
		||||
 | 
			
		||||
-- Quake-like Dropdown application spawn
 | 
			
		||||
local quake = {}
 | 
			
		||||
 | 
			
		||||
-- If you have a rule like "awful.client.setslave" for your terminals,
 | 
			
		||||
-- ensure you use an exception for QuakeDD. Otherwise, you may
 | 
			
		||||
-- run into problems with focus.
 | 
			
		||||
 | 
			
		||||
function quake:display()
 | 
			
		||||
    if self.followtag then self.screen = awful.screen.focused() end
 | 
			
		||||
 | 
			
		||||
    -- First, we locate the client
 | 
			
		||||
    local client = nil
 | 
			
		||||
    local i = 0
 | 
			
		||||
    for c in awful.client.iterate(function (c)
 | 
			
		||||
        -- c.name may be changed!
 | 
			
		||||
        return c.instance == self.name
 | 
			
		||||
    end)
 | 
			
		||||
    do
 | 
			
		||||
        i = i + 1
 | 
			
		||||
        if i == 1 then
 | 
			
		||||
            client = c
 | 
			
		||||
        else
 | 
			
		||||
            -- Additional matching clients, let's remove the sticky bit
 | 
			
		||||
            -- which may persist between awesome restarts. We don't close
 | 
			
		||||
            -- them as they may be valuable. They will just turn into
 | 
			
		||||
            -- normal clients.
 | 
			
		||||
            c.sticky = false
 | 
			
		||||
            c.ontop = false
 | 
			
		||||
            c.above = false
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if not client and not self.visible then return end
 | 
			
		||||
 | 
			
		||||
    if not client then
 | 
			
		||||
        -- The client does not exist, we spawn it
 | 
			
		||||
        local cmd = string.format("%s %s %s", self.app,
 | 
			
		||||
              string.format(self.argname, self.name), self.extra)
 | 
			
		||||
        awful.spawn(cmd, { tag = self.screen.selected_tag })
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    -- Set geometry
 | 
			
		||||
    client.floating = true
 | 
			
		||||
    client.border_width = self.border
 | 
			
		||||
    client.size_hints_honor = false
 | 
			
		||||
    local maximized = client.maximized
 | 
			
		||||
    local fullscreen = client.fullscreen
 | 
			
		||||
    client:geometry(self.geometry[self.screen.index] or self:compute_size())
 | 
			
		||||
 | 
			
		||||
    -- Set not sticky and on top
 | 
			
		||||
    client.sticky = false
 | 
			
		||||
    client.ontop = true
 | 
			
		||||
    client.above = true
 | 
			
		||||
    client.skip_taskbar = true
 | 
			
		||||
 | 
			
		||||
    -- Additional user settings
 | 
			
		||||
    if self.settings then self.settings(client) end
 | 
			
		||||
 | 
			
		||||
    -- Toggle display
 | 
			
		||||
    if self.visible then
 | 
			
		||||
        client.hidden = false
 | 
			
		||||
        client.maximized = self.maximized
 | 
			
		||||
        client.fullscreen = self.fullscreen
 | 
			
		||||
        client:raise()
 | 
			
		||||
        self.last_tag = self.screen.selected_tag
 | 
			
		||||
        client:tags({self.screen.selected_tag})
 | 
			
		||||
        capi.client.focus = client
 | 
			
		||||
    else
 | 
			
		||||
        self.maximized = maximized
 | 
			
		||||
        self.fullscreen = fullscreen
 | 
			
		||||
        client.maximized = false
 | 
			
		||||
        client.fullscreen = false
 | 
			
		||||
        client.hidden = true
 | 
			
		||||
        local ctags = client:tags()
 | 
			
		||||
        for j, _ in pairs(ctags) do
 | 
			
		||||
            ctags[j] = nil
 | 
			
		||||
        end
 | 
			
		||||
        client:tags(ctags)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return client
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function quake:compute_size()
 | 
			
		||||
    -- skip if we already have a geometry for this screen
 | 
			
		||||
    if not self.geometry[self.screen.index] then
 | 
			
		||||
        local geom
 | 
			
		||||
        if not self.overlap then
 | 
			
		||||
            geom = screen[self.screen.index].workarea
 | 
			
		||||
        else
 | 
			
		||||
            geom = screen[self.screen.index].geometry
 | 
			
		||||
        end
 | 
			
		||||
        local width, height = self.width, self.height
 | 
			
		||||
        if width  <= 1 then width = math.floor(geom.width * width) - 2 * self.border end
 | 
			
		||||
        if height <= 1 then height = math.floor(geom.height * height) end
 | 
			
		||||
        local x, y
 | 
			
		||||
        if     self.horiz == "left"  then x = geom.x
 | 
			
		||||
        elseif self.horiz == "right" then x = geom.width + geom.x - width
 | 
			
		||||
        else   x = geom.x + (geom.width - width)/2 end
 | 
			
		||||
        if     self.vert == "top"    then y = geom.y
 | 
			
		||||
        elseif self.vert == "bottom" then y = geom.height + geom.y - height
 | 
			
		||||
        else   y = geom.y + (geom.height - height)/2 end
 | 
			
		||||
        self.geometry[self.screen.index] = { x = x, y = y, width = width, height = height }
 | 
			
		||||
    end
 | 
			
		||||
    return self.geometry[self.screen.index]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function quake:toggle()
 | 
			
		||||
     if self.followtag then self.screen = awful.screen.focused() end
 | 
			
		||||
     local current_tag = self.screen.selected_tag
 | 
			
		||||
     if current_tag and self.last_tag ~= current_tag and self.visible then
 | 
			
		||||
         local c=self:display()
 | 
			
		||||
         if c then
 | 
			
		||||
            c:move_to_tag(current_tag)
 | 
			
		||||
        end
 | 
			
		||||
     else
 | 
			
		||||
         self.visible = not self.visible
 | 
			
		||||
         self:display()
 | 
			
		||||
     end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function quake.new(conf)
 | 
			
		||||
    conf = conf or {}
 | 
			
		||||
 | 
			
		||||
    conf.app        = conf.app       or "xterm"    -- application to spawn
 | 
			
		||||
    conf.name       = conf.name      or "QuakeDD"  -- window name
 | 
			
		||||
    conf.argname    = conf.argname   or "-name %s" -- how to specify window name
 | 
			
		||||
    conf.extra      = conf.extra     or ""         -- extra arguments
 | 
			
		||||
    conf.border     = conf.border    or 1          -- client border width
 | 
			
		||||
    conf.visible    = conf.visible   or false      -- initially not visible
 | 
			
		||||
    conf.followtag  = conf.followtag or false      -- spawn on currently focused screen
 | 
			
		||||
    conf.overlap    = conf.overlap   or false      -- overlap wibox
 | 
			
		||||
    conf.screen     = conf.screen    or awful.screen.focused()
 | 
			
		||||
    conf.settings   = conf.settings
 | 
			
		||||
 | 
			
		||||
    -- If width or height <= 1 this is a proportion of the workspace
 | 
			
		||||
    conf.height     = conf.height    or 0.25       -- height
 | 
			
		||||
    conf.width      = conf.width     or 1          -- width
 | 
			
		||||
    conf.vert       = conf.vert      or "top"      -- top, bottom or center
 | 
			
		||||
    conf.horiz      = conf.horiz     or "left"     -- left, right or center
 | 
			
		||||
    conf.geometry   = {}                           -- internal use
 | 
			
		||||
 | 
			
		||||
    conf.maximized = false
 | 
			
		||||
    conf.fullscreen = false
 | 
			
		||||
 | 
			
		||||
    local dropdown = setmetatable(conf, { __index = quake })
 | 
			
		||||
 | 
			
		||||
    capi.client.connect_signal("manage", function(c)
 | 
			
		||||
        if c.instance == dropdown.name and c.screen == dropdown.screen then
 | 
			
		||||
            dropdown:display()
 | 
			
		||||
        end
 | 
			
		||||
    end)
 | 
			
		||||
    capi.client.connect_signal("unmanage", function(c)
 | 
			
		||||
        if c.instance == dropdown.name and c.screen == dropdown.screen then
 | 
			
		||||
            dropdown.visible = false
 | 
			
		||||
        end
 | 
			
		||||
     end)
 | 
			
		||||
 | 
			
		||||
    return dropdown
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return setmetatable(quake, { __call = function(_, ...) return quake.new(...) end })
 | 
			
		||||
							
								
								
									
										118
									
								
								.config/awesome/lain/util/separators.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								.config/awesome/lain/util/separators.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2015, Luca CPZ
 | 
			
		||||
      * (c) 2015, plotnikovanton
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local wibox = require("wibox")
 | 
			
		||||
local gears = require("gears")
 | 
			
		||||
local beautiful = require("beautiful")
 | 
			
		||||
 | 
			
		||||
-- Lain Cairo separators util submodule
 | 
			
		||||
-- lain.util.separators
 | 
			
		||||
local separators = { height = beautiful.separators_height or 0, width = beautiful.separators_width or 9 }
 | 
			
		||||
 | 
			
		||||
-- [[ Arrow
 | 
			
		||||
 | 
			
		||||
-- Right
 | 
			
		||||
function separators.arrow_right(col1, col2)
 | 
			
		||||
    local widget = wibox.widget.base.make_widget()
 | 
			
		||||
    widget.col1 = col1
 | 
			
		||||
    widget.col2 = col2
 | 
			
		||||
 | 
			
		||||
    widget.fit = function(_, _, _)
 | 
			
		||||
        return separators.width, separators.height
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    widget.update = function(_, _)
 | 
			
		||||
        widget.col1 = col1
 | 
			
		||||
        widget.col2 = col2
 | 
			
		||||
        widget:emit_signal("widget::redraw_needed")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    widget.draw = function(_, _, cr, width, height)
 | 
			
		||||
        if widget.col2 ~= "alpha" then
 | 
			
		||||
            cr:set_source_rgba(gears.color.parse_color(widget.col2))
 | 
			
		||||
            cr:new_path()
 | 
			
		||||
            cr:move_to(0, 0)
 | 
			
		||||
            cr:line_to(width, height/2)
 | 
			
		||||
            cr:line_to(width, 0)
 | 
			
		||||
            cr:close_path()
 | 
			
		||||
            cr:fill()
 | 
			
		||||
 | 
			
		||||
            cr:new_path()
 | 
			
		||||
            cr:move_to(0, height)
 | 
			
		||||
            cr:line_to(width, height/2)
 | 
			
		||||
            cr:line_to(width, height)
 | 
			
		||||
            cr:close_path()
 | 
			
		||||
            cr:fill()
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if widget.col1 ~= "alpha" then
 | 
			
		||||
            cr:set_source_rgba(gears.color.parse_color(widget.col1))
 | 
			
		||||
            cr:new_path()
 | 
			
		||||
            cr:move_to(0, 0)
 | 
			
		||||
            cr:line_to(width, height/2)
 | 
			
		||||
            cr:line_to(0, height)
 | 
			
		||||
            cr:close_path()
 | 
			
		||||
            cr:fill()
 | 
			
		||||
        end
 | 
			
		||||
   end
 | 
			
		||||
 | 
			
		||||
   return widget
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Left
 | 
			
		||||
function separators.arrow_left(col1, col2)
 | 
			
		||||
    local widget = wibox.widget.base.make_widget()
 | 
			
		||||
    widget.col1 = col1
 | 
			
		||||
    widget.col2 = col2
 | 
			
		||||
 | 
			
		||||
    widget.fit = function(_,  _, _)
 | 
			
		||||
        return separators.width, separators.height
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    widget.update = function(c1, c2)
 | 
			
		||||
        widget.col1 = c1
 | 
			
		||||
        widget.col2 = c2
 | 
			
		||||
        widget:emit_signal("widget::redraw_needed")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    widget.draw = function(_, _, cr, width, height)
 | 
			
		||||
        if widget.col1 ~= "alpha" then
 | 
			
		||||
            cr:set_source_rgba(gears.color.parse_color(widget.col1))
 | 
			
		||||
            cr:new_path()
 | 
			
		||||
            cr:move_to(width, 0)
 | 
			
		||||
            cr:line_to(0, height/2)
 | 
			
		||||
            cr:line_to(0, 0)
 | 
			
		||||
            cr:close_path()
 | 
			
		||||
            cr:fill()
 | 
			
		||||
 | 
			
		||||
            cr:new_path()
 | 
			
		||||
            cr:move_to(width, height)
 | 
			
		||||
            cr:line_to(0, height/2)
 | 
			
		||||
            cr:line_to(0, height)
 | 
			
		||||
            cr:close_path()
 | 
			
		||||
            cr:fill()
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if widget.col2 ~= "alpha" then
 | 
			
		||||
            cr:new_path()
 | 
			
		||||
            cr:move_to(width, 0)
 | 
			
		||||
            cr:line_to(0, height/2)
 | 
			
		||||
            cr:line_to(width, height)
 | 
			
		||||
            cr:close_path()
 | 
			
		||||
 | 
			
		||||
            cr:set_source_rgba(gears.color.parse_color(widget.col2))
 | 
			
		||||
            cr:fill()
 | 
			
		||||
        end
 | 
			
		||||
   end
 | 
			
		||||
 | 
			
		||||
   return widget
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- ]]
 | 
			
		||||
 | 
			
		||||
return separators
 | 
			
		||||
		Reference in New Issue
	
	Block a user