--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+
+--]]
+
+local debug = require("debug")
+
+local capi = { timer = timer }
+local io = { open = io.open,
+<<<<<<< HEAD
+ lines = io.lines }
+=======
+ lines = io.lines,
+ popen = io.popen }
+>>>>>>> upstream/master
+local rawget = rawget
+
+-- Lain helper functions for internal use
+-- lain.helpers
+local helpers = {}
+
+helpers.lain_dir = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
+helpers.icons_dir = helpers.lain_dir .. 'icons/'
+helpers.scripts_dir = helpers.lain_dir .. 'scripts/'
+
+-- {{{ Modules loader
+
+function helpers.wrequire(table, key)
+ local module = rawget(table, key)
+ return module or require(table._NAME .. '.' .. key)
+end
+
+-- }}}
+
+-- {{{ File operations
+
+-- see if the file exists and is readable
+function helpers.file_exists(file)
+ local f = io.open(file)
+ if f then
+ local s = f:read()
+ f:close()
+ f = s
+ end
+ return f ~= nil
+end
+
+-- get all lines from a file, returns an empty
+-- list/table if the file does not exist
+function helpers.lines_from(file)
+ if not helpers.file_exists(file) then return {} end
+ lines = {}
+ for line in io.lines(file) do
+ lines[#lines + 1] = line
+ end
+ return lines
+end
+
+-- get first line of a file, return nil if
+-- the file does not exist
+function helpers.first_line(file)
+ return helpers.lines_from(file)[1]
+end
+
+-- get first non empty line from a file,
+-- returns nil otherwise
+function helpers.first_nonempty_line(file)
+ for k,v in pairs(helpers.lines_from(file)) do
+ if #v then return v end
+ end
+ return nil
+end
+
+-- }}}
+
+-- {{{ Timer maker
+
+helpers.timer_table = {}
+
+function helpers.newtimer(name, timeout, fun, nostart)
+ helpers.timer_table[name] = capi.timer({ timeout = timeout })
+ helpers.timer_table[name]:connect_signal("timeout", fun)
+ helpers.timer_table[name]:start()
+ if not nostart then
+ helpers.timer_table[name]:emit_signal("timeout")
+ end
+end
+
+-- }}}
+
+<<<<<<< HEAD
+=======
+-- {{{ Pipe operations
+
+-- read the full output of a pipe (command)
+function helpers.read_pipe(cmd)
+ local f = assert(io.popen(cmd))
+ local output = f:read("*all")
+ f:close()
+ return output
+end
+
+-- }}}
+
+>>>>>>> upstream/master
+-- {{{ A map utility
+
+helpers.map_table = {}
+
+function helpers.set_map(element, value)
+ helpers.map_table[element] = value
+end
+
+function helpers.get_map(element)
+ return helpers.map_table[element]
+end
+
+-- }}}
+
+return helpers
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2014, Luke Bonham
+
+--]]
+
+local newtimer = require("lain.helpers").newtimer
+local async = require("lain.asyncshell")
+local wibox = require("wibox")
+
+local setmetatable = setmetatable
+
+-- Basic template for custom widgets
+-- Asynchronous version
+-- lain.widgets.abase
+
+local function worker(args)
+ local abase = {}
+ local args = args or {}
+ local timeout = args.timeout or 5
+ local cmd = args.cmd or ""
+ local settings = args.settings or function() end
+
+ abase.widget = wibox.widget.textbox('')
+
+ function abase.update()
+ async.request(cmd, function(f)
+ output = f
+ widget = abase.widget
+ settings()
+ end)
+ end
+
+ newtimer(cmd, timeout, abase.update)
+
+ return setmetatable(abase, { __index = abase.widget })
+end
+
+return setmetatable({}, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+ * (c) 2010, Adrian C. <anrxc@sysphere.org>
+
+--]]
+
+local newtimer = require("lain.helpers").newtimer
+<<<<<<< HEAD
+
+local wibox = require("wibox")
+
+local io = { popen = io.popen }
+=======
+local read_pipe = require("lain.helpers").read_pipe
+
+local wibox = require("wibox")
+
+>>>>>>> upstream/master
+local string = { match = string.match,
+ format = string.format }
+
+local setmetatable = setmetatable
+
+-- ALSA volume
+-- lain.widgets.alsa
+local alsa = {}
+
+local function worker(args)
+ local args = args or {}
+ 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.widget = wibox.widget.textbox('')
+
+ function alsa.update()
+<<<<<<< HEAD
+ local f = assert(io.popen(string.format("%s get %s", alsa.cmd, alsa.channel)))
+ local mixer = f:read("*a")
+ f:close()
+=======
+ local mixer = read_pipe(string.format("%s get %s", alsa.cmd, alsa.channel))
+>>>>>>> upstream/master
+
+ volume_now = {}
+
+ volume_now.level, volume_now.status = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
+
+ if volume_now.level == nil
+ then
+ volume_now.level = "0"
+ volume_now.status = "off"
+ end
+
+ if volume_now.status == ""
+ then
+ if volume_now.level == "0"
+ then
+ volume_now.status = "off"
+ else
+ volume_now.status = "on"
+ end
+ end
+
+ widget = alsa.widget
+ settings()
+ end
+
+ timer_id = string.format("alsa-%s-%s", alsa.cmd, alsa.channel)
+
+ newtimer(timer_id, timeout, alsa.update)
+
+ return setmetatable(alsa, { __index = alsa.widget })
+end
+
+return setmetatable(alsa, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+ * (c) 2013, Rman
+
+--]]
+
+local newtimer = require("lain.helpers").newtimer
+<<<<<<< HEAD
+=======
+local read_pipe = require("lain.helpers").read_pipe
+>>>>>>> upstream/master
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local naughty = require("naughty")
+
+<<<<<<< HEAD
+local io = { popen = io.popen }
+local math = { modf = math.modf }
+=======
+local math = { modf = math.modf }
+local mouse = mouse
+>>>>>>> upstream/master
+local string = { format = string.format,
+ match = string.match,
+ rep = string.rep }
+local tonumber = tonumber
+
+local setmetatable = setmetatable
+
+-- ALSA volume bar
+-- lain.widgets.alsabar
+local alsabar = {
+<<<<<<< HEAD
+ card = "0",
+=======
+>>>>>>> upstream/master
+ channel = "Master",
+ step = "2%",
+
+ colors = {
+ background = beautiful.bg_normal,
+ mute = "#EB8F8F",
+ unmute = "#A4CE8A"
+ },
+
+ terminal = terminal or "xterm",
+ mixer = terminal .. " -e alsamixer",
+
+ notifications = {
+ font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")),
+ font_size = "11",
+ color = beautiful.fg_normal,
+ bar_size = 18,
+ screen = 1
+ },
+
+ _current_level = 0,
+ _muted = false
+}
+
+function alsabar.notify()
+ alsabar.update()
+
+ local preset = {
+ title = "",
+ text = "",
+ timeout = 5,
+ screen = alsabar.notifications.screen,
+ font = alsabar.notifications.font .. " " ..
+ alsabar.notifications.font_size,
+ fg = alsabar.notifications.color
+ }
+
+ if alsabar._muted
+ then
+ preset.title = alsabar.channel .. " - Muted"
+ else
+ preset.title = alsabar.channel .. " - " .. alsabar._current_level .. "%"
+ end
+
+ int = math.modf((alsabar._current_level / 100) * alsabar.notifications.bar_size)
+ preset.text = "["
+ .. string.rep("|", int)
+ .. string.rep(" ", alsabar.notifications.bar_size - int)
+ .. "]"
+
+<<<<<<< HEAD
+=======
+ if alsabar.followmouse then
+ preset.screen = mouse.screen
+ end
+
+>>>>>>> upstream/master
+ if alsabar._notify ~= nil then
+ alsabar._notify = naughty.notify ({
+ replaces_id = alsabar._notify.id,
+ preset = preset,
+ })
+ else
+ alsabar._notify = naughty.notify ({
+ preset = preset,
+ })
+ end
+end
+
+local function worker(args)
+ local 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.heigth or 1
+ local ticks = args.ticks or false
+ local ticks_size = args.ticks_size or 7
+ local vertical = args.vertical or false
+
+ alsabar.cmd = args.cmd or "amixer"
+ alsabar.channel = args.channel or alsabar.channel
+ alsabar.step = args.step or alsabar.step
+ alsabar.colors = args.colors or alsabar.colors
+ alsabar.notifications = args.notifications or alsabar.notifications
+<<<<<<< HEAD
+=======
+ alsabar.followmouse = args.followmouse or false
+>>>>>>> upstream/master
+
+ alsabar.bar = awful.widget.progressbar()
+
+ alsabar.bar:set_background_color(alsabar.colors.background)
+ alsabar.bar:set_color(alsabar.colors.unmute)
+ alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
+ alsabar.bar:set_width(width)
+ alsabar.bar:set_height(height)
+ alsabar.bar:set_ticks(ticks)
+ alsabar.bar:set_ticks_size(ticks_size)
+ alsabar.bar:set_vertical(vertical)
+
+ function alsabar.update()
+ -- Get mixer control contents
+<<<<<<< HEAD
+ local f = assert(io.popen(string.format("%s get %s", alsabar.cmd, alsabar.channel)))
+ local mixer = f:read("*a")
+ f:close()
+=======
+ local mixer = read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.channel))
+>>>>>>> upstream/master
+
+ -- Capture mixer control state: [5%] ... ... [on]
+ local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
+
+ if volu == nil then
+ volu = 0
+ mute = "off"
+ end
+
+ alsabar._current_level = tonumber(volu)
+ alsabar.bar:set_value(alsabar._current_level / 100)
+ if not mute and tonumber(volu) == 0 or mute == "off"
+ then
+ alsabar._muted = true
+ alsabar.tooltip:set_text (" [Muted] ")
+ alsabar.bar:set_color(alsabar.colors.mute)
+ else
+ alsabar._muted = false
+ alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu))
+ alsabar.bar:set_color(alsabar.colors.unmute)
+ end
+
+ volume_now = {}
+ volume_now.level = tonumber(volu)
+ volume_now.status = mute
+ settings()
+ end
+
+ alsabar.bar:buttons (awful.util.table.join (
+ awful.button ({}, 1, function()
+ awful.util.spawn(alsabar.mixer)
+ end),
+ awful.button ({}, 3, function()
+<<<<<<< HEAD
+ awful.util.spawn(string.format("amixer -c %s set %s toggle", alsabar.card, alsabar.channel))
+ alsabar.update()
+ end),
+ awful.button ({}, 4, function()
+ awful.util.spawn(string.format("amixer -c %s set %s %s+", alsabar.card, alsabar.channel, alsabar.step))
+ alsabar.update()
+ end),
+ awful.button ({}, 5, function()
+ awful.util.spawn(string.format("amixer -c %s set %s %s-", alsabar.card, alsabar.channel, alsabar.step))
+=======
+ awful.util.spawn(string.format("%s set %s toggle", alsabar.cmd, alsabar.channel))
+ alsabar.update()
+ end),
+ awful.button ({}, 4, function()
+ awful.util.spawn(string.format("%s set %s %s+", alsabar.cmd, alsabar.channel, alsabar.step))
+ alsabar.update()
+ end),
+ awful.button ({}, 5, function()
+ awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step))
+>>>>>>> upstream/master
+ alsabar.update()
+ end)
+ ))
+
+ timer_id = string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel)
+
+ newtimer(timer_id, timeout, alsabar.update)
+
+ return alsabar
+end
+
+return setmetatable(alsabar, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2014, Luke Bonham
+
+--]]
+
+local newtimer = require("lain.helpers").newtimer
+<<<<<<< HEAD
+local wibox = require("wibox")
+
+local io = { popen = io.popen }
+=======
+local read_pipe = require("lain.helpers").read_pipe
+
+local wibox = require("wibox")
+
+>>>>>>> upstream/master
+local setmetatable = setmetatable
+
+-- Basic template for custom widgets
+-- lain.widgets.base
+
+local function worker(args)
+ local base = {}
+ local args = args or {}
+ local timeout = args.timeout or 5
+ local cmd = args.cmd or ""
+ local settings = args.settings or function() end
+
+ base.widget = wibox.widget.textbox('')
+
+ function base.update()
+<<<<<<< HEAD
+ local f = assert(io.popen(cmd))
+ output = f:read("*a")
+ f:close()
+=======
+ output = read_pipe(cmd)
+>>>>>>> upstream/master
+ widget = base.widget
+ settings()
+ end
+
+ newtimer(cmd, timeout, base.update)
+
+ return setmetatable(base, { __index = base.widget })
+end
+
+return setmetatable({}, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+
+--]]
+
+local icons_dir = require("lain.helpers").icons_dir
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local naughty = require("naughty")
+
+local io = { popen = io.popen }
+local os = { date = os.date }
+<<<<<<< HEAD
+=======
+local mouse = mouse
+>>>>>>> upstream/master
+local tonumber = tonumber
+
+local setmetatable = setmetatable
+
+-- Calendar notification
+-- lain.widgets.calendar
+local calendar = {}
+local cal_notification = nil
+
+function calendar:hide()
+ if cal_notification ~= nil then
+ naughty.destroy(cal_notification)
+ cal_notification = nil
+ end
+end
+
+function calendar:show(t_out, inc_offset, scr)
+ calendar:hide()
+
+ local offs = inc_offset or 0
+ local tims = t_out or 0
+ local f, c_text
+ local today = tonumber(os.date('%d'))
+ local init_t = calendar.cal .. ' ' .. calendar.post_cal .. ' ' ..
+ ' | sed -r -e "s/_\\x08//g" | sed -r -e "s/(^| )('
+
+ calendar.offset = calendar.offset + offs
+
+ if offs == 0 or calendar.offset == 0
+ then -- current month showing, today highlighted
+ calendar.offset = 0
+ calendar.notify_icon = calendar.icons .. today .. ".png"
+
+ -- bg and fg inverted to highlight today
+ f = io.popen( init_t .. today ..
+ ')($| )/\\1<b><span foreground=\\"'
+ .. calendar.bg ..
+ '\\" background=\\"'
+ .. calendar.fg ..
+ '\\">\\2<\\/span><\\/b>\\3/"' )
+
+ else -- no current month showing, no day to highlight
+ local month = tonumber(os.date('%m'))
+ local year = tonumber(os.date('%Y'))
+
+ month = month + calendar.offset
+
+ if month > 12 then
+ month = month % 12
+ year = year + 1
+ if month <= 0 then
+ month = 12
+ end
+ elseif month < 1 then
+ month = month + 12
+ year = year - 1
+ if month <= 0 then
+ month = 1
+ end
+ end
+
+ calendar.notify_icon = nil
+
+ f = io.popen(calendar.cal .. ' ' .. month .. ' ' .. year .. ' ' ..
+ calendar.post_cal)
+ end
+
+ c_text = "<tt><span font='" .. calendar.font .. " "
+ .. calendar.font_size .. "'><b>"
+ .. f:read() .. "</b>\n\n"
+ .. f:read() .. "\n"
+<<<<<<< HEAD
+ .. f:read("*a"):gsub("\n*$", "")
+ .. "</span></tt>"
+ f:close()
+
+=======
+ .. f:read("*all"):gsub("\n*$", "")
+ .. "</span></tt>"
+ f:close()
+
+ if calendar.followmouse then
+ scrp = mouse.screen
+ else
+ scrp = scr or calendar.scr_pos
+ end
+
+>>>>>>> upstream/master
+ cal_notification = naughty.notify({
+ text = c_text,
+ icon = calendar.notify_icon,
+ position = calendar.position,
+ fg = calendar.fg,
+ bg = calendar.bg,
+ timeout = tims,
+<<<<<<< HEAD
+ screen = scr or 1
+=======
+ screen = scrp
+>>>>>>> upstream/master
+ })
+end
+
+function calendar:attach(widget, args)
+ local args = args or {}
+<<<<<<< HEAD
+ calendar.cal = args.cal or "/usr/bin/cal"
+ calendar.post_cal = args.post_cal or ""
+ calendar.icons = args.icons or icons_dir .. "cal/white/"
+ calendar.font = args.font or beautiful.font:sub(beautiful.font:find(""),
+ beautiful.font:find(" "))
+ calendar.font_size = tonumber(args.font_size) or 11
+ calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF"
+ calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF"
+ calendar.position = args.position or "top_right"
+ calendar.scr_pos = args.scr_pos or 1
+
+ calendar.offset = 0
+ calendar.notify_icon = nil
+
+ widget:connect_signal("mouse::enter", function () calendar:show(0, 0, scr_pos) end)
+ widget:connect_signal("mouse::leave", function () calendar:hide() end)
+ widget:buttons(awful.util.table.join( awful.button({ }, 1, function ()
+ calendar:show(0, -1, scr_pos) end),
+ awful.button({ }, 3, function ()
+ calendar:show(0, 1, scr_pos) end),
+ awful.button({ }, 4, function ()
+ calendar:show(0, -1, scr_pos) end),
+ awful.button({ }, 5, function ()
+ calendar:show(0, 1, scr_pos) end)))
+=======
+
+ calendar.cal = args.cal or "/usr/bin/cal"
+ calendar.post_cal = args.post_cal or ""
+ calendar.icons = args.icons or icons_dir .. "cal/white/"
+ calendar.font = args.font or beautiful.font:sub(beautiful.font:find(""),
+ beautiful.font:find(" "))
+ calendar.font_size = tonumber(args.font_size) or 11
+ calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF"
+ calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF"
+ calendar.position = args.position or "top_right"
+ calendar.scr_pos = args.scr_pos or 1
+ calendar.followmouse = args.followmouse or false
+
+ calendar.offset = 0
+ calendar.notify_icon = nil
+
+ widget:connect_signal("mouse::enter", function () calendar:show(0, 0, calendar.scr_pos) end)
+ widget:connect_signal("mouse::leave", function () calendar:hide() end)
+ widget:buttons(awful.util.table.join(awful.button({ }, 1, function ()
+ calendar:show(0, -1, calendar.scr_pos) end),
+ awful.button({ }, 3, function ()
+ calendar:show(0, 1, calendar.scr_pos) end),
+ awful.button({ }, 4, function ()
+ calendar:show(0, -1, calendar.scr_pos) end),
+ awful.button({ }, 5, function ()
+ calendar:show(0, 1, calendar.scr_pos) end)))
+>>>>>>> upstream/master
+end
+
+return setmetatable(calendar, { __call = function(_, ...) return create(...) end })
--- /dev/null
+
+--[[
+
+ Lain
+ Layouts, widgets and utilities for Awesome WM
+
+ Users contributed widgets section
+
+ Licensed under GNU General Public License v2
+<<<<<<< HEAD
+ * (c) 2013, Luke Bonham
+=======
+ * (c) 2013, Luke Bonham
+>>>>>>> upstream/master
+
+--]]
+
+local wrequire = require("lain.helpers").wrequire
+local setmetatable = setmetatable
+
+local widgets = { _NAME = "lain.widgets.contrib" }
+
+return setmetatable(widgets, { __index = wrequire })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2014, anticlockwise <http://github.com/anticlockwise>
+
+--]]
+
+local helpers = require("lain.helpers")
+local async = require("lain.asyncshell")
+
+local escape_f = require("awful.util").escape
+local naughty = require("naughty")
+local wibox = require("wibox")
+
+local io = { popen = io.popen }
+local os = { execute = os.execute,
+ getenv = os.getenv }
+local string = { format = string.format,
+ gmatch = string.gmatch }
+
+local setmetatable = setmetatable
+
+local moc = {}
+
+local function worker(args)
+ local args = args or {}
+ local timeout = args.timeout or 2
+ local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
+ local cover_size = args.cover_size or 100
+ local default_art = args.default_art or ""
+<<<<<<< HEAD
+=======
+ local followmouse = args.followmouse or false
+>>>>>>> upstream/master
+ local settings = args.settings or function() end
+
+ local mpdcover = helpers.scripts_dir .. "mpdcover"
+
+ moc.widget = wibox.widget.textbox('')
+
+ moc_notification_preset = {
+ title = "Now playing",
+ timeout = 6
+ }
+
+ helpers.set_map("current moc track", nil)
+
+ function moc.update()
+ -- mocp -i will produce output like:
+ -- Artist: Travis
+ -- Album: The Man Who
+ -- etc.
+ async.request("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"
+ }
+
+<<<<<<< HEAD
+ for line in f:lines() do
+=======
+ for line in string.gmatch(f, "[^\n]+") do
+>>>>>>> upstream/master
+ 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)
+ os.execute(string.format("%s %q %q %d %q", mpdcover, "",
+ moc_now.file, cover_size, default_art))
+
+<<<<<<< HEAD
+=======
+ if followmouse then
+ moc_notification_preset.screen = mouse.screen
+ end
+
+>>>>>>> upstream/master
+ moc.id = naughty.notify({
+ preset = moc_notification_preset,
+ icon = "/tmp/mpdcover.png",
+ replaces_id = moc.id,
+ }).id
+ end
+ elseif moc_now.state ~= "PAUSE" then
+ helpers.set_map("current moc track", nil)
+ end
+ end)
+ end
+
+ helpers.newtimer("moc", timeout, moc.update)
+
+ return setmetatable(moc, { __index = moc.widget })
+end
+
+return setmetatable(moc, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Jan Xie
+
+--]]
+
+local icons_dir = require("lain.helpers").icons_dir
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local naughty = require("naughty")
+
+<<<<<<< HEAD
+=======
+local mouse = mouse
+>>>>>>> upstream/master
+local io = io
+local string = { len = string.len }
+local tonumber = tonumber
+
+local setmetatable = setmetatable
+
+-- Taskwarrior notification
+-- lain.widgets.contrib.task
+local task = {}
+
+local task_notification = nil
+
+function task:hide()
+ if task_notification ~= nil then
+ naughty.destroy(task_notification)
+ task_notification = nil
+ end
+end
+
+<<<<<<< HEAD
+function task:show()
+=======
+function task:show(scr_pos)
+>>>>>>> upstream/master
+ task:hide()
+
+ local f, c_text
+
+<<<<<<< HEAD
+=======
+ if task.followmouse then
+ local scrp = mouse.screen
+ else
+ local scrp = scr_pos or task.scr_pos
+ end
+
+>>>>>>> upstream/master
+ f = io.popen('task')
+ c_text = "<span font='"
+ .. task.font .. " "
+ .. task.font_size .. "'>"
+ .. f:read("*all"):gsub("\n*$", "")
+ .. "</span>"
+ f:close()
+
+ task_notification = naughty.notify({ title = "[task next]",
+ text = c_text,
+ icon = task.notify_icon,
+ position = task.position,
+ fg = task.fg,
+ bg = task.bg,
+ timeout = task.timeout,
+<<<<<<< HEAD
+=======
+ screen = scrp
+>>>>>>> upstream/master
+ })
+end
+
+function task:prompt_add()
+ awful.prompt.run({ prompt = "Add task: " },
+ mypromptbox[mouse.screen].widget,
+ function (...)
+ local f = io.popen("task add " .. ...)
+ c_text = "\n<span font='"
+ .. task.font .. " "
+ .. task.font_size .. "'>"
+ .. f:read("*all")
+ .. "</span>"
+ f:close()
+
+ naughty.notify({
+ text = c_text,
+ icon = task.notify_icon,
+ position = task.position,
+ fg = task.fg,
+ bg = task.bg,
+ timeout = task.timeout,
+ })
+ end,
+ nil,
+ awful.util.getdir("cache") .. "/history_task_add")
+end
+
+function task:prompt_search()
+ awful.prompt.run({ prompt = "Search task: " },
+ mypromptbox[mouse.screen].widget,
+ function (...)
+ local f = io.popen("task " .. ...)
+ c_text = f:read("*all"):gsub(" \n*$", "")
+ f:close()
+
+ if string.len(c_text) == 0
+ then
+ c_text = "No results found."
+ else
+ c_text = "<span font='"
+ .. task.font .. " "
+ .. task.font_size .. "'>"
+ .. c_text
+ .. "</span>"
+ end
+
+ naughty.notify({
+ title = "[task next " .. ... .. "]",
+ text = c_text,
+ icon = task.notify_icon,
+ position = task.position,
+ fg = task.fg,
+ bg = task.bg,
+ timeout = task.timeout,
+<<<<<<< HEAD
+=======
+ screen = mouse.screen
+>>>>>>> upstream/master
+ })
+ end,
+ nil,
+ awful.util.getdir("cache") .. "/history_task")
+end
+
+function task:attach(widget, args)
+<<<<<<< HEAD
+ local args = args or {}
+
+ task.font_size = tonumber(args.font_size) or 12
+ task.font = beautiful.font:sub(beautiful.font:find(""),
+ beautiful.font:find(" "))
+ task.fg = args.fg or beautiful.fg_normal or "#FFFFFF"
+ task.bg = args.bg or beautiful.bg_normal or "#FFFFFF"
+ task.position = args.position or "top_right"
+ task.timeout = args.timeout or 7
+=======
+ local args = args or {}
+
+ task.font_size = tonumber(args.font_size) or 12
+ task.font = beautiful.font:sub(beautiful.font:find(""),
+ beautiful.font:find(" "))
+ task.fg = args.fg or beautiful.fg_normal or "#FFFFFF"
+ task.bg = args.bg or beautiful.bg_normal or "#FFFFFF"
+ task.position = args.position or "top_right"
+ task.timeout = args.timeout or 7
+ task.scr_pos = args.scr_pos or 1
+ task.followmouse = args.followmouse or false
+>>>>>>> upstream/master
+
+ task.notify_icon = icons_dir .. "/taskwarrior/task.png"
+ task.notify_icon_small = icons_dir .. "/taskwarrior/tasksmall.png"
+
+<<<<<<< HEAD
+ widget:connect_signal("mouse::enter", function () task:show() end)
+=======
+ widget:connect_signal("mouse::enter", function () task:show(task.scr_pos) end)
+>>>>>>> upstream/master
+ widget:connect_signal("mouse::leave", function () task:hide() end)
+end
+
+return setmetatable(task, { __call = function(_, ...) return create(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+ * (c) 2010, Adrian C. <anrxc@sysphere.org>
+ * (c) 2009, Lucas de Vries <lucas@glacicle.com>
+
+--]]
+
+local helpers = require("lain.helpers")
+
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+local naughty = require("naughty")
+
+local io = { popen = io.popen }
+local pairs = pairs
+<<<<<<< HEAD
+=======
+local mouse = mouse
+>>>>>>> upstream/master
+local string = { match = string.match,
+ format = string.format }
+local tonumber = tonumber
+
+local setmetatable = setmetatable
+
+-- File system disk space usage
+-- lain.widgets.fs
+local fs = {}
+<<<<<<< HEAD
+
+local notification = nil
+fs_notification_preset = { fg = beautiful.fg_normal }
+
+function fs:hide()
+ if notification ~= nil then
+ naughty.destroy(notification)
+ notification = nil
+=======
+local fs_notification = nil
+
+function fs:hide()
+ if fs_notification ~= nil then
+ naughty.destroy(fs_notification)
+ fs_notification = nil
+>>>>>>> upstream/master
+ end
+end
+
+function fs:show(t_out)
+ fs:hide()
+
+<<<<<<< HEAD
+ local f = io.popen(helpers.scripts_dir .. "dfs")
+ ws = f:read("*a"):gsub("\n*$", "")
+ f:close()
+
+ notification = naughty.notify({
+ preset = fs_notification_preset,
+ text = ws,
+ timeout = t_out,
+=======
+ local ws = helpers.read_pipe(helpers.scripts_dir .. "dfs"):gsub("\n*$", "")
+
+ if fs.followmouse then
+ fs.notification_preset.screen = mouse.screen
+ end
+
+ fs_notification = naughty.notify({
+ preset = fs.notification_preset,
+ text = ws,
+ timeout = t_out
+>>>>>>> upstream/master
+ })
+end
+
+-- Unit definitions
+local unit = { ["mb"] = 1024, ["gb"] = 1024^2 }
+
+local function worker(args)
+<<<<<<< HEAD
+ local args = args or {}
+ local timeout = args.timeout or 600
+ local partition = args.partition or "/"
+ local settings = args.settings or function() end
+=======
+ local args = args or {}
+ local timeout = args.timeout or 600
+ local partition = args.partition or "/"
+ local settings = args.settings or function() end
+
+ fs.followmouse = args.followmouse or false
+ fs.notification_preset = args.notification_preset or { fg = beautiful.fg_normal }
+>>>>>>> upstream/master
+
+ fs.widget = wibox.widget.textbox('')
+
+ helpers.set_map(partition, false)
+
+ function update()
+ fs_info = {}
+ fs_now = {}
+ local f = assert(io.popen("LC_ALL=C df -kP"))
+
+ for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount)
+ local s = string.match(line, "^.-[%s]([%d]+)")
+ local u,a,p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%")
+ local m = string.match(line, "%%[%s]([%p%w]+)")
+
+ if u and m then -- Handle 1st line and broken regexp
+ fs_info[m .. " size_mb"] = string.format("%.1f", tonumber(s) / unit["mb"])
+ fs_info[m .. " size_gb"] = string.format("%.1f", tonumber(s) / unit["gb"])
+ fs_info[m .. " used_p"] = tonumber(p)
+ fs_info[m .. " avail_p"] = 100 - tonumber(p)
+ end
+ end
+
+ f:close()
+
+ fs_now.used = tonumber(fs_info[partition .. " used_p"]) or 0
+ fs_now.available = tonumber(fs_info[partition .. " avail_p"]) or 0
+ fs_now.size_mb = tonumber(fs_info[partition .. " size_mb"]) or 0
+ fs_now.size_gb = tonumber(fs_info[partition .. " size_gb"]) or 0
+
+ widget = fs.widget
+ settings()
+
+ if fs_now.used >= 99 and not helpers.get_map(partition)
+ then
+ naughty.notify({
+ title = "warning",
+ text = partition .. " ran out!\nmake some room",
+ timeout = 8,
+ fg = "#000000",
+ bg = "#FFFFFF",
+ })
+ helpers.set_map(partition, true)
+ else
+ helpers.set_map(partition, false)
+ end
+ end
+
+ fs.widget:connect_signal('mouse::enter', function () fs:show(0) end)
+ fs.widget:connect_signal('mouse::leave', function () fs:hide() end)
+
+ helpers.newtimer(partition, timeout, update)
+
+ return setmetatable(fs, { __index = fs.widget })
+end
+
+return setmetatable(fs, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+
+--]]
+
+local helpers = require("lain.helpers")
+local async = require("lain.asyncshell")
+
+local naughty = require("naughty")
+local wibox = require("wibox")
+
+<<<<<<< HEAD
+=======
+local mouse = mouse
+>>>>>>> upstream/master
+local string = { format = string.format,
+ gsub = string.gsub }
+local tonumber = tonumber
+
+local setmetatable = setmetatable
+
+-- Mail IMAP check
+-- lain.widgets.imap
+
+local function worker(args)
+<<<<<<< HEAD
+ local imap = {}
+ local args = args or {}
+
+ 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 is_plain = args.is_plain or false
+ local settings = args.settings or function() end
+=======
+ local imap = {}
+ local args = args or {}
+
+ 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 is_plain = args.is_plain or false
+ local followmouse = args.followmouse or false
+ local settings = args.settings or function() end
+>>>>>>> upstream/master
+
+ local head_command = "curl --connect-timeout 3 -fsm 3"
+ local request = "-X 'SEARCH (UNSEEN)'"
+
+ helpers.set_map(mail, 0)
+
+ if not is_plain
+ then
+<<<<<<< HEAD
+ local f = io.popen(password)
+ password = f:read("*a"):gsub("\n", "")
+ f:close()
+=======
+ password = helpers.read_pipe(password):gsub("\n", "")
+>>>>>>> upstream/master
+ end
+
+ imap.widget = wibox.widget.textbox('')
+
+ function update()
+ mail_notification_preset = {
+ icon = helpers.icons_dir .. "mail.png",
+ position = "top_left"
+ }
+
+<<<<<<< HEAD
+=======
+ if followmouse then
+ mail_notification_preset.screen = mouse.screen
+ end
+
+>>>>>>> upstream/master
+ curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%q %s -k",
+ head_command, server, port, mail, password, request)
+
+ async.request(curl, function(f)
+<<<<<<< HEAD
+ ws = f:read("*a")
+ f:close()
+
+ _, mailcount = string.gsub(ws, "%d+", "")
+=======
+ _, mailcount = string.gsub(f, "%d+", "")
+>>>>>>> upstream/master
+ _ = nil
+
+ widget = imap.widget
+ settings()
+
+ if mailcount >= 1 and mailcount > helpers.get_map(mail)
+ then
+ if mailcount == 1 then
+ nt = mail .. " has one new message"
+ else
+ nt = mail .. " has <b>" .. mailcount .. "</b> new messages"
+ end
+ naughty.notify({
+ preset = mail_notification_preset,
+<<<<<<< HEAD
+ text = nt,
+=======
+ text = nt
+>>>>>>> upstream/master
+ })
+ end
+
+ helpers.set_map(mail, mailcount)
+ end)
+
+ end
+
+ helpers.newtimer(mail, timeout, update, true)
+
+ return setmetatable(imap, { __index = imap.widget })
+end
+
+return setmetatable({}, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+ * (c) 2010-2012, Peter Hofmann
+
+--]]
+
+local newtimer = require("lain.helpers").newtimer
+<<<<<<< HEAD
+=======
+local read_pipe = require("lain.helpers").read_pipe
+>>>>>>> upstream/master
+
+local wibox = require("wibox")
+
+local util = require("lain.util")
+
+local io = { popen = io.popen }
+local os = { getenv = os.getenv }
+local pairs = pairs
+local string = { len = string.len,
+ match = string.match }
+local table = { sort = table.sort }
+
+local setmetatable = setmetatable
+
+-- Maildir check
+-- lain.widgets.maildir
+local maildir = {}
+
+local function worker(args)
+ local args = args or {}
+ local timeout = args.timeout or 60
+ local mailpath = args.mailpath or os.getenv("HOME") .. "/Mail"
+ local ignore_boxes = args.ignore_boxes or {}
+ local settings = args.settings or function() end
+
+ maildir.widget = wibox.widget.textbox('')
+
+ function update()
+ -- Find pathes to mailboxes.
+ local p = io.popen("find " .. mailpath ..
+ " -mindepth 1 -maxdepth 1 -type d" ..
+ " -not -name .git")
+ local boxes = {}
+ repeat
+ line = p:read("*l")
+ if line ~= nil
+ then
+ -- Find all files in the "new" subdirectory. For each
+ -- file, print a single character (no newline). Don't
+ -- match files that begin with a dot.
+ -- Afterwards the length of this string is the number of
+ -- new mails in that box.
+<<<<<<< HEAD
+ local np = io.popen("find " .. line ..
+ "/new -mindepth 1 -type f " ..
+ "-not -name '.*' -printf a")
+ local mailstring = np:read("*a")
+=======
+ local mailstring = read_pipe("find " .. line ..
+ "/new -mindepth 1 -type f " ..
+ "-not -name '.*' -printf a")
+>>>>>>> upstream/master
+
+ -- Strip off leading mailpath.
+ local box = string.match(line, mailpath .. "/*([^/]+)")
+ local nummails = string.len(mailstring)
+ if nummails > 0
+ then
+ boxes[box] = nummails
+ end
+ end
+ until line == nil
+
+<<<<<<< HEAD
+ table.sort(boxes)
+
+ newmail = "no mail"
+ --Count the total number of mails irrespective of where it was found
+=======
+ p:close()
+ table.sort(boxes)
+
+ newmail = "no mail"
+ -- Count the total number of mails irrespective of where it was found
+>>>>>>> upstream/master
+ total = 0
+
+ for box, number in pairs(boxes)
+ do
+ -- Add this box only if it's not to be ignored.
+ if not util.element_in_table(box, ignore_boxes)
+ then
+ total = total + number
+ if newmail == "no mail"
+ then
+ newmail = box .. "(" .. number .. ")"
+ else
+ newmail = newmail .. ", " ..
+ box .. "(" .. number .. ")"
+ end
+ end
+ end
+
+ widget = maildir.widget
+ settings()
+ end
+
+ newtimer(mailpath, timeout, update, true)
+ return maildir.widget
+end
+
+return setmetatable(maildir, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+ * (c) 2010, Adrian C. <anrxc@sysphere.org>
+
+--]]
+
+local helpers = require("lain.helpers")
+local async = require("lain.asyncshell")
+
+local escape_f = require("awful.util").escape
+local naughty = require("naughty")
+local wibox = require("wibox")
+
+local os = { execute = os.execute,
+ getenv = os.getenv }
+local math = { floor = math.floor }
+<<<<<<< HEAD
+=======
+local mouse = mouse
+>>>>>>> upstream/master
+local string = { format = string.format,
+ match = string.match,
+ gmatch = string.gmatch }
+
+local setmetatable = setmetatable
+
+-- MPD infos
+-- lain.widgets.mpd
+local mpd = {}
+
+local function worker(args)
+ local args = args or {}
+ local timeout = args.timeout or 2
+ local password = args.password or ""
+ local host = args.host or "127.0.0.1"
+ local port = args.port or "6600"
+ local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
+ local cover_size = args.cover_size or 100
+ local default_art = args.default_art or ""
+<<<<<<< HEAD
+=======
+ local followmouse = args.followmouse or false
+ local echo_cmd = args.echo_cmd or "echo"
+>>>>>>> upstream/master
+ local settings = args.settings or function() end
+
+ local mpdcover = helpers.scripts_dir .. "mpdcover"
+ local mpdh = "telnet://" .. host .. ":" .. port
+<<<<<<< HEAD
+ local echo = "echo 'password " .. password .. "\nstatus\ncurrentsong\nclose'"
+=======
+ local echo = echo_cmd .. " 'password " .. password .. "\nstatus\ncurrentsong\nclose'"
+>>>>>>> upstream/master
+
+ mpd.widget = wibox.widget.textbox('')
+
+ mpd_notification_preset = {
+ title = "Now playing",
+ timeout = 6
+ }
+
+ helpers.set_map("current mpd track", nil)
+
+ function mpd.update()
+ async.request(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh, function (f)
+ mpd_now = {
+ state = "N/A",
+ file = "N/A",
+ artist = "N/A",
+ title = "N/A",
+ album = "N/A",
+ date = "N/A",
+ time = "N/A",
+ elapsed = "N/A"
+ }
+
+<<<<<<< HEAD
+ for line in f:lines() do
+=======
+ for line in string.gmatch(f, "[^\n]+") do
+>>>>>>> upstream/master
+ 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 == "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 == "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+")
+ 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 mpd_now.title ~= helpers.get_map("current mpd track")
+ then
+ helpers.set_map("current mpd track", mpd_now.title)
+
+<<<<<<< HEAD
+ if string.match(mpd_now.file, "http://") == nil
+=======
+ if string.match(mpd_now.file, "http.*://") == nil
+>>>>>>> upstream/master
+ then -- local file
+ os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir,
+ mpd_now.file, cover_size, default_art))
+ current_icon = "/tmp/mpdcover.png"
+ else -- http stream
+ current_icon = default_art
+ end
+
+<<<<<<< HEAD
+=======
+ if followmouse then
+ mpd_notification_preset.screen = mouse.screen
+ end
+
+>>>>>>> upstream/master
+ mpd.id = naughty.notify({
+ preset = mpd_notification_preset,
+ icon = current_icon,
+ replaces_id = mpd.id,
+ }).id
+ end
+ elseif mpd_now.state ~= "pause"
+ then
+ helpers.set_map("current mpd track", nil)
+ end
+ end)
+ end
+
+ helpers.newtimer("mpd", timeout, mpd.update)
+
+ return setmetatable(mpd, { __index = mpd.widget })
+end
+
+return setmetatable(mpd, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+ * (c) 2010-2012, Peter Hofmann
+
+--]]
+
+local helpers = require("lain.helpers")
+
+local notify_fg = require("beautiful").fg_focus
+local naughty = require("naughty")
+local wibox = require("wibox")
+
+<<<<<<< HEAD
+local io = { popen = io.popen }
+=======
+>>>>>>> upstream/master
+local string = { format = string.format,
+ gsub = string.gsub,
+ match = string.match }
+
+local setmetatable = setmetatable
+
+-- Network infos
+-- lain.widgets.net
+local net = {
+ last_t = 0,
+ last_r = 0
+}
+
+function net.get_device()
+<<<<<<< HEAD
+ f = io.popen("ip link show | cut -d' ' -f2,9")
+ ws = f:read("*a")
+ f:close()
+=======
+ local ws = helpers.read_pipe("ip link show | cut -d' ' -f2,9")
+>>>>>>> upstream/master
+ ws = ws:match("%w+: UP") or ws:match("ppp%w+: UNKNOWN")
+ if ws ~= nil then
+ return ws:match("(%w+):")
+ else
+ return "network off"
+ end
+end
+
+local function worker(args)
+ local args = args or {}
+ local timeout = args.timeout or 2
+ local units = args.units or 1024 --kb
+ local notify = args.notify or "on"
+ local screen = args.screen or 1
+ local settings = args.settings or function() end
+
+ iface = args.iface or net.get_device()
+
+ net.widget = wibox.widget.textbox('')
+
+ helpers.set_map(iface, true)
+
+ function update()
+ net_now = {}
+
+ if iface == "" or string.match(iface, "network off")
+ then
+ iface = net.get_device()
+ end
+
+ net_now.carrier = helpers.first_line('/sys/class/net/' .. iface ..
+ '/carrier') or "0"
+ net_now.state = helpers.first_line('/sys/class/net/' .. iface ..
+ '/operstate') or "down"
+ local now_t = helpers.first_line('/sys/class/net/' .. iface ..
+ '/statistics/tx_bytes') or 0
+ local now_r = helpers.first_line('/sys/class/net/' .. iface ..
+ '/statistics/rx_bytes') or 0
+
+ net_now.sent = (now_t - net.last_t) / timeout / units
+ net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ",", ".")
+
+ net_now.received = (now_r - net.last_r) / timeout / units
+ net_now.received = string.gsub(string.format('%.1f', net_now.received), ",", ".")
+
+ widget = net.widget
+ settings()
+
+ net.last_t = now_t
+ net.last_r = now_r
+
+ if net_now.carrier ~= "1" and notify == "on"
+ then
+ if helpers.get_map(iface)
+ then
+ naughty.notify({
+ title = iface,
+ text = "no carrier",
+ timeout = 7,
+ position = "top_left",
+ icon = helpers.icons_dir .. "no_net.png",
+ fg = notify_fg or "#FFFFFF",
+ screen = screen
+ })
+ helpers.set_map(iface, false)
+ end
+ else
+ helpers.set_map(iface, true)
+ end
+ end
+
+ helpers.newtimer(iface, timeout, update)
+ return net.widget
+end
+
+return setmetatable(net, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+ * (c) 2010-2012, Peter Hofmann
+
+--]]
+
+local newtimer = require("lain.helpers").newtimer
+
+local wibox = require("wibox")
+
+local io = { open = io.open }
+local string = { match = string.match }
+
+local setmetatable = setmetatable
+
+-- System load
+-- lain.widgets.sysload
+local sysload = {}
+
+local function worker(args)
+ local args = args or {}
+ local timeout = args.timeout or 2
+ local settings = args.settings or function() end
+
+ sysload.widget = wibox.widget.textbox('')
+
+ function update()
+ local f = io.open("/proc/loadavg")
+<<<<<<< HEAD
+ local ret = f:read("*a")
+=======
+ local ret = f:read("*all")
+>>>>>>> upstream/master
+ f:close()
+
+ load_1, load_5, load_15 = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)")
+
+ widget = sysload.widget
+ settings()
+ end
+
+ newtimer("sysload", timeout, update)
+ return sysload.widget
+end
+
+return setmetatable(sysload, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2013, Luke Bonham
+
+--]]
+
+local newtimer = require("lain.helpers").newtimer
+
+local wibox = require("wibox")
+
+local io = { open = io.open }
+local tonumber = tonumber
+
+local setmetatable = setmetatable
+
+-- coretemp
+-- lain.widgets.temp
+local temp = {}
+
+local function worker(args)
+ local args = args or {}
+ local timeout = args.timeout or 2
+ local tempfile = args.tempfile or "/sys/class/thermal/thermal_zone0/temp"
+ local settings = args.settings or function() end
+
+ temp.widget = wibox.widget.textbox('')
+
+ function update()
+ local f = io.open(tempfile)
+ if f ~= nil
+ then
+<<<<<<< HEAD
+ coretemp_now = tonumber(f:read("*a")) / 1000
+=======
+ coretemp_now = tonumber(f:read("*all")) / 1000
+>>>>>>> upstream/master
+ f:close()
+ else
+ coretemp_now = "N/A"
+ end
+
+ widget = temp.widget
+ settings()
+ end
+
+ newtimer("coretemp", timeout, update)
+ return temp.widget
+end
+
+return setmetatable(temp, { __call = function(_, ...) return worker(...) end })
--- /dev/null
+
+--[[
+
+ Licensed under GNU General Public License v2
+ * (c) 2015, Luke Bonham
+
+--]]
+
+local newtimer = require("lain.helpers").newtimer
+<<<<<<< HEAD
+local async = require("lain.asyncshell")
+local json = require("lain.util").dkjson
+local lain_icons = require("lain.helpers").icons_dir
+=======
+local read_pipe = require("lain.helpers").read_pipe
+
+local async = require("lain.asyncshell")
+local json = require("lain.util").dkjson
+local lain_icons = require("lain.helpers").icons_dir
+
+>>>>>>> upstream/master
+local naughty = require("naughty")
+local wibox = require("wibox")
+
+local math = { floor = math.floor }
+<<<<<<< HEAD
+=======
+local mouse = mouse
+>>>>>>> upstream/master
+local string = { format = string.format,
+ gsub = string.gsub }
+
+local setmetatable = setmetatable
+
+-- OpenWeatherMap
+-- current weather and X-days forecast
+-- lain.widgets.weather
+
+local function worker(args)
+<<<<<<< HEAD
+ local weather = {}
+ local args = args or {}
+ local timeout = args.timeout or 900 -- 15 min
+ local timeout_forecast = args.timeout or 86400 -- 24 hrs
+ local current_call = "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s'"
+ local forecast_call = "curl -s 'http://api.openweathermap.org/data/2.5/forecast/daily?id=%s&units=%s&lang=%s&cnt=%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 7
+ local date_cmd = args.date_cmd or "date -u -d @%d +'%%a %%d'"
+ local icons_path = args.icons_path or lain_icons .. "openweathermap/"
+ local w_notification_preset = args.w_notification_preset or {}
+ local settings = args.settings or function() end
+=======
+ local weather = {}
+ local args = args or {}
+ local timeout = args.timeout or 900 -- 15 min
+ local timeout_forecast = args.timeout or 86400 -- 24 hrs
+ local current_call = "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s'"
+ local forecast_call = "curl -s 'http://api.openweathermap.org/data/2.5/forecast/daily?id=%s&units=%s&lang=%s&cnt=%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 7
+ local date_cmd = args.date_cmd or "date -u -d @%d +'%%a %%d'"
+ local icons_path = args.icons_path or lain_icons .. "openweathermap/"
+ local notification_preset = args.notification_preset or {}
+ local followmouse = args.followmouse or false
+ local settings = args.settings or function() end
+>>>>>>> upstream/master
+
+ weather.widget = wibox.widget.textbox('')
+ weather.icon = wibox.widget.imagebox()
+
+ function weather.show(t_out)
+ weather.hide()
+<<<<<<< HEAD
+=======
+
+ if followmouse then
+ notification_preset.screen = mouse.screen
+ end
+
+>>>>>>> upstream/master
+ weather.notification = naughty.notify({
+ text = weather.notification_text,
+ icon = weather.icon_path,
+ timeout = t_out,
+<<<<<<< HEAD
+ preset = w_notification_preset
+=======
+ preset = notification_preset
+>>>>>>> upstream/master
+ })
+ end
+
+ function weather.hide()
+ if weather.notification ~= nil 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, cnt)
+ async.request(cmd, function(f)
+<<<<<<< HEAD
+ j = f:read("*a")
+ f:close()
+ weather_now, pos, err = json.decode(j, 1, nil)
+=======
+ weather_now, pos, err = json.decode(f, 1, nil)
+>>>>>>> upstream/master
+
+ if not err and weather_now ~= nil and tonumber(weather_now["cod"]) == 200 then
+ weather.notification_text = ''
+ for i = 1, weather_now["cnt"] do
+<<<<<<< HEAD
+ local f = assert(io.popen(string.format(date_cmd, weather_now["list"][i]["dt"])))
+ day = string.gsub(f:read("a"), "\n", "")
+ f:close()
+=======
+ day = string.gsub(read_pipe(string.format(date_cmd, weather_now["list"][i]["dt"])), "\n", "")
+>>>>>>> upstream/master
+
+ tmin = math.floor(weather_now["list"][i]["temp"]["min"])
+ tmax = math.floor(weather_now["list"][i]["temp"]["max"])
+ desc = weather_now["list"][i]["weather"][1]["description"]
+
+ weather.notification_text = weather.notification_text ..
+ string.format("<b>%s</b>: %s, %d - %d ", day, desc, tmin, tmax)
+
+ if i < weather_now["cnt"] then
+ weather.notification_text = weather.notification_text .. "\n"
+ end
+ end
+ else
+ weather.icon_path = icons_path .. "na.png"
+ weather.notification_text = "API/connection error or bad/not set city ID"
+ end
+ end)
+ end
+
+ function weather.update()
+ local cmd = string.format(current_call, city_id, units, lang)
+ async.request(cmd, function(f)
+<<<<<<< HEAD
+ j = f:read("*a")
+ f:close()
+ weather_now, pos, err = json.decode(j, 1, nil)
+=======
+ weather_now, pos, err = json.decode(f, 1, nil)
+>>>>>>> upstream/master
+
+ if not err and weather_now ~= nil and tonumber(weather_now["cod"]) == 200 then
+ weather.icon_path = icons_path .. weather_now["weather"][1]["icon"] .. ".png"
+ weather.icon:set_image(weather.icon_path)
+ widget = weather.widget
+ settings()
+ else
+ weather.widget._layout.text = " N/A " -- tries to avoid textbox bugs
+ weather.icon:set_image(icons_path .. "na.png")
+ end
+ end)
+ end
+
+ weather.attach(weather.widget)
+
+ newtimer("weather-" .. city_id, timeout, weather.update)
+ newtimer("weather_forecast" .. city_id, timeout, weather.forecast_update)
+
+ return setmetatable(weather, { __index = weather.widget })
+end
+
+return setmetatable({}, { __call = function(_, ...) return worker(...) end })