]> 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:

merging with upstream
authoraajjbb <jefersonlsiq@gmail.com>
Tue, 18 Aug 2015 13:52:05 +0000 (10:52 -0300)
committeraajjbb <jefersonlsiq@gmail.com>
Tue, 18 Aug 2015 13:52:05 +0000 (10:52 -0300)
48 files changed:
README.rst
README.rst.orig [new file with mode: 0644]
asyncshell.lua
asyncshell.lua.orig [new file with mode: 0644]
asyncshell_BACKUP_1080.lua [new file with mode: 0644]
asyncshell_BACKUP_32072.lua [new file with mode: 0644]
asyncshell_BASE_1080.lua [new file with mode: 0644]
asyncshell_BASE_32072.lua [new file with mode: 0644]
asyncshell_LOCAL_1080.lua [new file with mode: 0644]
asyncshell_LOCAL_32072.lua [new file with mode: 0644]
asyncshell_REMOTE_1080.lua [new file with mode: 0644]
asyncshell_REMOTE_32072.lua [new file with mode: 0644]
helpers.lua
helpers.lua.orig [new file with mode: 0644]
widgets/abase.lua
widgets/abase.lua.orig [new file with mode: 0644]
widgets/alsa.lua
widgets/alsa.lua.orig [new file with mode: 0644]
widgets/alsabar.lua
widgets/alsabar.lua.orig [new file with mode: 0644]
widgets/base.lua
widgets/base.lua.orig [new file with mode: 0644]
widgets/calendar.lua
widgets/calendar.lua.orig [new file with mode: 0644]
widgets/contrib/init.lua
widgets/contrib/init.lua.orig [new file with mode: 0644]
widgets/contrib/kbdlayout.lua [new file with mode: 0644]
widgets/contrib/moc.lua
widgets/contrib/moc.lua.orig [new file with mode: 0644]
widgets/contrib/task.lua
widgets/contrib/task.lua.orig [new file with mode: 0644]
widgets/fs.lua
widgets/fs.lua.orig [new file with mode: 0644]
widgets/imap.lua
widgets/imap.lua.orig [new file with mode: 0644]
widgets/maildir.lua
widgets/maildir.lua.orig [new file with mode: 0644]
widgets/mpd.lua
widgets/mpd.lua.orig [new file with mode: 0644]
widgets/net.lua
widgets/net.lua.orig [new file with mode: 0644]
widgets/sysload.lua
widgets/sysload.lua.orig [new file with mode: 0644]
widgets/temp.lua
widgets/temp.lua.orig [new file with mode: 0644]
widgets/weather.lua
widgets/weather.lua.orig [new file with mode: 0644]
wiki

index a06b64ee89a0ce473377ddbec5aac014f046547a..be3e37792665f99b39496d99d9b463bee9398bc3 100644 (file)
@@ -7,7 +7,7 @@ Layouts, widgets and utilities for Awesome WM 3.5+
 
 :Author: Luke Bonham <dada [at] archlinux [dot] info>
 :Version: git
-:License: GNU-GPLv2_
+:License: GNU-GPL2_
 :Source: https://github.com/copycat-killer/lain
 
 Description
@@ -41,7 +41,7 @@ Screenshots
 .. image:: http://i.imgur.com/9Iv3OR3.png
 .. image:: http://i.imgur.com/STCPcaJ.png
 
-.. _GNU-GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+.. _GNU-GPL2: http://www.gnu.org/licenses/gpl-2.0.html
 .. _awesome-vain: https://github.com/vain/awesome-vain
 .. _Awesome: http://awesome.naquadah.org/
 .. _wiki: https://github.com/copycat-killer/lain/wiki
diff --git a/README.rst.orig b/README.rst.orig
new file mode 100644 (file)
index 0000000..7c6d786
--- /dev/null
@@ -0,0 +1,55 @@
+Lain
+====
+
+--------------------------------------------------
+Layouts, widgets and utilities for Awesome WM 3.5+
+--------------------------------------------------
+
+:Author: Luke Bonham <dada [at] archlinux [dot] info>
+:Version: git
+<<<<<<< HEAD
+:License: GNU-GPLv2_
+=======
+:License: GNU-GPL2_
+>>>>>>> upstream/master
+:Source: https://github.com/copycat-killer/lain
+
+Description
+-----------
+
+Successor of awesome-vain_, this module provides new layouts, a set of widgets and utility functions, in order to improve Awesome_ usability and configurability.
+
+Read the wiki_ for all the info.
+
+Contributions
+-------------
+
+Any contribution is welcome! Feel free to make a pull request.
+
+Just make sure that:
+
+- Your code fits with the general style of the module. In particular, you should use the same indentation pattern that the code uses, and also avoid adding space at the ends of lines.
+
+- Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions or using ``lain.helpers``. If something is unclear, and you can't write it in such a way that it will be clear, explain it with a comment.
+
+- You test your changes before submitting to make sure that not only your code works, but did not break other parts of the module too!
+
+- You eventually update ``wiki`` submodule with a thorough section.
+
+Contributed widgets have to be put in ``lain/widgets/contrib``.
+
+Screenshots
+-----------
+
+.. image:: http://i.imgur.com/8D9A7lW.png
+.. image:: http://i.imgur.com/9Iv3OR3.png
+.. image:: http://i.imgur.com/STCPcaJ.png
+
+<<<<<<< HEAD
+.. _GNU-GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+=======
+.. _GNU-GPL2: http://www.gnu.org/licenses/gpl-2.0.html
+>>>>>>> upstream/master
+.. _awesome-vain: https://github.com/vain/awesome-vain
+.. _Awesome: http://awesome.naquadah.org/
+.. _wiki: https://github.com/copycat-killer/lain/wiki
index 0aafa17e7df9ffb2194c4ee76baa25575af65774..827cf4be4b0f500174ba2279429039d5f39516aa 100644 (file)
@@ -2,78 +2,71 @@
 --[[
                                                   
      Licensed under GNU General Public License v2 
+      * (c) 2015, worron                          
       * (c) 2013, Alexander Yakushev              
                                                   
 --]]
 
 -- Asynchronous io.popen for Awesome WM.
--- How to use...
--- ...asynchronously:
--- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end)
--- ...synchronously:
--- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error")
+-- How to use:
+-- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end)
 
