]> git.madduck.net Git - etc/awesome.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

from asynchshell to awful.spawn.easy_async; started making every widget asynchronous
authorcopycat-killer <dada@archlinux.info>
Fri, 20 Jan 2017 19:58:22 +0000 (20:58 +0100)
committercopycat-killer <dada@archlinux.info>
Fri, 20 Jan 2017 19:58:22 +0000 (20:58 +0100)
13 files changed:
asyncshell.lua [deleted file]
helpers.lua
widgets/abase.lua
widgets/alsa.lua
widgets/alsabar.lua
widgets/contrib/gpmdp.lua
widgets/contrib/kbdlayout.lua
widgets/contrib/moc.lua
widgets/contrib/task.lua
widgets/imap.lua
widgets/mpd.lua
widgets/weather.lua
wiki

diff --git a/asyncshell.lua b/asyncshell.lua
deleted file mode 100644 (file)
index 61336db..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-
---[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2015, worron                          
-      * (c) 2013, Alexander Yakushev              
-                                                  
---]]
-
--- Asynchronous io.popen for Awesome WM.
--- How to use:
--- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end)
-
--- Grab environment
-local awful = require('awful')
-
--- Avoid discrepancies across multiple shells
-awful.util.shell = '/bin/sh'
-
--- Initialize tables for module
-asyncshell = { request_table = {}, id_counter = 0 }
-
--- Request counter
-local function next_id()
-    asyncshell.id_counter = (asyncshell.id_counter + 1) % 10000
-    return asyncshell.id_counter
-end
-
--- Remove given request
-function asyncshell.clear(id)
-    if asyncshell.request_table[id] then
-        if asyncshell.request_table[id].timer then
-            asyncshell.request_table[id].timer:stop()
-            asyncshell.request_table[id].timer = nil
-        end
-        asyncshell.request_table[id] = nil
-    end
-end
-
--- Sends an asynchronous request for an output of the shell command
--- @param command Command to be executed and taken output from
--- @param callback Function to be called when the command finishes
--- @param timeout Maximum amount of time to wait for the result (optional)
-function asyncshell.request(command, callback, timeout)
-    local id = next_id()
-    asyncshell.request_table[id] = { callback = callback }
-
-    local formatted_command = string.gsub(command, '"','\"')
-
-    local req = string.format(
-        "echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &",
-        id, formatted_command
-    )
-
-    if type(awful.spawn) == 'table' and awful.spawn.with_shell then
-        awful.spawn.with_shell(req)
-    else
-        awful.util.spawn_with_shell(req)
-    end
-
-    if timeout then
-        asyncshell.request_table[id].timer = timer({ timeout = timeout })
-        asyncshell.request_table[id].timer:connect_signal("timeout", function() asyncshell.clear(id) end)
-        asyncshell.request_table[id].timer:start()
-    end
-end
-
--- Calls the remembered callback function on the output of the shell command
--- @param id Request ID
--- @param output Shell command output to be delievered
-function asyncshell.deliver(id, output)
-    local output = string.sub(output, 2, -2)
-    if asyncshell.request_table[id] then
-        asyncshell.request_table[id].callback(output)
-        asyncshell.clear(id)
-    end
-end
-
-return asyncshell
index a10aa7aaf8412304244de738dd8223cb2ace3679..9755dc0405e072980b6e937d8e47acb8206c0432 100644 (file)
@@ -6,17 +6,17 @@
                                                   
 --]]
 
-local debug  = require("debug")
 
-local assert = assert
-local capi   = { timer = require("gears.timer") }
-local io     = { open  = io.open,
-                 lines = io.lines,
-                 popen = io.popen }
-local rawget = rawget
-local table  = { sort   = table.sort }
+local debug      = require("debug")
+local io         = { lines = io.lines,
+                     open  = io.open,
+                     popen = io.popen }
+local rawget     = rawget
+local table      = { sort  = table.sort }
 
-local wibox  = require("wibox")
+local easy_async = require("awful.spawn").easy_async
+local timer      = require("gears.timer")
+local wibox      = require("wibox")
 
 -- Lain helper functions for internal use
 -- lain.helpers
@@ -95,7 +95,7 @@ helpers.timer_table = {}
 function helpers.newtimer(_name, timeout, fun, nostart)
     local name = timeout
     if not helpers.timer_table[name] then
