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

Merge commit '33c0e0c2360a04fcc6f51bccb0ad2a7a9e9c07b3'
authormartin f. krafft <madduck@madduck.net>
Sat, 2 Nov 2019 09:41:23 +0000 (22:41 +1300)
committermartin f. krafft <madduck@madduck.net>
Sat, 2 Nov 2019 09:41:23 +0000 (22:41 +1300)
131 files changed:
.config/awesome/lain/.gitmodules
.config/awesome/lain/ISSUE_TEMPLATE.md
.config/awesome/lain/README.rst
.config/awesome/lain/helpers.lua
.config/awesome/lain/icons/cal/black/1.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/10.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/11.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/12.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/13.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/14.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/15.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/16.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/17.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/18.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/19.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/2.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/20.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/21.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/22.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/23.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/24.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/25.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/26.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/27.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/28.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/29.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/3.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/30.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/31.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/4.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/5.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/6.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/7.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/8.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/black/9.png [new file with mode: 0644]
.config/awesome/lain/icons/cal/white/1.png
.config/awesome/lain/icons/cal/white/10.png
.config/awesome/lain/icons/cal/white/11.png
.config/awesome/lain/icons/cal/white/12.png
.config/awesome/lain/icons/cal/white/13.png
.config/awesome/lain/icons/cal/white/14.png
.config/awesome/lain/icons/cal/white/18.png
.config/awesome/lain/icons/cal/white/19.png
.config/awesome/lain/icons/cal/white/2.png
.config/awesome/lain/icons/cal/white/20.png
.config/awesome/lain/icons/cal/white/21.png
.config/awesome/lain/icons/cal/white/22.png
.config/awesome/lain/icons/cal/white/23.png
.config/awesome/lain/icons/cal/white/24.png
.config/awesome/lain/icons/cal/white/25.png
.config/awesome/lain/icons/cal/white/26.png
.config/awesome/lain/icons/cal/white/27.png
.config/awesome/lain/icons/cal/white/28.png
.config/awesome/lain/icons/cal/white/29.png
.config/awesome/lain/icons/cal/white/3.png
.config/awesome/lain/icons/cal/white/30.png
.config/awesome/lain/icons/cal/white/31.png
.config/awesome/lain/icons/cal/white/4.png
.config/awesome/lain/icons/cal/white/6.png
.config/awesome/lain/icons/cal/white/8.png
.config/awesome/lain/icons/cal/white/9.png
.config/awesome/lain/icons/layout/default/cascadetile.png
.config/awesome/lain/icons/layout/default/cascadetilew.png
.config/awesome/lain/icons/layout/default/centerwork.png
.config/awesome/lain/icons/layout/default/centerworkh.png
.config/awesome/lain/icons/layout/default/centerworkhw.png
.config/awesome/lain/icons/layout/default/centerworkw.png
.config/awesome/lain/icons/layout/zenburn/cascade.png
.config/awesome/lain/icons/layout/zenburn/cascadetile.png
.config/awesome/lain/icons/layout/zenburn/centerfair.png
.config/awesome/lain/icons/layout/zenburn/centerwork.png
.config/awesome/lain/icons/layout/zenburn/centerworkh.png
.config/awesome/lain/icons/layout/zenburn/termfair.png
.config/awesome/lain/icons/mail.png
.config/awesome/lain/icons/no_net.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/01d.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/01n.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/02d.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/02n.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/03d.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/03n.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/04d.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/09d.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/10d.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/11d.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/13d.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/50d.png [changed mode: 0755->0644]
.config/awesome/lain/icons/openweathermap/na.png [changed mode: 0755->0644]
.config/awesome/lain/icons/taskwarrior.png
.config/awesome/lain/init.lua
.config/awesome/lain/lain-git.rockspec [deleted file]
.config/awesome/lain/lain-scm-1.rockspec [new file with mode: 0644]
.config/awesome/lain/layout/cascade.lua
.config/awesome/lain/layout/centerwork.lua
.config/awesome/lain/layout/init.lua
.config/awesome/lain/layout/termfair.lua
.config/awesome/lain/scripts/dfs [deleted file]
.config/awesome/lain/util/init.lua
.config/awesome/lain/util/markup.lua
.config/awesome/lain/util/menu_iterator.lua [new file with mode: 0644]
.config/awesome/lain/util/quake.lua
.config/awesome/lain/util/separators.lua
.config/awesome/lain/widget/alsa.lua
.config/awesome/lain/widget/alsabar.lua
.config/awesome/lain/widget/bat.lua
.config/awesome/lain/widget/cal.lua [new file with mode: 0644]
.config/awesome/lain/widget/calendar.lua [deleted file]
.config/awesome/lain/widget/contrib/gpmdp.lua [deleted file]
.config/awesome/lain/widget/contrib/init.lua
.config/awesome/lain/widget/contrib/kbdlayout.lua [deleted file]
.config/awesome/lain/widget/contrib/moc.lua
.config/awesome/lain/widget/contrib/redshift.lua
.config/awesome/lain/widget/contrib/task.lua
.config/awesome/lain/widget/contrib/tp_smapi.lua [new file with mode: 0644]
.config/awesome/lain/widget/contrib/tpbat/init.lua [deleted file]
.config/awesome/lain/widget/contrib/tpbat/smapi.lua [deleted file]
.config/awesome/lain/widget/cpu.lua
.config/awesome/lain/widget/fs.lua
.config/awesome/lain/widget/imap.lua
.config/awesome/lain/widget/init.lua
.config/awesome/lain/widget/mem.lua
.config/awesome/lain/widget/mpd.lua
.config/awesome/lain/widget/net.lua
.config/awesome/lain/widget/pulse.lua [new file with mode: 0644]
.config/awesome/lain/widget/pulseaudio.lua [deleted file]
.config/awesome/lain/widget/pulsebar.lua
.config/awesome/lain/widget/sysload.lua
.config/awesome/lain/widget/temp.lua
.config/awesome/lain/widget/watch.lua [deleted file]
.config/awesome/lain/widget/weather.lua
.config/awesome/lain/wiki

index a50818fd507d0ed5c2283eba482ad16842ebc072..d95bcb57322f746bfd5e79c4fa9edff5cafdd045 100644 (file)
@@ -1,3 +1,3 @@
 [submodule "lain.wiki"]
        path = wiki
-       url = https://github.com/copycat-killer/lain.wiki.git
+       url = https://github.com/lcpz/lain.wiki.git
index 37c2141da70793b0ff81182bc269551997123543..e9dcc0bc84153ab625241f7907997231c71b43a6 100644 (file)
@@ -1,21 +1,33 @@
-# If you have a question
+# Please, read me!
 