-local spawn = require('awful.util').spawn
+-- Grab environment
+local awful = require('awful')
 
-asyncshell               = {}
-asyncshell.request_table = {}
-asyncshell.id_counter    = 0
-asyncshell.folder        = "/tmp/asyncshell"
-asyncshell.file_template = asyncshell.folder .. '/req'
+-- Initialize tables for module
+asyncshell = { request_table = {}, id_counter = 0 }
 
--- Create a directory for asynchell response files
-os.execute("mkdir -p " .. asyncshell.folder)
-
--- Returns next tag - unique identifier of the request
+-- Request counter
 local function next_id()
-   asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000
-   return asyncshell.id_counter
+    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.
+-- 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
--- @return Request ID
-function asyncshell.request(command, callback)
-   local id = next_id()
-   local tmpfname = asyncshell.file_template .. id
-   asyncshell.request_table[id] = { callback = callback }
-   local req =
-      string.format("sh -c '%s > %s; " ..
-                    'echo "asyncshell.deliver(%s)" | ' ..
-                    "awesome-client' 2> /dev/null",
-                    string.gsub(command, "'", "'\\''"), tmpfname, id)
-   spawn(req, false)
-   return id
-end
+-- @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 }
 
--- Calls the remembered callback function on the output of the shell
--- command.
--- @param id Request ID
--- @param output The output file of the shell command to be delievered
-function asyncshell.deliver(id)
-   if asyncshell.request_table[id] and
-      asyncshell.request_table[id].callback then
-      local output = io.open(asyncshell.file_template .. id, 'r')
-      asyncshell.request_table[id].callback(output)
-   end
+    local formatted_command = string.gsub(command, '"','\"')
+
+    local req = string.format(
+        "echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &",
+        id, formatted_command
+    )
+
+    awful.util.spawn_with_shell(req)
+
+    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
 