-        helpers.timer_table[name] = capi.timer({ timeout = timeout })
+        helpers.timer_table[name] = timer({ timeout = timeout })
         helpers.timer_table[name]:start()
     end
     helpers.timer_table[name]:connect_signal("timeout", fun)
@@ -108,22 +108,25 @@ end
 
 -- {{{ Pipe operations
 
--- read the full output of a command output
+-- return the full output of an input command (synchronous pipe)
+-- @param cmd the input command
+-- @return command output (string)
 function helpers.read_pipe(cmd)
-   local f = assert(io.popen(cmd))
+   local f = io.popen(cmd)
    local output = f:read("*all")
    f:close()
    return output
 end
 
--- return line iterator of a command output
-function helpers.pipelines(...)
-    local f = assert(io.popen(...))
-    return function () -- iterator
-        local data = f:read()
-        if data == nil then f:close() end
-        return data
-    end
+-- run a command and execute a function on its output (asynchronous pipe)
+-- @param cmd the input command
+-- @param callback function to execute on cmd output
+-- @return cmd PID
+function helpers.async(cmd, callback)
+    return easy_async(cmd,
+    function (stdout, stderr, reason, exit_code)
+        callback(stdout)
+    end)
 end
 
 -- }}}
index 60d86ab2fa44be30e333fbac69531194c5a12ada..a176cf1fed7d9296ab194361816c4062a9d7a361 100644 (file)
@@ -6,10 +6,8 @@
                                                   
 --]]
 
-local newtimer     = require("lain.helpers").newtimer
-local async        = require("lain.asyncshell")
+local helpers      = require("lain.helpers")
 local wibox        = require("wibox")
-
 local setmetatable = setmetatable
 
 -- Basic template for custom widgets (asynchronous version)
@@ -22,10 +20,10 @@ local function worker(args)
     local cmd      = args.cmd or ""
     local settings = args.settings or function() end
 
-    abase.widget = wibox.widget.textbox('')
+    abase.widget = wibox.widget.textbox()
 
     function abase.update()
-        async.request(cmd, function(f)
+        helpers.async(cmd, function(f)
             output = f
             if output ~= abase.prev then
                 widget = abase.widget
@@ -35,7 +33,7 @@ local function worker(args)
         end)
     end
 
-    newtimer(cmd, timeout, abase.update)
+    helpers.newtimer(cmd, timeout, abase.update)
 
     return setmetatable(abase, { __index = abase.widget })
 end
index 670765acf826e21ffd8a2454fbb08e1657464186..7c853c971fe4fb2876f00598ee34ceedd413c4db 100644 (file)
@@ -8,13 +8,9 @@
 --]]
 
 local helpers      = require("lain.helpers")
-local read_pipe    = require("lain.helpers").read_pipe
-
 local wibox        = require("wibox")
-
 local string       = { match  = string.match,
                        format = string.format }
-
 local setmetatable = setmetatable
 
 -- ALSA volume
@@ -26,29 +22,20 @@ local function worker(args)
     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
-    alsa.last_level    = "0"
-    alsa.last_status   = ""
+    alsa.cmd     = args.cmd or "amixer"
+    alsa.channel = args.channel or "Master"
+    alsa.last    = {}
 
     function alsa.update()
-        mixer = read_pipe(string.format("%s get %s", alsa.cmd, alsa.channel))
-        l, s  = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
-
-        -- HDMIs can have a channel different from Master for toggling mute
-        if alsa.togglechannel then
-            s = string.match(read_pipe(string.format("%s get %s", alsa.cmd, alsa.togglechannel)), "%[(%a+)%]")
-        end
-
-        if alsa.last_level ~= l or alsa.last_status ~= s then
-            volume_now = { level = l, status = s }
-            alsa.last_level  = l
-            alsa.last_status = s
-
-            widget = alsa.widget
-            settings()
-        end
+        helpers.async(alsa.cmd, function(mixer)
+            local l,s = string.match(mixer, "([%d]+)%%.*%[([%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
 
     timer_id = string.format("alsa-%s-%s", alsa.cmd, alsa.channel)
index cdbefd26590dca83a7acc318f886782cf3285a14..9fe5339da8f14d5caac645f397775fba66c96d06 100644 (file)
@@ -7,8 +7,7 @@
                                                   
 --]]
 
