Initial commit
This commit is contained in:
		
							
								
								
									
										54
									
								
								.config/awesome/lain/widget/alsa.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								.config/awesome/lain/widget/alsa.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013, Luca CPZ
 | 
			
		||||
      * (c) 2010, Adrian C. <anrxc@sysphere.org>
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers = require("lain.helpers")
 | 
			
		||||
local shell   = require("awful.util").shell
 | 
			
		||||
local wibox   = require("wibox")
 | 
			
		||||
local string  = string
 | 
			
		||||
 | 
			
		||||
-- ALSA volume
 | 
			
		||||
-- lain.widget.alsa
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args           = args or {}
 | 
			
		||||
    local alsa     = { widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local timeout  = args.timeout or 5
 | 
			
		||||
    local settings = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    alsa.cmd           = args.cmd or "amixer"
 | 
			
		||||
    alsa.channel       = args.channel or "Master"
 | 
			
		||||
    alsa.togglechannel = args.togglechannel
 | 
			
		||||
 | 
			
		||||
    local format_cmd = string.format("%s get %s", alsa.cmd, alsa.channel)
 | 
			
		||||
 | 
			
		||||
    if alsa.togglechannel then
 | 
			
		||||
        format_cmd = { shell, "-c", string.format("%s get %s; %s get %s",
 | 
			
		||||
        alsa.cmd, alsa.channel, alsa.cmd, alsa.togglechannel) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    alsa.last = {}
 | 
			
		||||
 | 
			
		||||
    function alsa.update()
 | 
			
		||||
        helpers.async(format_cmd, function(mixer)
 | 
			
		||||
            local l,s = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
 | 
			
		||||
            l = tonumber(l)
 | 
			
		||||
            if alsa.last.level ~= l or alsa.last.status ~= s then
 | 
			
		||||
                volume_now = { level = l, status = s }
 | 
			
		||||
                widget = alsa.widget
 | 
			
		||||
                settings()
 | 
			
		||||
                alsa.last = volume_now
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer(string.format("alsa-%s-%s", alsa.cmd, alsa.channel), timeout, alsa.update)
 | 
			
		||||
 | 
			
		||||
    return alsa
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										166
									
								
								.config/awesome/lain/widget/alsabar.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								.config/awesome/lain/widget/alsabar.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013, Luca CPZ
 | 
			
		||||
      * (c) 2013, Rman
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers  = require("lain.helpers")
 | 
			
		||||
local awful    = require("awful")
 | 
			
		||||
local naughty  = require("naughty")
 | 
			
		||||
local wibox    = require("wibox")
 | 
			
		||||
local math     = math
 | 
			
		||||
local string   = string
 | 
			
		||||
local type     = type
 | 
			
		||||
local tonumber = tonumber
 | 
			
		||||
 | 
			
		||||
-- ALSA volume bar
 | 
			
		||||
-- lain.widget.alsabar
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    local alsabar = {
 | 
			
		||||
        colors = {
 | 
			
		||||
            background = "#000000",
 | 
			
		||||
            mute       = "#EB8F8F",
 | 
			
		||||
            unmute     = "#A4CE8A"
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        _current_level = 0,
 | 
			
		||||
        _playback      = "off"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    args             = args or {}
 | 
			
		||||
 | 
			
		||||
    local timeout    = args.timeout or 5
 | 
			
		||||
    local settings   = args.settings or function() end
 | 
			
		||||
    local width      = args.width or 63
 | 
			
		||||
    local height     = args.height or 1
 | 
			
		||||
    local margins    = args.margins or 1
 | 
			
		||||
    local ticks      = args.ticks or false
 | 
			
		||||
    local ticks_size = args.ticks_size or 7
 | 
			
		||||
    local tick       = args.tick or "|"
 | 
			
		||||
    local tick_pre   = args.tick_pre or "["
 | 
			
		||||
    local tick_post  = args.tick_post or "]"
 | 
			
		||||
    local tick_none  = args.tick_none or " "
 | 
			
		||||
 | 
			
		||||
    alsabar.cmd                 = args.cmd or "amixer"
 | 
			
		||||
    alsabar.channel             = args.channel or "Master"
 | 
			
		||||
    alsabar.togglechannel       = args.togglechannel
 | 
			
		||||
    alsabar.colors              = args.colors or alsabar.colors
 | 
			
		||||
    alsabar.followtag           = args.followtag or false
 | 
			
		||||
    alsabar.notification_preset = args.notification_preset
 | 
			
		||||
 | 
			
		||||
    if not alsabar.notification_preset then
 | 
			
		||||
        alsabar.notification_preset = { font = "Monospace 10" }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local format_cmd = string.format("%s get %s", alsabar.cmd, alsabar.channel)
 | 
			
		||||
 | 
			
		||||
    if alsabar.togglechannel then
 | 
			
		||||
        format_cmd = { awful.util.shell, "-c", string.format("%s get %s; %s get %s",
 | 
			
		||||
        alsabar.cmd, alsabar.channel, alsabar.cmd, alsabar.togglechannel) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    alsabar.bar = wibox.widget {
 | 
			
		||||
        color            = alsabar.colors.unmute,
 | 
			
		||||
        background_color = alsabar.colors.background,
 | 
			
		||||
        forced_height    = height,
 | 
			
		||||
        forced_width     = width,
 | 
			
		||||
        margins          = margins,
 | 
			
		||||
        paddings         = margins,
 | 
			
		||||
        ticks            = ticks,
 | 
			
		||||
        ticks_size       = ticks_size,
 | 
			
		||||
        widget           = wibox.widget.progressbar
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
 | 
			
		||||
 | 
			
		||||
    function alsabar.update(callback)
 | 
			
		||||
        helpers.async(format_cmd, function(mixer)
 | 
			
		||||
            local vol, playback = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
 | 
			
		||||
 | 
			
		||||
            if not vol or not playback then return end
 | 
			
		||||
 | 
			
		||||
            if vol ~= alsabar._current_level or playback ~= alsabar._playback then
 | 
			
		||||
                alsabar._current_level = tonumber(vol)
 | 
			
		||||
                alsabar.bar:set_value(alsabar._current_level / 100)
 | 
			
		||||
                if alsabar._current_level == 0 or playback == "off" then
 | 
			
		||||
                    alsabar._playback = playback
 | 
			
		||||
                    alsabar.tooltip:set_text("[Muted]")
 | 
			
		||||
                    alsabar.bar.color = alsabar.colors.mute
 | 
			
		||||
                else
 | 
			
		||||
                    alsabar._playback = "on"
 | 
			
		||||
                    alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, vol))
 | 
			
		||||
                    alsabar.bar.color = alsabar.colors.unmute
 | 
			
		||||
                end
 | 
			
		||||
 | 
			
		||||
                volume_now = {
 | 
			
		||||
                    level  = alsabar._current_level,
 | 
			
		||||
                    status = alsabar._playback
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                settings()
 | 
			
		||||
 | 
			
		||||
                if type(callback) == "function" then callback() end
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function alsabar.notify()
 | 
			
		||||
        alsabar.update(function()
 | 
			
		||||
            local preset = alsabar.notification_preset
 | 
			
		||||
 | 
			
		||||
            preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
 | 
			
		||||
 | 
			
		||||
            if alsabar._playback == "off" then
 | 
			
		||||
                preset.title = preset.title .. " Muted"
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            -- tot is the maximum number of ticks to display in the notification
 | 
			
		||||
            local tot = alsabar.notification_preset.max_ticks
 | 
			
		||||
 | 
			
		||||
            if not tot then
 | 
			
		||||
                local wib = awful.screen.focused().mywibox
 | 
			
		||||
                -- if we can grab mywibox, tot is defined as its height if
 | 
			
		||||
                -- horizontal, or width otherwise
 | 
			
		||||
                if wib then
 | 
			
		||||
                    if wib.position == "left" or wib.position == "right" then
 | 
			
		||||
                        tot = wib.width
 | 
			
		||||
                    else
 | 
			
		||||
                        tot = wib.height
 | 
			
		||||
                    end
 | 
			
		||||
                -- fallback: default horizontal wibox height
 | 
			
		||||
                else
 | 
			
		||||
                    tot = 20
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            local int = math.modf((alsabar._current_level / 100) * tot)
 | 
			
		||||
            preset.text = string.format(
 | 
			
		||||
                "%s%s%s%s",
 | 
			
		||||
                tick_pre,
 | 
			
		||||
                string.rep(tick, int),
 | 
			
		||||
                string.rep(tick_none, tot - int),
 | 
			
		||||
                tick_post
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            if alsabar.followtag then preset.screen = awful.screen.focused() end
 | 
			
		||||
 | 
			
		||||
            if not alsabar.notification then
 | 
			
		||||
                alsabar.notification = naughty.notify {
 | 
			
		||||
                    preset  = preset,
 | 
			
		||||
                    destroy = function() alsabar.notification = nil end
 | 
			
		||||
                }
 | 
			
		||||
            else
 | 
			
		||||
                naughty.replace_text(alsabar.notification, preset.title, preset.text)
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer(string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel), timeout, alsabar.update)
 | 
			
		||||
 | 
			
		||||
    return alsabar
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										236
									
								
								.config/awesome/lain/widget/bat.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								.config/awesome/lain/widget/bat.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,236 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
	 Licensed under GNU General Public License v2
 | 
			
		||||
	  * (c) 2013,      Luca CPZ
 | 
			
		||||
	  * (c) 2010-2012, Peter Hofmann
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers  = require("lain.helpers")
 | 
			
		||||
local fs       = require("gears.filesystem")
 | 
			
		||||
local naughty  = require("naughty")
 | 
			
		||||
local wibox    = require("wibox")
 | 
			
		||||
local math     = math
 | 
			
		||||
local string   = string
 | 
			
		||||
local ipairs   = ipairs
 | 
			
		||||
local tonumber = tonumber
 | 
			
		||||
 | 
			
		||||
-- Battery infos
 | 
			
		||||
-- lain.widget.bat
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    local pspath = args.pspath or "/sys/class/power_supply/"
 | 
			
		||||
 | 
			
		||||
    if not fs.is_dir(pspath) then
 | 
			
		||||
        naughty.notify { text = "lain.widget.bat: invalid power supply path", timeout = 0 }
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    args              = args or {}
 | 
			
		||||
 | 
			
		||||
    local bat         = { widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local timeout     = args.timeout or 30
 | 
			
		||||
    local notify      = args.notify or "on"
 | 
			
		||||
    local full_notify = args.full_notify or notify
 | 
			
		||||
    local n_perc      = args.n_perc or { 5, 15 }
 | 
			
		||||
    local batteries   = args.batteries or (args.battery and {args.battery}) or {}
 | 
			
		||||
    local ac          = args.ac or "AC0"
 | 
			
		||||
    local settings    = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    function bat.get_batteries()
 | 
			
		||||
        helpers.line_callback("ls -1 " .. pspath, function(line)
 | 
			
		||||
            local bstr =  string.match(line, "BAT%w+")
 | 
			
		||||
            if bstr then
 | 
			
		||||
                batteries[#batteries + 1] = bstr
 | 
			
		||||
            else
 | 
			
		||||
                ac = string.match(line, "A%w+") or ac
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if #batteries == 0 then bat.get_batteries() end
 | 
			
		||||
 | 
			
		||||
    bat_notification_critical_preset = {
 | 
			
		||||
        title   = "Battery exhausted",
 | 
			
		||||
        text    = "Shutdown imminent",
 | 
			
		||||
        timeout = 15,
 | 
			
		||||
        fg      = "#000000",
 | 
			
		||||
        bg      = "#FFFFFF"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bat_notification_low_preset = {
 | 
			
		||||
        title   = "Battery low",
 | 
			
		||||
        text    = "Plug the cable!",
 | 
			
		||||
        timeout = 15,
 | 
			
		||||
        fg      = "#202020",
 | 
			
		||||
        bg      = "#CDCDCD"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bat_notification_charged_preset = {
 | 
			
		||||
        title   = "Battery full",
 | 
			
		||||
        text    = "You can unplug the cable",
 | 
			
		||||
        timeout = 15,
 | 
			
		||||
        fg      = "#202020",
 | 
			
		||||
        bg      = "#CDCDCD"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bat_now = {
 | 
			
		||||
        status    = "N/A",
 | 
			
		||||
        ac_status = "N/A",
 | 
			
		||||
        perc      = "N/A",
 | 
			
		||||
        time      = "N/A",
 | 
			
		||||
        watt      = "N/A",
 | 
			
		||||
        capacity  = "N/A"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bat_now.n_status   = {}
 | 
			
		||||
    bat_now.n_perc     = {}
 | 
			
		||||
    bat_now.n_capacity = {}
 | 
			
		||||
    for i = 1, #batteries do
 | 
			
		||||
        bat_now.n_status[i] = "N/A"
 | 
			
		||||
        bat_now.n_perc[i] = 0
 | 
			
		||||
        bat_now.n_capacity[i] = 0
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    -- used to notify full charge only once before discharging
 | 
			
		||||
    local fullnotification = false
 | 
			
		||||
 | 
			
		||||
    function bat.update()
 | 
			
		||||
        -- luacheck: globals bat_now
 | 
			
		||||
        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_charge_full   = 0
 | 
			
		||||
        local sum_charge_design = 0
 | 
			
		||||
 | 
			
		||||
        for i, battery in ipairs(batteries) do
 | 
			
		||||
            local bstr    = pspath .. battery
 | 
			
		||||
            local present = helpers.first_line(bstr .. "/present")
 | 
			
		||||
 | 
			
		||||
            if tonumber(present) == 1 then
 | 
			
		||||
                -- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW]
 | 
			
		||||
                local rate_current = tonumber(helpers.first_line(bstr .. "/current_now"))
 | 
			
		||||
                local rate_voltage = tonumber(helpers.first_line(bstr .. "/voltage_now"))
 | 
			
		||||
                local rate_power   = tonumber(helpers.first_line(bstr .. "/power_now"))
 | 
			
		||||
                local charge_full  = tonumber(helpers.first_line(bstr .. "/charge_full"))
 | 
			
		||||
                local charge_design = tonumber(helpers.first_line(bstr .. "/charge_full_design"))
 | 
			
		||||
 | 
			
		||||
                -- energy_now(P)[uWh], charge_now(I)[uAh]
 | 
			
		||||
                local energy_now = tonumber(helpers.first_line(bstr .. "/energy_now") or
 | 
			
		||||
                                   helpers.first_line(bstr .. "/charge_now"))
 | 
			
		||||
 | 
			
		||||
                -- energy_full(P)[uWh], charge_full(I)[uAh]
 | 
			
		||||
                local energy_full = tonumber(helpers.first_line(bstr .. "/energy_full") or
 | 
			
		||||
                                    charge_full)
 | 
			
		||||
 | 
			
		||||
                local energy_percentage = tonumber(helpers.first_line(bstr .. "/capacity")) or
 | 
			
		||||
                                          math.floor((energy_now / energy_full) * 100)
 | 
			
		||||
 | 
			
		||||
                bat_now.n_status[i] = helpers.first_line(bstr .. "/status") or "N/A"
 | 
			
		||||
                bat_now.n_perc[i]   = energy_percentage or bat_now.n_perc[i]
 | 
			
		||||
 | 
			
		||||
                if not charge_design or charge_design == 0 then
 | 
			
		||||
                    bat_now.n_capacity[i] = 0
 | 
			
		||||
                else
 | 
			
		||||
                    bat_now.n_capacity[i] = math.floor((charge_full / charge_design) * 100)
 | 
			
		||||
                end
 | 
			
		||||
 | 
			
		||||
                sum_rate_current  = sum_rate_current + (rate_current or 0)
 | 
			
		||||
                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 or 0)
 | 
			
		||||
                sum_charge_full   = sum_charge_full + (charge_full or 0)
 | 
			
		||||
                sum_charge_design = sum_charge_design + (charge_design or 0)
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        bat_now.capacity = math.floor(math.min(100, (sum_charge_full / sum_charge_design) * 100))
 | 
			
		||||
 | 
			
		||||
        -- When one of the battery is charging, others' status are either
 | 
			
		||||
        -- "Full", "Unknown" or "Charging". When the laptop is not plugged in,
 | 
			
		||||
        -- one or more of the batteries may be full, but only one battery
 | 
			
		||||
        -- discharging suffices to set global status to "Discharging".
 | 
			
		||||
        bat_now.status = bat_now.n_status[1] or "N/A"
 | 
			
		||||
        for _,status in ipairs(bat_now.n_status) do
 | 
			
		||||
            if status == "Discharging" or status == "Charging" then
 | 
			
		||||
                bat_now.status = status
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
        bat_now.ac_status = tonumber(helpers.first_line(string.format("%s%s/online", pspath, ac))) or "N/A"
 | 
			
		||||
 | 
			
		||||
        if bat_now.status ~= "N/A" then
 | 
			
		||||
            if bat_now.status ~= "Full" and sum_rate_power == 0 and bat_now.ac_status == 1 then
 | 
			
		||||
                bat_now.perc  = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100))
 | 
			
		||||
                bat_now.time  = "00:00"
 | 
			
		||||
                bat_now.watt  = 0
 | 
			
		||||
 | 
			
		||||
            -- update {perc,time,watt} iff battery not full and rate > 0
 | 
			
		||||
            elseif bat_now.status ~= "Full" then
 | 
			
		||||
                local rate_time = 0
 | 
			
		||||
                -- Calculate time and watt if rates are greater then 0
 | 
			
		||||
                if (sum_rate_power > 0 or sum_rate_current > 0) then
 | 
			
		||||
                    local div = (sum_rate_power > 0 and sum_rate_power) or sum_rate_current
 | 
			
		||||
 | 
			
		||||
                    if bat_now.status == "Charging" then
 | 
			
		||||
                        rate_time = (sum_energy_full - sum_energy_now) / div
 | 
			
		||||
                    else -- Discharging
 | 
			
		||||
                        rate_time = sum_energy_now / div
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                    if 0 < rate_time and rate_time < 0.01 then -- check for magnitude discrepancies (#199)
 | 
			
		||||
                        rate_time_magnitude = math.abs(math.floor(math.log10(rate_time)))
 | 
			
		||||
                        rate_time = rate_time * 10^(rate_time_magnitude - 2)
 | 
			
		||||
                    end
 | 
			
		||||
                 end
 | 
			
		||||
 | 
			
		||||
                local hours   = math.floor(rate_time)
 | 
			
		||||
                local minutes = math.floor((rate_time - hours) * 60)
 | 
			
		||||
                bat_now.perc  = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100))
 | 
			
		||||
                bat_now.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
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        widget = bat.widget
 | 
			
		||||
        settings()
 | 
			
		||||
 | 
			
		||||
        -- notifications for critical, low, and full levels
 | 
			
		||||
        if notify == "on" then
 | 
			
		||||
            if bat_now.status == "Discharging" then
 | 
			
		||||
                if tonumber(bat_now.perc) <= n_perc[1] then
 | 
			
		||||
                    bat.id = naughty.notify({
 | 
			
		||||
                        preset = bat_notification_critical_preset,
 | 
			
		||||
                        replaces_id = bat.id
 | 
			
		||||
                    }).id
 | 
			
		||||
                elseif tonumber(bat_now.perc) <= n_perc[2] then
 | 
			
		||||
                    bat.id = naughty.notify({
 | 
			
		||||
                        preset = bat_notification_low_preset,
 | 
			
		||||
                        replaces_id = bat.id
 | 
			
		||||
                    }).id
 | 
			
		||||
                end
 | 
			
		||||
                fullnotification = false
 | 
			
		||||
            elseif bat_now.status == "Full" and full_notify == "on" and not fullnotification then
 | 
			
		||||
                bat.id = naughty.notify({
 | 
			
		||||
                    preset = bat_notification_charged_preset,
 | 
			
		||||
                    replaces_id = bat.id
 | 
			
		||||
                }).id
 | 
			
		||||
                fullnotification = true
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer("batteries", timeout, bat.update)
 | 
			
		||||
 | 
			
		||||
    return bat
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										191
									
								
								.config/awesome/lain/widget/cal.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								.config/awesome/lain/widget/cal.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2018, Luca CPZ
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers  = require("lain.helpers")
 | 
			
		||||
local markup   = require("lain.util.markup")
 | 
			
		||||
local awful    = require("awful")
 | 
			
		||||
local naughty  = require("naughty")
 | 
			
		||||
local floor    = math.floor
 | 
			
		||||
local os       = os
 | 
			
		||||
local pairs    = pairs
 | 
			
		||||
local string   = string
 | 
			
		||||
local tconcat  = table.concat
 | 
			
		||||
local type     = type
 | 
			
		||||
local tonumber = tonumber
 | 
			
		||||
local tostring = tostring
 | 
			
		||||
 | 
			
		||||
-- Calendar notification
 | 
			
		||||
-- lain.widget.cal
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args = args or {}
 | 
			
		||||
    local cal = {
 | 
			
		||||
        attach_to           = args.attach_to or {},
 | 
			
		||||
        week_start          = args.week_start or 2,
 | 
			
		||||
        three               = args.three or false,
 | 
			
		||||
        followtag           = args.followtag or false,
 | 
			
		||||
        week_number         = args.week_number or "none",
 | 
			
		||||
        week_number_format  = args.week_number_format or args.week_number == "left" and "%3d | " or "| %-3d",
 | 
			
		||||
        icons               = args.icons or helpers.icons_dir .. "cal/white/",
 | 
			
		||||
        notification_preset = args.notification_preset or {
 | 
			
		||||
            font = "Monospace 10", fg = "#FFFFFF", bg = "#000000"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function cal.get_week_number(m, st_day, x)
 | 
			
		||||
        local date = os.date("*t", m)
 | 
			
		||||
 | 
			
		||||
        local week_step = (x ~= 0 and floor((x + st_day) / 7) - 1 or 0);
 | 
			
		||||
 | 
			
		||||
        local display_time = os.time {
 | 
			
		||||
            year = date.year, month = date.month, day = date.day + 7 * week_step
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return string.format(cal.week_number_format, os.date("%V", display_time))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function cal.sum_week_days(x, y)
 | 
			
		||||
        return (x + y) % 7
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function cal.build(month, year)
 | 
			
		||||
        local current_month, current_year = tonumber(os.date("%m")), tonumber(os.date("%Y"))
 | 
			
		||||
        local is_current_month = (not month or not year) or (month == current_month and year == current_year)
 | 
			
		||||
        local today = is_current_month and tonumber(os.date("%d")) -- otherwise nil and not highlighted
 | 
			
		||||
        local t = os.time { year = year or current_year, month = month and month+1 or current_month+1, day = 0 }
 | 
			
		||||
        local d = os.date("*t", t)
 | 
			
		||||
        local mth_days, st_day, this_month = d.day, (d.wday-d.day-cal.week_start+1)%7, os.date("%B %Y", t)
 | 
			
		||||
        local notifytable = { [1] = string.format("%s%s\n", string.rep(" ", floor((28 - this_month:len())/2)), markup.bold(this_month)) }
 | 
			
		||||
        for day_num = 0, 6 do
 | 
			
		||||
            notifytable[#notifytable+1] = string.format("%3s ", os.date("%a", os.time { year = 2006, month = 1, day = day_num + cal.week_start }))
 | 
			
		||||
        end
 | 
			
		||||
        notifytable[#notifytable] = string.format("%s\n%s", notifytable[#notifytable]:sub(1, -2), string.rep(" ", st_day*4))
 | 
			
		||||
        local strx
 | 
			
		||||
        for x = 1,mth_days do
 | 
			
		||||
            strx = x
 | 
			
		||||
            if x == today then
 | 
			
		||||
                if x < 10 then x = " " .. x end
 | 
			
		||||
                strx = markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. " ")
 | 
			
		||||
            end
 | 
			
		||||
            strx = string.format("%s%s", string.rep(" ", 3 - tostring(x):len()), strx)
 | 
			
		||||
            notifytable[#notifytable+1] = string.format("%-4s%s", strx, (x+st_day)%7==0 and x ~= mth_days and "\n" or "")
 | 
			
		||||
        end
 | 
			
		||||
        if string.len(cal.icons or "") > 0 and today then cal.icon = cal.icons .. today .. ".png" end
 | 
			
		||||
        cal.month, cal.year = d.month, d.year
 | 
			
		||||
 | 
			
		||||
        if cal.week_number ~= "none" then
 | 
			
		||||
            local m = os.time { year = year or current_year, month = month and month or current_month, day = 1 }
 | 
			
		||||
            local head_prepend = string.rep(" ", tostring(string.format(cal.week_number_format, 0)):len())
 | 
			
		||||
 | 
			
		||||
            if cal.week_number == "left" then
 | 
			
		||||
                notifytable[1] = head_prepend .. notifytable[1] -- month-year row
 | 
			
		||||
                notifytable[2] = head_prepend .. notifytable[2] -- weekdays row
 | 
			
		||||
                notifytable[8] = notifytable[8]:gsub("\n", "\n" .. cal.get_week_number(m, st_day, 0)) -- first week of the month
 | 
			
		||||
 | 
			
		||||
                for x = 10,#notifytable do
 | 
			
		||||
                    if cal.sum_week_days(st_day, x) == 2 then
 | 
			
		||||
                        notifytable[x] = cal.get_week_number(m, st_day, x) .. notifytable[x]
 | 
			
		||||
                    end
 | 
			
		||||
                end
 | 
			
		||||
            elseif cal.week_number == "right" then
 | 
			
		||||
                notifytable[8] = notifytable[8]:gsub("\n", head_prepend .. "\n") -- weekdays row
 | 
			
		||||
                for x = 9,#notifytable do
 | 
			
		||||
                    if cal.sum_week_days(st_day, x) == 1 then
 | 
			
		||||
                        notifytable[x] = notifytable[x]:gsub("\n", cal.get_week_number(m, st_day, x - 7) .. "\n")
 | 
			
		||||
                    end
 | 
			
		||||
                end
 | 
			
		||||
                -- last week of the month
 | 
			
		||||
                local end_days = cal.sum_week_days(st_day, mth_days)
 | 
			
		||||
                if end_days ~= 0 then end_days = 7 - end_days end
 | 
			
		||||
                notifytable[#notifytable] = notifytable[#notifytable] .. string.rep(" ", 4 * end_days) .. cal.get_week_number(m, st_day, mth_days + end_days)
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        return notifytable
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function cal.getdate(month, year, offset)
 | 
			
		||||
        if not month or not year then
 | 
			
		||||
            month = tonumber(os.date("%m"))
 | 
			
		||||
            year  = tonumber(os.date("%Y"))
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        month = month + offset
 | 
			
		||||
 | 
			
		||||
        while month > 12 do
 | 
			
		||||
            month = month - 12
 | 
			
		||||
            year = year + 1
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        while month < 1 do
 | 
			
		||||
            month = month + 12
 | 
			
		||||
            year = year - 1
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        return month, year
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function cal.hide()
 | 
			
		||||
        if not cal.notification then return end
 | 
			
		||||
        naughty.destroy(cal.notification)
 | 
			
		||||
        cal.notification = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function cal.show(seconds, month, year, scr)
 | 
			
		||||
        local text = tconcat(cal.build(month, year))
 | 
			
		||||
 | 
			
		||||
        if cal.three then
 | 
			
		||||
            local current_month, current_year = cal.month, cal.year
 | 
			
		||||
            local prev_month, prev_year = cal.getdate(cal.month, cal.year, -1)
 | 
			
		||||
            local next_month, next_year = cal.getdate(cal.month, cal.year,  1)
 | 
			
		||||
            text = string.format("%s\n\n%s\n\n%s",
 | 
			
		||||
            tconcat(cal.build(prev_month, prev_year)), text,
 | 
			
		||||
            tconcat(cal.build(next_month, next_year)))
 | 
			
		||||
            cal.month, cal.year = current_month, current_year
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if cal.notification then
 | 
			
		||||
            local title = cal.notification_preset.title or nil
 | 
			
		||||
            naughty.replace_text(cal.notification, title, text)
 | 
			
		||||
            return
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        cal.notification = naughty.notify {
 | 
			
		||||
            preset  = cal.notification_preset,
 | 
			
		||||
            screen  = cal.followtag and awful.screen.focused() or scr or 1,
 | 
			
		||||
            icon    = cal.icon,
 | 
			
		||||
            timeout = type(seconds) == "number" and seconds or cal.notification_preset.timeout or 5,
 | 
			
		||||
            text    = text
 | 
			
		||||
        }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function cal.hover_on() cal.show(0) end
 | 
			
		||||
    function cal.move(offset)
 | 
			
		||||
        offset = offset or 0
 | 
			
		||||
        cal.month, cal.year = cal.getdate(cal.month, cal.year, offset)
 | 
			
		||||
        cal.show(0, cal.month, cal.year)
 | 
			
		||||
    end
 | 
			
		||||
    function cal.prev() cal.move(-1) end
 | 
			
		||||
    function cal.next() cal.move( 1) end
 | 
			
		||||
 | 
			
		||||
    function cal.attach(widget)
 | 
			
		||||
        widget:connect_signal("mouse::enter", cal.hover_on)
 | 
			
		||||
        widget:connect_signal("mouse::leave", cal.hide)
 | 
			
		||||
        widget:buttons(awful.util.table.join(
 | 
			
		||||
                    awful.button({}, 1, cal.prev),
 | 
			
		||||
                    awful.button({}, 3, cal.next),
 | 
			
		||||
                    awful.button({}, 2, cal.hover_on),
 | 
			
		||||
                    awful.button({}, 5, cal.prev),
 | 
			
		||||
                    awful.button({}, 4, cal.next)))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    for _, widget in pairs(cal.attach_to) do cal.attach(widget) end
 | 
			
		||||
 | 
			
		||||
    return cal
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										18
									
								
								.config/awesome/lain/widget/contrib/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.config/awesome/lain/widget/contrib/init.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Lain
 | 
			
		||||
     Layouts, widgets and utilities for Awesome WM
 | 
			
		||||
 | 
			
		||||
     Users contributed widgets section
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013, Luca CPZ
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local wrequire     = require("lain.helpers").wrequire
 | 
			
		||||
local setmetatable = setmetatable
 | 
			
		||||
 | 
			
		||||
local widget = { _NAME = "lain.widget.contrib" }
 | 
			
		||||
 | 
			
		||||
return setmetatable(widget, { __index = wrequire })
 | 
			
		||||
							
								
								
									
										97
									
								
								.config/awesome/lain/widget/contrib/moc.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								.config/awesome/lain/widget/contrib/moc.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2014, anticlockwise <http://github.com/anticlockwise>
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers      = require("lain.helpers")
 | 
			
		||||
local shell        = require("awful.util").shell
 | 
			
		||||
local focused      = require("awful.screen").focused
 | 
			
		||||
local escape_f     = require("awful.util").escape
 | 
			
		||||
local naughty      = require("naughty")
 | 
			
		||||
local wibox        = require("wibox")
 | 
			
		||||
local os           = os
 | 
			
		||||
local string       = string
 | 
			
		||||
 | 
			
		||||
-- MOC audio player
 | 
			
		||||
-- lain.widget.contrib.moc
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args                = args or {}
 | 
			
		||||
 | 
			
		||||
    local moc           = { widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local timeout       = args.timeout or 2
 | 
			
		||||
    local music_dir     = args.music_dir or os.getenv("HOME") .. "/Music"
 | 
			
		||||
    local cover_pattern = args.cover_pattern or "*\\.(jpg|jpeg|png|gif)$"
 | 
			
		||||
    local cover_size    = args.cover_size or 100
 | 
			
		||||
    local default_art   = args.default_art or ""
 | 
			
		||||
    local followtag     = args.followtag or false
 | 
			
		||||
    local settings      = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    moc_notification_preset = { title = "Now playing", timeout = 6 }
 | 
			
		||||
 | 
			
		||||
    helpers.set_map("current moc track", nil)
 | 
			
		||||
 | 
			
		||||
    function moc.update()
 | 
			
		||||
        helpers.async("mocp -i", function(f)
 | 
			
		||||
            moc_now = {
 | 
			
		||||
                state   = "N/A",
 | 
			
		||||
                file    = "N/A",
 | 
			
		||||
                artist  = "N/A",
 | 
			
		||||
                title   = "N/A",
 | 
			
		||||
                album   = "N/A",
 | 
			
		||||
                elapsed = "N/A",
 | 
			
		||||
                total   = "N/A"
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for line in string.gmatch(f, "[^\n]+") do
 | 
			
		||||
                for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
 | 
			
		||||
                    if     k == "State"       then moc_now.state   = v
 | 
			
		||||
                    elseif k == "File"        then moc_now.file    = v
 | 
			
		||||
                    elseif k == "Artist"      then moc_now.artist  = escape_f(v)
 | 
			
		||||
                    elseif k == "SongTitle"   then moc_now.title   = escape_f(v)
 | 
			
		||||
                    elseif k == "Album"       then moc_now.album   = escape_f(v)
 | 
			
		||||
                    elseif k == "CurrentTime" then moc_now.elapsed = escape_f(v)
 | 
			
		||||
                    elseif k == "TotalTime"   then moc_now.total   = escape_f(v)
 | 
			
		||||
                    end
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            moc_notification_preset.text = string.format("%s (%s) - %s\n%s", moc_now.artist,
 | 
			
		||||
                                           moc_now.album, moc_now.total, moc_now.title)
 | 
			
		||||
            widget = moc.widget
 | 
			
		||||
            settings()
 | 
			
		||||
 | 
			
		||||
            if moc_now.state == "PLAY" then
 | 
			
		||||
                if moc_now.title ~= helpers.get_map("current moc track") then
 | 
			
		||||
                    helpers.set_map("current moc track", moc_now.title)
 | 
			
		||||
 | 
			
		||||
                    if followtag then moc_notification_preset.screen = focused() end
 | 
			
		||||
 | 
			
		||||
                    local common =  {
 | 
			
		||||
                        preset      = moc_notification_preset,
 | 
			
		||||
                        icon        = default_art,
 | 
			
		||||
                        icon_size   = cover_size,
 | 
			
		||||
                        replaces_id = moc.id,
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    local path   = string.format("%s/%s", music_dir, string.match(moc_now.file, ".*/"))
 | 
			
		||||
                    local cover  = string.format("find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'", path, cover_pattern)
 | 
			
		||||
                    helpers.async({ shell, "-c", cover }, function(current_icon)
 | 
			
		||||
                        common.icon = current_icon:gsub("\n", "")
 | 
			
		||||
                        moc.id = naughty.notify(common).id
 | 
			
		||||
                    end)
 | 
			
		||||
                end
 | 
			
		||||
            elseif  moc_now.state ~= "PAUSE" then
 | 
			
		||||
                helpers.set_map("current moc track", nil)
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    moc.timer = helpers.newtimer("moc", timeout, moc.update, true, true)
 | 
			
		||||
 | 
			
		||||
    return moc
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										54
									
								
								.config/awesome/lain/widget/contrib/redshift.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								.config/awesome/lain/widget/contrib/redshift.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2017, Luca CPZ
 | 
			
		||||
      * (c) 2014, blueluke <http://github.com/blueluke>
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local async   = require("lain.helpers").async
 | 
			
		||||
local awful   = require("awful")
 | 
			
		||||
local execute = os.execute
 | 
			
		||||
local type    = type
 | 
			
		||||
 | 
			
		||||
-- Redshift
 | 
			
		||||
-- lain.widget.contrib.redshift
 | 
			
		||||
local redshift = { active = false, pid = nil }
 | 
			
		||||
 | 
			
		||||
function redshift.start()
 | 
			
		||||
    execute("pkill redshift")
 | 
			
		||||
    awful.spawn.with_shell("redshift -x") -- clear adjustments
 | 
			
		||||
    redshift.pid = awful.spawn.with_shell("redshift")
 | 
			
		||||
    redshift.active = true
 | 
			
		||||
    if type(redshift.update_fun) == "function" then
 | 
			
		||||
        redshift.update_fun(redshift.active)
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function redshift.toggle()
 | 
			
		||||
    async({ awful.util.shell, "-c", string.format("ps -p %d -o pid=", redshift.pid) }, function(f)
 | 
			
		||||
        if f and #f > 0 then -- redshift is running
 | 
			
		||||
            -- Sending -USR1 toggles redshift (See project website)
 | 
			
		||||
            execute("pkill -USR1 redshift")
 | 
			
		||||
            redshift.active = not redshift.active
 | 
			
		||||
        else -- not started or killed, (re)start it
 | 
			
		||||
            redshift.start()
 | 
			
		||||
        end
 | 
			
		||||
        redshift.update_fun(redshift.active)
 | 
			
		||||
    end)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Attach to a widget
 | 
			
		||||
-- Provides a button which toggles redshift on/off on click
 | 
			
		||||
-- @param widget:  Widget to attach to.
 | 
			
		||||
-- @param fun:     Function to be run each time redshift is toggled (optional).
 | 
			
		||||
--                 Use it to update widget text or icons on status change.
 | 
			
		||||
function redshift.attach(widget, fun)
 | 
			
		||||
    redshift.update_fun = fun or function() end
 | 
			
		||||
    if not redshift.pid then redshift.start() end
 | 
			
		||||
    if widget then
 | 
			
		||||
        widget:buttons(awful.util.table.join(awful.button({}, 1, function () redshift.toggle() end)))
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return redshift
 | 
			
		||||
							
								
								
									
										92
									
								
								.config/awesome/lain/widget/contrib/task.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								.config/awesome/lain/widget/contrib/task.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013, Jan Xie
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers = require("lain.helpers")
 | 
			
		||||
local markup  = require("lain.util").markup
 | 
			
		||||
local awful   = require("awful")
 | 
			
		||||
local naughty = require("naughty")
 | 
			
		||||
local mouse   = mouse
 | 
			
		||||
 | 
			
		||||
-- Taskwarrior notification
 | 
			
		||||
-- lain.widget.contrib.task
 | 
			
		||||
local task = {}
 | 
			
		||||
 | 
			
		||||
function task.hide()
 | 
			
		||||
    if not task.notification then return end
 | 
			
		||||
    naughty.destroy(task.notification)
 | 
			
		||||
    task.notification = nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function task.show(scr)
 | 
			
		||||
    task.notification_preset.screen = task.followtag and awful.screen.focused() or scr or 1
 | 
			
		||||
 | 
			
		||||
    helpers.async({ awful.util.shell, "-c", task.show_cmd }, function(f)
 | 
			
		||||
        local widget_focused = true
 | 
			
		||||
 | 
			
		||||
        if mouse.current_widgets then
 | 
			
		||||
            widget_focused = false
 | 
			
		||||
            for _,v in ipairs(mouse.current_widgets) do
 | 
			
		||||
                if task.widget == v then
 | 
			
		||||
                    widget_focused = true
 | 
			
		||||
                    break
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if widget_focused then
 | 
			
		||||
            task.hide()
 | 
			
		||||
            task.notification = naughty.notify {
 | 
			
		||||
                preset = task.notification_preset,
 | 
			
		||||
                title  = "task next",
 | 
			
		||||
                text   = markup.font(task.notification_preset.font,
 | 
			
		||||
                         awful.util.escape(f:gsub("\n*$", "")))
 | 
			
		||||
            }
 | 
			
		||||
        end
 | 
			
		||||
    end)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function task.prompt()
 | 
			
		||||
    awful.prompt.run {
 | 
			
		||||
        prompt       = task.prompt_text,
 | 
			
		||||
        textbox      = awful.screen.focused().mypromptbox.widget,
 | 
			
		||||
        exe_callback = function(t)
 | 
			
		||||
            helpers.async(t, function(f)
 | 
			
		||||
                naughty.notify {
 | 
			
		||||
                    preset = task.notification_preset,
 | 
			
		||||
                    title  = t,
 | 
			
		||||
                    text   = markup.font(task.notification_preset.font,
 | 
			
		||||
                             awful.util.escape(f:gsub("\n*$", "")))
 | 
			
		||||
                }
 | 
			
		||||
            end)
 | 
			
		||||
        end,
 | 
			
		||||
        history_path = awful.util.getdir("cache") .. "/history_task"
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function task.attach(widget, args)
 | 
			
		||||
    args                     = args or {}
 | 
			
		||||
 | 
			
		||||
    task.show_cmd            = args.show_cmd or "task next"
 | 
			
		||||
    task.prompt_text         = args.prompt_text or "Enter task command: "
 | 
			
		||||
    task.followtag           = args.followtag or false
 | 
			
		||||
    task.notification_preset = args.notification_preset
 | 
			
		||||
    task.widget              = widget
 | 
			
		||||
 | 
			
		||||
    if not task.notification_preset then
 | 
			
		||||
        task.notification_preset = {
 | 
			
		||||
            font = "Monospace 10",
 | 
			
		||||
            icon = helpers.icons_dir .. "/taskwarrior.png"
 | 
			
		||||
        }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if widget then
 | 
			
		||||
        widget:connect_signal("mouse::enter", function () task.show() end)
 | 
			
		||||
        widget:connect_signal("mouse::leave", function () task.hide() end)
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return task
 | 
			
		||||
							
								
								
									
										147
									
								
								.config/awesome/lain/widget/contrib/tp_smapi.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								.config/awesome/lain/widget/contrib/tp_smapi.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,147 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2018, Luca CPZ
 | 
			
		||||
      * (c) 2013, Conor Heine
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers = require("lain.helpers")
 | 
			
		||||
local focused = require("awful.screen").focused
 | 
			
		||||
local naughty = require("naughty")
 | 
			
		||||
local wibox   = require("wibox")
 | 
			
		||||
local string  = string
 | 
			
		||||
local type    = type
 | 
			
		||||
 | 
			
		||||
-- ThinkPad battery infos and widget creator
 | 
			
		||||
-- http://www.thinkwiki.org/wiki/Tp_smapi
 | 
			
		||||
-- lain.widget.contrib.tp_smapi
 | 
			
		||||
 | 
			
		||||
local function factory(apipath)
 | 
			
		||||
    local tp_smapi = {
 | 
			
		||||
        path = apipath or "/sys/devices/platform/smapi"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function tp_smapi.get(batid, feature)
 | 
			
		||||
        return helpers.first_line(string.format("%s/%s/%s", tp_smapi.path, batid or "BAT0", feature or ""))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function tp_smapi.installed(batid)
 | 
			
		||||
        return tp_smapi.get(batid, "installed") == "1"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function tp_smapi.status(batid)
 | 
			
		||||
        return tp_smapi.get(batid, "state")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function tp_smapi.percentage(batid)
 | 
			
		||||
        return tp_smapi.get(batid, "remaining_percent")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    -- either running or charging time
 | 
			
		||||
    function tp_smapi.time(batid)
 | 
			
		||||
        local status = tp_smapi.status(batid)
 | 
			
		||||
        local mins_left = tp_smapi.get(batid, string.match(string.lower(status), "discharging") and "remaining_running_time" or "remaining_charging_time")
 | 
			
		||||
        if not string.find(mins_left, "^%d+") then return "N/A" end
 | 
			
		||||
        return string.format("%02d:%02d", math.floor(mins_left / 60), mins_left % 60) -- HH:mm
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function tp_smapi.hide()
 | 
			
		||||
        if not tp_smapi.notification then return end
 | 
			
		||||
        naughty.destroy(tp_smapi.notification)
 | 
			
		||||
        tp_smapi.notification = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function tp_smapi.show(batid, seconds, scr)
 | 
			
		||||
        if not tp_smapi.installed(batid) then return end
 | 
			
		||||
 | 
			
		||||
        local mfgr   = tp_smapi.get(batid, "manufacturer") or "no_mfgr"
 | 
			
		||||
        local model  = tp_smapi.get(batid, "model") or "no_model"
 | 
			
		||||
        local chem   = tp_smapi.get(batid, "chemistry") or "no_chem"
 | 
			
		||||
        local status = tp_smapi.get(batid, "state")
 | 
			
		||||
        local time   = tp_smapi.time(batid)
 | 
			
		||||
        local msg
 | 
			
		||||
 | 
			
		||||
        if status and status ~= "idle" then
 | 
			
		||||
            msg = string.format("[%s] %s %s", status, time ~= "N/A" and time or "unknown remaining time",
 | 
			
		||||
                  string.lower(status):gsub(" ", ""):gsub("\n", "") == "charging" and " until charged" or " remaining")
 | 
			
		||||
        else
 | 
			
		||||
            msg = "On AC power"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        tp_smapi.hide()
 | 
			
		||||
        tp_smapi.notification = naughty.notify {
 | 
			
		||||
            title   = string.format("%s: %s %s (%s)", batid, mfgr, model, chem),
 | 
			
		||||
            text    = msg,
 | 
			
		||||
            timeout = type(seconds) == "number" and seconds or 0,
 | 
			
		||||
            screen  = scr or focused()
 | 
			
		||||
        }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function tp_smapi.create_widget(args)
 | 
			
		||||
        args            = args or {}
 | 
			
		||||
 | 
			
		||||
        local pspath    = args.pspath or "/sys/class/power_supply/"
 | 
			
		||||
        local batteries = args.batteries or (args.battery and {args.battery}) or {}
 | 
			
		||||
        local timeout   = args.timeout or 30
 | 
			
		||||
        local settings  = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
        if #batteries == 0 then
 | 
			
		||||
            helpers.line_callback("ls -1 " .. pspath, function(line)
 | 
			
		||||
                local bstr = string.match(line, "BAT%w+")
 | 
			
		||||
                if bstr then batteries[#batteries + 1] = bstr end
 | 
			
		||||
            end)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        local all_batteries_installed = true
 | 
			
		||||
 | 
			
		||||
        for _, battery in ipairs(batteries) do
 | 
			
		||||
            if not tp_smapi.installed(battery) then
 | 
			
		||||
                naughty.notify {
 | 
			
		||||
                    preset = naughty.config.critical,
 | 
			
		||||
                    title  = "tp_smapi: error while creating widget",
 | 
			
		||||
                    text   = string.format("battery %s is not installed", battery)
 | 
			
		||||
                }
 | 
			
		||||
                all_batteries_installed = false
 | 
			
		||||
                break
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if not all_batteries_installed then return end
 | 
			
		||||
 | 
			
		||||
        tpbat = {
 | 
			
		||||
            batteries = batteries,
 | 
			
		||||
            widget    = args.widget or wibox.widget.textbox()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        function tpbat.update()
 | 
			
		||||
            tpbat_now = {
 | 
			
		||||
                n_status = {},
 | 
			
		||||
                n_perc   = {},
 | 
			
		||||
                n_time   = {},
 | 
			
		||||
                status   = "N/A"
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for i = 1, #batteries do
 | 
			
		||||
                tpbat_now.n_status[i] = tp_smapi.status(batteries[i]) or "N/A"
 | 
			
		||||
                tpbat_now.n_perc[i] = tp_smapi.percentage(batteries[i])
 | 
			
		||||
                tpbat_now.n_time[i] = tp_smapi.time(batteries[i]) or "N/A"
 | 
			
		||||
 | 
			
		||||
                if not tpbat_now.n_status[i]:lower():match("full") then
 | 
			
		||||
                    tpbat_now.status = tpbat_now.n_status[i]
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            widget = tpbat.widget -- backwards compatibility
 | 
			
		||||
            settings()
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        helpers.newtimer("thinkpad-batteries", timeout, tpbat.update)
 | 
			
		||||
 | 
			
		||||
        return tpbat
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return tp_smapi
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										75
									
								
								.config/awesome/lain/widget/cpu.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								.config/awesome/lain/widget/cpu.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013,      Luca CPZ
 | 
			
		||||
      * (c) 2010-2012, Peter Hofmann
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers  = require("lain.helpers")
 | 
			
		||||
local wibox    = require("wibox")
 | 
			
		||||
local math     = math
 | 
			
		||||
local string   = string
 | 
			
		||||
 | 
			
		||||
-- CPU usage
 | 
			
		||||
-- lain.widget.cpu
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args           = args or {}
 | 
			
		||||
 | 
			
		||||
    local cpu      = { core = {}, widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local timeout  = args.timeout or 2
 | 
			
		||||
    local settings = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    function cpu.update()
 | 
			
		||||
        -- Read the amount of time the CPUs have spent performing
 | 
			
		||||
        -- different kinds of work. Read the first line of /proc/stat
 | 
			
		||||
        -- which is the sum of all CPUs.
 | 
			
		||||
        for index,time in pairs(helpers.lines_match("cpu","/proc/stat")) do
 | 
			
		||||
            local coreid = index - 1
 | 
			
		||||
            local core   = cpu.core[coreid] or
 | 
			
		||||
                           { last_active = 0 , last_total = 0, usage = 0 }
 | 
			
		||||
            local at     = 1
 | 
			
		||||
            local idle   = 0
 | 
			
		||||
            local total  = 0
 | 
			
		||||
 | 
			
		||||
            for field in string.gmatch(time, "[%s]+([^%s]+)") do
 | 
			
		||||
                -- 4 = idle, 5 = ioWait. Essentially, the CPUs have done
 | 
			
		||||
                -- nothing during these times.
 | 
			
		||||
                if at == 4 or at == 5 then
 | 
			
		||||
                    idle = idle + field
 | 
			
		||||
                end
 | 
			
		||||
                total = total + field
 | 
			
		||||
                at = at + 1
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            local active = total - idle
 | 
			
		||||
 | 
			
		||||
            if core.last_active ~= active or core.last_total ~= total then
 | 
			
		||||
                -- Read current data and calculate relative values.
 | 
			
		||||
                local dactive = active - core.last_active
 | 
			
		||||
                local dtotal  = total - core.last_total
 | 
			
		||||
                local usage   = math.ceil(math.abs((dactive / dtotal) * 100))
 | 
			
		||||
 | 
			
		||||
                core.last_active = active
 | 
			
		||||
                core.last_total  = total
 | 
			
		||||
                core.usage       = usage
 | 
			
		||||
 | 
			
		||||
                -- Save current data for the next run.
 | 
			
		||||
                cpu.core[coreid] = core
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        cpu_now = cpu.core
 | 
			
		||||
        cpu_now.usage = cpu_now[0].usage
 | 
			
		||||
        widget = cpu.widget
 | 
			
		||||
 | 
			
		||||
        settings()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer("cpu", timeout, cpu.update)
 | 
			
		||||
 | 
			
		||||
    return cpu
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										156
									
								
								.config/awesome/lain/widget/fs.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								.config/awesome/lain/widget/fs.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,156 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2018, Uli Schlacter
 | 
			
		||||
      * (c) 2018, Otto Modinos
 | 
			
		||||
      * (c) 2013, Luca CPZ
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers    = require("lain.helpers")
 | 
			
		||||
local Gio        = require("lgi").Gio
 | 
			
		||||
local focused    = require("awful.screen").focused
 | 
			
		||||
local wibox      = require("wibox")
 | 
			
		||||
local naughty    = require("naughty")
 | 
			
		||||
local gears      = require("gears")
 | 
			
		||||
local math       = math
 | 
			
		||||
local string     = string
 | 
			
		||||
local tconcat    = table.concat
 | 
			
		||||
local type       = type
 | 
			
		||||
local query_size = Gio.FILE_ATTRIBUTE_FILESYSTEM_SIZE
 | 
			
		||||
local query_free = Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE
 | 
			
		||||
local query_used = Gio.FILE_ATTRIBUTE_FILESYSTEM_USED
 | 
			
		||||
local query      = query_size .. "," .. query_free .. "," .. query_used
 | 
			
		||||
 | 
			
		||||
-- File systems info
 | 
			
		||||
-- lain.widget.fs
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args     = args or {}
 | 
			
		||||
 | 
			
		||||
    local fs = {
 | 
			
		||||
        widget = args.widget or wibox.widget.textbox(),
 | 
			
		||||
        units = {
 | 
			
		||||
            [1] = "Kb", [2] = "Mb", [3] = "Gb",
 | 
			
		||||
            [4] = "Tb", [5] = "Pb", [6] = "Eb",
 | 
			
		||||
            [7] = "Zb", [8] = "Yb"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function fs.hide()
 | 
			
		||||
        if not fs.notification then return end
 | 
			
		||||
        naughty.destroy(fs.notification)
 | 
			
		||||
        fs.notification = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function fs.show(seconds, scr)
 | 
			
		||||
        fs.hide()
 | 
			
		||||
        fs.update(function()
 | 
			
		||||
            fs.notification_preset.screen = fs.followtag and focused() or scr or 1
 | 
			
		||||
            fs.notification = naughty.notify {
 | 
			
		||||
                preset  = fs.notification_preset,
 | 
			
		||||
                timeout = type(seconds) == "number" and seconds or 5
 | 
			
		||||
            }
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local timeout   = args.timeout or 600
 | 
			
		||||
    local partition = args.partition
 | 
			
		||||
    local threshold = args.threshold or 99
 | 
			
		||||
    local showpopup = args.showpopup or "on"
 | 
			
		||||
    local settings  = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    fs.followtag           = args.followtag or false
 | 
			
		||||
    fs.notification_preset = args.notification_preset
 | 
			
		||||
 | 
			
		||||
    if not fs.notification_preset then
 | 
			
		||||
        fs.notification_preset = {
 | 
			
		||||
            font = "Monospace 10",
 | 
			
		||||
            fg   = "#FFFFFF",
 | 
			
		||||
            bg   = "#000000"
 | 
			
		||||
        }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local function update_synced()
 | 
			
		||||
        local pathlen = 10
 | 
			
		||||
        fs_now = {}
 | 
			
		||||
 | 
			
		||||
        local notifypaths = {}
 | 
			
		||||
        for _, mount in ipairs(Gio.unix_mounts_get()) do
 | 
			
		||||
            local path = Gio.unix_mount_get_mount_path(mount)
 | 
			
		||||
            local root = Gio.File.new_for_path(path)
 | 
			
		||||
            local info = root:query_filesystem_info(query)
 | 
			
		||||
 | 
			
		||||
            if info then
 | 
			
		||||
                local size = info:get_attribute_uint64(query_size)
 | 
			
		||||
                local used = info:get_attribute_uint64(query_used)
 | 
			
		||||
                local free = info:get_attribute_uint64(query_free)
 | 
			
		||||
 | 
			
		||||
                if size > 0 then
 | 
			
		||||
                    local units = math.floor(math.log(size)/math.log(1024))
 | 
			
		||||
 | 
			
		||||
                    fs_now[path] = {
 | 
			
		||||
                        units      = fs.units[units],
 | 
			
		||||
                        percentage = math.floor(100 * used / size), -- used percentage
 | 
			
		||||
                        size       = size / math.pow(1024, units),
 | 
			
		||||
                        used       = used / math.pow(1024, units),
 | 
			
		||||
                        free       = free / math.pow(1024, units)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if fs_now[path].percentage > 0 then -- don't notify unused file systems
 | 
			
		||||
                        notifypaths[#notifypaths+1] = path
 | 
			
		||||
 | 
			
		||||
                        if #path > pathlen then
 | 
			
		||||
                            pathlen = #path
 | 
			
		||||
                        end
 | 
			
		||||
                    end
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        widget = fs.widget
 | 
			
		||||
        settings()
 | 
			
		||||
 | 
			
		||||
        if partition and fs_now[partition] and fs_now[partition].percentage >= threshold then
 | 
			
		||||
            if not helpers.get_map(partition) then
 | 
			
		||||
                naughty.notify {
 | 
			
		||||
                    preset = naughty.config.presets.critical,
 | 
			
		||||
                    title  = "Warning",
 | 
			
		||||
                    text   = string.format("%s is above %d%% (%d%%)", partition, threshold, fs_now[partition].percentage)
 | 
			
		||||
                }
 | 
			
		||||
                helpers.set_map(partition, true)
 | 
			
		||||
            else
 | 
			
		||||
                helpers.set_map(partition, false)
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        local fmt = "%-" .. tostring(pathlen) .. "s %4s\t%6s\t%6s\n"
 | 
			
		||||
        local notifytable = { [1] = string.format(fmt, "path", "used", "free", "size") }
 | 
			
		||||
        fmt = "\n%-" .. tostring(pathlen) .. "s %3s%%\t%6.2f\t%6.2f %s"
 | 
			
		||||
        for _, path in ipairs(notifypaths) do
 | 
			
		||||
            notifytable[#notifytable+1] = string.format(fmt, path, fs_now[path].percentage, fs_now[path].free, fs_now[path].size, fs_now[path].units)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        fs.notification_preset.text = tconcat(notifytable)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function fs.update(callback)
 | 
			
		||||
        Gio.Async.start(gears.protected_call.call)(function()
 | 
			
		||||
            update_synced()
 | 
			
		||||
            if type(callback) == "function" and callback then
 | 
			
		||||
                callback()
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if showpopup == "on" then
 | 
			
		||||
       fs.widget:connect_signal('mouse::enter', function () fs.show(0) end)
 | 
			
		||||
       fs.widget:connect_signal('mouse::leave', function () fs.hide() end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer(partition or "fs", timeout, fs.update)
 | 
			
		||||
 | 
			
		||||
    return fs
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										94
									
								
								.config/awesome/lain/widget/imap.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								.config/awesome/lain/widget/imap.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013, Luca CPZ
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers  = require("lain.helpers")
 | 
			
		||||
local naughty  = require("naughty")
 | 
			
		||||
local wibox    = require("wibox")
 | 
			
		||||
local awful    = require("awful")
 | 
			
		||||
local string   = string
 | 
			
		||||
local type     = type
 | 
			
		||||
local tonumber = tonumber
 | 
			
		||||
 | 
			
		||||
-- Mail IMAP check
 | 
			
		||||
-- lain.widget.imap
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args             = args or {}
 | 
			
		||||
 | 
			
		||||
    local imap       = { widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local server     = args.server
 | 
			
		||||
    local mail       = args.mail
 | 
			
		||||
    local password   = args.password
 | 
			
		||||
    local port       = args.port or 993
 | 
			
		||||
    local timeout    = args.timeout or 60
 | 
			
		||||
    local pwdtimeout = args.pwdtimeout or 10
 | 
			
		||||
    local is_plain   = args.is_plain or false
 | 
			
		||||
    local followtag  = args.followtag or false
 | 
			
		||||
    local notify     = args.notify or "on"
 | 
			
		||||
    local settings   = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    local head_command = "curl --connect-timeout 3 -fsm 3"
 | 
			
		||||
    local request = "-X 'STATUS INBOX (MESSAGES RECENT UNSEEN)'"
 | 
			
		||||
 | 
			
		||||
    if not server or not mail or not password then return end
 | 
			
		||||
 | 
			
		||||
    mail_notification_preset = {
 | 
			
		||||
        icon     = helpers.icons_dir .. "mail.png",
 | 
			
		||||
        position = "top_left"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    helpers.set_map(mail, 0)
 | 
			
		||||
 | 
			
		||||
    if not is_plain then
 | 
			
		||||
        if type(password) == "string" or type(password) == "table" then
 | 
			
		||||
            helpers.async(password, function(f) password = f:gsub("\n", "") end)
 | 
			
		||||
        elseif type(password) == "function" then
 | 
			
		||||
            imap.pwdtimer = helpers.newtimer(mail .. "-password", pwdtimeout, function()
 | 
			
		||||
                local retrieved_password, try_again = password()
 | 
			
		||||
                if not try_again then
 | 
			
		||||
                    imap.pwdtimer:stop() -- stop trying to retrieve
 | 
			
		||||
                    password = retrieved_password or "" -- failsafe
 | 
			
		||||
                end
 | 
			
		||||
            end, true, true)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function imap.update()
 | 
			
		||||
        -- do not update if the password has not been retrieved yet
 | 
			
		||||
        if type(password) ~= "string" then return end
 | 
			
		||||
 | 
			
		||||
        local curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:'%s' %s -k",
 | 
			
		||||
                     head_command, server, port, mail, password, request)
 | 
			
		||||
 | 
			
		||||
        helpers.async(curl, function(f)
 | 
			
		||||
            imap_now = { ["MESSAGES"] = 0, ["RECENT"] = 0, ["UNSEEN"] = 0 }
 | 
			
		||||
 | 
			
		||||
            for s,d in f:gmatch("(%w+)%s+(%d+)") do imap_now[s] = tonumber(d) end
 | 
			
		||||
            mailcount = imap_now["UNSEEN"] -- backwards compatibility
 | 
			
		||||
            widget = imap.widget
 | 
			
		||||
 | 
			
		||||
            settings()
 | 
			
		||||
 | 
			
		||||
            if notify == "on" and mailcount and mailcount >= 1 and mailcount > helpers.get_map(mail) then
 | 
			
		||||
                if followtag then mail_notification_preset.screen = awful.screen.focused() end
 | 
			
		||||
                naughty.notify {
 | 
			
		||||
                    preset = mail_notification_preset,
 | 
			
		||||
                    text   = string.format("%s has <b>%d</b> new message%s", mail, mailcount, mailcount == 1 and "" or "s")
 | 
			
		||||
                }
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            helpers.set_map(mail, imap_now["UNSEEN"])
 | 
			
		||||
        end)
 | 
			
		||||
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    imap.timer = helpers.newtimer(mail, timeout, imap.update, true, true)
 | 
			
		||||
 | 
			
		||||
    return imap
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										19
									
								
								.config/awesome/lain/widget/init.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.config/awesome/lain/widget/init.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Lain
 | 
			
		||||
     Layouts, widgets and utilities for Awesome WM
 | 
			
		||||
 | 
			
		||||
     Widgets section
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013,      Luca CPZ
 | 
			
		||||
      * (c) 2010-2012, Peter Hofmann
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local wrequire     = require("lain.helpers").wrequire
 | 
			
		||||
local setmetatable = setmetatable
 | 
			
		||||
 | 
			
		||||
local widget = { _NAME = "lain.widget" }
 | 
			
		||||
 | 
			
		||||
return setmetatable(widget, { __index = wrequire })
 | 
			
		||||
							
								
								
									
										51
									
								
								.config/awesome/lain/widget/mem.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								.config/awesome/lain/widget/mem.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013,      Luca CPZ
 | 
			
		||||
      * (c) 2010-2012, Peter Hofmann
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers              = require("lain.helpers")
 | 
			
		||||
local wibox                = require("wibox")
 | 
			
		||||
local gmatch, lines, floor = string.gmatch, io.lines, math.floor
 | 
			
		||||
 | 
			
		||||
-- Memory usage (ignoring caches)
 | 
			
		||||
-- lain.widget.mem
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args           = args or {}
 | 
			
		||||
 | 
			
		||||
    local mem      = { widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local timeout  = args.timeout or 2
 | 
			
		||||
    local settings = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    function mem.update()
 | 
			
		||||
        mem_now = {}
 | 
			
		||||
        for line in lines("/proc/meminfo") do
 | 
			
		||||
            for k, v in gmatch(line, "([%a]+):[%s]+([%d]+).+") do
 | 
			
		||||
                if     k == "MemTotal"     then mem_now.total = floor(v / 1024 + 0.5)
 | 
			
		||||
                elseif k == "MemFree"      then mem_now.free  = floor(v / 1024 + 0.5)
 | 
			
		||||
                elseif k == "Buffers"      then mem_now.buf   = floor(v / 1024 + 0.5)
 | 
			
		||||
                elseif k == "Cached"       then mem_now.cache = floor(v / 1024 + 0.5)
 | 
			
		||||
                elseif k == "SwapTotal"    then mem_now.swap  = floor(v / 1024 + 0.5)
 | 
			
		||||
                elseif k == "SwapFree"     then mem_now.swapf = floor(v / 1024 + 0.5)
 | 
			
		||||
                elseif k == "SReclaimable" then mem_now.srec  = floor(v / 1024 + 0.5)
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        mem_now.used = mem_now.total - mem_now.free - mem_now.buf - mem_now.cache - mem_now.srec
 | 
			
		||||
        mem_now.swapused = mem_now.swap - mem_now.swapf
 | 
			
		||||
        mem_now.perc = math.floor(mem_now.used / mem_now.total * 100)
 | 
			
		||||
 | 
			
		||||
        widget = mem.widget
 | 
			
		||||
        settings()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer("mem", timeout, mem.update)
 | 
			
		||||
 | 
			
		||||
    return mem
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										135
									
								
								.config/awesome/lain/widget/mpd.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								.config/awesome/lain/widget/mpd.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013, Luca CPZ
 | 
			
		||||
      * (c) 2010, Adrian C. <anrxc@sysphere.org>
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers  = require("lain.helpers")
 | 
			
		||||
local shell    = require("awful.util").shell
 | 
			
		||||
local escape_f = require("awful.util").escape
 | 
			
		||||
local focused  = require("awful.screen").focused
 | 
			
		||||
local naughty  = require("naughty")
 | 
			
		||||
local wibox    = require("wibox")
 | 
			
		||||
local os       = os
 | 
			
		||||
local string   = string
 | 
			
		||||
 | 
			
		||||
-- MPD infos
 | 
			
		||||
-- lain.widget.mpd
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args                = args or {}
 | 
			
		||||
 | 
			
		||||
    local mpd           = { widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local timeout       = args.timeout or 2
 | 
			
		||||
    local password      = (args.password and #args.password > 0 and string.format("password %s\\n", args.password)) or ""
 | 
			
		||||
    local host          = args.host or os.getenv("MPD_HOST") or "127.0.0.1"
 | 
			
		||||
    local port          = args.port or os.getenv("MPD_PORT") or "6600"
 | 
			
		||||
    local music_dir     = args.music_dir or os.getenv("HOME") .. "/Music"
 | 
			
		||||
    local cover_pattern = args.cover_pattern or "*\\.(jpg|jpeg|png|gif)$"
 | 
			
		||||
    local cover_size    = args.cover_size or 100
 | 
			
		||||
    local default_art   = args.default_art
 | 
			
		||||
    local notify        = args.notify or "on"
 | 
			
		||||
    local followtag     = args.followtag or false
 | 
			
		||||
    local settings      = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    local mpdh = string.format("telnet://%s:%s", host, port)
 | 
			
		||||
    local echo = string.format("printf \"%sstatus\\ncurrentsong\\nclose\\n\"", password)
 | 
			
		||||
    local cmd  = string.format("%s | curl --connect-timeout 1 -fsm 3 %s", echo, mpdh)
 | 
			
		||||
 | 
			
		||||
    mpd_notification_preset = { title = "Now playing", timeout = 6 }
 | 
			
		||||
 | 
			
		||||
    helpers.set_map("current mpd track", nil)
 | 
			
		||||
 | 
			
		||||
    function mpd.update()
 | 
			
		||||
        helpers.async({ shell, "-c", cmd }, function(f)
 | 
			
		||||
            mpd_now = {
 | 
			
		||||
                random_mode  = false,
 | 
			
		||||
                single_mode  = false,
 | 
			
		||||
                repeat_mode  = false,
 | 
			
		||||
                consume_mode = false,
 | 
			
		||||
                pls_pos      = "N/A",
 | 
			
		||||
                pls_len      = "N/A",
 | 
			
		||||
                state        = "N/A",
 | 
			
		||||
                file         = "N/A",
 | 
			
		||||
                name         = "N/A",
 | 
			
		||||
                artist       = "N/A",
 | 
			
		||||
                title        = "N/A",
 | 
			
		||||
                album        = "N/A",
 | 
			
		||||
                genre        = "N/A",
 | 
			
		||||
                track        = "N/A",
 | 
			
		||||
                date         = "N/A",
 | 
			
		||||
                time         = "N/A",
 | 
			
		||||
                elapsed      = "N/A",
 | 
			
		||||
                volume       = "N/A"
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for line in string.gmatch(f, "[^\n]+") do
 | 
			
		||||
                for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
 | 
			
		||||
                    if     k == "state"          then mpd_now.state        = v
 | 
			
		||||
                    elseif k == "file"           then mpd_now.file         = v
 | 
			
		||||
                    elseif k == "Name"           then mpd_now.name         = escape_f(v)
 | 
			
		||||
                    elseif k == "Artist"         then mpd_now.artist       = escape_f(v)
 | 
			
		||||
                    elseif k == "Title"          then mpd_now.title        = escape_f(v)
 | 
			
		||||
                    elseif k == "Album"          then mpd_now.album        = escape_f(v)
 | 
			
		||||
                    elseif k == "Genre"          then mpd_now.genre        = escape_f(v)
 | 
			
		||||
                    elseif k == "Track"          then mpd_now.track        = escape_f(v)
 | 
			
		||||
                    elseif k == "Date"           then mpd_now.date         = escape_f(v)
 | 
			
		||||
                    elseif k == "Time"           then mpd_now.time         = v
 | 
			
		||||
                    elseif k == "elapsed"        then mpd_now.elapsed      = string.match(v, "%d+")
 | 
			
		||||
                    elseif k == "song"           then mpd_now.pls_pos      = v
 | 
			
		||||
                    elseif k == "playlistlength" then mpd_now.pls_len      = v
 | 
			
		||||
                    elseif k == "repeat"         then mpd_now.repeat_mode  = v ~= "0"
 | 
			
		||||
                    elseif k == "single"         then mpd_now.single_mode  = v ~= "0"
 | 
			
		||||
                    elseif k == "random"         then mpd_now.random_mode  = v ~= "0"
 | 
			
		||||
                    elseif k == "consume"        then mpd_now.consume_mode = v ~= "0"
 | 
			
		||||
                    elseif k == "volume"         then mpd_now.volume       = v
 | 
			
		||||
                    end
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist,
 | 
			
		||||
                                           mpd_now.album, mpd_now.date, mpd_now.title)
 | 
			
		||||
            widget = mpd.widget
 | 
			
		||||
            settings()
 | 
			
		||||
 | 
			
		||||
            if mpd_now.state == "play" then
 | 
			
		||||
                if notify == "on" and mpd_now.title ~= helpers.get_map("current mpd track") then
 | 
			
		||||
                    helpers.set_map("current mpd track", mpd_now.title)
 | 
			
		||||
 | 
			
		||||
                    if followtag then mpd_notification_preset.screen = focused() end
 | 
			
		||||
 | 
			
		||||
                    local common =  {
 | 
			
		||||
                        preset      = mpd_notification_preset,
 | 
			
		||||
                        icon        = default_art,
 | 
			
		||||
                        icon_size   = cover_size,
 | 
			
		||||
                        replaces_id = mpd.id
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if not string.match(mpd_now.file, "http.*://") then -- local file instead of http stream
 | 
			
		||||
                        local path   = string.format("%s/%s", music_dir, string.match(mpd_now.file, ".*/"))
 | 
			
		||||
                        local cover  = string.format("find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'",
 | 
			
		||||
                                       path:gsub("'", "'\\''"), cover_pattern)
 | 
			
		||||
                        helpers.async({ shell, "-c", cover }, function(current_icon)
 | 
			
		||||
                            common.icon = current_icon:gsub("\n", "")
 | 
			
		||||
                            if #common.icon == 0 then common.icon = nil end
 | 
			
		||||
                            mpd.id = naughty.notify(common).id
 | 
			
		||||
                        end)
 | 
			
		||||
                    else
 | 
			
		||||
                        mpd.id = naughty.notify(common).id
 | 
			
		||||
                    end
 | 
			
		||||
 | 
			
		||||
                end
 | 
			
		||||
            elseif mpd_now.state ~= "pause" then
 | 
			
		||||
                helpers.set_map("current mpd track", nil)
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    mpd.timer = helpers.newtimer("mpd", timeout, mpd.update, true, true)
 | 
			
		||||
 | 
			
		||||
    return mpd
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										122
									
								
								.config/awesome/lain/widget/net.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								.config/awesome/lain/widget/net.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013,      Luca CPZ
 | 
			
		||||
      * (c) 2010-2012, Peter Hofmann
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers = require("lain.helpers")
 | 
			
		||||
local naughty = require("naughty")
 | 
			
		||||
local wibox   = require("wibox")
 | 
			
		||||
local string  = string
 | 
			
		||||
 | 
			
		||||
-- Network infos
 | 
			
		||||
-- lain.widget.net
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args             = args or {}
 | 
			
		||||
 | 
			
		||||
    local net        = { widget = args.widget or wibox.widget.textbox(), devices = {} }
 | 
			
		||||
    local timeout    = args.timeout or 2
 | 
			
		||||
    local units      = args.units or 1024 -- KB
 | 
			
		||||
    local notify     = args.notify or "on"
 | 
			
		||||
    local wifi_state = args.wifi_state or "off"
 | 
			
		||||
    local eth_state  = args.eth_state or "off"
 | 
			
		||||
    local screen     = args.screen or 1
 | 
			
		||||
    local format     = args.format or "%.1f"
 | 
			
		||||
    local settings   = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    -- Compatibility with old API where iface was a string corresponding to 1 interface
 | 
			
		||||
    net.iface = (args.iface and (type(args.iface) == "string" and {args.iface}) or
 | 
			
		||||
                (type(args.iface) == "table" and args.iface)) or {}
 | 
			
		||||
 | 
			
		||||
    function net.get_devices()
 | 
			
		||||
        net.iface = {} -- reset at every call
 | 
			
		||||
        helpers.line_callback("ip link", function(line)
 | 
			
		||||
            net.iface[#net.iface + 1] = not string.match(line, "LOOPBACK") and string.match(line, "(%w+): <") or nil
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if #net.iface == 0 then net.get_devices() end
 | 
			
		||||
 | 
			
		||||
    function net.update()
 | 
			
		||||
        -- These are the totals over all specified interfaces
 | 
			
		||||
        net_now = {
 | 
			
		||||
            devices  = {},
 | 
			
		||||
            -- Bytes since last iteration
 | 
			
		||||
            sent     = 0,
 | 
			
		||||
            received = 0
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for _, dev in ipairs(net.iface) do
 | 
			
		||||
            local dev_now    = {}
 | 
			
		||||
            local dev_before = net.devices[dev] or { last_t = 0, last_r = 0 }
 | 
			
		||||
            local now_t      = tonumber(helpers.first_line(string.format("/sys/class/net/%s/statistics/tx_bytes", dev)) or 0)
 | 
			
		||||
            local now_r      = tonumber(helpers.first_line(string.format("/sys/class/net/%s/statistics/rx_bytes", dev)) or 0)
 | 
			
		||||
 | 
			
		||||
            dev_now.carrier  = helpers.first_line(string.format("/sys/class/net/%s/carrier", dev)) or "0"
 | 
			
		||||
            dev_now.state    = helpers.first_line(string.format("/sys/class/net/%s/operstate", dev)) or "down"
 | 
			
		||||
 | 
			
		||||
            dev_now.sent     = (now_t - dev_before.last_t) / timeout / units
 | 
			
		||||
            dev_now.received = (now_r - dev_before.last_r) / timeout / units
 | 
			
		||||
 | 
			
		||||
            net_now.sent     = net_now.sent + dev_now.sent
 | 
			
		||||
            net_now.received = net_now.received + dev_now.received
 | 
			
		||||
 | 
			
		||||
            dev_now.sent     = string.format(format, dev_now.sent)
 | 
			
		||||
            dev_now.received = string.format(format, dev_now.received)
 | 
			
		||||
 | 
			
		||||
            dev_now.last_t   = now_t
 | 
			
		||||
            dev_now.last_r   = now_r
 | 
			
		||||
 | 
			
		||||
            if wifi_state == "on" and helpers.first_line(string.format("/sys/class/net/%s/uevent", dev)) == "DEVTYPE=wlan" then
 | 
			
		||||
                dev_now.wifi   = true
 | 
			
		||||
                if string.match(dev_now.carrier, "1") then
 | 
			
		||||
                        dev_now.signal = tonumber(string.match(helpers.lines_from("/proc/net/wireless")[3], "(%-%d+%.)")) or nil
 | 
			
		||||
                end
 | 
			
		||||
            else
 | 
			
		||||
                dev_now.wifi   = false
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            if eth_state == "on" and helpers.first_line(string.format("/sys/class/net/%s/uevent", dev)) ~= "DEVTYPE=wlan" then
 | 
			
		||||
                dev_now.ethernet = true
 | 
			
		||||
            else
 | 
			
		||||
                dev_now.ethernet = false
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            net.devices[dev] = dev_now
 | 
			
		||||
 | 
			
		||||
            -- Notify only once when connection is lost
 | 
			
		||||
            if string.match(dev_now.carrier, "0") and notify == "on" and helpers.get_map(dev) then
 | 
			
		||||
                naughty.notify {
 | 
			
		||||
                    title    = dev,
 | 
			
		||||
                    text     = "No carrier",
 | 
			
		||||
                    icon     = helpers.icons_dir .. "no_net.png",
 | 
			
		||||
                    screen   = screen
 | 
			
		||||
                }
 | 
			
		||||
                helpers.set_map(dev, false)
 | 
			
		||||
            elseif string.match(dev_now.carrier, "1") then
 | 
			
		||||
                helpers.set_map(dev, true)
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            net_now.carrier = dev_now.carrier
 | 
			
		||||
            net_now.state = dev_now.state
 | 
			
		||||
            net_now.devices[dev] = dev_now
 | 
			
		||||
            -- net_now.sent and net_now.received will be
 | 
			
		||||
            -- the totals across all specified devices
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        net_now.sent = string.format(format, net_now.sent)
 | 
			
		||||
        net_now.received = string.format(format, net_now.received)
 | 
			
		||||
 | 
			
		||||
        widget = net.widget
 | 
			
		||||
        settings()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer("network", timeout, net.update)
 | 
			
		||||
 | 
			
		||||
    return net
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										58
									
								
								.config/awesome/lain/widget/pulse.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								.config/awesome/lain/widget/pulse.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2016, Luca CPZ
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers = require("lain.helpers")
 | 
			
		||||
local shell   = require("awful.util").shell
 | 
			
		||||
local wibox   = require("wibox")
 | 
			
		||||
local string  = string
 | 
			
		||||
local type    = type
 | 
			
		||||
 | 
			
		||||
-- PulseAudio volume
 | 
			
		||||
-- lain.widget.pulse
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args           = args or {}
 | 
			
		||||
 | 
			
		||||
    local pulse    = { widget = args.widget or wibox.widget.textbox(), device = "N/A" }
 | 
			
		||||
    local timeout  = args.timeout or 5
 | 
			
		||||
    local settings = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    pulse.devicetype = args.devicetype or "sink"
 | 
			
		||||
    pulse.cmd = args.cmd or "pacmd list-" .. pulse.devicetype .. "s | sed -n -e '/*/,$!d' -e '/index/p' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'"
 | 
			
		||||
 | 
			
		||||
    function pulse.update()
 | 
			
		||||
        helpers.async({ shell, "-c", type(pulse.cmd) == "string" and pulse.cmd or pulse.cmd() },
 | 
			
		||||
        function(s)
 | 
			
		||||
            volume_now = {
 | 
			
		||||
                index  = string.match(s, "index: (%S+)") or "N/A",
 | 
			
		||||
                device = string.match(s, "device.string = \"(%S+)\"") or "N/A",
 | 
			
		||||
                muted  = string.match(s, "muted: (%S+)") or "N/A"
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            pulse.device = volume_now.index
 | 
			
		||||
 | 
			
		||||
            local ch = 1
 | 
			
		||||
            volume_now.channel = {}
 | 
			
		||||
            for v in string.gmatch(s, ":.-(%d+)%%") do
 | 
			
		||||
                volume_now.channel[ch] = v
 | 
			
		||||
                ch = ch + 1
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            volume_now.left  = volume_now.channel[1] or "N/A"
 | 
			
		||||
            volume_now.right = volume_now.channel[2] or "N/A"
 | 
			
		||||
 | 
			
		||||
            widget = pulse.widget
 | 
			
		||||
            settings()
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer("pulse", timeout, pulse.update)
 | 
			
		||||
 | 
			
		||||
    return pulse
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										175
									
								
								.config/awesome/lain/widget/pulsebar.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								.config/awesome/lain/widget/pulsebar.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,175 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013, Luca CPZ
 | 
			
		||||
      * (c) 2013, Rman
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers  = require("lain.helpers")
 | 
			
		||||
local awful    = require("awful")
 | 
			
		||||
local naughty  = require("naughty")
 | 
			
		||||
local wibox    = require("wibox")
 | 
			
		||||
local math     = math
 | 
			
		||||
local string   = string
 | 
			
		||||
local type     = type
 | 
			
		||||
local tonumber = tonumber
 | 
			
		||||
 | 
			
		||||
-- PulseAudio volume bar
 | 
			
		||||
-- lain.widget.pulsebar
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    local pulsebar = {
 | 
			
		||||
        colors = {
 | 
			
		||||
            background      = "#000000",
 | 
			
		||||
            mute_background = "#000000",
 | 
			
		||||
            mute            = "#EB8F8F",
 | 
			
		||||
            unmute          = "#A4CE8A"
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        _current_level = 0,
 | 
			
		||||
        _mute          = "no",
 | 
			
		||||
        device         = "N/A"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    args             = args or {}
 | 
			
		||||
 | 
			
		||||
    local timeout    = args.timeout or 5
 | 
			
		||||
    local settings   = args.settings or function() end
 | 
			
		||||
    local width      = args.width or 63
 | 
			
		||||
    local height     = args.height or 1
 | 
			
		||||
    local margins    = args.margins or 1
 | 
			
		||||
    local paddings   = args.paddings or 1
 | 
			
		||||
    local ticks      = args.ticks or false
 | 
			
		||||
    local ticks_size = args.ticks_size or 7
 | 
			
		||||
    local tick       = args.tick or "|"
 | 
			
		||||
    local tick_pre   = args.tick_pre or "["
 | 
			
		||||
    local tick_post  = args.tick_post or "]"
 | 
			
		||||
    local tick_none  = args.tick_none or " "
 | 
			
		||||
 | 
			
		||||
    pulsebar.colors              = args.colors or pulsebar.colors
 | 
			
		||||
    pulsebar.followtag           = args.followtag or false
 | 
			
		||||
    pulsebar.notification_preset = args.notification_preset
 | 
			
		||||
    pulsebar.devicetype          = args.devicetype or "sink"
 | 
			
		||||
    pulsebar.cmd                 = args.cmd or "pacmd list-" .. pulsebar.devicetype .. "s | sed -n -e '/*/,$!d' -e '/index/p' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'"
 | 
			
		||||
 | 
			
		||||
    if not pulsebar.notification_preset then
 | 
			
		||||
        pulsebar.notification_preset = {
 | 
			
		||||
            font = "Monospace 10"
 | 
			
		||||
        }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    pulsebar.bar = wibox.widget {
 | 
			
		||||
        color            = pulsebar.colors.unmute,
 | 
			
		||||
        background_color = pulsebar.colors.background,
 | 
			
		||||
        forced_height    = height,
 | 
			
		||||
        forced_width     = width,
 | 
			
		||||
        margins          = margins,
 | 
			
		||||
        paddings         = paddings,
 | 
			
		||||
        ticks            = ticks,
 | 
			
		||||
        ticks_size       = ticks_size,
 | 
			
		||||
        widget           = wibox.widget.progressbar,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pulsebar.tooltip = awful.tooltip({ objects = { pulsebar.bar } })
 | 
			
		||||
 | 
			
		||||
    function pulsebar.update(callback)
 | 
			
		||||
        helpers.async({ awful.util.shell, "-c", type(pulsebar.cmd) == "string" and pulsebar.cmd or pulsebar.cmd() },
 | 
			
		||||
        function(s)
 | 
			
		||||
            volume_now = {
 | 
			
		||||
                index  = string.match(s, "index: (%S+)") or "N/A",
 | 
			
		||||
                device = string.match(s, "device.string = \"(%S+)\"") or "N/A",
 | 
			
		||||
                muted  = string.match(s, "muted: (%S+)") or "N/A"
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            pulsebar.device = volume_now.index
 | 
			
		||||
 | 
			
		||||
            local ch = 1
 | 
			
		||||
            volume_now.channel = {}
 | 
			
		||||
            for v in string.gmatch(s, ":.-(%d+)%%") do
 | 
			
		||||
              volume_now.channel[ch] = v
 | 
			
		||||
              ch = ch + 1
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            volume_now.left  = volume_now.channel[1] or "N/A"
 | 
			
		||||
            volume_now.right = volume_now.channel[2] or "N/A"
 | 
			
		||||
 | 
			
		||||
            local volu = volume_now.left
 | 
			
		||||
            local mute = volume_now.muted
 | 
			
		||||
 | 
			
		||||
            if volu:match("N/A") or mute:match("N/A") then return end
 | 
			
		||||
 | 
			
		||||
            if volu ~= pulsebar._current_level or mute ~= pulsebar._mute then
 | 
			
		||||
                pulsebar._current_level = tonumber(volu)
 | 
			
		||||
                pulsebar.bar:set_value(pulsebar._current_level / 100)
 | 
			
		||||
                if pulsebar._current_level == 0 or mute == "yes" then
 | 
			
		||||
                    pulsebar._mute = mute
 | 
			
		||||
                    pulsebar.tooltip:set_text ("[muted]")
 | 
			
		||||
                    pulsebar.bar.color = pulsebar.colors.mute
 | 
			
		||||
                    pulsebar.bar.background_color = pulsebar.colors.mute_background
 | 
			
		||||
                else
 | 
			
		||||
                    pulsebar._mute = "no"
 | 
			
		||||
                    pulsebar.tooltip:set_text(string.format("%s %s: %s", pulsebar.devicetype, pulsebar.device, volu))
 | 
			
		||||
                    pulsebar.bar.color = pulsebar.colors.unmute
 | 
			
		||||
                    pulsebar.bar.background_color = pulsebar.colors.background
 | 
			
		||||
                end
 | 
			
		||||
 | 
			
		||||
                settings()
 | 
			
		||||
 | 
			
		||||
                if type(callback) == "function" then callback() end
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function pulsebar.notify()
 | 
			
		||||
        pulsebar.update(function()
 | 
			
		||||
            local preset = pulsebar.notification_preset
 | 
			
		||||
 | 
			
		||||
            preset.title = string.format("%s %s - %s%%", pulsebar.devicetype, pulsebar.device, pulsebar._current_level)
 | 
			
		||||
 | 
			
		||||
            if pulsebar._mute == "yes" then
 | 
			
		||||
                preset.title = preset.title .. " muted"
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            -- tot is the maximum number of ticks to display in the notification
 | 
			
		||||
            -- fallback: default horizontal wibox height
 | 
			
		||||
            local wib, tot = awful.screen.focused().mywibox, 20
 | 
			
		||||
 | 
			
		||||
            -- if we can grab mywibox, tot is defined as its height if
 | 
			
		||||
            -- horizontal, or width otherwise
 | 
			
		||||
            if wib then
 | 
			
		||||
                if wib.position == "left" or wib.position == "right" then
 | 
			
		||||
                    tot = wib.width
 | 
			
		||||
                else
 | 
			
		||||
                    tot = wib.height
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            local int = math.modf((pulsebar._current_level / 100) * tot)
 | 
			
		||||
            preset.text = string.format(
 | 
			
		||||
                "%s%s%s%s",
 | 
			
		||||
                tick_pre,
 | 
			
		||||
                string.rep(tick, int),
 | 
			
		||||
                string.rep(tick_none, tot - int),
 | 
			
		||||
                tick_post
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            if pulsebar.followtag then preset.screen = awful.screen.focused() end
 | 
			
		||||
 | 
			
		||||
            if not pulsebar.notification then
 | 
			
		||||
                pulsebar.notification = naughty.notify {
 | 
			
		||||
                    preset  = preset,
 | 
			
		||||
                    destroy = function() pulsebar.notification = nil end
 | 
			
		||||
                }
 | 
			
		||||
            else
 | 
			
		||||
                naughty.replace_text(pulsebar.notification, preset.title, preset.text)
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer(string.format("pulsebar-%s-%s", pulsebar.devicetype, pulsebar.device), timeout, pulsebar.update)
 | 
			
		||||
 | 
			
		||||
    return pulsebar
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										39
									
								
								.config/awesome/lain/widget/sysload.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								.config/awesome/lain/widget/sysload.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013,      Luca CPZ
 | 
			
		||||
      * (c) 2010-2012, Peter Hofmann
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers     = require("lain.helpers")
 | 
			
		||||
local wibox       = require("wibox")
 | 
			
		||||
local open, match = io.open, string.match
 | 
			
		||||
 | 
			
		||||
-- System load
 | 
			
		||||
-- lain.widget.sysload
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args           = args or {}
 | 
			
		||||
 | 
			
		||||
    local sysload  = { widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local timeout  = args.timeout or 2
 | 
			
		||||
    local settings = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    function sysload.update()
 | 
			
		||||
        local f = open("/proc/loadavg")
 | 
			
		||||
        local ret = f:read("*all")
 | 
			
		||||
        f:close()
 | 
			
		||||
 | 
			
		||||
        load_1, load_5, load_15 = match(ret, "([^%s]+) ([^%s]+) ([^%s]+)")
 | 
			
		||||
 | 
			
		||||
        widget = sysload.widget
 | 
			
		||||
        settings()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer("sysload", timeout, sysload.update)
 | 
			
		||||
 | 
			
		||||
    return sysload
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										50
									
								
								.config/awesome/lain/widget/temp.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								.config/awesome/lain/widget/temp.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2013, Luca CPZ
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers  = require("lain.helpers")
 | 
			
		||||
local wibox    = require("wibox")
 | 
			
		||||
local tonumber = tonumber
 | 
			
		||||
 | 
			
		||||
-- {thermal,core} temperature info
 | 
			
		||||
-- lain.widget.temp
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args           = args or {}
 | 
			
		||||
 | 
			
		||||
    local temp     = { widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local timeout  = args.timeout or 30
 | 
			
		||||
    local tempfile = args.tempfile or "/sys/devices/virtual/thermal/thermal_zone0/temp"
 | 
			
		||||
    local format   = args.format or "%.1f"
 | 
			
		||||
    local settings = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    function temp.update()
 | 
			
		||||
        helpers.async({"find", "/sys/devices", "-type", "f", "-name", "*temp*"}, function(f)
 | 
			
		||||
            temp_now = {}
 | 
			
		||||
            local temp_fl, temp_value
 | 
			
		||||
            for t in f:gmatch("[^\n]+") do
 | 
			
		||||
                temp_fl = helpers.first_line(t)
 | 
			
		||||
                if temp_fl then
 | 
			
		||||
                    temp_value = tonumber(temp_fl)
 | 
			
		||||
                    temp_now[t] = temp_value and temp_value/1e3 or temp_fl
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
            if temp_now[tempfile] then
 | 
			
		||||
                coretemp_now = string.format(format, temp_now[tempfile])
 | 
			
		||||
            else
 | 
			
		||||
                coretemp_now = "N/A"
 | 
			
		||||
            end
 | 
			
		||||
            widget = temp.widget
 | 
			
		||||
            settings()
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    helpers.newtimer("thermal", timeout, temp.update)
 | 
			
		||||
 | 
			
		||||
    return temp
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
							
								
								
									
										146
									
								
								.config/awesome/lain/widget/weather.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								.config/awesome/lain/widget/weather.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
			
		||||
--[[
 | 
			
		||||
 | 
			
		||||
     Licensed under GNU General Public License v2
 | 
			
		||||
      * (c) 2015, Luca CPZ
 | 
			
		||||
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
local helpers  = require("lain.helpers")
 | 
			
		||||
local json     = require("lain.util").dkjson
 | 
			
		||||
local focused  = require("awful.screen").focused
 | 
			
		||||
local naughty  = require("naughty")
 | 
			
		||||
local wibox    = require("wibox")
 | 
			
		||||
local math     = math
 | 
			
		||||
local os       = os
 | 
			
		||||
local string   = string
 | 
			
		||||
local type     = type
 | 
			
		||||
local tonumber = tonumber
 | 
			
		||||
 | 
			
		||||
-- OpenWeatherMap
 | 
			
		||||
-- current weather and X-days forecast
 | 
			
		||||
-- lain.widget.weather
 | 
			
		||||
 | 
			
		||||
local function factory(args)
 | 
			
		||||
    args                        = args or {}
 | 
			
		||||
 | 
			
		||||
    local weather               = { widget = args.widget or wibox.widget.textbox() }
 | 
			
		||||
    local APPID                 = args.APPID -- mandatory
 | 
			
		||||
    local timeout               = args.timeout or 60 * 15 -- 15 min
 | 
			
		||||
    local current_call          = args.current_call  or "curl -s 'https://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s&APPID=%s'"
 | 
			
		||||
    local forecast_call         = args.forecast_call or "curl -s 'https://api.openweathermap.org/data/2.5/forecast?id=%s&units=%s&lang=%s&APPID=%s'"
 | 
			
		||||
    local city_id               = args.city_id or 0 -- placeholder
 | 
			
		||||
    local units                 = args.units or "metric"
 | 
			
		||||
    local lang                  = args.lang or "en"
 | 
			
		||||
    local cnt                   = args.cnt or 5
 | 
			
		||||
    local icons_path            = args.icons_path or helpers.icons_dir .. "openweathermap/"
 | 
			
		||||
    local notification_preset   = args.notification_preset or {}
 | 
			
		||||
    local notification_text_fun = args.notification_text_fun or
 | 
			
		||||
                                  function (wn)
 | 
			
		||||
                                      local day = os.date("%a %d", wn["dt"])
 | 
			
		||||
                                      local temp = math.floor(wn["main"]["temp"])
 | 
			
		||||
                                      local desc = wn["weather"][1]["description"]
 | 
			
		||||
                                      return string.format("<b>%s</b>: %s, %d ", day, desc, temp)
 | 
			
		||||
                                  end
 | 
			
		||||
    local weather_na_markup     = args.weather_na_markup or " N/A "
 | 
			
		||||
    local followtag             = args.followtag or false
 | 
			
		||||
    local showpopup             = args.showpopup or "on"
 | 
			
		||||
    local settings              = args.settings or function() end
 | 
			
		||||
 | 
			
		||||
    weather.widget:set_markup(weather_na_markup)
 | 
			
		||||
    weather.icon_path = icons_path .. "na.png"
 | 
			
		||||
    weather.icon = wibox.widget.imagebox(weather.icon_path)
 | 
			
		||||
 | 
			
		||||
    function weather.show(seconds)
 | 
			
		||||
        weather.hide()
 | 
			
		||||
 | 
			
		||||
        if followtag then
 | 
			
		||||
            notification_preset.screen = focused()
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if not weather.notification_text then
 | 
			
		||||
            weather.update()
 | 
			
		||||
            weather.forecast_update()
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        weather.notification = naughty.notify {
 | 
			
		||||
            preset  = notification_preset,
 | 
			
		||||
            text    = weather.notification_text,
 | 
			
		||||
            icon    = weather.icon_path,
 | 
			
		||||
            timeout = type(seconds) == "number" and seconds or notification_preset.timeout
 | 
			
		||||
        }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function weather.hide()
 | 
			
		||||
        if weather.notification then
 | 
			
		||||
            naughty.destroy(weather.notification)
 | 
			
		||||
            weather.notification = nil
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function weather.attach(obj)
 | 
			
		||||
        obj:connect_signal("mouse::enter", function()
 | 
			
		||||
            weather.show(0)
 | 
			
		||||
        end)
 | 
			
		||||
        obj:connect_signal("mouse::leave", function()
 | 
			
		||||
            weather.hide()
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function weather.forecast_update()
 | 
			
		||||
        local cmd = string.format(forecast_call, city_id, units, lang, APPID)
 | 
			
		||||
        helpers.async(cmd, function(f)
 | 
			
		||||
            local err
 | 
			
		||||
            weather_now, _, err = json.decode(f, 1, nil)
 | 
			
		||||
 | 
			
		||||
            if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then
 | 
			
		||||
                weather.notification_text = ""
 | 
			
		||||
                for i = 1, weather_now["cnt"], math.floor(weather_now["cnt"] / cnt) do
 | 
			
		||||
                    weather.notification_text = weather.notification_text ..
 | 
			
		||||
                                                notification_text_fun(weather_now["list"][i])
 | 
			
		||||
                    if i < weather_now["cnt"] then
 | 
			
		||||
                        weather.notification_text = weather.notification_text .. "\n"
 | 
			
		||||
                    end
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    function weather.update()
 | 
			
		||||
        local cmd = string.format(current_call, city_id, units, lang, APPID)
 | 
			
		||||
        helpers.async(cmd, function(f)
 | 
			
		||||
            local err
 | 
			
		||||
            weather_now, _, err = json.decode(f, 1, nil)
 | 
			
		||||
 | 
			
		||||
            if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then
 | 
			
		||||
                local sunrise = tonumber(weather_now["sys"]["sunrise"])
 | 
			
		||||
                local sunset  = tonumber(weather_now["sys"]["sunset"])
 | 
			
		||||
                local icon    = weather_now["weather"][1]["icon"]
 | 
			
		||||
                local loc_now = os.time()
 | 
			
		||||
 | 
			
		||||
                if sunrise <= loc_now and loc_now <= sunset then
 | 
			
		||||
                    icon = string.gsub(icon, "n", "d")
 | 
			
		||||
                else
 | 
			
		||||
                    icon = string.gsub(icon, "d", "n")
 | 
			
		||||
                end
 | 
			
		||||
 | 
			
		||||
                weather.icon_path = icons_path .. icon .. ".png"
 | 
			
		||||
                widget = weather.widget
 | 
			
		||||
                settings()
 | 
			
		||||
            else
 | 
			
		||||
                weather.icon_path = icons_path .. "na.png"
 | 
			
		||||
                weather.widget:set_markup(weather_na_markup)
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            weather.icon:set_image(weather.icon_path)
 | 
			
		||||
        end)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if showpopup == "on" then weather.attach(weather.widget) end
 | 
			
		||||
 | 
			
		||||
    weather.timer = helpers.newtimer("weather-" .. city_id, timeout, weather.update, false, true)
 | 
			
		||||
    weather.timer_forecast = helpers.newtimer("weather_forecast-" .. city_id, timeout, weather.forecast_update, false, true)
 | 
			
		||||
 | 
			
		||||
    return weather
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return factory
 | 
			
		||||
		Reference in New Issue
	
	Block a user