--- Sends a synchronous request for an output of the command. Waits for
--- the output, but if the given timeout expires returns nil.
--- @param command Command to be executed and taken output from
--- @param timeout Maximum amount of time to wait for the result
--- @return File handler on success, nil otherwise
-function asyncshell.demand(command, timeout)
-   local id = next_id()
-   local tmpfname = asyncshell.file_template .. id
-   local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " ..
-                                    "(sleep %s; echo asynchell_timeout)",
-                                    command, tmpfname, timeout))
-   local result = f:read("*line")
-   if result == "asyncshell_done" then
-      return io.open(tmpfname)
-   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
diff --git a/asyncshell.lua.orig b/asyncshell.lua.orig
new file mode 100644 (file)
index 0000000..5c6e7e8
--- /dev/null
@@ -0,0 +1,145 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+<<<<<<< HEAD
+=======
+      * (c) 2015, worron                          
+>>>>>>> upstream/master
+      * (c) 2013, Alexander Yakushev              
+                                                  
+--]]
+
+-- Asynchronous io.popen for Awesome WM.
+<<<<<<< HEAD
+-- How to use...
+-- ...asynchronously:
+-- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end)
+-- ...synchronously:
+-- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error")
+
+local spawn = require('awful.util').spawn
+
+asyncshell               = {}
+asyncshell.request_table = {}
+asyncshell.id_counter    = 0
+asyncshell.folder        = "/tmp/asyncshell"
+asyncshell.file_template = asyncshell.folder .. '/req'
+
+-- Create a directory for asynchell response files
+os.execute("mkdir -p " .. asyncshell.folder)
+
+-- Returns next tag - unique identifier of the request
+local function next_id()
+   asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000
+   return asyncshell.id_counter
+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
+-- @return Request ID
+function asyncshell.request(command, callback)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   asyncshell.request_table[id] = { callback = callback }
+   local req =
+      string.format("sh -c '%s > %s; " ..
+                    'echo "asyncshell.deliver(%s)" | ' ..
+                    "awesome-client' 2> /dev/null",
+                    string.gsub(command, "'", "'\\''"), tmpfname, id)
+   spawn(req, false)
+   return id
+end
+
+-- Calls the remembered callback function on the output of the shell
+-- command.
+-- @param id Request ID
+-- @param output The output file of the shell command to be delievered
+function asyncshell.deliver(id)
+   if asyncshell.request_table[id] and
+      asyncshell.request_table[id].callback then
+      local output = io.open(asyncshell.file_template .. id, 'r')
+      asyncshell.request_table[id].callback(output)
+   end
+end
+
+-- Sends a synchronous request for an output of the command. Waits for
+-- the output, but if the given timeout expires returns nil.
+-- @param command Command to be executed and taken output from
+-- @param timeout Maximum amount of time to wait for the result
+-- @return File handler on success, nil otherwise
+function asyncshell.demand(command, timeout)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " ..
+                                    "(sleep %s; echo asynchell_timeout)",
+                                    command, tmpfname, timeout))
+   local result = f:read("*line")
+   if result == "asyncshell_done" then
+      return io.open(tmpfname)
+   end
+=======
+-- How to use:
+-- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end)
+
+-- Grab environment
+local awful = require('awful')
+
+-- 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
+    )
+
+    awful.util.spawn_with_shell(req)
+
+    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
+>>>>>>> upstream/master
+end
+
+return asyncshell
diff --git a/asyncshell_BACKUP_1080.lua b/asyncshell_BACKUP_1080.lua
new file mode 100644 (file)
index 0000000..5c6e7e8
--- /dev/null
@@ -0,0 +1,145 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+<<<<<<< HEAD
+=======
+      * (c) 2015, worron                          
+>>>>>>> upstream/master
+      * (c) 2013, Alexander Yakushev              
+                                                  
+--]]
+
+-- Asynchronous io.popen for Awesome WM.
+<<<<<<< HEAD
+-- How to use...
+-- ...asynchronously:
+-- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end)
+-- ...synchronously:
+-- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error")
+
+local spawn = require('awful.util').spawn
+
+asyncshell               = {}
+asyncshell.request_table = {}
+asyncshell.id_counter    = 0
+asyncshell.folder        = "/tmp/asyncshell"
+asyncshell.file_template = asyncshell.folder .. '/req'
+
+-- Create a directory for asynchell response files
+os.execute("mkdir -p " .. asyncshell.folder)
+
+-- Returns next tag - unique identifier of the request
+local function next_id()
+   asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000
+   return asyncshell.id_counter
+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
+-- @return Request ID
+function asyncshell.request(command, callback)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   asyncshell.request_table[id] = { callback = callback }
+   local req =
+      string.format("sh -c '%s > %s; " ..
+                    'echo "asyncshell.deliver(%s)" | ' ..
+                    "awesome-client' 2> /dev/null",
+                    string.gsub(command, "'", "'\\''"), tmpfname, id)
+   spawn(req, false)
+   return id
+end
+
+-- Calls the remembered callback function on the output of the shell
+-- command.
+-- @param id Request ID
+-- @param output The output file of the shell command to be delievered
+function asyncshell.deliver(id)
+   if asyncshell.request_table[id] and
+      asyncshell.request_table[id].callback then
+      local output = io.open(asyncshell.file_template .. id, 'r')
+      asyncshell.request_table[id].callback(output)
+   end
+end
+
+-- Sends a synchronous request for an output of the command. Waits for
+-- the output, but if the given timeout expires returns nil.
+-- @param command Command to be executed and taken output from
+-- @param timeout Maximum amount of time to wait for the result
+-- @return File handler on success, nil otherwise
+function asyncshell.demand(command, timeout)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " ..
+                                    "(sleep %s; echo asynchell_timeout)",
+                                    command, tmpfname, timeout))
+   local result = f:read("*line")
+   if result == "asyncshell_done" then
+      return io.open(tmpfname)
+   end
+=======
+-- How to use:
+-- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end)
+
+-- Grab environment
+local awful = require('awful')
+
+-- 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
+    )
+
+    awful.util.spawn_with_shell(req)
+
+    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
+>>>>>>> upstream/master
+end
+
+return asyncshell
diff --git a/asyncshell_BACKUP_32072.lua b/asyncshell_BACKUP_32072.lua
new file mode 100644 (file)
index 0000000..5c6e7e8
--- /dev/null
@@ -0,0 +1,145 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+<<<<<<< HEAD
+=======
+      * (c) 2015, worron                          
+>>>>>>> upstream/master
+      * (c) 2013, Alexander Yakushev              
+                                                  
+--]]
+
+-- Asynchronous io.popen for Awesome WM.
+<<<<<<< HEAD
+-- How to use...
+-- ...asynchronously:
+-- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end)
+-- ...synchronously:
+-- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error")
+
+local spawn = require('awful.util').spawn
+
+asyncshell               = {}
+asyncshell.request_table = {}
+asyncshell.id_counter    = 0
+asyncshell.folder        = "/tmp/asyncshell"
+asyncshell.file_template = asyncshell.folder .. '/req'
+
+-- Create a directory for asynchell response files
+os.execute("mkdir -p " .. asyncshell.folder)
+
+-- Returns next tag - unique identifier of the request
+local function next_id()
+   asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000
+   return asyncshell.id_counter
+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
+-- @return Request ID
+function asyncshell.request(command, callback)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   asyncshell.request_table[id] = { callback = callback }
+   local req =
+      string.format("sh -c '%s > %s; " ..
+                    'echo "asyncshell.deliver(%s)" | ' ..
+                    "awesome-client' 2> /dev/null",
+                    string.gsub(command, "'", "'\\''"), tmpfname, id)
+   spawn(req, false)
+   return id
+end
+
+-- Calls the remembered callback function on the output of the shell
+-- command.
+-- @param id Request ID
+-- @param output The output file of the shell command to be delievered
+function asyncshell.deliver(id)
+   if asyncshell.request_table[id] and
+      asyncshell.request_table[id].callback then
+      local output = io.open(asyncshell.file_template .. id, 'r')
+      asyncshell.request_table[id].callback(output)
+   end
+end
+
+-- Sends a synchronous request for an output of the command. Waits for
+-- the output, but if the given timeout expires returns nil.
+-- @param command Command to be executed and taken output from
+-- @param timeout Maximum amount of time to wait for the result
+-- @return File handler on success, nil otherwise
+function asyncshell.demand(command, timeout)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " ..
+                                    "(sleep %s; echo asynchell_timeout)",
+                                    command, tmpfname, timeout))
+   local result = f:read("*line")
+   if result == "asyncshell_done" then
+      return io.open(tmpfname)
+   end
+=======
+-- How to use:
+-- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end)
+
+-- Grab environment
+local awful = require('awful')
+
+-- 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
+    )
+
+    awful.util.spawn_with_shell(req)
+
+    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
+>>>>>>> upstream/master
+end
+
+return asyncshell
diff --git a/asyncshell_BASE_1080.lua b/asyncshell_BASE_1080.lua
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/asyncshell_BASE_32072.lua b/asyncshell_BASE_32072.lua
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/asyncshell_LOCAL_1080.lua b/asyncshell_LOCAL_1080.lua
new file mode 100644 (file)
index 0000000..0aafa17
--- /dev/null
@@ -0,0 +1,79 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Alexander Yakushev              
+                                                  
+--]]
+
+-- Asynchronous io.popen for Awesome WM.
+-- How to use...
+-- ...asynchronously:
+-- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end)
+-- ...synchronously:
+-- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error")
+
+local spawn = require('awful.util').spawn
+
+asyncshell               = {}
+asyncshell.request_table = {}
+asyncshell.id_counter    = 0
+asyncshell.folder        = "/tmp/asyncshell"
+asyncshell.file_template = asyncshell.folder .. '/req'
+
+-- Create a directory for asynchell response files
+os.execute("mkdir -p " .. asyncshell.folder)
+
+-- Returns next tag - unique identifier of the request
+local function next_id()
+   asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000
+   return asyncshell.id_counter
+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
+-- @return Request ID
+function asyncshell.request(command, callback)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   asyncshell.request_table[id] = { callback = callback }
+   local req =
+      string.format("sh -c '%s > %s; " ..
+                    'echo "asyncshell.deliver(%s)" | ' ..
+                    "awesome-client' 2> /dev/null",
+                    string.gsub(command, "'", "'\\''"), tmpfname, id)
+   spawn(req, false)
+   return id
+end
+
+-- Calls the remembered callback function on the output of the shell
+-- command.
+-- @param id Request ID
+-- @param output The output file of the shell command to be delievered
+function asyncshell.deliver(id)
+   if asyncshell.request_table[id] and
+      asyncshell.request_table[id].callback then
+      local output = io.open(asyncshell.file_template .. id, 'r')
+      asyncshell.request_table[id].callback(output)
+   end
+end
+
+-- Sends a synchronous request for an output of the command. Waits for
+-- the output, but if the given timeout expires returns nil.
+-- @param command Command to be executed and taken output from
+-- @param timeout Maximum amount of time to wait for the result
+-- @return File handler on success, nil otherwise
+function asyncshell.demand(command, timeout)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " ..
+                                    "(sleep %s; echo asynchell_timeout)",
+                                    command, tmpfname, timeout))
+   local result = f:read("*line")
+   if result == "asyncshell_done" then
+      return io.open(tmpfname)
+   end
+end
+
+return asyncshell
diff --git a/asyncshell_LOCAL_32072.lua b/asyncshell_LOCAL_32072.lua
new file mode 100644 (file)
index 0000000..0aafa17
--- /dev/null
@@ -0,0 +1,79 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Alexander Yakushev              
+                                                  
+--]]
+
+-- Asynchronous io.popen for Awesome WM.
+-- How to use...
+-- ...asynchronously:
+-- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end)
+-- ...synchronously:
+-- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error")
+
+local spawn = require('awful.util').spawn
+
+asyncshell               = {}
+asyncshell.request_table = {}
+asyncshell.id_counter    = 0
+asyncshell.folder        = "/tmp/asyncshell"
+asyncshell.file_template = asyncshell.folder .. '/req'
+
+-- Create a directory for asynchell response files
+os.execute("mkdir -p " .. asyncshell.folder)
+
+-- Returns next tag - unique identifier of the request
+local function next_id()
+   asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000
+   return asyncshell.id_counter
+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
+-- @return Request ID
+function asyncshell.request(command, callback)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   asyncshell.request_table[id] = { callback = callback }
+   local req =
+      string.format("sh -c '%s > %s; " ..
+                    'echo "asyncshell.deliver(%s)" | ' ..
+                    "awesome-client' 2> /dev/null",
+                    string.gsub(command, "'", "'\\''"), tmpfname, id)
+   spawn(req, false)
+   return id
+end
+
+-- Calls the remembered callback function on the output of the shell
+-- command.
+-- @param id Request ID
+-- @param output The output file of the shell command to be delievered
+function asyncshell.deliver(id)
+   if asyncshell.request_table[id] and
+      asyncshell.request_table[id].callback then
+      local output = io.open(asyncshell.file_template .. id, 'r')
+      asyncshell.request_table[id].callback(output)
+   end
+end
+
+-- Sends a synchronous request for an output of the command. Waits for
+-- the output, but if the given timeout expires returns nil.
+-- @param command Command to be executed and taken output from
+-- @param timeout Maximum amount of time to wait for the result
+-- @return File handler on success, nil otherwise
+function asyncshell.demand(command, timeout)
+   local id = next_id()
+   local tmpfname = asyncshell.file_template .. id
+   local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " ..
+                                    "(sleep %s; echo asynchell_timeout)",
+                                    command, tmpfname, timeout))
+   local result = f:read("*line")
+   if result == "asyncshell_done" then
+      return io.open(tmpfname)
+   end
+end
+
+return asyncshell
diff --git a/asyncshell_REMOTE_1080.lua b/asyncshell_REMOTE_1080.lua
new file mode 100644 (file)
index 0000000..827cf4b
--- /dev/null
@@ -0,0 +1,72 @@
+
+--[[
+                                                  
+     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')
+
+-- 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
+    )
+
+    awful.util.spawn_with_shell(req)
+
+    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
diff --git a/asyncshell_REMOTE_32072.lua b/asyncshell_REMOTE_32072.lua
new file mode 100644 (file)
index 0000000..827cf4b
--- /dev/null
@@ -0,0 +1,72 @@
+
+--[[
+                                                  
+     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')
+
+-- 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
+    )
+
+    awful.util.spawn_with_shell(req)
+
+    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 dbee617121e5fb661cb4f01cf264cc84ea0fa6c7..4e90e169c15a570bb31aa4c6fa3f1ac9e70c5336 100644 (file)
@@ -10,7 +10,8 @@ local debug  = require("debug")
 
 local capi   = { timer = timer }
 local io     = { open  = io.open,
-                 lines = io.lines }
+                 lines = io.lines,
+                 popen = io.popen }
 local rawget = rawget
 
 -- Lain helper functions for internal use
@@ -86,6 +87,18 @@ end
 
 -- }}}
 