-local newtimer     = require("lain.helpers").newtimer
-local read_pipe    = require("lain.helpers").read_pipe
+local helpers      = require("lain.helpers")
 
 local awful        = require("awful")
 local beautiful    = require("beautiful")
@@ -35,9 +34,6 @@ local alsabar = {
         unmute     = "#A4CE8A"
     },
 
-    terminal = terminal or "xterm",
-    mixer    = string.format("%s -e alsamixer", terminal),
-
     notifications = {
         font      = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")),
         font_size = "11",
@@ -49,46 +45,6 @@ local alsabar = {
     _muted         = false
 }
 
-function alsabar.notify()
-    alsabar.update()
-
-    local preset = {
-        title   = "",
-        text    = "",
-        timeout = 5,
-        screen  = alsabar.notifications.screen,
-        font    = string.format("%s %s", alsabar.notifications.font,
-                  alsabar.notifications.font_size),
-        fg      = alsabar.notifications.color
-    }
-
-    if alsabar._muted
-    then
-        preset.title = string.format("%s - Muted", alsabar.channel)
-    else
-        preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
-    end
-
-    int = math.modf((alsabar._current_level / 100) * awful.screen.focused().mywibox.height)
-    preset.text = string.format("[%s%s]", string.rep("|", int),
-                  string.rep(" ", awful.screen.focused().mywibox.height - int))
-
-    if alsabar.followtag then
-        preset.screen = awful.screen.focused()
-    end
-
-    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
@@ -101,7 +57,6 @@ local function worker(args)
 
     alsabar.cmd           = args.cmd or "amixer"
     alsabar.channel       = args.channel or alsabar.channel
-    alsabar.togglechannel = args.togglechannel
     alsabar.step          = args.step or alsabar.step
     alsabar.colors        = args.colors or alsabar.colors
     alsabar.notifications = args.notifications or alsabar.notifications
@@ -122,66 +77,72 @@ local function worker(args)
 
     alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
 
-    function alsabar.update()
-        -- Get mixer control contents
-        local mixer = read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.channel))
-
-        -- Capture mixer control state:          [5%] ... ... [on]
-        local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
-
-        -- HDMIs can have a channel different from Master for toggling mute
-        if alsabar.togglechannel then
-            mute = string.match(read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.togglechannel)), "%[(%a+)%]")
-        end
-
-        if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted)
-        then
-            alsabar._current_level = tonumber(volu) or alsabar._current_level
-            alsabar.bar:set_value(alsabar._current_level / 100)
-            if (not mute and tonumber(volu) == 0) or mute == "off"
+    function alsabar.update(callback)
+        helpers.async(alsabar.cmd, function(mixer)
+            local volu,mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
+            if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted)
             then
-                alsabar._muted = true
-                alsabar.tooltip:set_text ("[Muted]")
-                alsabar.bar.color = alsabar.colors.mute
+                alsabar._current_level = tonumber(volu) or alsabar._current_level
+                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.color = alsabar.colors.mute
+                else
+                    alsabar._muted = false
+                    alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, volu))
+                    alsabar.bar.color = alsabar.colors.unmute
+                end
+
+                volume_now = {}
+                volume_now.level = tonumber(volu)
+                volume_now.status = mute
+
+                settings()
+
+                if callback then callback() end
+            end
+        end)
+    end
+
+    function alsabar.notify()
+        alsabar.update(function()
+            local preset = {
+                title   = "",
+                text    = "",
+                timeout = 5,
+                screen  = alsabar.notifications.screen,
+                font    = string.format("%s %s", alsabar.notifications.font,
+                          alsabar.notifications.font_size),
+                fg      = alsabar.notifications.color
+            }
+
+            if alsabar._muted then
+                preset.title = string.format("%s - Muted", alsabar.channel)
             else
-                alsabar._muted = false
-                alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, volu))
-                alsabar.bar.color = alsabar.colors.unmute
+                preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
             end
 
-            volume_now = {}
-            volume_now.level = tonumber(volu)
-            volume_now.status = mute
+            int = math.modf((alsabar._current_level / 100) * awful.screen.focused().mywibox.height)
+            preset.text = string.format("[%s%s]", string.rep("|", int),
+                          string.rep(" ", awful.screen.focused().mywibox.height - int))
 