-Take the following steps:
-
-1. [Google it](https://encrypted.google.com)
-2. Search [Awesome doc](https://awesomewm.org/doc)
-3. Ask [community](https://awesomewm.org/community)
-
-and, if you still don't have an answer, you can ask here.
-
-**Please be warned:** if your question is __unrelated__ to this repository, a reply is only an act of kindness.
+So that I can help you quickly and without having to redirect you here.
 
 # If you have an issue
 
-**Please read the [wiki](https://github.com/copycat-killer/lain/wiki) and search the [Issues section](https://github.com/copycat-killer/lain/issues) first.**
+**Please read the [wiki](https://github.com/lcpz/lain/wiki) and search the [Issues section](https://github.com/lcpz/lain/issues) first.**
 
 If you can't find a solution there, then go ahead and provide:
 
 * output of `awesome -v` and `lua -v`
 * expected behavior and actual behavior
 * steps to reproduce the problem
+* X error log
+
+# How to provide X error log
+
+There are two ways:
+
+* (Physically) Restart X like this:
+  ```shell
+  startx -- -keeptty -nolisten tcp > $HOME/.xorg.log 2>&1
+  ```
+  the error log will be output into `$HOME/.xorg.log`.
+
+* (Virtually) Use [Xephyr](https://wikipedia.org/wiki/Xephyr):
+  ```shell
+  # set screen size as you like
+  Xephyr :1 -screen 1280x800 2> stdout.txt & DISPLAY=:1 awesome
+  ```
+  the error log will be output in the file `stdout.txt`.
+
+Before reporting, read the log and see if you can solve it yourself.
index 4515be7bfbea3c29d8d83e7723ff8ae2f4346258..2b77f9a7b5a13c87173d2bec5cfc64ad9d7c3950 100644 (file)
@@ -5,50 +5,34 @@ Lain
 Layouts, widgets and utilities for Awesome WM 4.x
 -------------------------------------------------
 
-:Author: Luke Bonham <dada [at] archlinux [dot] info>
+:Author: Luca CPZ
 :Version: git
 :License: GNU-GPL2_
-:Source: https://github.com/copycat-killer/lain
-
-Warning
--------
-
-If you still have to use branch 3.5.x, you can refer to the commit 301faf5_, but be aware that it's no longer supported.
+:Source: https://github.com/lcpz/lain
 
 Description
 -----------
 
-Successor of awesome-vain_, this module provides alternative layouts, asynchronous widgets and utility functions for Awesome_ WM.
-
-Read the wiki_ for all the info.
+Successor of awesome-vain_, this module provides alternative layouts, asynchronous widgets and utility functions for Awesome_.
 
 Contributions
 -------------
 
-Any contribution is welcome! Feel free to make a pull request.
+Constructive criticism and suggestions are welcome.
 
-Just make sure that:
+If you want to create a pull request, 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.
+- Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions to or using lain.helpers_. If something is unclear, or you can not 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 test your changes before submitting to make sure that you code works and does not break other parts of the module.
 
-- You eventually update ``wiki`` submodule with a thorough section.
+- You update ``wiki`` submodule with a thorough section, if necessary.
 
 Contributed widgets have to be put in ``widget/contrib``.
 
-Screenshots
------------
-
-.. image:: http://i.imgur.com/8D9A7lW.png
-.. image:: http://i.imgur.com/9Iv3OR3.png
-.. image:: http://i.imgur.com/STCPcaJ.png
-
 .. _GNU-GPL2: http://www.gnu.org/licenses/gpl-2.0.html
-.. _301faf5: https://github.com/copycat-killer/lain/tree/301faf5370d045e94c9c344acb0fdac84a2f25a6
 .. _awesome-vain: https://github.com/vain/awesome-vain
 .. _Awesome: https://github.com/awesomeWM/awesome
-.. _wiki: https://github.com/copycat-killer/lain/wiki
-.. _lain.helpers: https://github.com/copycat-killer/lain/blob/master/helpers.lua
+.. _lain.helpers: https://github.com/lcpz/lain/blob/master/helpers.lua
index 4e5ce1facc505c5a78617fa40181120b4f1f5826..d6f6b3c1fcf861c283fff9134a1b9587a40998cd 100644 (file)
@@ -1,19 +1,19 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Luke Bonham                     
-                                                  
---]]
 
+     Licensed under GNU General Public License v2
+      * (c) 2013, Luca CPZ
+
+--]]
 
-local easy_async = require("awful.spawn").easy_async
+local spawn      = require("awful.spawn")
 local timer      = require("gears.timer")
 local debug      = require("debug")
 local io         = { lines = io.lines,
                      open  = io.open }
+local pairs      = pairs
 local rawget     = rawget
-local table      = { sort  = table.sort }
+local table      = { sort  = table.sort, unpack = table.unpack }
+local unpack     = unpack or table.unpack -- lua 5.1 retro-compatibility
 
 -- Lain helper functions for internal use
 -- lain.helpers
@@ -34,53 +34,49 @@ 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
-  local lines = {}
-  for line in io.lines(file) do
-    lines[#lines + 1] = line
-  end
-  return lines
-end
-
--- match all lines from a file, returns an empty
--- list/table if the file or match does not exist
-function helpers.lines_match(regexp, file)
-       local lines = {}
-       for index,line in pairs(helpers.lines_from(file)) do
-               if string.match(line, regexp) then
-                       lines[index] = line
-               end
-       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
+-- check if the file exists and is readable
+function helpers.file_exists(path)
+    local file = io.open(path, "rb")
+    if file then file:close() end
+    return file ~= nil
+end
+
+-- get a table with all lines from a file
+function helpers.lines_from(path)
+    local lines = {}
+    for line in io.lines(path) do
+        lines[#lines + 1] = line
+    end
+    return lines
+end
+
+-- get a table with all lines from a file matching regexp
+function helpers.lines_match(regexp, path)
+    local lines = {}
+    for line in io.lines(path) do
+        if string.match(line, regexp) then
+            lines[#lines + 1] = line
+        end
+    end
+    return lines
+end
+
+-- get first line of a file
+function helpers.first_line(path)
+    local file, first = io.open(path, "rb"), nil
+    if file then
+        first = file:read("*l")
+        file:close()
+    end
+    return first
+end
+
+-- get first non empty line from a file
+function helpers.first_nonempty_line(path)
+    for line in io.lines(path) do
+        if #line then return line end
+    end
+    return nil
 end
 
 -- }}}
@@ -112,12 +108,29 @@ end
 -- @param callback function to execute on cmd output
 -- @return cmd PID
 function helpers.async(cmd, callback)
-    return easy_async(cmd,
+    return spawn.easy_async(cmd,
+    function (stdout, stderr, reason, exit_code)
+        callback(stdout, exit_code)
+    end)
+end
+
+-- like above, but call spawn.easy_async with a shell
+function helpers.async_with_shell(cmd, callback)
+    return spawn.easy_async_with_shell(cmd,
     function (stdout, stderr, reason, exit_code)
-        callback(stdout)
+        callback(stdout, exit_code)
     end)
 end
 
+-- run a command and execute a function on its output line by line
+function helpers.line_callback(cmd, callback)
+    return spawn.with_line_callback(cmd, {
+        stdout = function (line)
+            callback(line)
+        end,
+    })
+end
+
 -- }}}
 
 -- {{{ A map utility
@@ -164,6 +177,28 @@ function helpers.spairs(t)
     end
 end
 
+-- create the partition of singletons of a given set
+-- example: the trivial partition set of {a, b, c}, is {{a}, {b}, {c}}
+function helpers.trivial_partition_set(set)
+    local ss = {}
+    for _,e in pairs(set) do
+        ss[#ss+1] = {e}
+    end
+    return ss
+end
+
+-- create the powerset of a given set
+function helpers.powerset(s)
+    if not s then return {} end
+    local t = {{}}
+    for i = 1, #s do
+        for j = 1, #t do
+            t[#t+1] = {s[i],unpack(t[j])}
+        end
+    end
+    return t
+end
+
 -- }}}
 
 return helpers
diff --git a/.config/awesome/lain/icons/cal/black/1.png b/.config/awesome/lain/icons/cal/black/1.png
new file mode 100644 (file)
index 0000000..d2fb62e
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/1.png differ
diff --git a/.config/awesome/lain/icons/cal/black/10.png b/.config/awesome/lain/icons/cal/black/10.png
new file mode 100644 (file)
index 0000000..507b079
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/10.png differ
diff --git a/.config/awesome/lain/icons/cal/black/11.png b/.config/awesome/lain/icons/cal/black/11.png
new file mode 100644 (file)
index 0000000..336141b
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/11.png differ
diff --git a/.config/awesome/lain/icons/cal/black/12.png b/.config/awesome/lain/icons/cal/black/12.png
new file mode 100644 (file)
index 0000000..c589729
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/12.png differ
diff --git a/.config/awesome/lain/icons/cal/black/13.png b/.config/awesome/lain/icons/cal/black/13.png
new file mode 100644 (file)
index 0000000..377518b
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/13.png differ
diff --git a/.config/awesome/lain/icons/cal/black/14.png b/.config/awesome/lain/icons/cal/black/14.png
new file mode 100644 (file)
index 0000000..6f4a9fe
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/14.png differ
diff --git a/.config/awesome/lain/icons/cal/black/15.png b/.config/awesome/lain/icons/cal/black/15.png
new file mode 100644 (file)
index 0000000..1a271c1
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/15.png differ
diff --git a/.config/awesome/lain/icons/cal/black/16.png b/.config/awesome/lain/icons/cal/black/16.png
new file mode 100644 (file)
index 0000000..5e65835
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/16.png differ
diff --git a/.config/awesome/lain/icons/cal/black/17.png b/.config/awesome/lain/icons/cal/black/17.png
new file mode 100644 (file)
index 0000000..f3fa0a9
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/17.png differ
diff --git a/.config/awesome/lain/icons/cal/black/18.png b/.config/awesome/lain/icons/cal/black/18.png
new file mode 100644 (file)
index 0000000..7acb37a
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/18.png differ
diff --git a/.config/awesome/lain/icons/cal/black/19.png b/.config/awesome/lain/icons/cal/black/19.png
new file mode 100644 (file)
index 0000000..a557957
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/19.png differ
diff --git a/.config/awesome/lain/icons/cal/black/2.png b/.config/awesome/lain/icons/cal/black/2.png
new file mode 100644 (file)
index 0000000..17b33e0
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/2.png differ
diff --git a/.config/awesome/lain/icons/cal/black/20.png b/.config/awesome/lain/icons/cal/black/20.png
new file mode 100644 (file)
index 0000000..558d111
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/20.png differ
diff --git a/.config/awesome/lain/icons/cal/black/21.png b/.config/awesome/lain/icons/cal/black/21.png
new file mode 100644 (file)
index 0000000..0bbedc8
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/21.png differ
diff --git a/.config/awesome/lain/icons/cal/black/22.png b/.config/awesome/lain/icons/cal/black/22.png
new file mode 100644 (file)
index 0000000..762d262
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/22.png differ
diff --git a/.config/awesome/lain/icons/cal/black/23.png b/.config/awesome/lain/icons/cal/black/23.png
new file mode 100644 (file)
index 0000000..a39dcee
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/23.png differ
diff --git a/.config/awesome/lain/icons/cal/black/24.png b/.config/awesome/lain/icons/cal/black/24.png
new file mode 100644 (file)
index 0000000..c00dbca
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/24.png differ
diff --git a/.config/awesome/lain/icons/cal/black/25.png b/.config/awesome/lain/icons/cal/black/25.png
new file mode 100644 (file)
index 0000000..dc9243c
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/25.png differ
diff --git a/.config/awesome/lain/icons/cal/black/26.png b/.config/awesome/lain/icons/cal/black/26.png
new file mode 100644 (file)
index 0000000..50bb182
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/26.png differ
diff --git a/.config/awesome/lain/icons/cal/black/27.png b/.config/awesome/lain/icons/cal/black/27.png
new file mode 100644 (file)
index 0000000..0fbf9fc
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/27.png differ
diff --git a/.config/awesome/lain/icons/cal/black/28.png b/.config/awesome/lain/icons/cal/black/28.png
new file mode 100644 (file)
index 0000000..def6ab2
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/28.png differ
diff --git a/.config/awesome/lain/icons/cal/black/29.png b/.config/awesome/lain/icons/cal/black/29.png
new file mode 100644 (file)
index 0000000..531923c
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/29.png differ
diff --git a/.config/awesome/lain/icons/cal/black/3.png b/.config/awesome/lain/icons/cal/black/3.png
new file mode 100644 (file)
index 0000000..98b552d
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/3.png differ
diff --git a/.config/awesome/lain/icons/cal/black/30.png b/.config/awesome/lain/icons/cal/black/30.png
new file mode 100644 (file)
index 0000000..ca58151
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/30.png differ
diff --git a/.config/awesome/lain/icons/cal/black/31.png b/.config/awesome/lain/icons/cal/black/31.png
new file mode 100644 (file)
index 0000000..6e8da21
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/31.png differ
diff --git a/.config/awesome/lain/icons/cal/black/4.png b/.config/awesome/lain/icons/cal/black/4.png
new file mode 100644 (file)
index 0000000..4335979
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/4.png differ
diff --git a/.config/awesome/lain/icons/cal/black/5.png b/.config/awesome/lain/icons/cal/black/5.png
new file mode 100644 (file)
index 0000000..576ec11
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/5.png differ
diff --git a/.config/awesome/lain/icons/cal/black/6.png b/.config/awesome/lain/icons/cal/black/6.png
new file mode 100644 (file)
index 0000000..56fa8ab
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/6.png differ
diff --git a/.config/awesome/lain/icons/cal/black/7.png b/.config/awesome/lain/icons/cal/black/7.png
new file mode 100644 (file)
index 0000000..7c90b3a
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/7.png differ
diff --git a/.config/awesome/lain/icons/cal/black/8.png b/.config/awesome/lain/icons/cal/black/8.png
new file mode 100644 (file)
index 0000000..9d1f28e
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/8.png differ
diff --git a/.config/awesome/lain/icons/cal/black/9.png b/.config/awesome/lain/icons/cal/black/9.png
new file mode 100644 (file)
index 0000000..00d0933
Binary files /dev/null and b/.config/awesome/lain/icons/cal/black/9.png differ
index 90b696ca0820164118bea3af0df0f41b0b2ba4bb..a0faa20c7992d5894fff6667a78af0bc53891c11 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/1.png and b/.config/awesome/lain/icons/cal/white/1.png differ
index b462ffbf0d60bc57c236bc3aef3f388dcce152f9..7d9343bd4030e8bea49f994ad003730a0512cff5 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/10.png and b/.config/awesome/lain/icons/cal/white/10.png differ
index cf43296120793006ccdeb2b08da06fba5bc629a2..7af5e993e620ffc6402001b0f43e779cd81b7105 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/11.png and b/.config/awesome/lain/icons/cal/white/11.png differ
index 42cf092c707630612ecda89455794e1cecd2579f..b164f858f81b057490c770f5ed84c52cf21f73b1 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/12.png and b/.config/awesome/lain/icons/cal/white/12.png differ
index 37db670cb71fecb2f2932981b09dae765adee205..fef74f36e7c2a65ddff7ce9876e1c8c78fbc61de 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/13.png and b/.config/awesome/lain/icons/cal/white/13.png differ
index 01885040cb3d6920da2bf0c591ed3006e3e42709..d747a6bd1714fff027ea81b23d7e0f27dec67b38 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/14.png and b/.config/awesome/lain/icons/cal/white/14.png differ
index 817c4267d2d8d6fe36ae370c388aeae0f79c86d2..0cf1c2430217fb553f0a3994d5bf34e52afcbeaf 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/18.png and b/.config/awesome/lain/icons/cal/white/18.png differ
index 0e6dafcc9ff661f86836c6746265b9d2bb34f20e..bfd3530c249c7a3956a2ba1d693292696b9bebec 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/19.png and b/.config/awesome/lain/icons/cal/white/19.png differ
index b93789a59ad776ad87b50024d765abfe4b9258ee..e7f3fa49510883b734e09eb895a3960aff0f94e5 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/2.png and b/.config/awesome/lain/icons/cal/white/2.png differ
index 3d8d7c618fcf7b0bd4446be1fd26a9dd9e5647f1..9a5a1fb3c99ee20cc5d6f509955ea46d45611270 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/20.png and b/.config/awesome/lain/icons/cal/white/20.png differ
index 79a74f3d2ba82322a3ae7fb7be95ac6805f77747..266ab9f389a943587ea3a9b151d8d1e7b5fc6b78 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/21.png and b/.config/awesome/lain/icons/cal/white/21.png differ
index e8845ce2e8950e7a773d7fd9dad893f3f490882c..f4862892d4ac2f84484005e3af8377fdc7bca606 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/22.png and b/.config/awesome/lain/icons/cal/white/22.png differ
index a8d4dfb6dc75657f4b5b9cd07704bafc0b779340..244dceb8af83e9c769659a6f06b7b63f60a9f666 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/23.png and b/.config/awesome/lain/icons/cal/white/23.png differ
index 1a3b38ad29f89a08702f67ddb9cc2d37126673f4..0ce1c75530ec0afe555333ad26a6149084f53317 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/24.png and b/.config/awesome/lain/icons/cal/white/24.png differ
index c3621b7b6ea8705107ef54198389dde2c9325224..48d279c4a2ef0e55259633daf7b6c77b55959109 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/25.png and b/.config/awesome/lain/icons/cal/white/25.png differ
index f26731bbf41bb4fcebae8d075310abc25128c299..7535855dacaf32dd47f3caf28b5ce61208830c92 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/26.png and b/.config/awesome/lain/icons/cal/white/26.png differ
index e4dde7700dd2c86fed2c94ec070f3fb751ced45b..2aa9074280bf67089da3ee7c8048ae982d888a94 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/27.png and b/.config/awesome/lain/icons/cal/white/27.png differ
index b924c22a861495d22203257b4de5f3e71ee8b208..0201976903380d771849f3c8c109d53e35568fe2 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/28.png and b/.config/awesome/lain/icons/cal/white/28.png differ
index e9a74f8be9e55a8e7db753e3689354dea3f9028f..9305b9bd0411669c859a66c3c34789cc4f32232a 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/29.png and b/.config/awesome/lain/icons/cal/white/29.png differ
index 11242710cb04449563e2e6c56440d9f19c8afbe1..f1eb5de62db5f243352fd5aa91c0b82a86428177 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/3.png and b/.config/awesome/lain/icons/cal/white/3.png differ
index 8147d78f042bc2918a7cb6b8ff0f482c91a8f363..1ba61aacfa9adbf89acb2d084b42ab65411ae5c0 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/30.png and b/.config/awesome/lain/icons/cal/white/30.png differ
index a1be3e840049e04738875cebdb5f6f7d75ddcb40..e9a873bc290f1b488ae1bb8238de4e45fccf05c6 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/31.png and b/.config/awesome/lain/icons/cal/white/31.png differ
index 16713bcd6729a74a11856b7199365bffe6fd3689..ee1ed6a8829e464e0c591377cc0871ffc34bc996 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/4.png and b/.config/awesome/lain/icons/cal/white/4.png differ
index a1c9798bd0c4cf8f03ebdb6524f723c6f8e415ec..0a7bf4d704b2d10c3895cbda295627fd2ace3bab 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/6.png and b/.config/awesome/lain/icons/cal/white/6.png differ
index 909b72606b000c6c2642db09f2a3ae7ce71104d0..cb03d0b40d4204f869f9d90cdffb2335c51249dd 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/8.png and b/.config/awesome/lain/icons/cal/white/8.png differ
index dc636c48820ade07a45c24431101a4cff6f296e7..fca554a5bb00ceef5006b5ece6a208282abeb169 100644 (file)
Binary files a/.config/awesome/lain/icons/cal/white/9.png and b/.config/awesome/lain/icons/cal/white/9.png differ
index 2f12ada6300e54c16b5b2337824c7651c5909f29..ba30f43e0bc7adbd02e91e11c9033d591ebca574 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/default/cascadetile.png and b/.config/awesome/lain/icons/layout/default/cascadetile.png differ
index c46b48be2b4132ca68f77250765f4dc7bc6bb4be..d15eb70be374033aa153aa119bfd2821f7bad580 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/default/cascadetilew.png and b/.config/awesome/lain/icons/layout/default/cascadetilew.png differ
index 826b331b48679d671048f232a9c2c254ba5e7af4..51e06bc7e806dfe62b860b62fc1b94c78a93ce5c 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/default/centerwork.png and b/.config/awesome/lain/icons/layout/default/centerwork.png differ
index 4fb4fdd38e9e30d30537434d963a192b30ba154d..c59092f01d9dc94c48162ef26e1b343554a1a8f9 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/default/centerworkh.png and b/.config/awesome/lain/icons/layout/default/centerworkh.png differ
index fd27766ca2b2b7ded2f59c82901f4ce9defecde5..7820f8cb4a27f74ef55dbb3a5160ddc291de8291 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/default/centerworkhw.png and b/.config/awesome/lain/icons/layout/default/centerworkhw.png differ
index fcfa7e317d0c3a093c18568bf16418fc9010260c..85e699646d84d1832b9266bb663fd1c563da8257 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/default/centerworkw.png and b/.config/awesome/lain/icons/layout/default/centerworkw.png differ
index 532842ddcf2ebdf34f50f8450df45a288713510d..fbe4fac509426ab8c4cb17cbc24eea2514175e11 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/zenburn/cascade.png and b/.config/awesome/lain/icons/layout/zenburn/cascade.png differ
index 87be6581f6e9137f15b74c8f12db2c41eabe68f8..2e03a8072eba9f7b1337c575476424c57fbd626b 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/zenburn/cascadetile.png and b/.config/awesome/lain/icons/layout/zenburn/cascadetile.png differ
index 01cda8e89c14980825199778ed2c5defea611305..75dc993bed99b27d88637902db444ea5b292a57f 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/zenburn/centerfair.png and b/.config/awesome/lain/icons/layout/zenburn/centerfair.png differ
index 6a2ceccee81eee4fea2cd2fb05fc5890e6c66b85..af7a863d1f2d017866c8917d4eb5dd7f1b90ba31 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/zenburn/centerwork.png and b/.config/awesome/lain/icons/layout/zenburn/centerwork.png differ
index 00beeb50c49d50ade2e964925de8e14afe6db535..88019b309eada2ba102b9c09a6333e1d5e86bfbd 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/zenburn/centerworkh.png and b/.config/awesome/lain/icons/layout/zenburn/centerworkh.png differ
index b7d5880c64fb32af4906b58bae4a347e8f8db4f5..f7640b555f7b291ff8d69724fe6174bffae3313f 100644 (file)
Binary files a/.config/awesome/lain/icons/layout/zenburn/termfair.png and b/.config/awesome/lain/icons/layout/zenburn/termfair.png differ
index 60ba6e03c83096ece4c7b3e819fbf465a57c33db..9c0c7a39096084c198c0fc73334cdc90628a72ea 100644 (file)
Binary files a/.config/awesome/lain/icons/mail.png and b/.config/awesome/lain/icons/mail.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 1a3e8a8..3613372
Binary files a/.config/awesome/lain/icons/no_net.png and b/.config/awesome/lain/icons/no_net.png differ
old mode 100755 (executable)
new mode 100644 (file)
index d9e2745..569965e
Binary files a/.config/awesome/lain/icons/openweathermap/01d.png and b/.config/awesome/lain/icons/openweathermap/01d.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 84ea140..ce5b135
Binary files a/.config/awesome/lain/icons/openweathermap/01n.png and b/.config/awesome/lain/icons/openweathermap/01n.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 8fd0a5b..2ba9799
Binary files a/.config/awesome/lain/icons/openweathermap/02d.png and b/.config/awesome/lain/icons/openweathermap/02d.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 9e4404d..12e4283
Binary files a/.config/awesome/lain/icons/openweathermap/02n.png and b/.config/awesome/lain/icons/openweathermap/02n.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 22b929c..1cf0e9d
Binary files a/.config/awesome/lain/icons/openweathermap/03d.png and b/.config/awesome/lain/icons/openweathermap/03d.png differ
old mode 100755 (executable)
new mode 100644 (file)
index d8b3673..89a42b8
Binary files a/.config/awesome/lain/icons/openweathermap/03n.png and b/.config/awesome/lain/icons/openweathermap/03n.png differ
old mode 100755 (executable)
new mode 100644 (file)
index bac1e7e..e7fb67f
Binary files a/.config/awesome/lain/icons/openweathermap/04d.png and b/.config/awesome/lain/icons/openweathermap/04d.png differ
old mode 100755 (executable)
new mode 100644 (file)
index d00552a..cfa066a
Binary files a/.config/awesome/lain/icons/openweathermap/09d.png and b/.config/awesome/lain/icons/openweathermap/09d.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 3cc6665..712d0c8
Binary files a/.config/awesome/lain/icons/openweathermap/10d.png and b/.config/awesome/lain/icons/openweathermap/10d.png differ
old mode 100755 (executable)
new mode 100644 (file)
index d30e120..3b62f7c
Binary files a/.config/awesome/lain/icons/openweathermap/11d.png and b/.config/awesome/lain/icons/openweathermap/11d.png differ
old mode 100755 (executable)
new mode 100644 (file)
index ddcb8f3..e265b01
Binary files a/.config/awesome/lain/icons/openweathermap/13d.png and b/.config/awesome/lain/icons/openweathermap/13d.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 009039f..905ace3
Binary files a/.config/awesome/lain/icons/openweathermap/50d.png and b/.config/awesome/lain/icons/openweathermap/50d.png differ
old mode 100755 (executable)
new mode 100644 (file)
index 62a5350..1cc5132
Binary files a/.config/awesome/lain/icons/openweathermap/na.png and b/.config/awesome/lain/icons/openweathermap/na.png differ
index 859ca29120f197ef2f46a76baefd7b5cd81c58c1..c64fe8623044f41f204857ccbb3394b2c5450e79 100644 (file)
Binary files a/.config/awesome/lain/icons/taskwarrior.png and b/.config/awesome/lain/icons/taskwarrior.png differ
index 46ab825e370fd50a52dcf70a0481a56c35b0689f..b59d5dd93bb9568c83e80874f6a45a719d3ef54e 100644 (file)
@@ -1,12 +1,11 @@
-
 --[[
-                                                   
-     Lain                                          
-     Layouts, widgets and utilities for Awesome WM 
-                                                   
-     Licensed under GNU General Public License v2  
-      * (c) 2013, Luke Bonham                      
-                                                   
+
+     Lain
+     Layouts, widgets and utilities for Awesome WM
+
+     Licensed under GNU General Public License v2
+      * (c) 2013, Luca CPZ
+
 --]]
 
 return {
diff --git a/.config/awesome/lain/lain-git.rockspec b/.config/awesome/lain/lain-git.rockspec
deleted file mode 100644 (file)
index a264384..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-package = "lain"
-version = "git"
-source = {
-   url = "https://github.com/copycat-killer/lain",
-   tag = "git"
-}
-description = {
-   summary = "Layout, widgets and utilities for Awesome WM",
-   detailed = [[
-        Successor of awesome-vain, this module provides new layouts, a set of widgets and utility functions, with the aim of improving Awesome usability and configurability.
-
-        Optional dependency: curl (for IMAP and weather widgets).
-    ]],
-   homepage = "https://github.com/copycat-killer/lain",
-   license = "GPL v2"
-}
-dependencies = {
-   "lua >= 5.3",
-   "awesome >= 4.0",
-   "curl"
-}
-supported_platforms = { "linux" }
-build = {
-   type = "builtin",
-   modules = { lain = "init.lua" }
-}
diff --git a/.config/awesome/lain/lain-scm-1.rockspec b/.config/awesome/lain/lain-scm-1.rockspec
new file mode 100644 (file)
index 0000000..fb1eaaf
--- /dev/null
@@ -0,0 +1,27 @@
+package = "lain"
+version = "scm-1"
+source = {
+   url = "https://github.com/lcpz/lain",
+   tag = "scm-1`"
+}
+description = {
+   summary = "Layout, widgets and utilities for Awesome WM",
+   detailed = [[
+        Successor of awesome-vain, this module provides alternative layouts, asynchronous widgets and utility functions for Awesome WM.
+
+        Dependencies: curl (for IMAP, MPD and weather widgets); Glib >= 2.54 (for filesystems widget).
+    ]],
+   homepage = "https://github.com/lcpz/lain",
+   license = "GPL-2.0"
+}
+dependencies = {
+   "lua >= 5.1",
+   "awesome >= 4.0",
+   "Glib >= 2.54",
+   "curl"
+}
+supported_platforms = { "linux" }
+build = {
+   type = "builtin",
+   modules = { lain = "init.lua" }
+}
index 204ce4017bc211f532c750ae5f2e6c3979590486..cbc3877b0fb992ffb1570c898fb93049264fb9c8 100644 (file)
@@ -1,11 +1,10 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2014,      projektile                 
-      * (c) 2013,      Luke Bonham                
-      * (c) 2010-2012, Peter Hofmann              
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2014,      projektile
+      * (c) 2013,      Luca CPZ
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
 local floor  = math.floor
index eafab78ce5c5054f1834e616b97e555305f6294c..2b38a69f0378ff5e095e45266b0d1fd4183a49c1 100644 (file)
@@ -1,34 +1,32 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2016,      Henrik Antonsson           
-      * (c) 2015,      Joerg Jaspert              
-      * (c) 2014,      projektile                 
-      * (c) 2013,      Luke Bonham                
-      * (c) 2010-2012, Peter Hofmann              
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2018,      Eugene Pakhomov
+      * (c) 2016,      Henrik Antonsson
+      * (c) 2015,      Joerg Jaspert
+      * (c) 2014,      projektile
+      * (c) 2013,      Luca CPZ
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
-local floor  = math.floor
-local screen = screen
+local floor, max, mouse, mousegrabber, screen = math.floor, math.max, mouse, mousegrabber, screen
 
 local centerwork = {
-    name         = "centerwork",
-    horizontal   = { name = "centerworkh" }
+    name       = "centerwork",
+    horizontal = { name = "centerworkh" }
 }
 
-local function do_centerwork(p, orientation)
-    local t = p.tag or screen[p.screen].selected_tag
-    local wa = p.workarea
+local function arrange(p, layout)
+    local t   = p.tag or screen[p.screen].selected_tag
+    local wa  = p.workarea
     local cls = p.clients
 
     if #cls == 0 then return end
 
-    local c = cls[1]
-    local g = {}
+    local c, g = cls[1], {}
 
-    -- Main column, fixed width and height.
+    -- Main column, fixed width and height
     local mwfact          = t.master_width_factor
     local mainhei         = floor(wa.height * mwfact)
     local mainwid         = floor(wa.width * mwfact)
@@ -43,7 +41,7 @@ local function do_centerwork(p, orientation)
 
     local slaveFirstDim, slaveSecondDim = 0, 0
 
-    if orientation == "vertical" then
+    if layout.name == "centerwork" then -- vertical
         if nbrFirstSlaves  > 0 then slaveFirstDim  = floor(wa.height / nbrFirstSlaves) end
         if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.height / nbrSecondSlaves) end
 
@@ -52,7 +50,7 @@ local function do_centerwork(p, orientation)
 
         g.x = wa.x + slaveLwid
         g.y = wa.y
-    else
+    else -- horizontal
         if nbrFirstSlaves  > 0 then slaveFirstDim  = floor(wa.width / nbrFirstSlaves) end
         if nbrSecondSlaves > 0 then slaveSecondDim = floor(wa.width / nbrSecondSlaves) end
 
@@ -63,92 +61,134 @@ local function do_centerwork(p, orientation)
         g.y = wa.y + slaveThei
     end
 
-    if g.width  < 1 then g.width  = 1 end
-    if g.height < 1 then g.height = 1 end
+    g.width  = max(g.width, 1)
+    g.height = max(g.height, 1)
 
     p.geometries[c] = g
 
-    -- Auxiliary windows.
+    -- Auxiliary clients
     if #cls <= 1 then return end
-    for i = 2,#cls do
-        local c = cls[i]
-        local g = {}
+    for i = 2, #cls do
+        local c, g = cls[i], {}
+        local idxChecker, dimToAssign
 
         local rowIndex = floor(i/2)
 
-        if orientation == "vertical" then
-            if i % 2 == 0 then
-                -- left slave
-                g.x = wa.x
-                g.y = wa.y + (rowIndex-1)*slaveFirstDim
-
+        if layout.name == "centerwork" then
+            if i % 2 == 0 then -- left slave
+                g.x     = wa.x
+                g.y     = wa.y + (rowIndex - 1) * slaveFirstDim
                 g.width = slaveLwid
 
-                -- if last slave in left row use remaining space for that slave
-                if rowIndex == nbrFirstSlaves then
-                    g.height = wa.y + wa.height - g.y
-                else
-                    g.height = slaveFirstDim
-                end
-            else
-                -- right slave
-                g.x = wa.x + slaveLwid + mainwid
-                g.y = wa.y + (rowIndex-1)*slaveSecondDim
-
+                idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim
+            else -- right slave
+                g.x     = wa.x + slaveLwid + mainwid
+                g.y     = wa.y + (rowIndex - 1) * slaveSecondDim
                 g.width = slaveRwid
 
-                -- if last slave in right row use remaining space for that slave
-                if rowIndex == nbrSecondSlaves then
-                    g.height = wa.y + wa.height - g.y
-                else
-                    g.height = slaveSecondDim
-                end
+                idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim
             end
-        else
-            if i % 2 == 0 then
-                -- top slave
-                g.x = wa.x + (rowIndex-1)*slaveFirstDim
-                g.y = wa.y
-
-                g.height = slaveThei
 
-                -- if last slave in top row use remaining space for that slave
-                if rowIndex == nbrFirstSlaves then
-                    g.width = wa.x + wa.width - g.x
-                else
-                    g.width = slaveFirstDim
-                end
+            -- if last slave in row, use remaining space for it
+            if rowIndex == idxChecker then
+                g.height = wa.y + wa.height - g.y
             else
-                -- bottom slave
-                g.x = wa.x + (rowIndex-1)*slaveSecondDim
-                g.y = wa.y + slaveThei + mainhei
+                g.height = dimToAssign
+            end
+        else
+            if i % 2 == 0 then -- top slave
+                g.x      = wa.x + (rowIndex - 1) * slaveFirstDim
+                g.y      = wa.y
+                g.height = slaveThei
 
+                idxChecker, dimToAssign = nbrFirstSlaves, slaveFirstDim
+            else -- bottom slave
+                g.x      = wa.x + (rowIndex - 1) * slaveSecondDim
+                g.y      = wa.y + slaveThei + mainhei
                 g.height = slaveBhei
 
-                -- if last slave in bottom row use remaining space for that slave
-                if rowIndex == nbrSecondSlaves then
-                    g.width = wa.x + wa.width - g.x
-                else
-                    g.width = slaveSecondDim
-                end
+                idxChecker, dimToAssign = nbrSecondSlaves, slaveSecondDim
+            end
 
+            -- if last slave in row, use remaining space for it
+            if rowIndex == idxChecker then
+                g.width = wa.x + wa.width - g.x
+            else
+                g.width = dimToAssign
             end
         end
 
-        if g.width  < 1 then g.width  = 1 end
-        if g.height < 1 then g.height = 1 end
+        g.width  = max(g.width, 1)
+        g.height = max(g.height, 1)
 
         p.geometries[c] = g
     end
 end
 
+local function mouse_resize_handler(c, corner, x, y, orientation)
+    local wa     = c.screen.workarea
+    local mwfact = c.screen.selected_tag.master_width_factor
+    local g      = c:geometry()
+    local offset = 0
+    local cursor = "cross"
+
+    local corner_coords
+
+    if orientation == 'vertical' then
+        if g.height + 15 >= wa.height then
+            offset = g.height * .5
+            cursor = "sb_h_double_arrow"
+        elseif not (g.y + g.height + 15 > wa.y + wa.height) then
+            offset = g.height
+        end
+        corner_coords = { x = wa.x + wa.width * (1 - mwfact) / 2, y = g.y + offset }
+    else
+        if g.width + 15 >= wa.width then
+            offset = g.width * .5
+            cursor = "sb_v_double_arrow"
+        elseif not (g.x + g.width + 15 > wa.x + wa.width) then
+            offset = g.width
+        end
+        corner_coords = { y = wa.y + wa.height * (1 - mwfact) / 2, x = g.x + offset }
+    end
+
+    mouse.coords(corner_coords)
 
-function centerwork.horizontal.arrange(p)
-    return do_centerwork(p, "horizontal")
+    local prev_coords = {}
+
+    mousegrabber.run(function(_mouse)
+        if not c.valid then return false end
+        for _, v in ipairs(_mouse.buttons) do
+            if v then
+                prev_coords = { x = _mouse.x, y = _mouse.y }
+                local new_mwfact
+                if orientation == 'vertical' then
+                    new_mwfact = 1 - (_mouse.x - wa.x) / wa.width * 2
+                else
+                    new_mwfact = 1 - (_mouse.y - wa.y) / wa.height * 2
+                end
+                c.screen.selected_tag.master_width_factor = math.min(math.max(new_mwfact, 0.01), 0.99)
+                return true
+            end
+        end
+        return prev_coords.x == _mouse.x and prev_coords.y == _mouse.y
+    end, cursor)
 end
 
 function centerwork.arrange(p)
-    return do_centerwork(p, "vertical")
+    return arrange(p, centerwork)
+end
+
+function centerwork.horizontal.arrange(p)
+    return arrange(p, centerwork.horizontal)
+end
+
+function centerwork.mouse_resize_handler(c, corner, x, y)
+    return mouse_resize_handler(c, corner, x, y, 'vertical')
+end
+
+function centerwork.horizontal.mouse_resize_handler(c, corner, x, y)
+    return mouse_resize_handler(c, corner, x, y, 'horizontal')
 end
 
 return centerwork
index d79679a5f17620b736284afb077d10d38bc57ad7..6478b06052460446729a9f950fe12e136706da3c 100644 (file)
@@ -1,15 +1,14 @@
-
 --[[
-                                                   
-     Lain                                          
-     Layouts, widgets and utilities for Awesome WM 
-                                                   
-     Layouts section                               
-                                                   
-     Licensed under GNU General Public License v2  
-      * (c) 2013,      Luke Bonham                 
-      * (c) 2010-2012, Peter Hofmann               
-                                                   
+
+     Lain
+     Layouts, widgets and utilities for Awesome WM
+
+     Layouts section
+
+     Licensed under GNU General Public License v2
+      * (c) 2013,      Luca CPZ
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
 local wrequire     = require("lain.helpers").wrequire
index 33b7ffc7489634761565caab3248c336b494a975..e33894e11777ad85031ed6d9c1e21577869cc063 100644 (file)
@@ -1,17 +1,14 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2014,      projektile                 
-      * (c) 2013,      Luke Bonham                
-      * (c) 2010,      Nicolas Estibals           
-      * (c) 2010-2012, Peter Hofmann              
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2014,      projektile
+      * (c) 2013,      Luca CPZ
+      * (c) 2010,      Nicolas Estibals
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
-local math     = { ceil  = math.ceil,
-                   floor = math.floor,
-                   max   = math.max }
+local math     = math
 local screen   = screen
 local tonumber = tonumber
 
diff --git a/.config/awesome/lain/scripts/dfs b/.config/awesome/lain/scripts/dfs
deleted file mode 100755 (executable)
index df87150..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-#!/usr/bin/env sh
-#
-#   Adapted from Eridan's "fs" (cleanup, enhancements and switch to bash/Linux)
-#   JM,  10/12/2004
-#
-#   Integrated into Lain in september 2013
-#   https://github.com/copycat-killer/lain
-
-#   Requires gawk
-
-# -------------------------------------------------------------------------
-#   Decoding options
-# -------------------------------------------------------------------------
-USAGE="Usage: $0 [-h(elp)] | [-n(arrow mode)] | [-w(eb output) | --type=<fstype> | --exclude-type=<fstype>]"
-
-NARROW_MODE=0
-WEB_OUTPUT=0
-DF_OPTIONS=""
-
-while [ $# -gt 0 ]; do
-case "$1" in
-"-h" )
-echo $USAGE
-exit
-;;
-"-d" )
-DEBUG=1
-;;
-"-n" )
-NARROW_MODE=1
-;;
-"-w" )
-WEB_OUTPUT=1
-;;
---type=*)
-DF_OPTIONS+=" $1"
-;;
---exclude-type=*)
-DF_OPTIONS+=" $1"
-;;
-* )
-echo $USAGE
-exit
-;;
-esac
-shift
-done
-
-# -------------------------------------------------------------------------
-#   Preparations
-# -------------------------------------------------------------------------
-SYSTEM=`uname -s`
-PATTERN="/"
-
-case "$SYSTEM" in
-"Linux" )
-DF_COMMAND="/usr/bin/env df -k"
-SORT_COMMAND="/usr/bin/env sort -k6"
-AWK_COMMAND="/usr/bin/env awk"
-;;
-* )
-DF_COMMAND="/bin/df -k"
-SORT_COMMAND="/usr/bin/sort -k6"
-AWK_COMMAND="/usr/bin/env gawk"
-;;
-esac
-
-# Add additional df options
-DF_COMMAND+=$DF_OPTIONS
-
-# -------------------------------------------------------------------------
-#   Grabbing "df" result
-# -------------------------------------------------------------------------
-DF_RESULT=`$DF_COMMAND`
-if [ ! -z $DEBUG ]; then
-echo "--> DF_RESULT:"
-echo "$DF_RESULT"
-echo ""
-fi
-
-# -------------------------------------------------------------------------
-#   Preprocessing "df" result, to join split logical lines
-# -------------------------------------------------------------------------
-PREPROCESSING_RESULT=` \
-                                                                                echo "$DF_RESULT" | $AWK_COMMAND -v PATTERN=$PATTERN \
-                                                                                '
-                                                                                NF == 1 {
-                                                                                        printf ("%s", $0)
-                                                                                }
-
-NF == 5 {
-       printf ("%s\n", $0)
-}
-
-NF > 6  {
-}
-
-NF == 6 {
-       printf ("%s\n", $0)
-}'
-`
-if [ ! -z $DEBUG ]; then
-echo "--> PREPROCESSING_RESULT:"
-echo "$PREPROCESSING_RESULT"
-echo ""
-fi
-
-SORTED_FILE_SYSTEMS_INFO=`echo "$PREPROCESSING_RESULT" | $SORT_COMMAND`
-
-if [ ! -z $DEBUG ]; then
-echo "--> SORTED_FILE_SYSTEMS_INFO:"
-echo "$SORTED_FILE_SYSTEMS_INFO"
-echo ""
-fi
-
-# -------------------------------------------------------------------------
-#   Computing mount point max length
-# -------------------------------------------------------------------------
-MOUNT_POINT_MAX_LENGTH=` \
-                                                                                        echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v PATTERN=$PATTERN \
-                                                                                        '
-                                                                                        BEGIN       {
-                                                                                                mount_point_length_max = 15;
-                                                                                        }
-
-END     {
-       printf ("%d", mount_point_length_max);
-}
-
-$0 ~ PATTERN    {
-#       printf ("$6 = %s\n", $6);
-
-       mount_point = $6;
-#       printf ("mount_point = %s\n", mount_point);
-
-       mount_point_length = length (mount_point);
-#       printf ("mount_point_length = %d\n", mount_point_length);
-
-       if (mount_point_length > mount_point_length_max)
-               mount_point_length_max = mount_point_length;
-}'
-`
-if [ ! -z $DEBUG ]; then
-echo "MOUNT_POINT_MAX_LENGTH:      $MOUNT_POINT_MAX_LENGTH"
-fi
-
-# -------------------------------------------------------------------------
-#   Computing mount point data max size
-# -------------------------------------------------------------------------
-MOUNT_POINT_MAX_SIZE=` \
-                                                                                echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v PATTERN=$PATTERN \
-                                                                                '
-                                                                                BEGIN       {
-                                                                                        mount_point_size_max = 0;
-                                                                                }
-
-END     {
-       printf ("%d", mount_point_size_max);
-}
-
-$0 ~ PATTERN    {
-#       df -k shows k_bytes!
-#       printf ("$2 = %s\n", $2);
-
-       mount_point_size = $2 * 1024;
-#       printf ("mount_point_size = %d\n", mount_point_size);
-
-       if (mount_point_size > mount_point_size_max)
-               mount_point_size_max = mount_point_size;
-}'
-`
-if [ ! -z $DEBUG ]; then
-echo "MOUNT_POINT_MAX_SIZE:      $MOUNT_POINT_MAX_SIZE"
-fi
-
-# -------------------------------------------------------------------------
-#   Let's go!
-# -------------------------------------------------------------------------
-echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v DEBUG=$DEBUG -v PATTERN=$PATTERN -v NARROW_MODE=$NARROW_MODE -v LEFT_COLUMN=$MOUNT_POINT_MAX_LENGTH -v MAX_SIZE=$MOUNT_POINT_MAX_SIZE -v SCALE=$SCALE -v WEB_OUTPUT=$WEB_OUTPUT \
-                        '
-#   {printf ("$0 = %s\n", $0);}
-#   {printf ("$1 = %s\n", $1);}
-#   {printf ("PATTERN = %s\n", PATTERN);}
-#   {printf ("LEFT_COLUMN = %s\n", LEFT_COLUMN);}
-
-                        BEGIN       {
-                                k_bytes = 1024.0;
-                                m_bytes = 1024.0 * k_bytes;
-                                g_bytes = 1024.0 * m_bytes;
-                                t_bytes = 1024.0 * g_bytes;
-
-                                if (WEB_OUTPUT)
-                                {
-                                        all_stars = "**************************************************";
-                                        current_date = strftime ("%d-%m-%Y @ %H:%M:%S", localtime (systime ()));
-                                        free_threshold = 10; # %
-
-                                printf ("<!-- DEBUT CONTENU -->\n");
-
-                                        printf ( \
-                                                        "<A NAME=\"top\"></A>\n" \
-                                                        "<P ALIGN=CENTER><SPAN CLASS=\"titleblue\">%s</SPAN><SPAN CLASS=\"textbold\">  --  STATUS OF <SPAN CLASS=\"titlered\">ALCOR</SPAN> FILE SYSTEMS</SPAN></P><BR>\n",
-                                                        current_date )
-
-                                                printf ("<TABLE WIDTH=\"100%%\" BORDER=1>\n");
-
-                                        printf ( \
-                                                        "<TR>\n" \
-                                                        "<TD ALIGN=LEFT><STRONG>Mount point</STRONG></TD>\n" \
-                                                        "<TD ALIGN=CENTER><STRONG>%% Usato&nbsp;(<SPAN CLASS=\"titleblue\">*</SPAN>)" \
-                                                        "&nbsp;-&nbsp;%% Free&nbsp;(<SPAN CLASS=\"titlegreen\">*</SPAN>)</STRONG></TD>\n" \
-                                                        "<TD ALIGN=CENTER><STRONG>%% Used</STRONG></TD>\n" \
-                                                        "<TD ALIGN=CENTER><STRONG>Free</STRONG></TD>\n" \
-                                                        "<TD ALIGN=CENTER><STRONG>Total</STRONG></TD>\n" \
-                                                        "</TR>\n" );
-                                }
-                                else
-                                {
-                                        narrow_margin = "       ";
-#           printf ("%-*s", LEFT_COLUMN + 2, "Mount point");
-                                                if (NARROW_MODE)
-                                                        printf ("\n%s", narrow_margin);
-                                                else
-                                                        printf ("%-*s", LEFT_COLUMN + 2, "");
-                                        print "                                                    Used     Free       Total ";
-                                        if (! NARROW_MODE)
-                                                print " ";
-                                }
-                        }
-
-END     {
-       if (WEB_OUTPUT)
-       {
-               printf ("</TABLE>\n");
-
-               printf ("<!-- FIN CONTENU -->\n");
-       }
-       else
-       {
-               if (NARROW_MODE)
-                       printf ("%s", narrow_margin);
-               else
-                       printf ("%-*s", LEFT_COLUMN + 2, "");
-               print "|----|----|----|----|----|----|----|----|----|----|"
-                       if (NARROW_MODE)
-                               printf ("\n%s", narrow_margin);
-                       else
-                               printf ("%-*s", LEFT_COLUMN + 2, "");
-               print "0   10   20   30   40   50   60   70   80   90  100";
-               print "";
-       }
-}
-
-$0 ~ PATTERN    {
-
-       if (index ($0, "members") == 0 && index ($0, "Download") == 0 && index ($0, "admin") == 0)
-       {
-#       df -k shows k_bytes!
-
-               total_size = $2 * k_bytes;
-               free_size = $4 * k_bytes;
-               percentage_occupied = substr($5, 0, 3);
-               mount_point = $6;
-
-               percentage_free = int (100 - percentage_occupied);
-
-#       reduction_factor: 2
-               stars_number = int (percentage_occupied / 2);
-
-               if (WEB_OUTPUT)
-               {
-                       posGroup = index (mount_point, "scratch");
-                       if (posGroup == 0)
-                               posGroup = index (mount_point, "u1");
-                       if (posGroup == 0)
-                               posGroup = index (mount_point, "u2");
-                       if (posGroup == 0)
-                               posGroup = index (mount_point, "u4");
-                       if (posGroup == 0)
-                               posGroup = index (mount_point, "u5");
-
-                       printf ("<TR>\n");
-
-                       if (posGroup > 0 || percentage_free < free_threshold)
-                       {
-                               if (percentage_free < free_threshold)
-                               {
-                                       class = "titlered";
-                                       if (posGroup == 0)
-                                               posGroup = 1;   # to display the whole mount_point in this color anyway
-                               }
-                               else if ((index (mount_point, "scratch") != 0) || (index (mount_point, "u1") != 0) || (index (mount_point, "u2") != 0))
-                               {
-                                       class = "titleorange";
-                                       posGroup = 1;   # to display the whole mount_point in this color
-                               }
-                               else if ((index (mount_point, "u4") != 0) || (index (mount_point, "u5") != 0))
-                               {
-                                       class = "titlebrown";
-                                       posGroup = 1;   # to display the whole mount_point in this color
-                               }
-
-                               printf ( \
-                                               "<TD ALIGN=LEFT>%s<SPAN CLASS=\"%s\">%s</SPAN></TD>\n",
-                                               substr (mount_point, 1, posGroup - 1),
-                                               class,
-                                               substr (mount_point, posGroup) );
-                       }
-                       else
-                       {
-                               printf ("<TD ALIGN=LEFT>%s</TD>\n", mount_point);
-                       }
-
-                       printf ( \
-                                       "<TD ALIGN=CENTER><SPAN CLASS=\"titleblue\">%s</SPAN><SPAN CLASS=\"titlegreen\">%s</SPAN></TD>\n",
-                                       substr (all_stars, 1, stars_number), substr (all_stars, stars_number + 1, 49) );
-
-                       if (percentage_free < free_threshold)
-                       {
-                               color_beginning = "<SPAN CLASS=\"titlered\">";
-                               color_end = "</SPAN>"
-                       }
-                       else
-                       {
-                               color_beginning = "";
-                               color_end = ""
-                       }
-
-                       if (total_size > 1 * t_bytes)
-                               printf ( \
-                                               "<TD ALIGN=RIGHT>%s%3d%%%s</TD><TD ALIGN=RIGHT>%5.1f Tb</TD><TD ALIGN=RIGHT>%5.1f Tb</TD>\n", \
-                                               color_beginning, percentage_occupied, color_end, free_size / t_bytes, total_size / t_bytes \
-                                               );
-                       else if (total_size > 1 * g_bytes)
-                               printf ( \
-                                               "<TD ALIGN=RIGHT>%s%3d%%%s</TD><TD ALIGN=RIGHT>%5.1f Gb</TD><TD ALIGN=RIGHT>%5.1f Gb</TD>\n", \
-                                               color_beginning, percentage_occupied, color_end, free_size / g_bytes, total_size / g_bytes \
-                                               );
-                       else if (total_size > 1 * m_byptes)
-                               printf ( \
-                                               "<TD ALIGN=RIGHT>%s%3d%%%s</TD><TD ALIGN=RIGHT>%5.1f Mb</TD><TD ALIGN=RIGHT>%5.1f Mb</TD>\n", \
-                                               color_beginning, percentage_occupied, color_end, free_size / m_bytes, total_size / m_bytes \
-                                               );
-                       else
-                               printf ( \
-                                               "<TD ALIGN=RIGHT>%s%3d%%%s</TD><TD ALIGN=RIGHT>%5.1f Kb</TD><TD ALIGN=RIGHT>%5.1f Kb</TD>\n", \
-                                               color_beginning, percentage_occupied, color_end, free_size / k_bytes, total_size / k_bytes \
-                                               );
-
-                       printf ("</TR>\n");
-               }
-
-               else
-               {
-#           printf ("percentage_occupied = %d\n", percentage_occupied);
-#           printf ("percentage_free = %d\n", percentage_free);
-
-                       printf ("%-*s", LEFT_COLUMN + 2, mount_point);
-                       if (NARROW_MODE)
-                               printf ("\n%s", narrow_margin);
-
-#           printf ("stars_number = %d\n", stars_number);
-
-                       printf ("|");
-                       for (i = 1; i <= stars_number && i <= 49; i++)
-                       {
-                               printf ("%s", "*");
-                       }
-                       for (i = stars_number + 1; i <= 49; i++)
-                       {
-                               printf ("%s", "-");
-                       }
-
-
-                       if (total_size > 1 * t_bytes)
-                               printf ( \
-                                               "| %3d%%   %6.1f   %6.1f Tb\n", \
-                                               percentage_occupied, free_size / t_bytes, total_size / t_bytes \
-                                               );
-                       else if (total_size > 1 * g_bytes)
-                               printf ( \
-                                               "| %3d%%   %6.1f   %6.1f Gb\n", \
-                                               percentage_occupied, free_size / g_bytes, total_size / g_bytes \
-                                               );
-                       else if (total_size > 1 * m_byptes)
-                               printf ( \
-                                               "| %3d%%   %6.1f   %6.1f Mb\n", \
-                                               percentage_occupied, free_size / m_bytes, total_size / m_bytes \
-                                               );
-                       else
-                               printf ( \
-                                               "| %3d%%   %6.1f   %6.1f Kb\n", \
-                                               percentage_occupied, free_size / k_bytes, total_size / k_bytes \
-                                               );
-               }
-       }   # if
-}'
index 1fc5805be81c0d1a2293e4f98d32c3b03cf54b7a..55bfa26a557d7676331b7472a304bae0204372e2 100644 (file)
@@ -1,15 +1,14 @@
-
 --[[
-                                                   
-     Lain                                          
-     Layouts, widgets and utilities for Awesome WM 
-                                                   
-     Utilities section                             
-                                                   
-     Licensed under GNU General Public License v2  
-      * (c) 2013,      Luke Bonham                 
-      * (c) 2010-2012, Peter Hofmann               
-                                                   
+
+     Lain
+     Layouts, widgets and utilities for Awesome WM
+
+     Utilities section
+
+     Licensed under GNU General Public License v2
+      * (c) 2013,      Luca CPZ
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
 local awful        = require("awful")
@@ -77,7 +76,7 @@ function util.magnify_client(c, width_f, height_f)
     end
 end
 
--- https://github.com/copycat-killer/lain/issues/195
+-- https://github.com/lcpz/lain/issues/195
 function util.mc(c, width_f, height_f)
     c = c or util.magnified_client
     if not c then return end
@@ -117,7 +116,7 @@ function util.add_tag(layout)
         textbox      = awful.screen.focused().mypromptbox.widget,
         exe_callback = function(name)
             if not name or #name == 0 then return end
-            awful.tag.add(name, { screen = awful.screen.focused(), layout = layout or awful.layout.layouts[0] }):view_only()
+            awful.tag.add(name, { screen = awful.screen.focused(), layout = layout or awful.layout.suit.tile }):view_only()
         end
     }
 end
@@ -159,9 +158,10 @@ end
 -- }}}
 
 -- On the fly useless gaps change