+-- {{{ 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
+
+-- }}}
+
 -- {{{ A map utility
 
 helpers.map_table = {}
diff --git a/helpers.lua.orig b/helpers.lua.orig
new file mode 100644 (file)
index 0000000..f88c042
--- /dev/null
@@ -0,0 +1,123 @@
+
+--[[
+                                                  
+     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
index 8ffdf0ef052fb48b4608e1ea8d47d4e5f23c3509..98f7818d844fe2b2c7c004b2ed39a9abacd91eb9 100644 (file)
@@ -27,8 +27,7 @@ local function worker(args)
 
     function abase.update()
         async.request(cmd, function(f)
-            output = f:read("*a")
-            f:close()
+            output = f
             widget = abase.widget
             settings()
         end)
diff --git a/widgets/abase.lua.orig b/widgets/abase.lua.orig
new file mode 100644 (file)
index 0000000..98f7818
--- /dev/null
@@ -0,0 +1,41 @@
+
+--[[
+                                                  
+     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 })
index 979d9fd106470025942e650e99ac4e172d714fed..85d53114e132a683fe2af8af9f86908af61b8f39 100644 (file)
@@ -8,10 +8,10 @@
 --]]
 
 local newtimer        = require("lain.helpers").newtimer
+local read_pipe       = require("lain.helpers").read_pipe
 
 local wibox           = require("wibox")
 
-local io              = { popen  = io.popen }
 local string          = { match  = string.match,
                           format = string.format }
 
@@ -32,9 +32,7 @@ local function worker(args)
     alsa.widget = wibox.widget.textbox('')
 
     function alsa.update()
-        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))
 
         volume_now = {}
 
diff --git a/widgets/alsa.lua.orig b/widgets/alsa.lua.orig
new file mode 100644 (file)
index 0000000..0ed11c7
--- /dev/null
@@ -0,0 +1,81 @@
+
+--[[
+                                                  
+     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 })
index c957dbb997086fb40833254fd84ac091d4e725b3..c7498d2e6be2bf31fdac43ba8288e25e8d9eadfe 100644 (file)
@@ -8,13 +8,14 @@
 --]]
 
 local newtimer     = require("lain.helpers").newtimer