-            settings()
-        end
-    end
+            if alsabar.followtag then preset.screen = awful.screen.focused() end
 
-    alsabar.bar:buttons(awful.util.table.join (
-          awful.button({}, 1, function()
-            awful.util.spawn(alsabar.mixer)
-          end),
-          awful.button({}, 2, function()
-                                               awful.util.spawn(string.format("%s set %s 100%%", alsabar.cmd, alsabar.channel))
-            alsabar.update()
-          end),
-          awful.button({}, 3, function()
-            awful.util.spawn(string.format("%s set %s toggle", alsabar.cmd, alsabar.togglechannel or 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))
-            alsabar.update()
-          end)
-    ))
+            if alsabar._notify then
+                alsabar._notify = naughty.notify ({
+                    replaces_id = alsabar._notify.id,
+                    preset      = preset,
+                })
+            else
+                alsabar._notify = naughty.notify ({ preset = preset })
+            end
+        end)
+    end
 
     timer_id = string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel)
-
-    newtimer(timer_id, timeout, alsabar.update)
+    helpers.newtimer(timer_id, timeout, alsabar.update)
 
     return alsabar
 end
index ee40a8d108fa6c5f42d21bf6bccd7f596e15edda..de82b1e8ca6f7aaadab7fd4e40941d1dd79b2e77 100644 (file)
@@ -44,8 +44,7 @@ local function worker(args)
     function gpmdp.update()
         local filelines = helpers.lines_from(file_location)
 
-        if not next(filelines)
-        then
+        if not next(filelines) then
             local gpm_now = { running = false, playing = false }
         else
             dict, pos, err = json.decode(table.concat(filelines), 1, nil)
@@ -67,16 +66,12 @@ local function worker(args)
         widget = gpmdp.widget
         settings()
 
-        if gpm_now.playing
-        then
-            if notify == "on" and gpm_now.title ~= helpers.get_map("gpmdp_current")
-            then
+        if gpm_now.playing then
+            if notify == "on" and gpm_now.title ~= helpers.get_map("gpmdp_current") then
                 helpers.set_map("gpmdp_current", gpm_now.title)
                 os.execute(string.format("curl %d -o /tmp/gpmcover.png", gpm_now.cover_url))
 
-                if followtag then
-                    gpmdp_notification_preset.screen = focused()
-                end
+                if followtag then gpmdp_notification_preset.screen = focused() end
 
                 gpmdp.id = naughty.notify({
                     preset = gpmdp_notification_preset,
index 23dc6e3cb975b15e34c7f93883ab045478559de3..f57d2da2040f7408d1985b67c0f2cdede306ba41 100644 (file)
@@ -38,8 +38,10 @@ local function worker(args)
 
    local function run_settings(layout, variant)
       widget = kbdlayout.widget
-      kbdlayout_now = { layout=string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
-                       variant=variant }
+      kbdlayout_now = { 
+          layout=string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
+          variant=variant
+      }
       settings()
    end
 
index d4571e16711049dade9f72f8eebb0c1e7b6bb45a..f19b0d39d25e6057550c1a85b2e96dd9a0d9cab8 100644 (file)
@@ -6,52 +6,40 @@
                                                                   
 --]]
 
-local helpers  = require("lain.helpers")
-local async    = require("lain.asyncshell")
+local helpers      = require("lain.helpers")
 
-local focused  = require("awful.screen").focused
-local escape_f = require("awful.util").escape
-local naughty  = require("naughty")
-local wibox    = require("wibox")
+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 io       = { popen   = io.popen }
-local os       = { execute = os.execute,
-                   getenv  = os.getenv }
-local string   = { format  = string.format,
-                   gmatch  = string.gmatch }
+local os           = { getenv = os.getenv }
+local string       = { format = string.format,
+                       gmatch = string.gmatch }
 
 local setmetatable = setmetatable
 
 -- MOC audio player
 -- lain.widgets.contrib.moc
-local moc = {}
+local moc = helpers.make_widget_textbox()
 
 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 ""
-    local followtag    = args.followtag or false
-    local settings    = args.settings or function() end
+    local args          = args or {}
+    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
 
