From: Luke Bonham Date: Fri, 15 Jul 2016 15:38:07 +0000 (+0200) Subject: Merge pull request #213 from rohieb/feature/task-cmdline X-Git-Url: https://git.madduck.net/etc/awesome.git/commitdiff_plain/b9f31a6c6237f326405d6530b34416f94250c475?hp=d16094bc6811118f778e334a1bbf5fdafd966644 Merge pull request #213 from rohieb/feature/task-cmdline task widget: make command line configurable --- diff --git a/README.rst b/README.rst index be3e377..87e11b5 100644 --- a/README.rst +++ b/README.rst @@ -43,5 +43,5 @@ Screenshots .. _GNU-GPL2: http://www.gnu.org/licenses/gpl-2.0.html .. _awesome-vain: https://github.com/vain/awesome-vain -.. _Awesome: http://awesome.naquadah.org/ +.. _Awesome: https://github.com/awesomeWM/awesome .. _wiki: https://github.com/copycat-killer/lain/wiki diff --git a/util/quake.lua b/util/quake.lua new file mode 100644 index 0000000..ab412ac --- /dev/null +++ b/util/quake.lua @@ -0,0 +1,155 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2016, Luke Bonham + +--]] + +local awful = require("awful") +local capi = { client = client, + mouse = mouse, + screen = screen, + timer = timer } +local string = string + +local pairs = pairs +local setmetatable = setmetatable +local tostring = tostring + +-- Quake-like Dropdown application spawn +-- Original version: https://awesomewm.org/wiki/Drop-down_terminal#Another_solution +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() + -- 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, nil, self.screen) + 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 + awful.util.spawn(self.app .. " " .. string.format(self.argname, self.name), + false, self.screen) + return + end + + -- Resize + awful.client.floating.set(client, true) + client.border_width = 0 + client.size_hints_honor = false + client:geometry(self.geometry) + + -- Not sticky and on top + client.ontop = true + client.above = true + client.skip_taskbar = true + client.sticky = false + + -- Toggle display + if self.visible then + client.hidden = false + client:raise() + self.last_tag = tostring(awful.tag.selected(self.screen)) + client:tags({awful.tag.selected(self.screen)}) + capi.client.focus = client + else + client.hidden = true + local ctags = client:tags() + for i, t in pairs(ctags) do + ctags[i] = nil + end + client:tags(ctags) + end + + return client +end + +function quake:new(config) + local conf = config 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.visible = conf.visible or false -- initially not visible + conf.screen = conf.screen or capi.mouse.screen + + -- If width or height <= 1 this is a proportion of the workspace + wibox_height = conf.wibox_height or 18 -- statusbar weight + height = conf.height or 0.25 -- height + width = conf.width or 1 -- width + vert = conf.vert or "top" -- top, bottom or center + horiz = conf.horiz or "center" -- left, right or center + + -- Compute size + local geom = capi.screen[conf.screen].workarea + if width <= 1 then width = geom.width * width end + if height <= 1 then height = geom.height * height end + local x, y + if horiz == "left" then x = geom.x + elseif horiz == "right" then x = geom.width + geom.x - width + else x = geom.x + (geom.width - width)/2 end + if vert == "top" then y = geom.y + elseif vert == "bottom" then y = geom.height + geom.y - height + else y = geom.y + (geom.height - height)/2 end + conf.geometry = { x = x, y = y + wibox_height, width = width, height = height } + + local console = setmetatable(conf, { __index = quake }) + capi.client.connect_signal("manage", function(c) + if c.instance == console.name and c.screen == console.screen then + console:display() + end + end) + capi.client.connect_signal("unmanage", function(c) + if c.instance == console.name and c.screen == console.screen then + console.visible = false + end + end) + + -- "Reattach" currently running quake application. This is in case awesome is restarted. + local reattach = capi.timer { timeout = 0 } + reattach:connect_signal("timeout", function() + reattach:stop() + console:display() + end) + reattach:start() + + return console +end + +function quake:toggle() + current_tag = awful.tag.selected(self.screen) + if self.last_tag ~= tostring(current_tag) and self.visible then + awful.client.movetotag(current_tag, self:display()) + else + self.visible = not self.visible + self:display() + end +end + +setmetatable(quake, { __call = function(_, ...) return quake:new(...) end }) + +return quake diff --git a/widgets/bat.lua b/widgets/bat.lua index 0c8fe5f..ec9a289 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -13,10 +13,14 @@ local first_line = require("lain.helpers").first_line local naughty = require("naughty") local wibox = require("wibox") -local math = { floor = math.floor, min = math.min } +local math = { abs = math.abs, + floor = math.floor, + log10 = math.log10, + min = math.min } local string = { format = string.format } -local tonumber = tonumber +local type = type +local tonumber = tonumber local setmetatable = setmetatable -- Battery infos @@ -63,25 +67,25 @@ local function worker(args) end function update() - local sum_rate_current = 0 - local sum_rate_voltage = 0 - local sum_rate_power = 0 - local sum_energy_now = 0 - local sum_energy_full = 0 + local sum_rate_current = 0 + local sum_rate_voltage = 0 + local sum_rate_power = 0 + local sum_rate_energy = 0 + local sum_energy_now = 0 + local sum_energy_full = 0 local sum_energy_percentage = 0 + local pspath = "/sys/class/power_supply/" for i, battery in ipairs(batteries) do - local bstr = "/sys/class/power_supply/" .. battery + local bstr = pspath .. battery local present = first_line(bstr .. "/present") - if tonumber(present) == 1 - then + if tonumber(present) == 1 then -- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW] local rate_current = tonumber(first_line(bstr .. "/current_now")) local rate_voltage = tonumber(first_line(bstr .. "/voltage_now")) local rate_power = tonumber(first_line(bstr .. "/power_now")) - -- energy_now(P)[uWh], charge_now(I)[uAh] local energy_now = tonumber(first_line(bstr .. "/energy_now") or first_line(bstr .. "/charge_now")) @@ -96,37 +100,44 @@ local function worker(args) bat_now.n_status[i] = first_line(bstr .. "/status") or "N/A" sum_rate_current = sum_rate_current + (rate_current or 0) - sum_rate_voltage = sum_rate_voltage + rate_voltage - sum_rate_power = sum_rate_power + (rate_power or ((rate_voltage * rate_current) / 1e6)) + sum_rate_voltage = sum_rate_voltage + (rate_voltage or 0) + sum_rate_power = sum_rate_power + (rate_power or 0) + sum_rate_energy = sum_rate_energy + (rate_power or (((rate_voltage or 0) * (rate_current or 0)) / 1e6)) sum_energy_now = sum_energy_now + (energy_now or 0) - sum_energy_full = sum_energy_full + energy_full - sum_energy_percentage = sum_energy_percentage + energy_percentage + sum_energy_full = sum_energy_full + (energy_full or 0) + sum_energy_percentage = sum_energy_percentage + (energy_percentage or 0) end end bat_now.status = bat_now.n_status[1] - bat_now.ac_status = tonumber(first_line(string.format("/sys/class/power_supply/%s/online", ac))) or "N/A" + bat_now.ac_status = tonumber(first_line(string.format("%s%s/online", pspath, ac))) or "N/A" if bat_now.status ~= "N/A" then -- update {perc,time,watt} iff battery not full and rate > 0 - if bat_now.status ~= "Full" and (sum_rate_current > 0 or sum_rate_power > 0) then + if bat_now.status ~= "Full" and (sum_rate_power > 0 or sum_rate_current > 0) then local rate_time = 0 + local div = (sum_rate_power > 0 and sum_rate_power) or sum_rate_current if bat_now.status == "Charging" then - rate_time = (sum_energy_full - sum_energy_now) / (sum_rate_power or sum_rate_current) - elseif bat_now.status == "Discharging" then - rate_time = sum_energy_now / (sum_rate_power or sum_rate_current) + rate_time = (sum_energy_full - sum_energy_now) / div + else -- Discharging + rate_time = sum_energy_now / div + end + + if rate_time < 0.01 then -- check for magnitude discrepancies (#199) + rate_time_magnitude = math.abs(math.floor(math.log10(rate_time))) + rate_time = rate_time * 10^(rate_time_magnitude - 2) end - local hours = math.floor(rate_time) - local minutes = math.floor((rate_time - hours) * 60) - bat_now.perc = tonumber(string.format("%d", math.min(100, sum_energy_percentage / #batteries))) - bat_now.time = string.format("%02d:%02d", hours, minutes) - bat_now.watt = tonumber(string.format("%.2f", sum_rate_power / 1e6)) + local hours = math.floor(rate_time) + local minutes = math.floor((rate_time - hours) * 60) + bat_now.perc = tonumber(string.format("%d", math.floor(math.min(100, sum_energy_percentage / #batteries)))) + bat_now.time = string.format("%02d:%02d", hours, minutes) + bat_now.watt = tonumber(string.format("%.2f", sum_rate_energy / 1e6)) elseif bat_now.status == "Full" then - bat_now.perc = 100 - bat_now.time = "00:00" - bat_now.watt = 0 + bat_now.perc = 100 + bat_now.time = "00:00" + bat_now.watt = 0 end end @@ -134,7 +145,7 @@ local function worker(args) settings() -- notifications for low and critical states - if notify == "on" and bat_now.perc and bat_now.status == "Discharging" then + if notify == "on" and type(bat_now.perc) == "number" and bat_now.status == "Discharging" then if bat_now.perc <= 5 then bat.id = naughty.notify({ preset = bat_notification_critical_preset, diff --git a/widgets/contrib/ccurr.lua b/widgets/contrib/ccurr.lua deleted file mode 100644 index 980e19b..0000000 --- a/widgets/contrib/ccurr.lua +++ /dev/null @@ -1,82 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2014, Aaron Lebo - ---]] - -local newtimer = require("lain.helpers").newtimer -local json = require("lain.util").dkjson - -local wibox = require("wibox") - -local string = { format = string.format } -local tonumber = tonumber - --- Crypto currencies widget --- lain.widgets.contrib.ccurr -local ccurr = {} - --- Currently gets --- * BTC/USD --- * DOGE/USD --- using Coinbase and Cryptsy APIs. - --- requires http://dkolf.de/src/dkjson-lua.fsl/home --- based upon http://awesome.naquadah.org/wiki/Bitcoin_Price_Widget - -local function get(url) - local f = io.popen('curl -m 5 -s "' .. url .. '"') - if not f then - return 0 - else - local s = f:read("*all") - f:close() - return s - end -end - -local function parse(j) - local obj, pos, err = json.decode(j, 1, nil) - if err then - return nil - else - return obj - end -end - -local function worker(args) - local args = args or {} - local timeout = args.timeout or 600 - local btc_url = args.btc_url or "https://coinbase.com/api/v1/prices/buy" - local doge_url = args.doge_url or "http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=132" - local settings = args.settings or function() end - - ccurr.widget = wibox.widget.textbox('') - - local function update() - price_now = { - btc = "N/A", - doge = "N/A" - } - - btc = parse(get(btc_url)) - doge = parse(get(doge_url)) - - if btc and doge then - price_now.btc = tonumber(btc["subtotal"]["amount"]) - price_now.doge = tonumber(doge["return"]["markets"]["DOGE"]["lasttradeprice"]) - price_now.doge = string.format("%.4f", price_now.btc * price_now.doge) - end - - widget = ccurr.widget - settings() - end - - newtimer("ccurr", timeout, update) - - return ccurr.widget -end - -return setmetatable(ccurr, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/contrib/gpmdp.lua b/widgets/contrib/gpmdp.lua new file mode 100644 index 0000000..fa51440 --- /dev/null +++ b/widgets/contrib/gpmdp.lua @@ -0,0 +1,95 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2016, Alexandre Terrien + +--]] + +local helpers = require("lain.helpers") +local json = require("lain.util.dkjson") +local pread = require("awful.util").pread +local naughty = require("naughty") +local wibox = require("wibox") +local mouse = mouse +local os = { getenv = os.getenv } + +local setmetatable = setmetatable + +-- Google Play Music Desktop infos +-- lain.widget.contrib.gpmdp +local gpmdp = {} + +local function worker(args) + local args = args or {} + local timeout = args.timeout or 2 + local notify = args.notify or "off" + local followmouse = args.followmouse or false + local file_location = args.file_location or + os.getenv("HOME") .. "/.config/Google Play Music Desktop Player/json_store/playback.json" + local settings = args.settings or function() end + + gpmdp.widget = wibox.widget.textbox('') + + gpmdp_notification_preset = { + title = "Now playing", + timeout = 6 + } + + helpers.set_map("gpmdp_current", nil) + + function gpmdp.update() + file, err = io.open(file_location, "r") + if not file + then + gpm_now = { running = false, playing = false } + else + dict, pos, err = json.decode(file:read "*a", 1, nil) + file:close() + gpm_now = {} + gpm_now.artist = dict.song.artist + gpm_now.album = dict.song.album + gpm_now.title = dict.song.title + gpm_now.cover_url = dict.song.albumArt + gpm_now.playing = dict.playing + end + + if (pread("pidof 'Google Play Music Desktop Player'") ~= '') then + gpm_now.running = true + else + gpm_now.running = false + end + + gpmdp_notification_preset.text = string.format("%s (%s) - %s", gpm_now.artist, gpm_now.album, gpm_now.title) + widget = gpmdp.widget + settings() + + if gpm_now.playing + then + if notify == "on" and gpm_now.title ~= helpers.get_map("gpmdp_current") + then + helpers.set_map("gpmdp_current", gpm_now.title) + os.execute("curl " .. gpm_now.cover_url .. " -o /tmp/gpmcover.png") + + if followmouse then + gpmdp_notification_preset.screen = mouse.screen + end + + gpmdp.id = naughty.notify({ + preset = gpmdp_notification_preset, + icon = "/tmp/gpmcover.png", + replaces_id = gpmdp.id, + }).id + end + elseif not gpm_now.running + then + helpers.set_map("gpmdp_current", nil) + end + end + + helpers.newtimer("gpmdp", timeout, gpmdp.update) + + return setmetatable(gpmdp, { __index = gpmdp.widget }) +end + +return setmetatable(gpmdp, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/fs.lua b/widgets/fs.lua index a1d5d95..6ec8dac 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -92,6 +92,7 @@ local function worker(args) fs_now.size_mb = tonumber(fs_info[partition .. " size_mb"]) or 0 fs_now.size_gb = tonumber(fs_info[partition .. " size_gb"]) or 0 + notification_preset = fs.notification_preset widget = fs.widget settings() diff --git a/widgets/net.lua b/widgets/net.lua index ee2cfa7..1883168 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -128,12 +128,12 @@ local function worker(args) net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ',', '.') net_now.received = string.gsub(string.format('%.1f', net_now.received), ',', '.') - widget = net.widget - settings() - net.last_t = total_t net.last_r = total_r end + + widget = net.widget + settings() end helpers.newtimer(iface, timeout, update) diff --git a/wiki b/wiki index eaa4aaa..52da2ca 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit eaa4aaac7fb0123a4dba05ac2ee63a5fa1247525 +Subproject commit 52da2ca514814006be9762fa3ba4f225d555aad4