+local read_pipe    = require("lain.helpers").read_pipe
 
 local awful        = require("awful")
 local beautiful    = require("beautiful")
 local naughty      = require("naughty")
 
-local io           = { popen  = io.popen }
 local math         = { modf   = math.modf }
+local mouse        = mouse
 local string       = { format = string.format,
                        match  = string.match,
                        rep    = string.rep }
@@ -25,7 +26,6 @@ local setmetatable = setmetatable
 -- ALSA volume bar
 -- lain.widgets.alsabar
 local alsabar = {
-    card    = "0",
     channel = "Master",
     step    = "2%",
 
@@ -76,6 +76,10 @@ function alsabar.notify()
                 .. string.rep(" ", alsabar.notifications.bar_size - int)
                 .. "]"
 
+    if alsabar.followmouse then
+        preset.screen = mouse.screen
+    end
+
     if alsabar._notify ~= nil then
         alsabar._notify = naughty.notify ({
             replaces_id = alsabar._notify.id,
@@ -103,6 +107,7 @@ local function worker(args)
     alsabar.step          = args.step or alsabar.step
     alsabar.colors        = args.colors or alsabar.colors
     alsabar.notifications = args.notifications or alsabar.notifications
+    alsabar.followmouse   = args.followmouse or false
 
     alsabar.bar = awful.widget.progressbar()
 
@@ -117,9 +122,7 @@ local function worker(args)
 
     function alsabar.update()
         -- Get mixer control contents
-        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))
 
         -- Capture mixer control state:          [5%] ... ... [on]
         local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
@@ -153,15 +156,15 @@ local function worker(args)
             awful.util.spawn(alsabar.mixer)
           end),
           awful.button ({}, 3, function()
-            awful.util.spawn(string.format("amixer -c %s set %s toggle", alsabar.card, alsabar.channel))
+            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("amixer -c %s set %s %s+", alsabar.card, alsabar.channel, alsabar.step))
+            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("amixer -c %s set %s %s-", alsabar.card, alsabar.channel, alsabar.step))
+            awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step))
             alsabar.update()
           end)
     ))
diff --git a/widgets/alsabar.lua.orig b/widgets/alsabar.lua.orig
new file mode 100644 (file)
index 0000000..3cda639
--- /dev/null
@@ -0,0 +1,215 @@
+
+--[[
+                                                  
+     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 })
index 39b0863e4dfbf8ba1b01ea751d9520d1b2977330..2f377f78bb4ccd552bf01f5299476719f21e2d53 100644 (file)
@@ -7,9 +7,10 @@
 --]]
 
 local newtimer     = require("lain.helpers").newtimer
+local read_pipe    = require("lain.helpers").read_pipe
+
 local wibox        = require("wibox")
 
-local io           = { popen = io.popen }
 local setmetatable = setmetatable
 
 -- Basic template for custom widgets
@@ -25,9 +26,7 @@ local function worker(args)
     base.widget = wibox.widget.textbox('')
 
     function base.update()
-        local f = assert(io.popen(cmd))
-        output = f:read("*a")
-        f:close()
+        output = read_pipe(cmd)
         widget = base.widget
         settings()
     end
diff --git a/widgets/base.lua.orig b/widgets/base.lua.orig
new file mode 100644 (file)
index 0000000..ae9dd10
--- /dev/null
@@ -0,0 +1,51 @@
+
+--[[
+                                                  
+     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 })
index 3e65f38bb8596e8114cb2071c92d814f72a8649f..7e5230851652ad8b8a7cc937920871c1761549d8 100644 (file)
@@ -14,6 +14,7 @@ local naughty      = require("naughty")
 
 local io           = { popen = io.popen }
 local os           = { date = os.date }
+local mouse        = mouse
 local tonumber     = tonumber
 
 local setmetatable = setmetatable
@@ -85,10 +86,16 @@ function calendar:show(t_out, inc_offset, scr)
              .. calendar.font_size .. "'><b>"
              .. f:read() .. "</b>\n\n"
              .. f:read() .. "\n"
-             .. f:read("*a"):gsub("\n*$", "")
+             .. f:read("*all"):gsub("\n*$", "")
              .. "</span></tt>"
     f:close()
 
+    if calendar.followmouse then
+        scrp = mouse.screen
+    else
+        scrp = scr or calendar.scr_pos
+    end
+
     cal_notification = naughty.notify({
         text = c_text,
         icon = calendar.notify_icon,
@@ -96,36 +103,38 @@ function calendar:show(t_out, inc_offset, scr)
         fg = calendar.fg,
         bg = calendar.bg,
         timeout = tims,
-        screen = scr or 1
+        screen = scrp
     })
 end
 
 function calendar:attach(widget, args)
     local args = args or {}
-    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.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, scr_pos) end)
+    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, 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)))
+    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)))
 end
 
 return setmetatable(calendar, { __call = function(_, ...) return create(...) end })
diff --git a/widgets/calendar.lua.orig b/widgets/calendar.lua.orig
new file mode 100644 (file)
index 0000000..187fdc0
--- /dev/null
@@ -0,0 +1,181 @@
+
+--[[
+                                                  
+     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 })
index ccaed82bbb50656631fef57f3be8d55b5e601a0e..eb5d610e79840ecc308b5f7be5f0a8e3ebeb0a2d 100644 (file)
@@ -7,7 +7,7 @@
      Users contributed widgets section             
                                                    
      Licensed under GNU General Public License v2  
-      * (c) 2013,      Luke Bonham                 
+      * (c) 2013, Luke Bonham                      
                                                    
 --]]
 