-    local mpdcover = helpers.scripts_dir .. "mpdcover"
-
-    moc.widget = wibox.widget.textbox('')
-
-    moc_notification_preset = {
-        title   = "Now playing",
-        timeout = 6
-    }
+    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)
+        helpers.async("mocp -i", function(f)
             moc_now = {
                 state   = "N/A",
                 file    = "N/A",
@@ -64,13 +52,13 @@ local function worker(args)
 
             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)
+                    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)
+                    elseif k == "TotalTime"   then moc_now.total   = escape_f(v)
                     end
                 end
             end
@@ -83,18 +71,22 @@ local function worker(args)
             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))
 
-                    if followtag then
-                        moc_notification_preset.screen = focused()
-                    end
+                    if followtag then moc_notification_preset.screen = focused() end
 
-                    moc.id = naughty.notify({
-                        preset = moc_notification_preset,
-                        icon = "/tmp/mpdcover.png",
+                    local common =  {
+                        preset      = moc_notification_preset,
+                        icon        = default_art,
+                        icon_size   = cover_size,
                         replaces_id = moc.id,
-                    }).id
+                    }
+
+                    local path   = string.format("%s/%s", music_dir, string.match(moc_now.file, ".*/"))
+                    local cover  = string.format("%s -c \"find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'\"", shell, path, cover_pattern)
+                    helpers.async(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)
index 1b8f119811059cfaa6a6bfde6ce936a84b3291c8..6c8c9cce01518496a654b29ed2afcca05b979458 100644 (file)
@@ -12,7 +12,6 @@ local awful        = require("awful")
 local beautiful    = require("beautiful")
 local naughty      = require("naughty")
 
-local mouse        = mouse
 local io           = io
 local string       = { len = string.len }
 local tonumber     = tonumber
index 06b42452da9f20dfe2f10a6fa66a74f108d15656..3caf31a6f647518f276183ebdd740f34fb676fe8 100644 (file)
@@ -7,7 +7,6 @@
 --]]
 
 local helpers      = require("lain.helpers")
-local async        = require("lain.asyncshell")
 
 local naughty      = require("naughty")
 local wibox        = require("wibox")
@@ -59,24 +58,19 @@ local function worker(args)
         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)
+        helpers.async(curl, function(f)
             _, mailcount = string.gsub(f, "%d+", "")
-            _ = nil
 
             widget = imap.widget
             settings()
 
-            if mailcount >= 1 and mailcount > helpers.get_map(mail)
-            then
+            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,
-                    text = nt
-                })
+                naughty.notify({ preset = mail_notification_preset, text = nt })
             end
 
             helpers.set_map(mail, mailcount)
index ebdda98a456295f2f36d70fb2ed5695fe3697544..defa710ac602b5013a15d0d052f20e50c7e11ad1 100644 (file)
@@ -7,9 +7,9 @@
                                                   
 --]]
 
-local async        = require("lain.asyncshell")
 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")
@@ -29,7 +29,7 @@ local mpd = helpers.make_widget_textbox()
 local function worker(args)
     local args          = args or {}
     local timeout       = args.timeout or 2