-function util.useless_gaps_resize(thatmuch)
-    local scr = awful.screen.focused()
-    scr.selected_tag.gap = scr.selected_tag.gap + tonumber(thatmuch)
+function util.useless_gaps_resize(thatmuch, s, t)
+    local scr = s or awful.screen.focused()
+    local tag = t or scr.selected_tag
+    tag.gap = tag.gap + tonumber(thatmuch)
     awful.layout.arrange(scr)
 end
 
index 0d3b17a1b1da7b8655a3ceda569871c34e7e8e5e..63f94864da231fed330a7f6cdb268df1076f205c 100644 (file)
@@ -1,62 +1,61 @@
-
 --[[
-                                 
-     Licensed under MIT License  
-      * (c) 2013, Luke Bonham    
-      * (c) 2009, Uli Schlachter 
-      * (c) 2009, Majic          
-                                 
+
+     Licensed under MIT License
+      * (c) 2013, Luca CPZ
+      * (c) 2009, Uli Schlachter
+      * (c) 2009, Majic
+
 --]]
 
-local string       = { format = string.format }
+local format = string.format
 local setmetatable = setmetatable
 
 -- Lain markup util submodule
 -- lain.util.markup
 local markup = { fg = {}, bg = {} }
 
--- Convenience tags.
-function markup.bold(text)      return '<b>'     .. text .. '</b>'     end
-function markup.italic(text)    return '<i>'     .. text .. '</i>'     end
-function markup.strike(text)    return '<s>'     .. text .. '</s>'     end
-function markup.underline(text) return '<u>'     .. text .. '</u>'     end
-function markup.monospace(text) return '<tt>'    .. text .. '</tt>'    end
-function markup.big(text)       return '<big>'   .. text .. '</big>'   end
-function markup.small(text)     return '<small>' .. text .. '</small>' end
+-- Convenience tags
+function markup.bold(text)      return format("<b>%s</b>",         text) end
+function markup.italic(text)    return format("<i>%s</i>",         text) end
+function markup.strike(text)    return format("<s>%s</s>",         text) end
+function markup.underline(text) return format("<u>%s</u>",         text) end
+function markup.monospace(text) return format("<tt>%s</tt>",       text) end
+function markup.big(text)       return format("<big>%s</big>",     text) end
+function markup.small(text)     return format("<small>%s</small>", text) end
 