diff --git a/widgets/contrib/init.lua.orig b/widgets/contrib/init.lua.orig
new file mode 100644 (file)
index 0000000..3ad0835
--- /dev/null
@@ -0,0 +1,23 @@
+
+--[[
+                                                   
+     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 })
diff --git a/widgets/contrib/kbdlayout.lua b/widgets/contrib/kbdlayout.lua
new file mode 100644 (file)
index 0000000..f8164ce
--- /dev/null
@@ -0,0 +1,78 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2015, Dario Gjorgjevski               
+                                                  
+--]]
+
+local newtimer     = require("lain.helpers").newtimer
+local read_pipe    = require("lain.helpers").read_pipe
+
+local wibox        = require("wibox")
+local awful        = require("awful")
+
+local string       = { match = string.match }
+
+local setmetatable = setmetatable
+
+local function worker (args)
+   local kbdlayout    = {}
+   kbdlayout.widget   = wibox.widget.textbox('')
+
+   local layouts          = args.layouts
+   local settings         = args.settings or function () end
+   local add_us_secondary = args.add_us_secondary or true
+   local timeout          = args.timeout or 5
+
+   local idx              = 1
+
+   -- Mouse bindings
+   kbdlayout.widget:buttons(awful.util.table.join(
+                              awful.button({ }, 1, function () kbdlayout.next() end),
+                              awful.button({ }, 3, function () kbdlayout.prev() end)))
+
+   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 }
+      settings()
+   end
+
+   function kbdlayout.update ()
+      local status = read_pipe('setxkbmap -query')
+
+      run_settings(string.match(status, "layout:%s*([^\n]*)"),
+                   string.match(status, "variant:%s*([^\n]*)"))
+   end
+
+   function kbdlayout.set (i)
+      idx = ((i - 1) % #layouts) + 1 -- Make sure to wrap around as needed.
+      local to_execute = 'setxkbmap ' .. layouts[idx].layout
+
+      if add_us_secondary and not string.match(layouts[idx].layout, ",?us,?") then
+         to_execute = to_execute .. ",us"
+      end
+
+      if layouts[idx].variant then
+         to_execute = to_execute .. ' ' .. layouts[idx].variant
+      end
+
+      if os.execute(to_execute) then
+         run_settings(layouts[idx].layout, layouts[idx].variant)
+      end
+   end
+
+   function kbdlayout.next ()
+      kbdlayout.set(idx + 1)
+   end
+
+   function kbdlayout.prev ()
+      kbdlayout.set(idx - 1)
+   end
+
+   newtimer("kbdlayout", timeout, kbdlayout.update)
+   return setmetatable(kbdlayout, { __index = kbdlayout.widget })
+end
+
+return setmetatable({}, { __call = function (_, ...) return worker(...) end })
index cfdbec7e71068f2c140e3f37134115c99a7ab192..b818bb6d3bcdeda76fe51acd1e00ca70f98bdf46 100644 (file)
@@ -29,6 +29,7 @@ local function worker(args)
     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 followmouse = args.followmouse or false
     local settings    = args.settings or function() end
 
     local mpdcover = helpers.scripts_dir .. "mpdcover"
@@ -58,7 +59,7 @@ local function worker(args)
                 total   = "N/A"
             }
 
-            for line in f:lines() do
+            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
@@ -82,6 +83,10 @@ local function worker(args)
                     os.execute(string.format("%s %q %q %d %q", mpdcover, "",
                                moc_now.file, cover_size, default_art))
 
+                    if followmouse then
+                        moc_notification_preset.screen = mouse.screen
+                    end
+
                     moc.id = naughty.notify({
                         preset = moc_notification_preset,
                         icon = "/tmp/mpdcover.png",
diff --git a/widgets/contrib/moc.lua.orig b/widgets/contrib/moc.lua.orig
new file mode 100644 (file)
index 0000000..fb8afec
--- /dev/null
@@ -0,0 +1,117 @@
+
+--[[
+                                                                  
+     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 })
index 6425926a6232cb5c02197226492f5ab321bb53da..6f131e216fe4f925deecc5b7ac65771688959fb1 100644 (file)
@@ -12,6 +12,7 @@ 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
@@ -31,11 +32,17 @@ function task:hide()
     end
 end
 
-function task:show()
+function task:show(scr_pos)
     task:hide()
 
     local f, c_text
 
+    if task.followmouse then
+        local scrp = mouse.screen
+    else
+        local scrp = scr_pos or task.scr_pos
+    end
+
     f = io.popen('task')
     c_text = "<span font='"
              .. task.font .. " "
@@ -51,6 +58,7 @@ function task:show()
                                          fg = task.fg,
                                          bg = task.bg,
                                          timeout = task.timeout,
+                                         screen = scrp
                                      })
 end
 
@@ -106,6 +114,7 @@ function task:prompt_search()
               fg       = task.fg,
               bg       = task.bg,
               timeout  = task.timeout,
+              screen   = mouse.screen
           })
       end,
       nil,
@@ -113,20 +122,22 @@ function task:prompt_search()
 end
 
 function task:attach(widget, args)
-    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
 
     task.notify_icon = icons_dir .. "/taskwarrior/task.png"
     task.notify_icon_small = icons_dir .. "/taskwarrior/tasksmall.png"
 
-    widget:connect_signal("mouse::enter", function () task:show() end)
+    widget:connect_signal("mouse::enter", function () task:show(task.scr_pos) end)
     widget:connect_signal("mouse::leave", function () task:hide() end)
 end
 
diff --git a/widgets/contrib/task.lua.orig b/widgets/contrib/task.lua.orig
new file mode 100644 (file)
index 0000000..d84e55f
--- /dev/null
@@ -0,0 +1,176 @@
+
+--[[
+                                                  
+     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 })
index 951f0cce98b98e0ba5187f40bf7fc2ca30ade4cd..a1d5d95beaa896362f403a59f8c2b81cf7ce77c7 100644 (file)
@@ -16,6 +16,7 @@ local naughty      = require("naughty")
 
 local io           = { popen  = io.popen }
 local pairs        = pairs
+local mouse        = mouse
 local string       = { match  = string.match,
                        format = string.format }
 local tonumber     = tonumber
@@ -25,28 +26,28 @@ local setmetatable = setmetatable
 -- File system disk space usage
 -- lain.widgets.fs
 local fs = {}