-    local password      = args.password or ""
+    local password      = (args.password and #args.password > 0 and string.format("password %s\\n", 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"
@@ -38,21 +38,18 @@ local function worker(args)
     local default_art   = args.default_art or ""
     local notify        = args.notify or "on"
     local followtag     = args.followtag or false
-    local echo_cmd      = args.echo_cmd or "echo"
     local settings      = args.settings or function() end
 
     local mpdh = string.format("telnet://%s:%s", host, port)
-    local echo = string.format("%s 'password %s\nstatus\ncurrentsong\nclose'", echo_cmd, password)
+    local echo = string.format("printf \"%sstatus\\ncurrentsong\\nclose\\n\"", password)
+    local cmd  = string.format("%s -c '%s | curl --connect-timeout 1 -fsm 3 %s'", shell, echo, mpdh)
 
-    mpd_notification_preset = {
-        title   = "Now playing",
-        timeout = 6
-    }
+    mpd_notification_preset = { title = "Now playing", timeout = 6 }
 
     helpers.set_map("current mpd track", nil)
 
     function mpd.update()
-        async.request(string.format("%s | curl --connect-timeout 1 -fsm 3 %s", echo, mpdh), function (f)
+        helpers.async(cmd, function(f)
             mpd_now = {
                 random_mode  = false,
                 single_mode  = false,
@@ -105,22 +102,26 @@ local function worker(args)
                 if notify == "on" and mpd_now.title ~= helpers.get_map("current mpd track") then
                     helpers.set_map("current mpd track", mpd_now.title)
 
-                    local current icon = default_art
-
-                    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, cover_pattern)
-                        current_icon = helpers.read_pipe(cover):gsub("\n", "")
-                    end
-
                     if followtag then mpd_notification_preset.screen = focused() end
 
-                    mpd.id = naughty.notify({
+                    local common =  {
                         preset      = mpd_notification_preset,
-                        icon        = current_icon,
+                        icon        = default_art,
                         icon_size   = cover_size,
                         replaces_id = mpd.id,
-                    }).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("%s -c \"find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'\"", shell, path, cover_pattern)
+                        helpers.async(cover, function(current_icon)
+                            common.icon = current_icon:gsub("\n", "")
+                            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)
index 015f43a56fdc665bb1bb33ac91b89ce76b880419..17b3d3463737ef338b79ed8ceeece3b873a4cb73 100644 (file)
@@ -6,12 +6,10 @@
                                                   
 --]]
 
+local async        = require("lain.helpers").async
 local newtimer     = require("lain.helpers").newtimer
-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
+local json         = require("lain.util").dkjson
 
 local focused      = require("awful.screen").focused
 local naughty      = require("naughty")
@@ -54,14 +52,14 @@ local function worker(args)
     local notification_preset   = args.notification_preset or {}
     local notification_text_fun = args.notification_text_fun or
                                   function (wn)
-                                      local day = string.gsub(read_pipe(string.format(date_cmd, wn["dt"])), "\n", "")
+                                      local day = os.date("%a %d", wn["dt"])
                                       local tmin = math.floor(wn["temp"]["min"])
                                       local tmax = math.floor(wn["temp"]["max"])
                                       local desc = wn["weather"][1]["description"]
                                       return string.format("<b>%s</b>: %s, %d - %d ", day, desc, tmin, tmax)
                                   end
     local weather_na_markup     = args.weather_na_markup or " N/A "
-    local followtag           = args.followtag or false
+    local followtag             = args.followtag or false
     local settings              = args.settings or function() end
 
     weather.widget    = wibox.widget.textbox(weather_na_markup)
@@ -105,7 +103,7 @@ local function worker(args)
 
     function weather.forecast_update()
         local cmd = string.format(forecast_call, city_id, units, lang, cnt, APPID)
-        async.request(cmd, function(f)
+        async(cmd, function(f)
             local pos, err
             weather_now, pos, err = json.decode(f, 1, nil)
 
@@ -125,7 +123,7 @@ local function worker(args)
 
     function weather.update()
         local cmd = string.format(current_call, city_id, units, lang, APPID)
-        async.request(cmd, function(f)
+        async(cmd, function(f)
             local pos, err, icon
             weather_now, pos, err = json.decode(f, 1, nil)
 
@@ -135,12 +133,9 @@ local function worker(args)
                 local sunrise = tonumber(weather_now["sys"]["sunrise"])
                 local sunset  = tonumber(weather_now["sys"]["sunset"])
                 local icon    = weather_now["weather"][1]["icon"]
-                local utc_m   = string.gsub(read_pipe(string.format("date -u -d 'today 00:00:00' +'%%s'")), "\n", "")
-                local loc_m   = string.gsub(read_pipe(string.format("date -d 'today 00:00:00' +'%%s'")), "\n", "")
-
-                loc_m  = tonumber(loc_m)
-                utc_m  = tonumber(utc_m)
-                offset = utc_offset()
+                local loc_m   = os.time { year = os.date("%Y"), month = os.date("%m"), day = os.date("%d"), hour = 0 }
+                local offset  = utc_offset()
+                local utc_m   = loc_m + offset
 
                 -- if we are 1 day after the GMT, return 1 day back, and viceversa
                 if offset > 0 and loc_m >= utc_m then
diff --git a/wiki b/wiki
index cf17caf2b889d58d4f00a47cd168f53ae85b6d9f..fd369119050a6674c7bb4ef3b2b1d6c6dbdecb83 160000 (submodule)
--- a/wiki
+++ b/wiki
@@ -1 +1 @@
-Subproject commit cf17caf2b889d58d4f00a47cd168f53ae85b6d9f
+Subproject commit fd369119050a6674c7bb4ef3b2b1d6c6dbdecb83