--- Set the font.
+-- Set the font
 function markup.font(font, text)
-  return '<span font="'  .. font  .. '">' .. text ..'</span>'
+    return format("<span font='%s'>%s</span>", font, text)
 end
 
--- Set the foreground.
+-- Set the foreground
 function markup.fg.color(color, text)
-  return '<span foreground="' .. color .. '">' .. text .. '</span>'
+    return format("<span foreground='%s'>%s</span>", color, text)
 end
 
--- Set the background.
+-- Set the background
 function markup.bg.color(color, text)
-  return '<span background="' .. color .. '">' .. text .. '</span>'
+    return format("<span background='%s'>%s</span>", color, text)
 end
 
--- Set foreground and background.
+-- Set foreground and background
 function markup.color(fg, bg, text)
-  return string.format('<span foreground="%s" background="%s">%s</span>', fg, bg, text)
+    return format("<span foreground='%s' background='%s'>%s</span>", fg, bg, text)
 end
 
--- Set font and foreground.
+-- Set font and foreground
 function markup.fontfg(font, fg, text)
-  return string.format('<span font="%s" foreground="%s">%s</span>', font, fg, text)
+    return format("<span font='%s' foreground='%s'>%s</span>", font, fg, text)
 end
 
--- Set font and background.
+-- Set font and background
 function markup.fontbg(font, bg, text)
-  return string.format('<span font="%s" background="%s">%s</span>', font, bg, text)
+    return format("<span font='%s' background='%s'>%s</span>", font, bg, text)
 end
 
--- Set font, foreground and background.
+-- Set font, foreground and background
 function markup.fontcolor(font, fg, bg, text)
-  return string.format('<span font="%s" foreground="%s" background="%s">%s</span>', font, fg, bg, text)
+    return format("<span font='%s' foreground='%s' background='%s'>%s</span>", font, fg, bg, text)
 end
 
 -- link markup.{fg,bg}(...) calls to markup.{fg,bg}.color(...)
diff --git a/.config/awesome/lain/util/menu_iterator.lua b/.config/awesome/lain/util/menu_iterator.lua
new file mode 100644 (file)
index 0000000..9959b25
--- /dev/null
@@ -0,0 +1,145 @@
+--[[
+
+     Licensed under GNU General Public License v2
+      * (c) 2017, Simon Désaulniers <sim.desaulniers@gmail.com>
+      * (c) 2017, Uli Schlachter
+      * (c) 2017, Jeferson Siqueira <jefersonlsiq@gmail.com>
+
+--]]
+
+-- Menu iterator with Naughty notifications
+-- lain.util.menu_iterator
+
+local naughty = require("naughty")
+local helpers = require("lain.helpers")
+local util    = require("lain.util")
+local atable  = require("awful.util").table
+local assert  = assert
+local pairs   = pairs
+local tconcat = table.concat
+local unpack = unpack or table.unpack -- lua 5.1 retro-compatibility
+
+local state = { cid = nil }
+
+local function naughty_destroy_callback(reason)
+    local closed = naughty.notificationClosedReason
+    if reason == closed.expired or reason == closed.dismissedByUser then
+        local actions = state.index and state.menu[state.index - 1][2]
+        if actions then
+            for _,action in pairs(actions) do
+                -- don't try to call nil callbacks
+                if action then action() end
+            end
+            state.index = nil
+        end
+    end
+end
+
+-- Iterates over a menu.
+-- After the timeout, callbacks associated to the last visited choice are
+-- executed. Inputs:
+-- * menu:    a list of {label, {callbacks}} pairs
+-- * timeout: time to wait before confirming the menu selection
+-- * icon:    icon to display in the notification of the chosen label
+local function iterate(menu, timeout, icon)
+    local timeout = timeout or 4 -- default timeout for each menu entry
+    local icon    = icon or nil  -- icon to display on the menu
+
+    -- Build the list of choices
+    if not state.index then
+        state.menu = menu
+        state.index = 1
+    end
+
+    -- Select one and display the appropriate notification
+    local label
+    local next = state.menu[state.index]
+    state.index = state.index + 1
+
+    if not next then
+        label = "Cancel"
+        state.index = nil
+    else
+        label, _ = unpack(next)
+    end
+
+    state.cid = naughty.notify({
+        text        = label,
+        icon        = icon,
+        timeout     = timeout,
+        screen      = mouse.screen,
+        replaces_id = state.cid,
+        destroy     = naughty_destroy_callback
+    }).id
+end
+
+-- Generates a menu compatible with the first argument of `iterate` function and
+-- suitable for the following cases:
+-- * all possible choices individually (partition of singletons);
+-- * all possible subsets of the set of choices (powerset).
+--
+-- Inputs:
+-- * args: an array containing the following members:
+--   * choices:       Array of choices (string) on which the menu will be
+--                    generated.
+--   * name:          Displayed name of the menu (in the form "name: choices").
+--   * selected_cb:   Callback to execute for each selected choice. Takes
+--                    the choice as a string argument. Can be `nil` (no action
+--                    to execute).
+--   * rejected_cb:   Callback to execute for each rejected choice (possible
+--                    choices which are not selected). Takes the choice as a
+--                    string argument. Can be `nil` (no action to execute).
+--   * extra_choices: An array of extra { choice_str, callback_fun } pairs to be
+--                    added to the menu. Each callback_fun can be `nil`.
+--   * combination:   The combination of choices to generate. Possible values:
+--                    "powerset" and "single" (default).
+-- Output:
+-- * m: menu to be iterated over.
+local function menu(args)
+    local choices       = assert(args.choices or args[1])
+    local name          = assert(args.name or args[2])
+    local selected_cb   = args.selected_cb
+    local rejected_cb   = args.rejected_cb
+    local extra_choices = args.extra_choices or {}
+
+    local ch_combinations = args.combination == "powerset" and helpers.powerset(choices) or helpers.trivial_partition_set(choices)
+
+    for _,c in pairs(extra_choices) do
+        ch_combinations = atable.join(ch_combinations, {{c[1]}})
+    end
+
+    local m = {} -- the menu
+
+    for _,c in pairs(ch_combinations) do
+        if #c > 0 then
+            local cbs = {}
+
+            -- selected choices
+            for _,ch in pairs(c) do
+                if atable.hasitem(choices, ch) then
+                    cbs[#cbs + 1] = selected_cb and function() selected_cb(ch) end or nil
+                end
+            end
+
+            -- rejected choices
+            for _,ch in pairs(choices) do
+                if not atable.hasitem(c, ch) and atable.hasitem(choices, ch) then
+                    cbs[#cbs + 1] = rejected_cb and function() rejected_cb(ch) end or nil
+                end
+            end
+
+            -- add user extra choices (like the choice "None" for example)
+            for _,x in pairs(extra_choices) do
+                if x[1] == c[1] then
+                    cbs[#cbs + 1] = x[2]
+                end
+            end
+
+            m[#m + 1] = { name .. ": " .. tconcat(c, " + "), cbs }
+        end
+    end
+
+    return m
+end
+
+return { iterate = iterate, menu = menu }
index 4c428039df23ec9c6d41732280219c5ec1b6fa7d..01891b037aba4ea34ab4d48b7aba365b8aa48568 100644 (file)
@@ -1,21 +1,17 @@
-
 --[[
-                                                   
-     Licensed under GNU General Public License v2  
-      * (c) 2016, Luke Bonham                      
-      * (c) 2015, unknown                          
-                                                   
+
+     Licensed under GNU General Public License v2
+      * (c) 2016, Luca CPZ
+      * (c) 2015, unknown
+
 --]]
 
 local awful        = require("awful")
 local capi         = { client = client }
-
-local math         = { floor  = math.floor }
-local string       = { format = string.format }
-
+local math         = math
+local string       = string
 local pairs        = pairs
 local screen       = screen
-
 local setmetatable = setmetatable
 
 -- Quake-like Dropdown application spawn
@@ -34,7 +30,7 @@ function quake:display()
     for c in awful.client.iterate(function (c)
         -- c.name may be changed!
         return c.instance == self.name
-    end, nil, self.screen)
+    end)
     do
         i = i + 1
         if i == 1 then
@@ -64,7 +60,7 @@ function quake:display()
     client.floating = true
     client.border_width = self.border
     client.size_hints_honor = false
-    client:geometry(self:compute_size())
+    client:geometry(self.geometry[self.screen.index] or self:compute_size())
 
     -- Set not sticky and on top
     client.sticky = false
@@ -96,12 +92,12 @@ end
 
 function quake:compute_size()
     -- skip if we already have a geometry for this screen
-    if not self.geometry[self.screen] then
+    if not self.geometry[self.screen.index] then
         local geom
         if not self.overlap then
-            geom = screen[self.screen].workarea
+            geom = screen[self.screen.index].workarea
         else
-            geom = screen[self.screen].geometry
+            geom = screen[self.screen.index].geometry
         end
         local width, height = self.width, self.height
         if width  <= 1 then width = math.floor(geom.width * width) - 2 * self.border end
@@ -113,9 +109,9 @@ function quake:compute_size()
         if     self.vert == "top"    then y = geom.y
         elseif self.vert == "bottom" then y = geom.height + geom.y - height
         else   y = geom.y + (geom.height - height)/2 end
-        self.geometry[self.screen] = { x = x, y = y, width = width, height = height }
+        self.geometry[self.screen.index] = { x = x, y = y, width = width, height = height }
     end
-    return self.geometry[self.screen]
+    return self.geometry[self.screen.index]
 end
 
 function quake:new(config)
@@ -159,7 +155,10 @@ function quake:toggle()
      if self.followtag then self.screen = awful.screen.focused() end
      local current_tag = self.screen.selected_tag
      if current_tag and self.last_tag ~= current_tag and self.visible then
-         self:display():move_to_tag(current_tag)
+         local c=self:display()
+         if c then
+            c:move_to_tag(current_tag)
+        end
      else
          self.visible = not self.visible
          self:display()
index abf57c4b9c0e75892127147dc2df135e5e7761f7..465132d56193d6de9d7098c6ec66f8a948b2c040 100644 (file)
@@ -1,14 +1,13 @@
-
 --[[
-                                                   
-     Licensed under GNU General Public License v2  
-      * (c) 2015, Luke Bonham                      
-      * (c) 2015, plotnikovanton                   
-                                                   
+
+     Licensed under GNU General Public License v2
+      * (c) 2015, Luca CPZ
+      * (c) 2015, plotnikovanton
+
 --]]
 
-local wibox     = require("wibox")
-local gears     = require("gears")
+local wibox = require("wibox")
+local gears = require("gears")
 
 -- Lain Cairo separators util submodule
 -- lain.util.separators
@@ -19,14 +18,22 @@ local separators = { height = 0, width = 9 }
 -- Right
 function separators.arrow_right(col1, col2)
     local widget = wibox.widget.base.make_widget()
+    widget.col1 = col1
+    widget.col2 = col2
 
     widget.fit = function(m, w, h)
         return separators.width, separators.height
     end
 
+    widget.update = function(col1, col2)
+        widget.col1 = col1
+        widget.col2 = col2
+        widget:emit_signal("widget::redraw_needed")
+    end
+
     widget.draw = function(mycross, wibox, cr, width, height)
-        if col2 ~= "alpha" then
-            cr:set_source_rgb(gears.color.parse_color(col2))
+        if widget.col2 ~= "alpha" then
+            cr:set_source_rgb(gears.color.parse_color(widget.col2))
             cr:new_path()
             cr:move_to(0, 0)
             cr:line_to(width, height/2)
@@ -42,8 +49,8 @@ function separators.arrow_right(col1, col2)
             cr:fill()
         end
 
-        if col1 ~= "alpha" then
-            cr:set_source_rgb(gears.color.parse_color(col1))
+        if widget.col1 ~= "alpha" then
+            cr:set_source_rgb(gears.color.parse_color(widget.col1))
             cr:new_path()
             cr:move_to(0, 0)
             cr:line_to(width, height/2)
@@ -59,14 +66,22 @@ end
 -- Left
 function separators.arrow_left(col1, col2)
     local widget = wibox.widget.base.make_widget()
+    widget.col1 = col1
+    widget.col2 = col2
 
     widget.fit = function(m, w, h)
         return separators.width, separators.height
     end
 
+    widget.update = function(col1, col2)
+        widget.col1 = col1
+        widget.col2 = col2
+        widget:emit_signal("widget::redraw_needed")
+    end
+
     widget.draw = function(mycross, wibox, cr, width, height)
-        if col1 ~= "alpha" then
-            cr:set_source_rgb(gears.color.parse_color(col1))
+        if widget.col1 ~= "alpha" then
+            cr:set_source_rgb(gears.color.parse_color(widget.col1))
             cr:new_path()
             cr:move_to(width, 0)
             cr:line_to(0, height/2)
@@ -82,14 +97,14 @@ function separators.arrow_left(col1, col2)
             cr:fill()
         end
 
-        if col2 ~= "alpha" then
+        if widget.col2 ~= "alpha" then
             cr:new_path()
             cr:move_to(width, 0)
             cr:line_to(0, height/2)
             cr:line_to(width, height)
             cr:close_path()
 
-            cr:set_source_rgb(gears.color.parse_color(col2))
+            cr:set_source_rgb(gears.color.parse_color(widget.col2))
             cr:fill()
         end
    end
index 36ccc719b3b38ac18d02b546b084bf39baf677f8..3b6c6d6d2e87ce69234e02a571e6c4bd9193a833 100644 (file)
@@ -1,17 +1,15 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Luke Bonham                     
-      * (c) 2010, Adrian C. <anrxc@sysphere.org>  
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013, Luca CPZ
+      * (c) 2010, Adrian C. <anrxc@sysphere.org>
+
 --]]
 
 local helpers = require("lain.helpers")
 local shell   = require("awful.util").shell
 local wibox   = require("wibox")
-local string  = { match  = string.match,
-                  format = string.format }
+local string  = string
 
 -- ALSA volume
 -- lain.widget.alsa
index 2ad021048a82880e6e79717ce38f2384ff05aab4..b2f7b44ec6e84987d5d7216136abb5522254ada7 100644 (file)
@@ -1,21 +1,19 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Luke Bonham                     
-      * (c) 2013, Rman                            
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013, Luca CPZ
+      * (c) 2013, Rman
+
 --]]
 
-local helpers        = require("lain.helpers")
-local awful          = require("awful")
-local naughty        = require("naughty")
-local wibox          = require("wibox")
-local math           = { modf   = math.modf }
-local string         = { format = string.format,
-                         match  = string.match,
-                         rep    = string.rep }
-local type, tonumber = type, tonumber
+local helpers  = require("lain.helpers")
+local awful    = require("awful")
+local naughty  = require("naughty")
+local wibox    = require("wibox")
+local math     = math
+local string   = string
+local type     = type
+local tonumber = tonumber
 
 -- ALSA volume bar
 -- lain.widget.alsabar
@@ -29,7 +27,7 @@ local function factory(args)
         },
 
         _current_level = 0,
-        _muted         = false
+        _playback      = "off"
     }
 
     local args       = args or {}
@@ -37,8 +35,14 @@ local function factory(args)
     local settings   = args.settings or function() end
     local width      = args.width or 63
     local height     = args.height or 1
+    local margins    = args.margins or 1
+    local paddings   = args.paddings or 1
     local ticks      = args.ticks or false
     local ticks_size = args.ticks_size or 7
+    local tick       = args.tick or "|"
+    local tick_pre   = args.tick_pre or "["
+    local tick_post  = args.tick_post or "]"
+    local tick_none  = args.tick_none or " "
 
     alsabar.cmd                 = args.cmd or "amixer"
     alsabar.channel             = args.channel or "Master"
@@ -48,8 +52,7 @@ local function factory(args)
     alsabar.notification_preset = args.notification_preset
 
     if not alsabar.notification_preset then
-        alsabar.notification_preset      = {}
-        alsabar.notification_preset.font = "Monospace 10"
+        alsabar.notification_preset = { font = "Monospace 10" }
     end
 
     local format_cmd = string.format("%s get %s", alsabar.cmd, alsabar.channel)
@@ -60,12 +63,12 @@ local function factory(args)
     end
 
     alsabar.bar = wibox.widget {
-        forced_height    = height,
-        forced_width     = width,
         color            = alsabar.colors.unmute,
         background_color = alsabar.colors.background,
-        margins          = 1,
-        paddings         = 1,
+        forced_height    = height,
+        forced_width     = width,
+        margins          = margins,
+        paddings         = margins,
         ticks            = ticks,
         ticks_size       = ticks_size,
         widget           = wibox.widget.progressbar
@@ -75,23 +78,27 @@ local function factory(args)
 
     function alsabar.update(callback)
         helpers.async(format_cmd, function(mixer)
-            local volu,mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
-            if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted) then
-                alsabar._current_level = tonumber(volu) or alsabar._current_level
+            local vol, playback = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
+
+            if not vol or not playback then return end
+
+            if vol ~= alsabar._current_level or playback ~= alsabar._playback then
+                alsabar._current_level = tonumber(vol)
                 alsabar.bar:set_value(alsabar._current_level / 100)
-                if (not mute and tonumber(volu) == 0) or mute == "off" then
-                    alsabar._muted = true
-                    alsabar.tooltip:set_text ("[Muted]")
+                if alsabar._current_level == 0 or playback == "off" then
+                    alsabar._playback = playback
+                    alsabar.tooltip:set_text("[Muted]")
                     alsabar.bar.color = alsabar.colors.mute
                 else
-                    alsabar._muted = false
-                    alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, volu))
+                    alsabar._playback = "on"
+                    alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, vol))
                     alsabar.bar.color = alsabar.colors.unmute
                 end
 
-                volume_now = {}
-                volume_now.level = tonumber(volu)
-                volume_now.status = mute
+                volume_now = {
+                    level  = alsabar._current_level,
+                    status = alsabar._playback
+                }
 
                 settings()
 