-
-local notification  = nil
-fs_notification_preset = { fg = beautiful.fg_normal }
+local fs_notification  = nil
 
 function fs:hide()
-    if notification ~= nil then
-        naughty.destroy(notification)
-        notification = nil
+    if fs_notification ~= nil then
+        naughty.destroy(fs_notification)
+        fs_notification = nil
     end
 end
 
 function fs:show(t_out)
     fs:hide()
 
-    local f = io.popen(helpers.scripts_dir .. "dfs")
-    ws = f:read("*a"):gsub("\n*$", "")
-    f:close()
+    local ws = helpers.read_pipe(helpers.scripts_dir .. "dfs"):gsub("\n*$", "")
+
+    if fs.followmouse then
+        fs.notification_preset.screen = mouse.screen
+    end
 
-    notification = naughty.notify({
-        preset = fs_notification_preset,
-        text = ws,
-        timeout = t_out,
+    fs_notification = naughty.notify({
+        preset  = fs.notification_preset,
+        text    = ws,
+        timeout = t_out
     })
 end
 
@@ -54,10 +55,13 @@ end
 local unit = { ["mb"] = 1024, ["gb"] = 1024^2 }
 
 local function worker(args)
-    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 }
 
     fs.widget = wibox.widget.textbox('')
 
diff --git a/widgets/fs.lua.orig b/widgets/fs.lua.orig
new file mode 100644 (file)
index 0000000..c1a3ab7
--- /dev/null
@@ -0,0 +1,153 @@
+
+--[[
+                                                      
+     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 })
index 1ebbb76da6af266608813aecd162fa976b4e2410..ea763dfa4127ff4baf1cdbd642b7abf61f789a1b 100644 (file)
@@ -12,6 +12,7 @@ local async        = require("lain.asyncshell")
 local naughty      = require("naughty")
 local wibox        = require("wibox")
 
+local mouse        = mouse
 local string       = { format = string.format,
                        gsub   = string.gsub }
 local tonumber     = tonumber
@@ -22,17 +23,18 @@ local setmetatable = setmetatable
 -- lain.widgets.imap
 
 local function worker(args)
-    local imap     = {}
-    local args     = args or {}
+    local imap        = {}
+    local args        = args or {}
 
-    local server   = args.server
-    local mail     = args.mail
-    local password = args.password
+    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 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
 
     local head_command  = "curl --connect-timeout 3 -fsm 3"
     local request = "-X 'SEARCH (UNSEEN)'"
@@ -41,9 +43,7 @@ local function worker(args)
 
     if not is_plain
     then
-        local f = io.popen(password)
-        password = f:read("*a"):gsub("\n", "")
-        f:close()
+        password = helpers.read_pipe(password):gsub("\n", "")
     end
 
     imap.widget = wibox.widget.textbox('')
@@ -54,14 +54,15 @@ local function worker(args)
             position = "top_left"
         }
 
+        if followmouse then
+            mail_notification_preset.screen = mouse.screen
+        end
+
         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)
-            ws = f:read("*a")
-            f:close()
-
-            _, mailcount = string.gsub(ws, "%d+", "")
+            _, mailcount = string.gsub(f, "%d+", "")
             _ = nil
 
             widget = imap.widget
@@ -76,7 +77,7 @@ local function worker(args)
                 end
                 naughty.notify({
                     preset = mail_notification_preset,
-                    text = nt,
+                    text = nt
                 })
             end
 
diff --git a/widgets/imap.lua.orig b/widgets/imap.lua.orig
new file mode 100644 (file)
index 0000000..1121f1a
--- /dev/null
@@ -0,0 +1,131 @@
+
+--[[
+                                                  
+     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 })
index 246341f98962b5d352a408ccb954738b2bf35665..eed613840921ecb955ee427489323be5db989a84 100644 (file)
@@ -8,6 +8,7 @@
 --]]
 
 local newtimer        = require("lain.helpers").newtimer
+local read_pipe       = require("lain.helpers").read_pipe
 
 local wibox           = require("wibox")
 
@@ -50,10 +51,9 @@ local function worker(args)
                 -- match files that begin with a dot.
                 -- Afterwards the length of this string is the number of
                 -- new mails in that box.
-                local np = io.popen("find " .. line ..
+                local mailstring = read_pipe("find " .. line ..
                                     "/new -mindepth 1 -type f " ..
                                     "-not -name '.*' -printf a")
-                local mailstring = np:read("*a")
 
                 -- Strip off leading mailpath.
                 local box = string.match(line, mailpath .. "/*([^/]+)")
@@ -65,10 +65,11 @@ local function worker(args)
             end
         until line == nil
 
+       p:close()
         table.sort(boxes)
 
         newmail = "no mail"
-        --Count the total number of mails irrespective of where it was found
+        -- Count the total number of mails irrespective of where it was found
         total = 0
 
         for box, number in pairs(boxes)
diff --git a/widgets/maildir.lua.orig b/widgets/maildir.lua.orig
new file mode 100644 (file)
index 0000000..a0d5e8c
--- /dev/null
@@ -0,0 +1,116 @@
+
+--[[
+                                                  
+     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 })
index 6b66f8138f06a2d49395e06602933185adb3ef6f..5af898b482ff5dd1f97635fb5ab6e50bf004eced 100644 (file)
@@ -17,6 +17,7 @@ local wibox        = require("wibox")
 local os           = { execute  = os.execute,
                        getenv   = os.getenv }
 local math         = { floor    = math.floor }
+local mouse        = mouse
 local string       = { format   = string.format,
                        match    = string.match,
                        gmatch   = string.gmatch }
@@ -36,11 +37,13 @@ local function worker(args)
     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 followmouse = args.followmouse or false
+    local echo_cmd    = args.echo_cmd or "echo"
     local settings    = args.settings or function() end
 
     local mpdcover = helpers.scripts_dir .. "mpdcover"
     local mpdh = "telnet://" .. host .. ":" .. port
-    local echo = "echo 'password " .. password .. "\nstatus\ncurrentsong\nclose'"
+    local echo = echo_cmd .. " 'password " .. password .. "\nstatus\ncurrentsong\nclose'"
 
     mpd.widget = wibox.widget.textbox('')
 
@@ -64,7 +67,7 @@ local function worker(args)
                 elapsed = "N/A"
             }
 
