diff --git a/install-deps.sh b/install-deps.sh new file mode 100755 index 0000000..fcacef9 --- /dev/null +++ b/install-deps.sh @@ -0,0 +1,4 @@ +#!/bin/sh +for pkg in awesome-audiowheel awesome-handy inspect; do + luarocks install --local "$pkg" +done diff --git a/lib/inspect.lua b/lib/inspect.lua deleted file mode 100644 index c79593e..0000000 --- a/lib/inspect.lua +++ /dev/null @@ -1,251 +0,0 @@ ------------------------------------------------------------------------------------------------------------------------ --- inspect.lua - v1.2.0 (2012-10) --- Enrique GarcĂ­a Cota - enrique.garcia.cota [AT] gmail [DOT] com --- human-readable representations of tables. --- inspired by http://lua-users.org/wiki/TableSerialization ------------------------------------------------------------------------------------------------------------------------ - -local inspect ={} -inspect.__VERSION = '1.2.0' - --- Apostrophizes the string if it has quotes, but not aphostrophes --- Otherwise, it returns a regular quoted string -local function smartQuote(str) - if string.match( string.gsub(str,"[^'\"]",""), '^"+$' ) then - return "'" .. str .. "'" - end - return string.format("%q", str ) -end - -local controlCharsTranslation = { - ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", - ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\\"] = "\\\\" -} - -local function unescapeChar(c) return controlCharsTranslation[c] end - -local function unescape(str) - local result, _ = string.gsub( str, "(%c)", unescapeChar ) - return result -end - -local function isIdentifier(str) - return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" ) -end - -local function isArrayKey(k, length) - return type(k)=='number' and 1 <= k and k <= length -end - -local function isDictionaryKey(k, length) - return not isArrayKey(k, length) -end - -local sortOrdersByType = { - ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, - ['function'] = 5, ['userdata'] = 6, ['thread'] = 7 -} - -local function sortKeys(a,b) - local ta, tb = type(a), type(b) - if ta ~= tb then return sortOrdersByType[ta] < sortOrdersByType[tb] end - if ta == 'string' or ta == 'number' then return a < b end - return false -end - -local function getDictionaryKeys(t) - local length = #t - local keys = {} - for k,_ in pairs(t) do - if isDictionaryKey(k, length) then table.insert(keys,k) end - end - table.sort(keys, sortKeys) - return keys -end - -local function getToStringResultSafely(t, mt) - local __tostring = type(mt) == 'table' and mt.__tostring - local string, status - if type(__tostring) == 'function' then - status, string = pcall(__tostring, t) - string = status and string or 'error: ' .. tostring(string) - end - return string -end - -local Inspector = {} - -function Inspector:new(t, depth) - local inspector = { - buffer = {}, - depth = depth, - level = 0, - maxIds = { - ['function'] = 0, - ['userdata'] = 0, - ['thread'] = 0, - ['table'] = 0, - ['key'] = 0, - ['tag'] = 0, - ['other'] = 0 - }, - ids = { - ['function'] = setmetatable({}, {__mode = "kv"}), - ['userdata'] = setmetatable({}, {__mode = "kv"}), - ['thread'] = setmetatable({}, {__mode = "kv"}), - ['table'] = setmetatable({}, {__mode = "kv"}), - ['key'] = setmetatable({}, {__mode = "kv"}), - ['tag'] = setmetatable({}, {__mode = "kv"}), - ['other'] = setmetatable({}, {__mode = "kv"}) - }, - tableAppearances = setmetatable({}, {__mode = "k"}) - } - - setmetatable(inspector, {__index = Inspector}) - - inspector:countTableAppearances(t) - - return inspector:putValue(t) -end - -function Inspector:countTableAppearances(t) - if type(t) == 'table' then - if not self.tableAppearances[t] then - self.tableAppearances[t] = 1 - for k,v in pairs(t) do - self:countTableAppearances(k) - self:countTableAppearances(v) - end - else - self.tableAppearances[t] = self.tableAppearances[t] + 1 - end - self:countTableAppearances(getmetatable(t)) - end -end - -function Inspector:tabify() - self:puts("\n", string.rep(" ", self.level)) - return self -end - -function Inspector:up() - self.level = self.level - 1 -end - -function Inspector:down() - self.level = self.level + 1 -end - -function Inspector:puts(...) - local args = {...} - local len = #self.buffer - for i=1, #args do - len = len + 1 - self.buffer[len] = tostring(args[i]) - end - return self -end - -function Inspector:commaControl(comma) - if comma then self:puts(',') end - return true -end - -function Inspector:putTable(t) - if self:alreadyVisited(t) then - self:puts('') - elseif self.depth and self.level >= self.depth then - self:puts('{...}') - else - if self.tableAppearances[t] > 1 then - self:puts('<',self:getId(t),'>') - end - self:puts('{') - self:down() - - local length = #t - local mt = getmetatable(t) - - local string = getToStringResultSafely(t, mt) - if type(string) == 'string' and #string > 0 then - self:puts(' -- ', unescape(string)) - if length >= 1 then self:tabify() end -- tabify the array values - end - - local comma = false - for i=1, length do - comma = self:commaControl(comma) - self:puts(' '):putValue(t[i]) - end - - local dictKeys = getDictionaryKeys(t) - - for _,k in ipairs(dictKeys) do - comma = self:commaControl(comma) - self:tabify():putKey(k):puts(' = '):putValue(t[k]) - end - - if mt then - comma = self:commaControl(comma) - self:tabify():puts(' = '):putValue(mt) - end - - self:up() - - if #dictKeys > 0 or mt then -- dictionary table. Justify closing } - self:tabify() - elseif length > 0 then -- array tables have one extra space before closing } - self:puts(' ') - end - self:puts('}') - end - return self -end - -function Inspector:alreadyVisited(v) - return self.ids[type(v)][v] ~= nil -end - -function Inspector:getId(v) - local tv = type(v) - local idtable = self.ids[tv] - local id = idtable and idtable[v] or nil - if not id then - if self.maxIds[tv] == nil then tv = 'other' end - id = self.maxIds[tv] + 1 - self.maxIds[tv] = id - self.ids[tv][v] = id - end - return id -end - -function Inspector:putValue(v) - local tv = type(v) - - if tv == 'string' then - self:puts(smartQuote(unescape(v))) - elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then - self:puts(tostring(v)) - elseif tv == 'table' then - self:putTable(v) - else - self:puts('<',tv,' ',self:getId(v),'>') - end - return self -end - -function Inspector:putKey(k) - if isIdentifier(k) then return self:puts(k) end - return self:puts( "[" ):putValue(k):puts("]") -end - -function Inspector:tostring() - return table.concat(self.buffer) -end - -setmetatable(inspect, { __call = function(_,t,depth) - return Inspector:new(t, depth):tostring() -end }) - -return inspect - diff --git a/rc.lua b/rc.lua index 156fb4a..9e5d2ee 100644 --- a/rc.lua +++ b/rc.lua @@ -7,9 +7,9 @@ local awful = require("awful") beautiful = require("beautiful") naughty = require("naughty") conf = require("localconf") - require("errors") + require("util.errors") gears = require("gears") -inspect = require("lib.inspect") +inspect = require("inspect") wibox = require("wibox") -- }}} diff --git a/util/errors.lua b/util/errors.lua new file mode 100644 index 0000000..2fc8a1d --- /dev/null +++ b/util/errors.lua @@ -0,0 +1,27 @@ +-- Notification library +local naughty = require("naughty") + +-- {{{ Error handling +-- Check if awesome encountered an error during startup and fell back to +-- another config (This code will only ever execute for the fallback config) +if awesome.startup_errors then + naughty.notify({ preset = naughty.config.presets.critical, + title = "Oops, there were errors during startup!", + text = awesome.startup_errors }) +end + +-- Handle runtime errors after startup +do + local in_error = false + awesome.connect_signal("debug::error", function (err) + -- Make sure we don't go into an endless error loop + if in_error then return end + in_error = true + + naughty.notify({ preset = naughty.config.presets.critical, + title = "Oops, an error happened!", + text = err }) + in_error = false + end) +end +-- }}}