@@ -104,15 +111,39 @@ local function factory(args)
         alsabar.update(function()
             local preset = alsabar.notification_preset
 
-            if alsabar._muted then
-                preset.title = string.format("%s - Muted", alsabar.channel)
-            else
-                preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
+            preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
+
+            if alsabar._playback == "off" then
+                preset.title = preset.title .. " Muted"
+            end
+
+            -- tot is the maximum number of ticks to display in the notification
+            local tot = alsabar.notification_preset.max_ticks
+
+            if not tot then
+                local wib = awful.screen.focused().mywibox
+                -- if we can grab mywibox, tot is defined as its height if
+                -- horizontal, or width otherwise
+                if wib then
+                    if wib.position == "left" or wib.position == "right" then
+                        tot = wib.width
+                    else
+                        tot = wib.height
+                    end
+                -- fallback: default horizontal wibox height
+                else
+                    tot = 20
+                end
             end
 
-            int = math.modf((alsabar._current_level / 100) * awful.screen.focused().mywibox.height)
-            preset.text = string.format("[%s%s]", string.rep("|", int),
-                          string.rep(" ", awful.screen.focused().mywibox.height - int))
+            int = math.modf((alsabar._current_level / 100) * tot)
+            preset.text = string.format(
+                "%s%s%s%s",
+                tick_pre,
+                string.rep(tick, int),
+                string.rep(tick_none, tot - int),
+                tick_post
+            )
 
             if alsabar.followtag then preset.screen = awful.screen.focused() end
 
index e901842f27fc0492d5fe75952b217d895177d91e..3cb801c8ef93eeda994dedcfe960171979e513dc 100644 (file)
@@ -1,36 +1,53 @@
-
 --[[
-                                                                                                                       
-        Licensed under GNU General Public License v2 
-         * (c) 2013,      Luke Bonham                
-         * (c) 2010-2012, Peter Hofmann              
-                                                                                                                       
+
+        Licensed under GNU General Public License v2
+         * (c) 2013,      Luca CPZ
+         * (c) 2010-2012, Peter Hofmann
+
 --]]
 
-local first_line = require("lain.helpers").first_line
-local newtimer   = require("lain.helpers").newtimer
-local naughty    = require("naughty")
-local wibox      = require("wibox")
-local math       = { abs    = math.abs,
-                     floor  = math.floor,
-                     log10  = math.log10,
-                     min    = math.min }
-local string     = { format = string.format }
-local ipairs     = ipairs
-local tonumber   = tonumber
+local helpers  = require("lain.helpers")
+local fs       = require("gears.filesystem")
+local naughty  = require("naughty")
+local wibox    = require("wibox")
+local math     = math
+local string   = string
+local ipairs   = ipairs
+local tonumber = tonumber
 
 -- Battery infos
 -- lain.widget.bat
 
 local function factory(args)
-    local bat       = { widget = wibox.widget.textbox() }
-    local args      = args or {}
-    local timeout   = args.timeout or 30
-    local batteries = args.batteries or (args.battery and {args.battery}) or {"BAT0"}
-    local ac        = args.ac or "AC0"
-    local notify    = args.notify or "on"
-    local n_perc    = args.n_perc or { 5, 15 }
-    local settings  = args.settings or function() end
+    local pspath = args.pspath or "/sys/class/power_supply/"
+
+    if not fs.is_dir(pspath) then
+        naughty.notify { text = "lain.widget.bat: invalid power supply path", timeout = 0 }
+        return
+    end
+
+    local bat         = { widget = wibox.widget.textbox() }
+    local args        = args or {}
+    local timeout     = args.timeout or 30
+    local notify      = args.notify or "on"
+    local full_notify = args.full_notify or notify
+    local n_perc      = args.n_perc or { 5, 15 }
+    local batteries   = args.batteries or (args.battery and {args.battery}) or {}
+    local ac          = args.ac or "AC0"
+    local settings    = args.settings or function() end
+
+    function bat.get_batteries()
+        helpers.line_callback("ls -1 " .. pspath, function(line)
+            local bstr =  string.match(line, "BAT%w+")
+            if bstr then
+                batteries[#batteries + 1] = bstr
+            else
+                ac = string.match(line, "A%w+") or "AC0"
+            end
+        end)
+    end
+
+    if #batteries == 0 then bat.get_batteries() end
 
     bat_notification_critical_preset = {
         title   = "Battery exhausted",
@@ -48,6 +65,14 @@ local function factory(args)
         bg      = "#CDCDCD"
     }
 
+    bat_notification_charged_preset = {
+        title   = "Battery full",
+        text    = "You can unplug the cable",
+        timeout = 15,
+        fg      = "#202020",
+        bg      = "#CDCDCD"
+    }
+
     bat_now = {
         status    = "N/A",
         ac_status = "N/A",
@@ -63,6 +88,9 @@ local function factory(args)
         bat_now.n_perc[i] = 0
     end
 
+    -- used to notify full charge only once before discharging
+    local fullnotification = false
+
     function bat.update()
         local sum_rate_current = 0
         local sum_rate_voltage = 0
@@ -70,30 +98,29 @@ local function factory(args)
         local sum_rate_energy  = 0
         local sum_energy_now   = 0
         local sum_energy_full  = 0
-        local pspath           = "/sys/class/power_supply/"
 
         for i, battery in ipairs(batteries) do
             local bstr    = pspath .. battery
-            local present = first_line(bstr .. "/present")
+            local present = helpers.first_line(bstr .. "/present")
 
             if tonumber(present) == 1 then
                 -- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW]
-                local rate_current = tonumber(first_line(bstr .. "/current_now"))
-                local rate_voltage = tonumber(first_line(bstr .. "/voltage_now"))
-                local rate_power   = tonumber(first_line(bstr .. "/power_now"))
+                local rate_current = tonumber(helpers.first_line(bstr .. "/current_now"))
+                local rate_voltage = tonumber(helpers.first_line(bstr .. "/voltage_now"))
+                local rate_power   = tonumber(helpers.first_line(bstr .. "/power_now"))
 
                 -- energy_now(P)[uWh], charge_now(I)[uAh]
-                local energy_now        = tonumber(first_line(bstr .. "/energy_now") or
-                                          first_line(bstr .. "/charge_now"))
+                local energy_now = tonumber(helpers.first_line(bstr .. "/energy_now") or
+                                   helpers.first_line(bstr .. "/charge_now"))
 
                 -- energy_full(P)[uWh], charge_full(I)[uAh]
-                local energy_full       = tonumber(first_line(bstr .. "/energy_full") or
-                                          first_line(bstr .. "/charge_full"))
+                local energy_full = tonumber(helpers.first_line(bstr .. "/energy_full") or
+                                    helpers.first_line(bstr .. "/charge_full"))
 
-                local energy_percentage = tonumber(first_line(bstr .. "/capacity")) or
+                local energy_percentage = tonumber(helpers.first_line(bstr .. "/capacity")) or
                                           math.floor((energy_now / energy_full) * 100)
 
-                bat_now.n_status[i] = first_line(bstr .. "/status") or "N/A"
+                bat_now.n_status[i] = helpers.first_line(bstr .. "/status") or "N/A"
                 bat_now.n_perc[i]   = energy_percentage or bat_now.n_perc[i]
 
                 sum_rate_current = sum_rate_current + (rate_current or 0)
@@ -115,7 +142,7 @@ local function factory(args)
                 bat_now.status = status
             end
         end
-        bat_now.ac_status = tonumber(first_line(string.format("%s%s/online", pspath, ac))) or "N/A"
+        bat_now.ac_status = tonumber(helpers.first_line(string.format("%s%s/online", pspath, ac))) or "N/A"
 
         if bat_now.status ~= "N/A" then
             if bat_now.status ~= "Full" and sum_rate_power == 0 and bat_now.ac_status == 1 then
@@ -157,23 +184,32 @@ local function factory(args)
         widget = bat.widget
         settings()
 
-        -- notifications for critical and low levels
-        if notify == "on" and bat_now.status == "Discharging" then
-            if tonumber(bat_now.perc) <= n_perc[1] then
-                bat.id = naughty.notify({
-                    preset = bat_notification_critical_preset,
-                    replaces_id = bat.id
-                }).id
-            elseif tonumber(bat_now.perc) <= n_perc[2] then
+        -- notifications for critical, low, and full levels
+        if notify == "on" then
+            if bat_now.status == "Discharging" then
+                if tonumber(bat_now.perc) <= n_perc[1] then
+                    bat.id = naughty.notify({
+                        preset = bat_notification_critical_preset,
+                        replaces_id = bat.id
+                    }).id
+                elseif tonumber(bat_now.perc) <= n_perc[2] then
+                    bat.id = naughty.notify({
+                        preset = bat_notification_low_preset,
+                        replaces_id = bat.id
+                    }).id
+                end
+                fullnotification = false
+            elseif bat_now.status == "Full" and full_notify == "on" and not fullnotification then
                 bat.id = naughty.notify({
-                    preset = bat_notification_low_preset,
+                    preset = bat_notification_charged_preset,
                     replaces_id = bat.id
                 }).id
+                fullnotification = true
             end
         end
     end
 
-    newtimer("batteries", timeout, bat.update)
+    helpers.newtimer("batteries", timeout, bat.update)
 
     return bat
 end
diff --git a/.config/awesome/lain/widget/cal.lua b/.config/awesome/lain/widget/cal.lua
new file mode 100644 (file)
index 0000000..928a7bd
--- /dev/null
@@ -0,0 +1,175 @@
+--[[
+
+     Licensed under GNU General Public License v2
+      * (c) 2018, Luca CPZ
+
+--]]
+
+local helpers  = require("lain.helpers")
+local markup   = require("lain.util.markup")
+local awful    = require("awful")
+local naughty  = require("naughty")
+local floor    = math.floor
+local os       = os
+local pairs    = pairs
+local string   = string
+local tconcat  = table.concat
+local type     = type
+local tonumber = tonumber
+local tostring = tostring
+
+-- Calendar notification
+-- lain.widget.cal
+
+local function factory(args)
+    args = args or {}
+    local cal = {
+        attach_to           = args.attach_to or {},
+        week_start          = args.week_start or 2,
+        three               = args.three or false,
+        followtag           = args.followtag or false,
+        week_number         = args.week_number or "none",
+        week_number_format  = args.week_number_format or args.week_number == "left" and "%3d | " or "| %-3d",
+        icons               = args.icons or helpers.icons_dir .. "cal/white/",
+        notification_preset = args.notification_preset or {
+            font = "Monospace 10", fg = "#FFFFFF", bg = "#000000"
+        }
+    }
+
+    function cal.get_week_number(m, st_day, x)
+        return string.format(cal.week_number_format, os.date("%V", m) + (x ~= 0 and floor((x + st_day) / 7) - 1 or 0))
+    end
+
+    function cal.sum_week_days(x, y)
+        return (x + y) % 7
+    end
+
+    function cal.build(month, year)
+        local current_month, current_year = tonumber(os.date("%m")), tonumber(os.date("%Y"))
+        local is_current_month = (not month or not year) or (month == current_month and year == current_year)
+        local today = is_current_month and tonumber(os.date("%d")) -- otherwise nil and not highlighted
+        local t = os.time { year = year or current_year, month = month and month+1 or current_month+1, day = 0 }
+        local d = os.date("*t", t)
+        local mth_days, st_day, this_month = d.day, (d.wday-d.day-cal.week_start+1)%7, os.date("%B %Y", t)
+        local notifytable = { [1] = string.format("%s%s\n", string.rep(" ", floor((28 - this_month:len())/2)), markup.bold(this_month)) }
+        for x = 0,6 do notifytable[#notifytable+1] = os.date("%a", os.time { year=2006, month=1, day=x+cal.week_start }):sub(1, 3) .. " " end
+        notifytable[#notifytable] = string.format("%s\n%s", notifytable[#notifytable]:sub(1, -2), string.rep(" ", st_day*4))
+        local strx
+        for x = 1,mth_days do
+            strx = x
+            if x == today then
+                if x < 10 then x = " " .. x end
+                strx = markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. " ")
+            end
+            strx = string.format("%s%s", string.rep(" ", 3 - tostring(x):len()), strx)
+            notifytable[#notifytable+1] = string.format("%-4s%s", strx, (x+st_day)%7==0 and x ~= mth_days and "\n" or "")
+        end
+        if string.len(cal.icons or "") > 0 and today then cal.icon = cal.icons .. today .. ".png" end
+        cal.month, cal.year = d.month, d.year
+
+        if cal.week_number ~= "none" then
+            local m = os.time { year = year or current_year, month = month and month or current_month, day = 0 }
+            local head_prepend = string.rep(" ", tostring(string.format(cal.week_number_format, 0)):len())
+
+            if cal.week_number == "left" then
+                notifytable[1] = head_prepend .. notifytable[1] -- month-year row
+                notifytable[2] = head_prepend .. notifytable[2] -- weekdays row
+                notifytable[8] = notifytable[8]:gsub("\n", "\n" .. cal.get_week_number(m, st_day, 0)) -- first week of the month
+
+                for x = 10,#notifytable do
+                    if cal.sum_week_days(st_day, x) == 2 then
+                        notifytable[x] = cal.get_week_number(m, st_day, x) .. notifytable[x]
+                    end
+                end
+            elseif cal.week_number == "right" then
+                notifytable[8] = notifytable[8]:gsub("\n", head_prepend .. "\n") -- weekdays row
+                for x = 9,#notifytable do
+                    if cal.sum_week_days(st_day, x) == 1 then
+                        notifytable[x] = notifytable[x]:gsub("\n", cal.get_week_number(m, st_day, x - 7) .. "\n")
+                    end
+                end
+                -- last week of the month
+                local end_days = cal.sum_week_days(st_day, mth_days)
+                if end_days ~= 0 then end_days = 7 - end_days end
+                notifytable[#notifytable] = notifytable[#notifytable] .. string.rep(" ", 4 * end_days) .. cal.get_week_number(m, st_day, mth_days + end_days)
+            end
+        end
+
+        return notifytable
+    end
+
+    function cal.getdate(month, year, offset)
+        if not month or not year then
+            month = tonumber(os.date("%m"))
+            year  = tonumber(os.date("%Y"))
+        end
+
+        month = month + offset
+
+        while month > 12 do
+            month = month - 12
+            year = year + 1
+        end
+
+        while month < 1 do
+            month = month + 12
+            year = year - 1
+        end
+
+        return month, year
+    end
+
+    function cal.hide()
+        if not cal.notification then return end
+        naughty.destroy(cal.notification)
+        cal.notification = nil
+    end
+
+    function cal.show(seconds, month, year, scr)
+        cal.notification_preset.text = tconcat(cal.build(month, year))
+
+        if cal.three then
+            local current_month, current_year = cal.month, cal.year
+            local prev_month, prev_year = cal.getdate(cal.month, cal.year, -1)
+            local next_month, next_year = cal.getdate(cal.month, cal.year,  1)
+            cal.notification_preset.text = string.format("%s\n\n%s\n\n%s",
+            tconcat(cal.build(prev_month, prev_year)), cal.notification_preset.text,
+            tconcat(cal.build(next_month, next_year)))
+            cal.month, cal.year = current_month, current_year
+        end
+
+        cal.hide()
+        cal.notification = naughty.notify {
+            preset  = cal.notification_preset,
+            screen  = cal.followtag and awful.screen.focused() or scr or 1,
+            icon    = cal.icon,
+            timeout = type(seconds) == "number" and seconds or cal.notification_preset.timeout or 5
+        }
+    end
+
+    function cal.hover_on() cal.show(0) end
+    function cal.move(offset)
+        local offset = offset or 0
+        cal.month, cal.year = cal.getdate(cal.month, cal.year, offset)
+        cal.show(0, cal.month, cal.year)
+    end
+    function cal.prev() cal.move(-1) end
+    function cal.next() cal.move( 1) end
+
+    function cal.attach(widget)
+        widget:connect_signal("mouse::enter", cal.hover_on)
+        widget:connect_signal("mouse::leave", cal.hide)
+        widget:buttons(awful.util.table.join(
+                    awful.button({}, 1, cal.prev),
+                    awful.button({}, 3, cal.next),
+                    awful.button({}, 2, cal.hover_on),
+                    awful.button({}, 5, cal.prev),
+                    awful.button({}, 4, cal.next)))
+    end
+
+    for _, widget in pairs(cal.attach_to) do cal.attach(widget) end
+
+    return cal
+end
+
+return factory
diff --git a/.config/awesome/lain/widget/calendar.lua b/.config/awesome/lain/widget/calendar.lua
deleted file mode 100644 (file)
index 99e8817..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-
---[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Luke Bonham                     
-                                                  
---]]
-
-local helpers      = require("lain.helpers")
-local markup       = require("lain.util.markup")
-local awful        = require("awful")
-local naughty      = require("naughty")
-local mouse        = mouse
-local os           = { date   = os.date }
-local string       = { format = string.format,
-                       gsub   = string.gsub }
-local ipairs       = ipairs
-local tonumber     = tonumber
-local setmetatable = setmetatable
-
--- Calendar notification
--- lain.widget.calendar
-local calendar = { offset = 0 }
-
-function calendar.hide()
-    if not calendar.notification then return end
-    naughty.destroy(calendar.notification)
-    calendar.notification = nil
-end
-
-function calendar.show(t_out, inc_offset, scr)
-    local f, offs = nil, inc_offset or 0
-
-    calendar.notification_preset.screen = scr or (calendar.followtag and awful.screen.focused()) or 1
-    calendar.offset = calendar.offset + offs
-
-    local current_month = (offs == 0 or calendar.offset == 0)
-
-    if current_month then -- today highlighted
-        calendar.offset = 0
-        calendar.icon = string.format("%s%s.png", calendar.icons, tonumber(os.date("%d")))
-        f = calendar.cal
-    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
-
-       while month > 12 do
-           month = month - 12
-           year = year + 1
-       end
-
-       while month < 1 do
-           month = month + 12
-           year = year - 1
-       end
-
-       calendar.icon = nil
-       f = string.format("%s %s %s", calendar.cal, month, year)
-    end
-
-    helpers.async(f, function(ws)
-        local fg, bg = calendar.notification_preset.fg, calendar.notification_preset.bg
-        calendar.notification_preset.text = ws:gsub("%c%[%d+[m]?%s?%d+%c%[%d+[m]?",
-        markup.bold(markup.color(bg, fg, os.date("%e")))):gsub("\n*$", "")
-
-        local widget_focused = true
-
-        if t_out == 0 and mouse.current_widgets then
-            widget_focused = false
-            for i, widget in ipairs(calendar.attach_to) do
-                for _,v in ipairs(mouse.current_widgets) do
-                    if widget == v then
-                        widget_focused = true
-                        break
-                    end
-                end
-            end
-        end
-
-        if widget_focused then
-            calendar.hide()
-            calendar.notification = naughty.notify({
-                preset  = calendar.notification_preset,
-                icon    = calendar.icon,
-                timeout = t_out or calendar.notification_preset.timeout or 5
-            })
-        end
-    end)
-end
-
-function calendar.hover_on() calendar.show(0) end
-function calendar.hover_off() calendar.hide() end
-function calendar.prev() calendar.show(0, -1) end
-function calendar.next() calendar.show(0, 1) end
-
-function calendar.attach(widget)
-    widget:connect_signal("mouse::enter", calendar.hover_on)
-    widget:connect_signal("mouse::leave", calendar.hover_off)
-    widget:buttons(awful.util.table.join(
-                awful.button({}, 1, calendar.prev),
-                awful.button({}, 3, calendar.next),
-                awful.button({}, 2, calendar.hover_on),
-                awful.button({}, 4, calendar.prev),
-                awful.button({}, 5, calendar.next)))
-end
-
-local function factory(args)
-    local args                   = args or {}
-    calendar.cal                 = args.cal or "/usr/bin/cal"
-    calendar.attach_to           = args.attach_to or {}
-    calendar.followtag           = args.followtag or false
-    calendar.icons               = args.icons or helpers.icons_dir .. "cal/white/"
-    calendar.notification_preset = args.notification_preset
-
-    if not calendar.notification_preset then
-        calendar.notification_preset = {
-            font = "Monospace 10",
-            fg   = "#FFFFFF",
-            bg   = "#000000"
-        }
-    end
-
-    for i, widget in ipairs(calendar.attach_to) do calendar.attach(widget) end
-end
-
-return setmetatable(calendar, { __call = function(_, ...) return factory(...) end })
diff --git a/.config/awesome/lain/widget/contrib/gpmdp.lua b/.config/awesome/lain/widget/contrib/gpmdp.lua
deleted file mode 100644 (file)
index e980209..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-
---[[
-                                                     
-        Licensed under GNU General Public License v2 
-        * (c) 2016, Alexandre Terrien                
-                                                     
---]]
-
-local helpers             = require("lain.helpers")
-local json                = require("lain.util.dkjson")
-local focused             = require("awful.screen").focused
-local pread               = require("awful.util").pread
-local naughty             = require("naughty")
-local wibox               = require("wibox")
-local next, getenv, table = next, os.getenv, table
-
--- Google Play Music Desktop infos
--- lain.widget.contrib.gpmdp
--- requires: curl
-
-local function factory(args)
-    local gpmdp         = { widget = wibox.widget.textbox() }
-    local args          = args or {}
-    local timeout       = args.timeout or 2
-    local notify        = args.notify or "off"
-    local followtag     = args.followtag or false
-    local file_location = args.file_location or
-                          getenv("HOME") .. "/.config/Google Play Music Desktop Player/json_store/playback.json"
-    local settings      = args.settings or function() end
-
-    gpmdp_notification_preset = {
-        title   = "Now playing",
-        timeout = 6
-    }
-
-    helpers.set_map("gpmdp_current", nil)
-
-    function gpmdp.update()
-        local filelines = helpers.lines_from(file_location)
-
-        if not next(filelines) then
-            local gpm_now = { running = false, playing = false }
-        else
-            dict, pos, err = json.decode(table.concat(filelines), 1, nil)
-            local gpm_now = {}
-            gpm_now.artist    = dict.song.artist
-            gpm_now.album     = dict.song.album
-            gpm_now.title     = dict.song.title
-            gpm_now.cover_url = dict.song.albumArt
-            gpm_now.playing   = dict.playing
-        end
-
-        if pread("pidof 'Google Play Music Desktop Player'") ~= '' then
-            gpm_now.running = true
-        else
-            gpm_now.running = false
-        end
-
-        gpmdp_notification_preset.text = string.format("%s (%s) - %s", gpm_now.artist, gpm_now.album, gpm_now.title)
-        widget = gpmdp.widget
-        settings()
-
-        if gpm_now.playing then
-            if notify == "on" and gpm_now.title ~= helpers.get_map("gpmdp_current") then
-                helpers.set_map("gpmdp_current", gpm_now.title)
-
-                if followtag then gpmdp_notification_preset.screen = focused() end
-
-                helpers.async(string.format("curl %d -o /tmp/gpmcover.png", gpm_now.cover_url),
-                function(f)
-                    gpmdp.id = naughty.notify({
-                        preset = gpmdp_notification_preset,
-                        icon = "/tmp/gpmcover.png",
-                        replaces_id = gpmdp.id
-                    }).id
-                end)
-            end
-        elseif not gpm_now.running then
-            helpers.set_map("gpmdp_current", nil)
-        end
-    end
-
-    gpmdp.timer = helpers.newtimer("gpmdp", timeout, gpmdp.update, true, true)
-
-    return gpmdp
-end
-
-return factory
index d7f130ebfe1a970dfcee8b2434876e7d28f11acf..9e863a528473cbb2e406d2bbf8ceaa19f209799e 100644 (file)
@@ -1,14 +1,13 @@
-
 --[[
-                                                   
-     Lain                                          
-     Layouts, widgets and utilities for Awesome WM 
-                                                   
-     Users contributed widgets section             
-                                                   
-     Licensed under GNU General Public License v2  
-      * (c) 2013, Luke Bonham                      
-                                                   
+
+     Lain
+     Layouts, widgets and utilities for Awesome WM
+
+     Users contributed widgets section
+
+     Licensed under GNU General Public License v2
+      * (c) 2013, Luca CPZ
+
 --]]
 
 local wrequire     = require("lain.helpers").wrequire
diff --git a/.config/awesome/lain/widget/contrib/kbdlayout.lua b/.config/awesome/lain/widget/contrib/kbdlayout.lua
deleted file mode 100644 (file)
index 5964bd7..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-
---[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2015, Dario Gjorgjevski               
-                                                  
---]]
-
-local helpers      = require("lain.helpers")
-local awful        = require("awful")
-local wibox        = require("wibox")
-local string       = { format = string.format,
-                       match  = string.match }
-local execute      = os.execute
-local setmetatable = setmetatable
-
--- Keyboard layout switcher
--- lain.widget.contrib.kblayout
-
-local function factory(args)
-    local kbdlayout        = { widget = wibox.widget.textbox() }
-    local args             = args or {}
-    local layouts          = args.layouts or {}
-    local settings         = args.settings or function () end
-    local add_us_secondary = true
-    local timeout          = args.timeout or 5
-    local idx              = 1
-
-    if args.add_us_secondary == false then add_us_secondary = false end
-
-    local function kbd_run_settings(layout, variant)
-        kbdlayout_now = {
-            layout  = string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
-            variant = variant
-        }
-        widget = kbdlayout.widget
-        settings()
-    end
-
-    function kbdlayout.update()
-        helpers.async("setxkbmap -query", function(status)
-            kbd_run_settings(string.match(status, "layout:%s*([^\n]*)"),
-            string.match(status, "variant:%s*([^\n]*)"))
-        end)
-    end
-
-    function kbdlayout.set(i)
-        if #layouts == 0 then return end
-        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 execute(to_execute) then
-            kbd_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
-
-   -- Mouse bindings
-   kbdlayout.widget:buttons(awful.util.table.join(
-                              awful.button({ }, 1, function () kbdlayout.next() end),
-                              awful.button({ }, 3, function () kbdlayout.prev() end)))
-
-   helpers.newtimer("kbdlayout", timeout, kbdlayout.update)
-
-   return kbdlayout
-end
-
-return factory
index 83d8aaf86870ef3dda47468fbc3468af992cd487..f429c7782fb277d2a4978fb0dd06678b5d5176a6 100644 (file)
@@ -1,9 +1,8 @@
-
 --[[
-                                                                  
-     Licensed under GNU General Public License v2                 
-      * (c) 2014, anticlockwise <http://github.com/anticlockwise> 
-                                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2014, anticlockwise <http://github.com/anticlockwise>
+
 --]]
 
 local helpers      = require("lain.helpers")
@@ -12,9 +11,8 @@ local focused      = require("awful.screen").focused
 local escape_f     = require("awful.util").escape
 local naughty      = require("naughty")
 local wibox        = require("wibox")
-local os           = { getenv = os.getenv }
-local string       = { format = string.format,
-                       gmatch = string.gmatch }
+local os           = os
+local string       = string
 
 -- MOC audio player
 -- lain.widget.contrib.moc
index 0babb3abe5227a1267292c88ab65ae5b5efd4864..d0e5eed77f47d01d7eb623c36f16fde8fce5bb6b 100644 (file)
@@ -1,9 +1,9 @@
-
 --[[
-                                                        
-     Licensed under GNU General Public License v2       
-      * (c) 2014, blueluke <http://github.com/blueluke> 
-                                                        
+
+     Licensed under GNU General Public License v2
+      * (c) 2017, Luca CPZ
+      * (c) 2014, blueluke <http://github.com/blueluke>
+
 --]]
 
 local async   = require("lain.helpers").async
index ba795538647f1b711e32056e5e0fd88cc5e6383a..536e0063087abd4b5152516dbbc218be735fd7ed 100644 (file)
@@ -1,16 +1,16 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Jan Xie                         
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013, Jan Xie
+
 --]]
 
 local helpers = require("lain.helpers")
 local markup  = require("lain.util").markup
 local awful   = require("awful")
 local naughty = require("naughty")
-local string  = { format = string.format, gsub = string.gsub }
+local mouse   = mouse
+local string  = string
 
 -- Taskwarrior notification
 -- lain.widget.contrib.task
@@ -23,21 +23,30 @@ function task.hide()
 end
 
 function task.show(scr)
-    task.hide()
+    task.notification_preset.screen = task.followtag and awful.screen.focused() or scr or 1
 
-    if task.followtag then
-        task.notification_preset.screen = awful.screen.focused()
-    elseif scr then
-        task.notification_preset.screen = scr
-    end
+    helpers.async({ awful.util.shell, "-c", task.show_cmd }, function(f)
+        local widget_focused = true
+
+        if mouse.current_widgets then
+            widget_focused = false
+            for _,v in ipairs(mouse.current_widgets) do
+                if task.widget == v then
+                    widget_focused = true
+                    break
+                end
+            end
+        end
 
-    helpers.async(task.show_cmd, function(f)
-        task.notification = naughty.notify({
-            preset = task.notification_preset,
-            title  = task.show_cmd,
-            text   = markup.font(task.notification_preset.font,
-                     awful.util.escape(f:gsub("\n*$", "")))
-        })
+        if widget_focused then
+            task.hide()
+            task.notification = naughty.notify {
+                preset = task.notification_preset,
+                title  = "task next",
+                text   = markup.font(task.notification_preset.font,
+                         awful.util.escape(f:gsub("\n*$", "")))
+            }
+        end
     end)
 end
 
@@ -49,9 +58,9 @@ function task.prompt()
             helpers.async(t, function(f)
                 naughty.notify {
                     preset = task.notification_preset,
-                    title    = t,
-                    text     = markup.font(task.notification_preset.font,
-                               awful.util.escape(f:gsub("\n*$", "")))
+                    title  = t,
+                    text   = markup.font(task.notification_preset.font,
+                             awful.util.escape(f:gsub("\n*$", "")))
                 }
             end)
         end,
@@ -65,6 +74,7 @@ function task.attach(widget, args)
     task.prompt_text         = args.prompt_text or "Enter task command: "
     task.followtag           = args.followtag or false
     task.notification_preset = args.notification_preset
+    task.widget              = widget
 
     if not task.notification_preset then
         task.notification_preset = {
diff --git a/.config/awesome/lain/widget/contrib/tp_smapi.lua b/.config/awesome/lain/widget/contrib/tp_smapi.lua
new file mode 100644 (file)
index 0000000..b8acbe2
--- /dev/null
@@ -0,0 +1,147 @@
+--[[
+
+     Licensed under GNU General Public License v2
+      * (c) 2018, Luca CPZ
+      * (c) 2013, Conor Heine
+
+--]]
+
+local helpers = require("lain.helpers")
+local focused = require("awful.screen").focused
+local gears   = require("gears")
+local naughty = require("naughty")
+local wibox   = require("wibox")
+local string  = string
+local type    = type
+
+-- ThinkPad battery infos and widget creator
+-- http://www.thinkwiki.org/wiki/Tp_smapi
+-- lain.widget.contrib.tp_smapi
+
+local function factory(apipath)
+    local tp_smapi = {
+        path = apipath or "/sys/devices/platform/smapi"
+    }
+
+    function tp_smapi.get(batid, feature)
+        return helpers.first_line(string.format("%s/%s/%s", tp_smapi.path, batid or "BAT0", feature or ""))
+    end
+
+    function tp_smapi.installed(batid)
+        return tp_smapi.get(batid, "installed") == "1"
+    end
+
+    function tp_smapi.status(batid)
+        return tp_smapi.get(batid, "state")
+    end
+
+    function tp_smapi.percentage(batid)
+        return tp_smapi.get(batid, "remaining_percent")
+    end
+
+    -- either running or charging time
+    function tp_smapi.time(batid)
+        local status = tp_smapi.status(batid)
+        local mins_left = tp_smapi.get(batid, string.match(string.lower(status), "discharging") and "remaining_running_time" or "remaining_charging_time")
+        if not string.find(mins_left, "^%d+") then return "N/A" end
+        return string.format("%02d:%02d", math.floor(mins_left / 60), mins_left % 60) -- HH:mm
+    end
+
+    function tp_smapi.hide()
+        if not tp_smapi.notification then return end
+        naughty.destroy(tp_smapi.notification)
+        tp_smapi.notification = nil
+    end
+
+    function tp_smapi.show(batid, seconds, scr)
+        if not tp_smapi.installed(batid) then return end
+
+        local mfgr   = tp_smapi.get(batid, "manufacturer") or "no_mfgr"
+        local model  = tp_smapi.get(batid, "model") or "no_model"
+        local chem   = tp_smapi.get(batid, "chemistry") or "no_chem"
+        local status = tp_smapi.get(batid, "state")
+        local time   = tp_smapi.time(batid)
+        local msg    = ""
+
+        if status and status ~= "idle" then
+            msg = string.format("[%s] %s %s", status, time ~= "N/A" and time or "unknown remaining time",
+                  string.lower(status):gsub(" ", ""):gsub("\n", "") == "charging" and " until charged" or " remaining")
+        else
+            msg = "On AC power"
+        end
+
+        tp_smapi.hide()
+        tp_smapi.notification = naughty.notify {
+            title   = string.format("%s: %s %s (%s)", batid, mfgr, model, chem),
+            text    = msg,
+            timeout = type(seconds) == "number" and seconds or 0,
+            screen  = scr or focused()
+        }
+    end
+
+    function tp_smapi.create_widget(args)
+        local args      = args or {}
+        local pspath    = args.pspath or "/sys/class/power_supply/"
+        local batteries = args.batteries or (args.battery and {args.battery}) or {}
+        local timeout   = args.timeout or 30
+        local settings  = args.settings or function() end
+
+        if #batteries == 0 then
+            helpers.line_callback("ls -1 " .. pspath, function(line)
+                local bstr = string.match(line, "BAT%w+")
+                if bstr then batteries[#batteries + 1] = bstr end
+            end)
+        end
+
+        local all_batteries_installed = true
+
+        for i, battery in ipairs(batteries) do
+            if not tp_smapi.installed(battery) then
+                naughty.notify {
+                    preset = naughty.config.critical,
+                    title  = "tp_smapi: error while creating widget",
+                    text   = string.format("battery %s is not installed", battery)
+                }
+                all_batteries_installed = false
+                break
+            end
+        end
+
+        if not all_batteries_installed then return end
+
+        tpbat = {
+            batteries = batteries,
+            widget    = args.widget or wibox.widget.textbox()
+        }
+
+        function tpbat.update()
+            tpbat_now = {
+                n_status = {},
+                n_perc   = {},
+                n_time   = {},
+                status   = "N/A"
+            }
+
+            for i = 1, #batteries do
+                tpbat_now.n_status[i] = tp_smapi.status(batteries[i]) or "N/A"
+                tpbat_now.n_perc[i] = tp_smapi.percentage(batteries[i])
+                tpbat_now.n_time[i] = tp_smapi.time(batteries[i]) or "N/A"
+
+                if not tpbat_now.n_status[i]:lower():match("full") then
+                    tpbat_now.status = tpbat_now.n_status[i]
+                end
+            end
+
+            widget = tpbat.widget -- backwards compatibility
+            settings()
+        end
+
+        helpers.newtimer("thinkpad-batteries", timeout, tpbat.update)
+
+        return tpbat
+    end
+
+    return tp_smapi
+end
+
+return factory
diff --git a/.config/awesome/lain/widget/contrib/tpbat/init.lua b/.config/awesome/lain/widget/contrib/tpbat/init.lua
deleted file mode 100644 (file)
index 49cc01a..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-
---[[
-                                                               
-     tpbat.lua                                                 
-     Battery status widget for ThinkPad laptops that use SMAPI 
-     lain.widget.contrib.tpbat                                
-                                                               
-     More on tp_smapi: http://www.thinkwiki.org/wiki/Tp_smapi  
-                                                               
-     Licensed under GNU General Public License v2              
-      * (c) 2013,      Conor Heine                             
-      * (c) 2013,      Luke Bonham                             
-      * (c) 2010-2012, Peter Hofmann                           
-                                                               
---]]
-
-local debug        = { getinfo = debug.getinfo }
-local newtimer     = require("lain.helpers").newtimer
-local first_line   = require("lain.helpers").first_line
-local naughty      = require("naughty")
-local wibox        = require("wibox")
-local string       = { format = string.format }
-local math         = { floor = math.floor }
-local tostring     = tostring
-local setmetatable = setmetatable
-package.path       = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .. "?.lua;" .. package.path
-local smapi        = require("smapi")
-
--- ThinkPad SMAPI-enabled battery info widget
--- lain.widget.contrib.tpbat
-local tpbat = {}
-
-function tpbat.hide()
-    if not tpbat.notification then return end
-    naughty.destroy(tpbat.notification)
-    tpbat.notification = nil
-end
-
-function tpbat.show(t_out)
-    tpbat.hide()
-
-    local bat = tpbat.bat
-
-    if bat == nil or not bat:installed() then return end
-
-    local t_out = t_out or 0
-    local mfgr   = bat:get('manufacturer') or "no_mfgr"
-    local model  = bat:get('model') or "no_model"
-    local chem   = bat:get('chemistry') or "no_chem"
-    local status = bat:get('state') or "nil"
-    local time   = bat:remaining_time()
-    local msg    = "\t"
-
-    if status ~= "idle" and status ~= "nil" then
-        if time == "N/A" then
-            msg = "...Calculating time remaining..."
-        else
-            msg = time .. (status == "charging" and " until charged" or " remaining")
-        end
-    else
-        msg = "On AC Power"
-    end
-
-    local str = string.format("%s : %s %s (%s)\n", bat.name, mfgr, model, chem)
-                .. string.format("\n%s \t\t\t %s", status:upper(), msg)
-
-    tpbat.notification = naughty.notify({
-        text    = str,
-        timeout = t_out,
-        screen  = client.focus and client.focus.screen or 1
-    })
-end
-
-function tpbat.register(args)
-    local args = args or {}
-    local timeout = args.timeout or 30
-    local battery = args.battery or "BAT0"
-    local settings = args.settings or function() end
-
-    tpbat.bat = smapi:battery(battery) -- Create a new battery
-    local bat = tpbat.bat
-
-    tpbat.widget = wibox.widget.textbox()
-
-    bat_notification_low_preset = {
-        title = "Battery low",
-        text = "Plug the cable!",
-        timeout = 15,
-        fg = "#202020",
-        bg = "#CDCDCD"
-    }
-
-    bat_notification_critical_preset = {
-        title = "Battery exhausted",
-        text = "Shutdown imminent",
-        timeout = 15,
-        fg = "#000000",
-        bg = "#FFFFFF"
-    }
-
-    if bat:get('state') == nil
-    then
-        local n = naughty.notify({
-            preset = bat_notification_low_preset,
-            title = "SMAPI Battery Warning: Unable to read battery state!",
-            text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths.",
-            screen = client.focus and client.focus.screen or 1
-        })
-    end
-
-    function tpbat.update()
-        bat_now = {
-            status = "Not present",
-            perc   = "N/A",
-            time   = "N/A",
-            watt   = "N/A"
-        }
-
-        if bat:installed()
-        then
-            bat_now.status = bat:status() or "N/A"
-            bat_now.perc   = bat:percent()
-            bat_now.time   = bat:remaining_time()
-            -- bat_now.watt = string.format("%.2fW", (VOLTS * AMPS) / 1e12)
-
-            -- notifications for low and critical states (when discharging)
-            if bat_now.status == "discharging"
-            then
-                if bat_now.perc <= 5
-                then
-                    tpbat.id = naughty.notify({
-                        preset = bat_notification_critical_preset,
-                        replaces_id = tpbat.id,
-                        screen = client.focus and client.focus.screen or 1
-                    }).id
-                elseif bat_now.perc <= 15
-                then
-                    tpbat.id = naughty.notify({
-                        preset = bat_notification_low_preset,
-                        replaces_id = tpbat.id,
-                        screen = client.focus and client.focus.screen or 1
-                    }).id
-                end
-            end
-
-            bat_now.perc = tostring(bat_now.perc)
-        end
-
-        widget = tpbat.widget
-
-        settings()
-    end
-
-    newtimer("tpbat-" .. bat.name, timeout, tpbat.update)
-
-    widget:connect_signal('mouse::enter', function () tpbat.show() end)
-    widget:connect_signal('mouse::leave', function () tpbat.hide() end)
-
-    return tpbat
-end
-
-return setmetatable(tpbat, { __call = function(_, ...) return tpbat.register(...) end })
diff --git a/.config/awesome/lain/widget/contrib/tpbat/smapi.lua b/.config/awesome/lain/widget/contrib/tpbat/smapi.lua
deleted file mode 100644 (file)
index 9002585..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-
---[[
-                                                  
-     smapi.lua                                    
-     Interface with thinkpad battery information  
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Conor Heine                     
-                                                  
---]]
-
-local first_line   = require("lain.helpers").first_line
-
-local string       = { format = string.format }
-local tonumber     = tonumber
-local setmetatable = setmetatable
-
-local smapi = {}
-local apipath = "/sys/devices/platform/smapi"
-
--- Most are readable values, but some can be written to (not implemented, yet?)
-local readable = {
-    barcoding                  = true,
-    charging_max_current       = true,
-    charging_max_voltage       = true,
-    chemistry                  = true,
-    current_avg                = true,
-    current_now                = true,
-    cycle_count                = true,
-    design_capacity            = true,
-    design_voltage             = true,
-    dump                       = true,
-    first_use_date             = true,
-    force_discharge            = false,
-    group0_voltage             = true,
-    group1_voltage             = true,
-    group2_voltage             = true,
-    group3_voltage             = true,
-    inhibit_charge_minutes     = false,
-    installed                  = true,
-    last_full_capacity         = true,
-    manufacture_date           = true,
-    manufacturer               = true,
-    model                      = true,
-    power_avg                  = true,
-    power_now                  = true,
-    remaining_capacity         = true,
-    remaining_charging_time    = true,
-    remaining_percent          = true,
-    remaining_percent_error    = true,
-    remaining_running_time     = true,
-    remaining_running_time_now = true,
-    serial                     = true,
-    start_charge_thresh        = false,
-    state                      = true,
-    stop_charge_thresh         = false,
-    temperature                = true,
-    voltage                    = true,
-}
-
-function smapi:battery(name)
-    local bat = {}
-
-    bat.name = name
-    bat.path = apipath .. "/" .. name
-
-    function bat:get(item)
-        return self.path ~= nil and readable[item] and first_line(self.path .. "/" .. item) or nil
-    end
-
-    function bat:installed()
-        return self:get("installed") == "1"
-    end
-
-    function bat:status()
-        return self:get('state')
-    end
-
-    -- Remaining time can either be time until battery dies or time until charging completes
-    function bat:remaining_time()
-        local time_val = bat_now.status == 'discharging' and 'remaining_running_time' or 'remaining_charging_time'
-        local mins_left = self:get(time_val)
-
-        if not mins_left:find("^%d+") then return "N/A" end
-
-        local hrs = math.floor(mins_left / 60)
-        local min = mins_left % 60
-
-        return string.format("%02d:%02d", hrs, min)
-    end
-
-    function bat:percent()
-        return tonumber(self:get("remaining_percent"))
-    end
-
-    return setmetatable(bat, {__metatable = false, __newindex = false})
-end
-
-return smapi
index 9a5a9648f01e679c5cdf7992fd5cb45eb03b3c3e..f4cce734763b5238302c73879c1d37284bd89047 100644 (file)
@@ -1,17 +1,15 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013,      Luke Bonham                
-      * (c) 2010-2012, Peter Hofmann              
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013,      Luca CPZ
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
 local helpers  = require("lain.helpers")
 local wibox    = require("wibox")
-local math     = { ceil   = math.ceil }
-local string   = { format = string.format,
-                   gmatch = string.gmatch }
+local math     = math
+local string   = string
 local tostring = tostring
 
 -- CPU usage
@@ -27,9 +25,7 @@ local function factory(args)
         -- Read the amount of time the CPUs have spent performing
         -- different kinds of work. Read the first line of /proc/stat
         -- which is the sum of all CPUs.
-        local times = helpers.lines_match("cpu","/proc/stat")
-
-        for index,time in pairs(times) do
+        for index,time in pairs(helpers.lines_match("cpu","/proc/stat")) do
             local coreid = index - 1
             local core   = cpu.core[coreid] or
                            { last_active = 0 , last_total = 0, usage = 0 }
index 473bd33fa77554274b31581f01ea56bf94d3479b..58fbf93ffbc574bcfebe8a7910a89c5e6fc7b1c1 100644 (file)
@@ -1,24 +1,39 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Luke Bonham                     
-                                                  
---]]
 
-local helpers  = require("lain.helpers")
-local shell    = require("awful.util").shell
-local focused  = require("awful.screen").focused
-local wibox    = require("wibox")
-local naughty  = require("naughty")
-local string   = string
-local tonumber = tonumber
+     Licensed under GNU General Public License v2
+      * (c) 2018, Uli Schlacter
+      * (c) 2018, Otto Modinos
+      * (c) 2013, Luca CPZ
+
+--]]
 