-            for line in f:lines() do
+            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
@@ -89,7 +92,7 @@ local function worker(args)
                 then
                     helpers.set_map("current mpd track", mpd_now.title)
 
-                    if string.match(mpd_now.file, "http://") == nil
+                    if string.match(mpd_now.file, "http.*://") == nil
                     then -- local file
                         os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir,
                                    mpd_now.file, cover_size, default_art))
@@ -98,6 +101,10 @@ local function worker(args)
                         current_icon = default_art
                     end
 
+                    if followmouse then
+                        mpd_notification_preset.screen = mouse.screen
+                    end
+
                     mpd.id = naughty.notify({
                         preset = mpd_notification_preset,
                         icon = current_icon,
diff --git a/widgets/mpd.lua.orig b/widgets/mpd.lua.orig
new file mode 100644 (file)
index 0000000..9207b15
--- /dev/null
@@ -0,0 +1,147 @@
+
+--[[
+                                                  
+     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 })
index 2585ad4b4e083372c7e8aee7596c93e711a9874e..a578ae4ca9cc405454c4cc57a6b23cd5a9be2a0e 100644 (file)
@@ -13,7 +13,6 @@ local notify_fg    = require("beautiful").fg_focus
 local naughty      = require("naughty")
 local wibox        = require("wibox")
 
-local io           = { popen  = io.popen }
 local string       = { format = string.format,
                        gsub   = string.gsub,
                        match  = string.match }
@@ -28,9 +27,7 @@ local net = {
 }
 
 function net.get_device()
-    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")
     ws = ws:match("%w+: UP") or ws:match("ppp%w+: UNKNOWN")
     if ws ~= nil then
         return ws:match("(%w+):")
diff --git a/widgets/net.lua.orig b/widgets/net.lua.orig
new file mode 100644 (file)
index 0000000..efd1386
--- /dev/null
@@ -0,0 +1,116 @@
+
+--[[
+                                                  
+     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 })
index b10c5e2300ec5737a97f5484610dc4e61944517e..d8e4713a77371088c2ac14693b1183b97ef4517a 100644 (file)
@@ -29,7 +29,7 @@ local function worker(args)
 
     function update()
         local f = io.open("/proc/loadavg")
-        local ret = f:read("*a")
+        local ret = f:read("*all")
         f:close()
 
         load_1, load_5, load_15 = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)")
diff --git a/widgets/sysload.lua.orig b/widgets/sysload.lua.orig
new file mode 100644 (file)
index 0000000..64ddd00
--- /dev/null
@@ -0,0 +1,49 @@
+
+--[[
+                                                  
+     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 })
index 1e93848e0419c9a0e993ec9389608dad7161d44b..67c94560b9a58e67fa15ef340c8862f4b473e020 100644 (file)
@@ -31,7 +31,7 @@ local function worker(args)
         local f = io.open(tempfile)
         if f ~= nil
         then
-            coretemp_now = tonumber(f:read("*a")) / 1000
+            coretemp_now = tonumber(f:read("*all")) / 1000
             f:close()
         else
             coretemp_now = "N/A"
diff --git a/widgets/temp.lua.orig b/widgets/temp.lua.orig
new file mode 100644 (file)
index 0000000..93f72af
--- /dev/null
@@ -0,0 +1,52 @@
+
+--[[
+                                                  
+     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 })
index 77d9b9be88268d25f599090123cac0f3c762dcc0..8a0d75150c372592360050650554a7f569080635 100644 (file)
@@ -7,13 +7,17 @@
 --]]
 
 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 naughty      = require("naughty")
 local wibox        = require("wibox")
 
 local math         = { floor  = math.floor }
+local mouse        = mouse
 local string       = { format = string.format,
                        gsub   = string.gsub }
 
@@ -24,31 +28,37 @@ local setmetatable = setmetatable
 -- lain.widgets.weather
 
 local function worker(args)
-    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
 
     weather.widget = wibox.widget.textbox('')
     weather.icon   = wibox.widget.imagebox()
 
     function weather.show(t_out)
         weather.hide()
+
+        if followmouse then
+            notification_preset.screen = mouse.screen
+        end
+
         weather.notification = naughty.notify({
             text    = weather.notification_text,
             icon    = weather.icon_path,
             timeout = t_out,
-            preset  = w_notification_preset
+            preset  = notification_preset
         })
     end
 
@@ -71,16 +81,12 @@ local function worker(args)
     function weather.forecast_update()
         local cmd = string.format(forecast_call, city_id, units, lang, cnt)
         async.request(cmd, function(f)
-            j = f:read("*a")
-            f:close()
-            weather_now, pos, err = json.decode(j, 1, nil)
+            weather_now, pos, err = json.decode(f, 1, nil)
 
             if not err and weather_now ~= nil and tonumber(weather_now["cod"]) == 200 then
                 weather.notification_text = ''
                 for i = 1, weather_now["cnt"] do
-                    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", "")
 
                     tmin = math.floor(weather_now["list"][i]["temp"]["min"])
                     tmax = math.floor(weather_now["list"][i]["temp"]["max"])
@@ -103,9 +109,7 @@ local function worker(args)
     function weather.update()
         local cmd = string.format(current_call, city_id, units, lang)
         async.request(cmd, function(f)
-            j = f:read("*a")
-            f:close()
-            weather_now, pos, err = json.decode(j, 1, nil)
+            weather_now, pos, err = json.decode(f, 1, nil)
 
             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"
diff --git a/widgets/weather.lua.orig b/widgets/weather.lua.orig
new file mode 100644 (file)
index 0000000..ce67156
--- /dev/null
@@ -0,0 +1,185 @@
+
+--[[
+                                                  
+     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 })
diff --git a/wiki b/wiki
index 4021f24b33be60d2e6b4050098bd8da131648a7e..e21f7ddbdd05019501136a7cca1ac6c897eae2ce 160000 (submodule)
--- a/wiki
+++ b/wiki
@@ -1 +1 @@
-Subproject commit 4021f24b33be60d2e6b4050098bd8da131648a7e
+Subproject commit e21f7ddbdd05019501136a7cca1ac6c897eae2ce