--- File system disk space usage
+local helpers    = require("lain.helpers")
+local Gio        = require("lgi").Gio
+local focused    = require("awful.screen").focused
+local wibox      = require("wibox")
+local naughty    = require("naughty")
+local math       = math
+local string     = string
+local tconcat    = table.concat
+local type       = type
+local tonumber   = tonumber
+local query_size = Gio.FILE_ATTRIBUTE_FILESYSTEM_SIZE
+local query_free = Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE
+local query_used = Gio.FILE_ATTRIBUTE_FILESYSTEM_USED
+local query      = query_size .. "," .. query_free .. "," .. query_used
+
+-- File systems info
 -- lain.widget.fs
 
 local function factory(args)
-    local fs = { unit  = { ["mb"] = 1024, ["gb"] = 1024^2 }, widget = wibox.widget.textbox() }
+    local fs = {
+        widget = wibox.widget.textbox(),
+        units = {
+            [1] = "Kb", [2] = "Mb", [3] = "Gb",
+            [4] = "Tb", [5] = "Pb", [6] = "Eb",
+            [7] = "Zb", [8] = "Yb"
+        }
+    }
 
     function fs.hide()
         if not fs.notification then return end
@@ -27,29 +42,21 @@ local function factory(args)
     end
 
     function fs.show(seconds, scr)
-        fs.update()
-        fs.hide()
-
-        if fs.followtag then
-            fs.notification_preset.screen = focused()
-        else
-            fs.notification_preset.screen = scr or 1
-        end
-
-        fs.notification = naughty.notify({
+        fs.hide(); fs.update()
+        fs.notification_preset.screen = fs.followtag and focused() or scr or 1
+        fs.notification = naughty.notify {
             preset  = fs.notification_preset,
-            timeout = seconds or 5
-        })
+            timeout = type(seconds) == "number" and seconds or 5
+        }
     end
 
-    local args             = args or {}
-    local timeout          = args.timeout or 600
-    local partition        = args.partition or "/"
-    local showpopup        = args.showpopup or "on"
-    local notify           = args.notify or "on"
-    local settings         = args.settings or function() end
+    local args      = args or {}
+    local timeout   = args.timeout or 600
+    local partition = args.partition
+    local threshold = args.threshold or 99
+    local showpopup = args.showpopup or "on"
+    local settings  = args.settings or function() end
 
-    fs.options             = args.options
     fs.followtag           = args.followtag or false
     fs.notification_preset = args.notification_preset
 
@@ -61,54 +68,74 @@ local function factory(args)
         }
     end
 
-    helpers.set_map(partition, false)
-
     function fs.update()
-        fs_info, fs_now  = {}, {}
-        helpers.async({ shell, "-c", "/usr/bin/env LC_ALL=C df -k --output=target,size,used,avail,pcent" }, function(f)
-            for line in string.gmatch(f, "\n[^\n]+") do
-                local m,s,u,a,p = string.match(line, "(/.-%s).-(%d+).-(%d+).-(%d+).-([%d]+)%%")
-                m = m:gsub(" ", "") -- clean target from any whitespace
-
-                fs_info[m .. " size_mb"]  = string.format("%.1f", tonumber(s) / fs.unit["mb"])
-                fs_info[m .. " size_gb"]  = string.format("%.1f", tonumber(s) / fs.unit["gb"])
-                fs_info[m .. " used_mb"]  = string.format("%.1f", tonumber(u) / fs.unit["mb"])
-                fs_info[m .. " used_gb"]  = string.format("%.1f", tonumber(u) / fs.unit["gb"])
-                fs_info[m .. " used_p"]   = p
-                fs_info[m .. " avail_mb"] = string.format("%.1f", tonumber(a) / fs.unit["mb"])
-                fs_info[m .. " avail_gb"] = string.format("%.1f", tonumber(a) / fs.unit["gb"])
-                fs_info[m .. " avail_p"]  = string.format("%d", 100 - tonumber(p))
+        local notifytable = { [1] = string.format("%-10s %4s\t%6s\t%6s\t\n", "path", "used", "free", "size") }
+        local pathlen = 10
+        local maxpathidx = 1
+        fs_now = {}
+
+        for _, mount in ipairs(Gio.unix_mounts_get()) do
+            local path = Gio.unix_mount_get_mount_path(mount)
+            local root = Gio.File.new_for_path(path)
+            local info = root:query_filesystem_info(query)
+
+            if info then
+                local size = info:get_attribute_uint64(query_size)
+                local used = info:get_attribute_uint64(query_used)
+                local free = info:get_attribute_uint64(query_free)
+
+                if size > 0 then
+                    local units = math.floor(math.log(size)/math.log(1024))
+
+                    fs_now[path] = {
+                        units      = fs.units[units],
+                        percentage = math.floor(100 * used / size), -- used percentage
+                        size       = size / math.pow(1024, math.floor(units)),
+                        used       = used / math.pow(1024, math.floor(units)),
+                        free       = free / math.pow(1024, math.floor(units))
+                    }
+
+                    if fs_now[path].percentage > 0 then -- don't notify unused file systems
+                        notifytable[#notifytable+1] = string.format("\n%-10s %3s%%\t%6.2f\t%6.2f\t%s", path,
+                        math.floor(fs_now[path].percentage), fs_now[path].free, fs_now[path].size,
+                        fs_now[path].units)
+
+                        if #path > pathlen then
+                            pathlen = #path
+                            maxpathidx = #notifytable
+                        end
+                    end
+                end
             end
+        end
+
+        widget = fs.widget
+        settings()
 
-            fs_now.size_mb      = fs_info[partition .. " size_mb"]  or "N/A"
-            fs_now.size_gb      = fs_info[partition .. " size_gb"]  or "N/A"
-            fs_now.used         = fs_info[partition .. " used_p"]   or "N/A"
-            fs_now.used_mb      = fs_info[partition .. " used_mb"]  or "N/A"
-            fs_now.used_gb      = fs_info[partition .. " used_gb"]  or "N/A"
-            fs_now.available    = fs_info[partition .. " avail_p"]  or "N/A"
-            fs_now.available_mb = fs_info[partition .. " avail_mb"] or "N/A"
-            fs_now.available_gb = fs_info[partition .. " avail_gb"] or "N/A"
-
-            notification_preset = fs.notification_preset
-            widget = fs.widget
-            settings()
-
-            if notify == "on" and #fs_now.used > 0 and tonumber(fs_now.used) >= 99 and not helpers.get_map(partition) then
-                naughty.notify({
+        if partition and fs_now[partition] and fs_now[partition].percentage >= threshold then
+            if not helpers.get_map(partition) then
+                naughty.notify {
                     preset = naughty.config.presets.critical,
                     title  = "Warning",
-                    text   = partition .. " is full",
-                })
+                    text   = string.format("%s is above %d%% (%d%%)", partition, threshold, fs_now[partition].percentage)
+                }
                 helpers.set_map(partition, true)
             else
                 helpers.set_map(partition, false)
             end
-        end)
+        end
+
+        if pathlen > 10 then -- if are there paths longer than 10 chars, reformat first column accordingly
+            local pathspaces
+            for i = 1, #notifytable do
+                pathspaces = notifytable[i]:match("[ ]+")
+                if i ~= maxpathidx and pathspaces then
+                    notifytable[i] = notifytable[i]:gsub(pathspaces, pathspaces .. string.rep(" ", pathlen - 10))
+                end
+            end
+        end
 
-        local notifycmd = (fs.options and string.format("dfs %s", fs.options)) or "dfs"
-        helpers.async(helpers.scripts_dir .. notifycmd, function(ws)
-            fs.notification_preset.text = ws:gsub("\n*$", "")
-        end)
+        fs.notification_preset.text = tconcat(notifytable)
     end
 
     if showpopup == "on" then
@@ -116,7 +143,7 @@ local function factory(args)
        fs.widget:connect_signal('mouse::leave', function () fs.hide() end)
     end
 
-    helpers.newtimer(partition, timeout, fs.update)
+    helpers.newtimer(partition or "fs", timeout, fs.update)
 
     return fs
 end
index 0f7fde56ca1ea384a2fa4c12a76047c3be42a88f..b3d9dc7d0d65965a1eea3bcb841cedefa763c2cd 100644 (file)
@@ -1,16 +1,15 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Luke Bonham                     
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013, Luca CPZ
+
 --]]
 
 local helpers  = require("lain.helpers")
 local naughty  = require("naughty")
 local wibox    = require("wibox")
-local string   = { format = string.format,
-                   gsub   = string.gsub }
+local awful    = require("awful")
+local string   = string
 local type     = type
 local tonumber = tonumber
 
@@ -18,67 +17,75 @@ local tonumber = tonumber
 -- lain.widget.imap
 
 local function factory(args)
-    local imap      = { widget = wibox.widget.textbox() }
-    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 followtag = args.followtag or false
-    local settings  = args.settings or function() end
+    local imap       = { widget = wibox.widget.textbox() }
+    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 pwdtimeout = args.pwdtimeout or 10
+    local is_plain   = args.is_plain or false
+    local followtag  = args.followtag or false
+    local notify     = args.notify or "on"
+    local settings   = args.settings or function() end
 
     local head_command = "curl --connect-timeout 3 -fsm 3"
-    local request = "-X 'SEARCH (UNSEEN)'"
+    local request = "-X 'STATUS INBOX (MESSAGES RECENT UNSEEN)'"
 
     if not server or not mail or not password then return end
 
+    mail_notification_preset = {
+        icon     = helpers.icons_dir .. "mail.png",
+        position = "top_left"
+    }
+
     helpers.set_map(mail, 0)
 
     if not is_plain then
         if type(password) == "string" or type(password) == "table" then
             helpers.async(password, function(f) password = f:gsub("\n", "") end)
         elseif type(password) == "function" then
-            local p = password()
+            imap.pwdtimer = helpers.newtimer(mail .. "-password", pwdtimeout, function()
+                local retrieved_password, try_again = password()
+                if not try_again then
+                    imap.pwdtimer:stop() -- stop trying to retrieve
+                    password = retrieved_password or "" -- failsafe
+                end
+            end, true, true)
         end
     end
 
-    function update()
-        mail_notification_preset = {
-            icon     = helpers.icons_dir .. "mail.png",
-            position = "top_left"
-        }
+    function imap.update()
+        -- do not update if the password has not been retrieved yet
+        if type(password) ~= "string" then return end
 
-        if followtag then
-            mail_notification_preset.screen = awful.screen.focused()
-        end
-
-        curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%q %s -k",
-               head_command, server, port, mail, password, request)
+        local curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:'%s' %s -k",
+                     head_command, server, port, mail, password, request)
 
         helpers.async(curl, function(f)
-            _, mailcount = string.gsub(f, "%d+", "")
-            _ = nil
+            imap_now = { ["MESSAGES"] = 0, ["RECENT"] = 0, ["UNSEEN"] = 0 }
 
+            for s,d in f:gmatch("(%w+)%s+(%d+)") do imap_now[s] = tonumber(d) end
+            mailcount = imap_now["UNSEEN"] -- backwards compatibility
             widget = imap.widget
+
             settings()
 
-            if mailcount >= 1 and mailcount > helpers.get_map(mail) then
-                if mailcount == 1 then
-                    nt = mail .. " has one new message"
-                else
-                    nt = mail .. " has <b>" .. mailcount .. "</b> new messages"
-                end
-                naughty.notify({ preset = mail_notification_preset, text = nt })
+            if notify == "on" and mailcount and mailcount >= 1 and mailcount > helpers.get_map(mail) then
+                if followtag then mail_notification_preset.screen = awful.screen.focused() end
+                naughty.notify {
+                    preset = mail_notification_preset,
+                    text   = string.format("%s has <b>%d</b> new message%s", mail, mailcount, mailcount == 1 and "" or "s")
+                }
             end
 
-            helpers.set_map(mail, mailcount)
+            helpers.set_map(mail, imap_now["UNSEEN"])
         end)
 
     end
 
-    imap.timer = helpers.newtimer(mail, timeout, update, true, true)
+    imap.timer = helpers.newtimer(mail, timeout, imap.update, true, true)
 
     return imap
 end
index f77f872314a01f855adb1e79e3552cab9582b201..57b86bb986b3c905e70a005bdb1dc30e82195765 100644 (file)
@@ -1,15 +1,14 @@
-
 --[[
-                                                   
-     Lain                                          
-     Layouts, widgets and utilities for Awesome WM 
-                                                   
-     Widgets section                               
-                                                   
-     Licensed under GNU General Public License v2  
-      * (c) 2013,      Luke Bonham                 
-      * (c) 2010-2012, Peter Hofmann               
-                                                   
+
+     Lain
+     Layouts, widgets and utilities for Awesome WM
+
+     Widgets section
+
+     Licensed under GNU General Public License v2
+      * (c) 2013,      Luca CPZ
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
 local wrequire     = require("lain.helpers").wrequire
index 50fff3bb7d62f78cd4bbfd6c5cd84987223d1786..3dcae2b7d9366dddfabf8da718ffe76eff85e79d 100644 (file)
@@ -1,10 +1,9 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013,      Luke Bonham                
-      * (c) 2010-2012, Peter Hofmann              
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013,      Luca CPZ
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
 local helpers              = require("lain.helpers")
index d0b37d7db0daaef3f3a97fa4ab83912bdd4c52e0..01f28e633e271c0fc617e7af454d2ab4c6732ad7 100644 (file)
@@ -1,22 +1,19 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Luke Bonham                     
-      * (c) 2010, Adrian C. <anrxc@sysphere.org>  
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013, Luca CPZ
+      * (c) 2010, Adrian C. <anrxc@sysphere.org>
+
 --]]
 
-local helpers      = require("lain.helpers")
-local shell        = require("awful.util").shell
-local escape_f     = require("awful.util").escape
-local focused      = require("awful.screen").focused
-local naughty      = require("naughty")
-local wibox        = require("wibox")
-local os           = { getenv = os.getenv }
-local string       = { format = string.format,
-                       gmatch = string.gmatch,
-                       match  = string.match }
+local helpers  = require("lain.helpers")
+local shell    = require("awful.util").shell
+local escape_f = require("awful.util").escape
+local focused  = require("awful.screen").focused
+local naughty  = require("naughty")
+local wibox    = require("wibox")
+local os       = os
+local string   = string
 
 -- MPD infos
 -- lain.widget.mpd
@@ -26,8 +23,8 @@ local function factory(args)
     local args          = args or {}
     local timeout       = args.timeout or 2
     local password      = (args.password and #args.password > 0 and string.format("password %s\\n", args.password)) or ""
-    local host          = args.host or "127.0.0.1"
-    local port          = args.port or "6600"
+    local host          = args.host or os.getenv("MPD_HOST") or "127.0.0.1"
+    local port          = args.port or os.getenv("MPD_PORT") or "6600"
     local music_dir     = args.music_dir or os.getenv("HOME") .. "/Music"
     local cover_pattern = args.cover_pattern or "*\\.(jpg|jpeg|png|gif)$"
     local cover_size    = args.cover_size or 100
index f42ec25d01a52a0f37f24b495a1993f08fce4753..805b5778f1199caad96390e9cf7f4ccc8f548a01 100644 (file)
@@ -1,37 +1,37 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013,      Luke Bonham                
-      * (c) 2010-2012, Peter Hofmann              
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013,      Luca CPZ
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
 local helpers = require("lain.helpers")
 local naughty = require("naughty")
 local wibox   = require("wibox")
-local string  = { format = string.format, match = string.match }
+local string  = string
 
 -- Network infos
 -- lain.widget.net
 
 local function factory(args)
-    local net      = { widget = wibox.widget.textbox(), devices = {} }
-    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
+    local net        = { widget = wibox.widget.textbox(), devices = {} }
+    local args       = args or {}
+    local timeout    = args.timeout or 2
+    local units      = args.units or 1024 -- KB
+    local notify     = args.notify or "on"
+    local wifi_state = args.wifi_state or "off"
+    local eth_state  = args.eth_state or "off"
+    local screen     = args.screen or 1
+    local settings   = args.settings or function() end
 
     -- Compatibility with old API where iface was a string corresponding to 1 interface
     net.iface = (args.iface and (type(args.iface) == "string" and {args.iface}) or
                 (type(args.iface) == "table" and args.iface)) or {}
 
     function net.get_device()
-        helpers.async(string.format("ip link show", device_cmd), function(ws)
-            ws = ws:match("(%w+): <BROADCAST,MULTICAST,.-UP,LOWER_UP>")
-            net.iface = ws and { ws } or {}
+        helpers.line_callback("ip link", function(line)
+            net.iface[#net.iface + 1] = not string.match(line, "LOOPBACK") and string.match(line, "(%w+): <") or nil
         end)
     end
 
@@ -46,7 +46,7 @@ local function factory(args)
             received = 0
         }
 
-        for i, dev in ipairs(net.iface) do
+        for _, dev in ipairs(net.iface) do
             local dev_now    = {}
             local dev_before = net.devices[dev] or { last_t = 0, last_r = 0 }
             local now_t      = tonumber(helpers.first_line(string.format("/sys/class/net/%s/statistics/tx_bytes", dev)) or 0)
@@ -67,9 +67,18 @@ local function factory(args)
             dev_now.last_t   = now_t
             dev_now.last_r   = now_r
 
+            if wifi_state == "on" and helpers.first_line(string.format("/sys/class/net/%s/uevent", dev)) == "DEVTYPE=wlan" and string.match(dev_now.carrier, "1") then
+                dev_now.wifi   = true
+                dev_now.signal = tonumber(string.match(helpers.lines_from("/proc/net/wireless")[3], "(%-%d+%.)")) or nil
+            end
+
+            if eth_state == "on" and helpers.first_line(string.format("/sys/class/net/%s/uevent", dev)) ~= "DEVTYPE=wlan" and string.match(dev_now.carrier, "1") then
+                dev_now.ethernet = true
+            end
+
             net.devices[dev] = dev_now
 
-            -- Notify only once when connection is loss
+            -- Notify only once when connection is lost
             if string.match(dev_now.carrier, "0") and notify == "on" and helpers.get_map(dev) then
                 naughty.notify {
                     title    = dev,
@@ -85,7 +94,7 @@ local function factory(args)
             net_now.carrier = dev_now.carrier
             net_now.state = dev_now.state
             net_now.devices[dev] = dev_now
-            -- new_now.sent and net_now.received will be
+            -- net_now.sent and net_now.received will be
             -- the totals across all specified devices
         end
 
diff --git a/.config/awesome/lain/widget/pulse.lua b/.config/awesome/lain/widget/pulse.lua
new file mode 100644 (file)
index 0000000..f63fe55
--- /dev/null
@@ -0,0 +1,57 @@
+--[[
+
+     Licensed under GNU General Public License v2
+      * (c) 2016, Luca CPZ
+
+--]]
+
+local helpers = require("lain.helpers")
+local shell   = require("awful.util").shell
+local wibox   = require("wibox")
+local string  = string
+local type    = type
+
+-- PulseAudio volume
+-- lain.widget.pulse
+
+local function factory(args)
+    local pulse    = { widget = wibox.widget.textbox(), device = "N/A" }
+    local args     = args or {}
+    local timeout  = args.timeout or 5
+    local settings = args.settings or function() end
+
+    pulse.devicetype = args.devicetype or "sink"
+    pulse.cmd = args.cmd or "pacmd list-" .. pulse.devicetype .. "s | sed -n -e '/*/,$!d' -e '/index/p' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'"
+
+    function pulse.update()
+        helpers.async({ shell, "-c", type(pulse.cmd) == "string" and pulse.cmd or pulse.cmd() },
+        function(s)
+            volume_now = {
+                index  = string.match(s, "index: (%S+)") or "N/A",
+                device = string.match(s, "device.string = \"(%S+)\"") or "N/A",
+                muted  = string.match(s, "muted: (%S+)") or "N/A"
+            }
+
+            pulse.device = volume_now.index
+
+            local ch = 1
+            volume_now.channel = {}
+            for v in string.gmatch(s, ":.-(%d+)%%") do
+                volume_now.channel[ch] = v
+                ch = ch + 1
+            end
+
+            volume_now.left  = volume_now.channel[1] or "N/A"
+            volume_now.right = volume_now.channel[2] or "N/A"
+
+            widget = pulse.widget
+            settings()
+        end)
+    end
+
+    helpers.newtimer("pulse", timeout, pulse.update)
+
+    return pulse
+end
+
+return factory
diff --git a/.config/awesome/lain/widget/pulseaudio.lua b/.config/awesome/lain/widget/pulseaudio.lua
deleted file mode 100644 (file)
index ed37cb5..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-
---[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2016, Luke Bonham                     
-                                                  
---]]
-
-local helpers = require("lain.helpers")
-local shell   = require("awful.util").shell
-local wibox   = require("wibox")
-local string  = { gmatch = string.gmatch,
-                  match  = string.match,
-                  format = string.format }
-
--- PulseAudio volume
--- lain.widget.pulseaudio
-
-local function factory(args)
-    local pulseaudio  = { widget = wibox.widget.textbox() }
-    local args        = args or {}
-    local timeout     = args.timeout or 5
-    local settings    = args.settings or function() end
-    local scallback   = args.scallback
-    pulseaudio.device = "N/A"
-    pulseaudio.devicetype = args.devicetype or "sink"
-    pulseaudio.cmd = args.cmd or "pacmd list-" .. pulseaudio.devicetype .. "s | sed -n -e '0,/*/d' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'"
-
-    function pulseaudio.update()
-        if scallback then pulseaudio.cmd = scallback() end
-
-        helpers.async({ shell, "-c", pulseaudio.cmd }, function(s)
-            volume_now = {
-                index = string.match(s, "index: (%S+)") or "N/A",
-                device = string.match(s, "device.string = \"(%S+)\"") or "N/A",
-                sink   = device, -- legacy API
-                muted  = string.match(s, "muted: (%S+)") or "N/A"
-            }
-
-            pulseaudio.device = volume_now.index
-
-            local ch = 1
-            volume_now.channel = {}
-            for v in string.gmatch(s, ":.-(%d+)%%") do
-                volume_now.channel[ch] = v
-                ch = ch + 1
-            end
-
-            volume_now.left  = volume_now.channel[1] or "N/A"
-            volume_now.right = volume_now.channel[2] or "N/A"
-
-            widget = pulseaudio.widget
-
-            settings()
-        end)
-    end
-
-    helpers.newtimer("pulseaudio", timeout, pulseaudio.update)
-
-    return pulseaudio
-end
-
-return factory
index 41a8ce36b608525ff3e164f8c006f25309fa2d47..51290f8cd9f84ef01213cd8b7f7d7b6d563d0326 100644 (file)
@@ -1,24 +1,21 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Luke Bonham                     
-      * (c) 2013, Rman                            
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013, Luca CPZ
+      * (c) 2013, Rman
+
 --]]
 
-local helpers        = require("lain.helpers")
-local awful          = require("awful")
-local naughty        = require("naughty")
-local wibox          = require("wibox")
-local math           = { modf   = math.modf }
-local string         = { format = string.format,
-                         match  = string.match,
-                         gmatch = string.gmatch,
-                         rep    = string.rep }
-local type, tonumber = type, tonumber
-
--- Pulseaudio volume bar
+local helpers  = require("lain.helpers")
+local awful    = require("awful")
+local naughty  = require("naughty")
+local wibox    = require("wibox")
+local math     = math
+local string   = string
+local type     = type
+local tonumber = tonumber
+
+-- PulseAudio volume bar
 -- lain.widget.pulsebar
 
 local function factory(args)
@@ -30,37 +27,43 @@ local function factory(args)
         },
 
         _current_level = 0,
-        _muted         = false
+        _mute          = "no",
+        device         = "N/A"
     }
 
     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 height     = args.height or 1
+    local margins    = args.margins or 1
+    local paddings   = args.paddings or 1
     local ticks      = args.ticks or false
     local ticks_size = args.ticks_size or 7
-    local scallback  = args.scallback
+    local tick       = args.tick or "|"
+    local tick_pre   = args.tick_pre or "["
+    local tick_post  = args.tick_post or "]"
+    local tick_none  = args.tick_none or " "
 
-    pulsebar.cmd           = args.cmd or "pacmd list-sinks | sed -n -e '0,/*/d' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'"
-    pulsebar.sink          = args.sink or 0
-    pulsebar.colors        = args.colors or pulsebar.colors
-    pulsebar.followtag     = args.followtag or false
-    pulsebar.notifications = args.notification_preset
-    pulsebar.device        = "N/A"
+    pulsebar.colors              = args.colors or pulsebar.colors
+    pulsebar.followtag           = args.followtag or false
+    pulsebar.notification_preset = args.notification_preset
+    pulsebar.devicetype          = args.devicetype or "sink"
+    pulsebar.cmd                 = args.cmd or "pacmd list-" .. pulsebar.devicetype .. "s | sed -n -e '/*/,$!d' -e '/index/p' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'"
 
     if not pulsebar.notification_preset then
-        pulsebar.notification_preset      = {}
-        pulsebar.notification_preset.font = "Monospace 10"
+        pulsebar.notification_preset = {
+            font = "Monospace 10"
+        }
     end
 
     pulsebar.bar = wibox.widget {
-        forced_height    = height,
-        forced_width     = width,
         color            = pulsebar.colors.unmute,
         background_color = pulsebar.colors.background,
-        margins          = 1,
-        paddings         = 1,
+        forced_height    = height,
+        forced_width     = width,
+        margins          = margins,
+        paddings         = paddings,
         ticks            = ticks,
         ticks_size       = ticks_size,
         widget           = wibox.widget.progressbar,
@@ -69,13 +72,12 @@ local function factory(args)
     pulsebar.tooltip = awful.tooltip({ objects = { pulsebar.bar } })
 
     function pulsebar.update(callback)
-        if scallback then pulsebar.cmd = scallback() end
-
-        helpers.async({ awful.util.shell, "-c", pulsebar.cmd }, function(s)
+        helpers.async({ awful.util.shell, "-c", type(pulsebar.cmd) == "string" and pulsebar.cmd or pulsebar.cmd() },
+        function(s)
             volume_now = {
-                index = string.match(s, "index: (%S+)") or "N/A",
-                sink  = string.match(s, "device.string = \"(%S+)\"") or "N/A",
-                muted = string.match(s, "muted: (%S+)") or "N/A"
+                index  = string.match(s, "index: (%S+)") or "N/A",
+                device = string.match(s, "device.string = \"(%S+)\"") or "N/A",
+                muted  = string.match(s, "muted: (%S+)") or "N/A"
             }
 
             pulsebar.device = volume_now.index
@@ -93,16 +95,18 @@ local function factory(args)
             local volu = volume_now.left
             local mute = volume_now.muted
 
-            if (volu and volu ~= pulsebar._current_level) or (mute and mute ~= pulsebar._muted) then
-                pulsebar._current_level = volu
+            if volu:match("N/A") or mute:match("N/A") then return end
+
+            if volu ~= pulsebar._current_level or mute ~= pulsebar._mute then
+                pulsebar._current_level = tonumber(volu)
                 pulsebar.bar:set_value(pulsebar._current_level / 100)
-                if (not mute and volu == 0) or mute == "yes" then
-                    pulsebar._muted = true
-                    pulsebar.tooltip:set_text ("[Muted]")
+                if pulsebar._current_level == 0 or mute == "yes" then
+                    pulsebar._mute = mute
+                    pulsebar.tooltip:set_text ("[muted]")
                     pulsebar.bar.color = pulsebar.colors.mute
                 else
-                    pulsebar._muted = false
-                    pulsebar.tooltip:set_text(string.format("%s: %s", pulsebar.sink, volu))
+                    pulsebar._mute = "no"
+                    pulsebar.tooltip:set_text(string.format("%s %s: %s", pulsebar.devicetype, pulsebar.device, volu))
                     pulsebar.bar.color = pulsebar.colors.unmute
                 end
 
@@ -117,15 +121,34 @@ local function factory(args)
         pulsebar.update(function()
             local preset = pulsebar.notification_preset
 
-            if pulsebar._muted then
-                preset.title = string.format("Sink %s - Muted", pulsebar.sink)
-            else
-                preset.title = string.format("%s - %s%%", pulsebar.sink, pulsebar._current_level)
+            preset.title = string.format("%s %s - %s%%", pulsebar.devicetype, pulsebar.device, pulsebar._current_level)
+
+            if pulsebar._mute == "yes" then
+                preset.title = preset.title .. " muted"
+            end
+
+            -- tot is the maximum number of ticks to display in the notification
+            -- fallback: default horizontal wibox height
+            local wib, tot = awful.screen.focused().mywibox, 20
+
+            -- if we can grab mywibox, tot is defined as its height if
+            -- horizontal, or width otherwise
+            if wib then
+                if wib.position == "left" or wib.position == "right" then
+                    tot = wib.width
+                else
+                    tot = wib.height
+                end
             end
 
-            int = math.modf((pulsebar._current_level / 100) * awful.screen.focused().mywibox.height)
-            preset.text = string.format("[%s%s]", string.rep("|", int),
-                          string.rep(" ", awful.screen.focused().mywibox.height - int))
+            int = math.modf((pulsebar._current_level / 100) * tot)
+            preset.text = string.format(
+                "%s%s%s%s",
+                tick_pre,
+                string.rep(tick, int),
+                string.rep(tick_none, tot - int),
+                tick_post
+            )
 
             if pulsebar.followtag then preset.screen = awful.screen.focused() end
 
@@ -140,7 +163,7 @@ local function factory(args)
         end)
     end
 
-    helpers.newtimer(string.format("pulsebar-%s", pulsebar.sink), timeout, pulsebar.update)
+    helpers.newtimer(string.format("pulsebar-%s-%s", pulsebar.devicetype, pulsebar.device), timeout, pulsebar.update)
 
     return pulsebar
 end
index d35868753135b02b9ad58e41de46d98363757c2f..adf3e035ba4cf5930021e561939fa3cc42761c38 100644 (file)
@@ -1,10 +1,9 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013,      Luke Bonham                
-      * (c) 2010-2012, Peter Hofmann              
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013,      Luca CPZ
+      * (c) 2010-2012, Peter Hofmann
+
 --]]
 
 local helpers     = require("lain.helpers")
index efe2ab931dd971af9f39b44889b07ed3b7003030..e909b322f14a197b1d51f4448dc845ab18df1069 100644 (file)
@@ -1,40 +1,42 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2013, Luke Bonham                     
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2013, Luca CPZ
+
 --]]
 
 local helpers  = require("lain.helpers")
 local wibox    = require("wibox")
-local open     = io.open
 local tonumber = tonumber
 
--- coretemp
+-- {thermal,core} temperature info
 -- lain.widget.temp
 
 local function factory(args)
     local temp     = { widget = wibox.widget.textbox() }
     local args     = args or {}
-    local timeout  = args.timeout or 2
-    local tempfile = args.tempfile or "/sys/class/thermal/thermal_zone0/temp"
+    local timeout  = args.timeout or 30
+    local tempfile = args.tempfile or "/sys/devices/virtual/thermal/thermal_zone0/temp"
     local settings = args.settings or function() end
 
     function temp.update()
-        local f = open(tempfile)
-        if f then
-            coretemp_now = tonumber(f:read("*all")) / 1000
-            f:close()
-        else
-            coretemp_now = "N/A"
-        end
-
-        widget = temp.widget
-        settings()
+        helpers.async({"find", "/sys/devices", "-type", "f", "-name", "*temp*"}, function(f)
+            temp_now = {}
+            local temp_fl, temp_value
+            for t in f:gmatch("[^\n]+") do
+                temp_fl = helpers.first_line(t)
+                if temp_fl then
+                    temp_value = tonumber(temp_fl)
+                    temp_now[t] = temp_value and temp_value/1e3 or temp_fl
+                end
+            end
+            coretemp_now = temp_now[tempfile] or "N/A"
+            widget = temp.widget
+            settings()
+        end)
     end
 
-    helpers.newtimer("coretemp", timeout, temp.update)
+    helpers.newtimer("thermal", timeout, temp.update)
 
     return temp
 end
diff --git a/.config/awesome/lain/widget/watch.lua b/.config/awesome/lain/widget/watch.lua
deleted file mode 100644 (file)
index 36118b8..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-
---[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2014, Luke Bonham                     
-                                                  
---]]
-
-local helpers = require("lain.helpers")
-local textbox = require("wibox.widget.textbox")
-
--- Template for asynchronous watcher widgets
--- lain.widget.watch
-
-local function factory(args)
-    local watch     = { widget = args.widget or textbox() }
-    local args      = args or {}
-    local timeout   = args.timeout or 5
-    local nostart   = args.nostart or false
-    local stoppable = args.stoppable or false
-    local cmd       = args.cmd
-    local settings  = args.settings or function() widget:set_text(output) end
-
-    function watch.update()
-        helpers.async(cmd, function(f)
-            output = f
-            if output ~= watch.prev then
-                widget = watch.widget
-                settings()
-                watch.prev = output
-            end
-        end)
-    end
-
-    watch.timer = helpers.newtimer(cmd, timeout, watch.update, nostart, stoppable)
-
-    return watch
-end
-
-return factory
index 10981466179f600900ca27c56c04d931a780c1dd..9c1e797fe8bb69eabc47b10f0b22f53395310ab3 100644 (file)
@@ -1,9 +1,8 @@
-
 --[[
-                                                  
-     Licensed under GNU General Public License v2 
-      * (c) 2015, Luke Bonham                     
-                                                  
+
+     Licensed under GNU General Public License v2
+      * (c) 2015, Luca CPZ
+
 --]]
 
 local helpers  = require("lain.helpers")
@@ -11,12 +10,10 @@ local json     = require("lain.util").dkjson
 local focused  = require("awful.screen").focused
 local naughty  = require("naughty")
 local wibox    = require("wibox")
-local math     = { floor    = math.floor }
-local os       = { time     = os.time,
-                   date     = os.date,
-                   difftime = os.difftime }
-local string   = { format   = string.format,
-                   gsub     = string.gsub }
+local math     = math
+local os       = os
+local string   = string
+local type     = type
 local tonumber = tonumber
 
 -- OpenWeatherMap
@@ -26,17 +23,12 @@ local tonumber = tonumber
 local function factory(args)
     local weather               = { widget = wibox.widget.textbox() }
     local args                  = args or {}
-    local APPID                 = args.APPID or "3e321f9414eaedbfab34983bda77a66e" -- lain default
-    local timeout               = args.timeout or 900   -- 15 min
-    local timeout_forecast      = args.timeout or 86400 -- 24 hrs
+    local APPID                 = args.APPID or "3e321f9414eaedbfab34983bda77a66e" -- lain's default
+    local timeout               = args.timeout or 60 * 15 -- 15 min
+    local timeout_forecast      = args.timeout or 60 * 60 * 24 -- 24 hrs
     local current_call          = args.current_call  or "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s&APPID=%s'"
     local forecast_call         = args.forecast_call or "curl -s 'http://api.openweathermap.org/data/2.5/forecast/daily?id=%s&units=%s&lang=%s&cnt=%s&APPID=%s'"
     local city_id               = args.city_id or 0 -- placeholder
-    local utc_offset            = args.utc_offset or
-                                  function ()
-                                      local now = os.time()
-                                      return os.difftime(now, os.time(os.date("!*t", now))) + ((os.date("*t").isdst and 1 or 0) * 3600)
-                                  end
     local units                 = args.units or "metric"
     local lang                  = args.lang or "en"
     local cnt                   = args.cnt or 5
@@ -53,13 +45,14 @@ local function factory(args)
                                   end
     local weather_na_markup     = args.weather_na_markup or " N/A "
     local followtag             = args.followtag or false
+    local showpopup             = args.showpopup or "on"
     local settings              = args.settings or function() end
 
     weather.widget:set_markup(weather_na_markup)
     weather.icon_path = icons_path .. "na.png"
     weather.icon = wibox.widget.imagebox(weather.icon_path)
 
-    function weather.show(t_out)
+    function weather.show(seconds)
         weather.hide()
 
         if followtag then
@@ -71,12 +64,12 @@ local function factory(args)
             weather.forecast_update()
         end
 
-        weather.notification = naughty.notify({
+        weather.notification = naughty.notify {
+            preset  = notification_preset,
             text    = weather.notification_text,
             icon    = weather.icon_path,
-            timeout = t_out,
-            preset  = notification_preset
-        })
+            timeout = type(seconds == "number") and seconds or notification_preset.timeout
+        }
     end
 
     function weather.hide()
@@ -102,11 +95,10 @@ local function factory(args)
             weather_now, pos, err = json.decode(f, 1, nil)
 
             if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then
-                weather.notification_text = ''
+                weather.notification_text = ""
                 for i = 1, weather_now["cnt"] do
                     weather.notification_text = weather.notification_text ..
                                                 notification_text_fun(weather_now["list"][i])
-
                     if i < weather_now["cnt"] then
                         weather.notification_text = weather.notification_text .. "\n"
                     end
@@ -122,29 +114,12 @@ local function factory(args)
             weather_now, pos, err = json.decode(f, 1, nil)
 
             if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then
-                -- weather icon based on localtime
-                local now     = os.time()
                 local sunrise = tonumber(weather_now["sys"]["sunrise"])
                 local sunset  = tonumber(weather_now["sys"]["sunset"])
                 local icon    = weather_now["weather"][1]["icon"]
-                local loc_m   = os.time { year = os.date("%Y"), month = os.date("%m"), day = os.date("%d"), hour = 0 }
-                local offset  = utc_offset()
-                local utc_m   = loc_m - offset
-
-                if offset > 0 and (now - utc_m)>=86400 then
-                    utc_m = utc_m + 86400
-                elseif offset < 0 and (utc_m - now)>=86400 then
-                    utc_m = utc_m - 86400
-                end
-
-                -- if we are 1 day after the GMT, return 1 day back, and viceversa
-                if offset > 0 and loc_m >= utc_m then
-                    now = now - 86400
-                elseif offset < 0 and loc_m <= utc_m then
-                    now = now + 86400
-                end
+                local loc_now = os.time()
 
-                if sunrise <= now and now <= sunset then
+                if sunrise <= loc_now and loc_now <= sunset then
                     icon = string.gsub(icon, "n", "d")
                 else
                     icon = string.gsub(icon, "d", "n")
@@ -162,7 +137,7 @@ local function factory(args)
         end)
     end
 
-    weather.attach(weather.widget)
+    if showpopup == "on" then weather.attach(weather.widget) end
 
     weather.timer = helpers.newtimer("weather-" .. city_id, timeout, weather.update, false, true)
     weather.timer_forecast = helpers.newtimer("weather_forecast-" .. city_id, timeout, weather.forecast_update, false, true)
index d6cf027a4c2535c179a8112137d065a5bc740fea..2899629c445cb12efb72cc538e36cfc2ec812201 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d6cf027a4c2535c179a8112137d065a5bc740fea
+Subproject commit 2899629c445cb12efb72cc538e36cfc2ec812201