Browse Source

Change to awesome wm. The awesome files contained are not git tracked from this repo. It might be a good idea to switch them to git tracking eventually

master
Taylor Bockman 9 years ago
parent
commit
f184c81a9d
  1. 143
      dotfiles/awesome/README.rst
  2. 57
      dotfiles/awesome/eminent/init.lua
  3. 47
      dotfiles/awesome/lain/README.rst
  4. 72
      dotfiles/awesome/lain/asyncshell.lua
  5. 116
      dotfiles/awesome/lain/helpers.lua
  6. BIN
      dotfiles/awesome/lain/icons/cal/white/1.png
  7. BIN
      dotfiles/awesome/lain/icons/cal/white/10.png
  8. BIN
      dotfiles/awesome/lain/icons/cal/white/11.png
  9. BIN
      dotfiles/awesome/lain/icons/cal/white/12.png
  10. BIN
      dotfiles/awesome/lain/icons/cal/white/13.png
  11. BIN
      dotfiles/awesome/lain/icons/cal/white/14.png
  12. BIN
      dotfiles/awesome/lain/icons/cal/white/15.png
  13. BIN
      dotfiles/awesome/lain/icons/cal/white/16.png
  14. BIN
      dotfiles/awesome/lain/icons/cal/white/17.png
  15. BIN
      dotfiles/awesome/lain/icons/cal/white/18.png
  16. BIN
      dotfiles/awesome/lain/icons/cal/white/19.png
  17. BIN
      dotfiles/awesome/lain/icons/cal/white/2.png
  18. BIN
      dotfiles/awesome/lain/icons/cal/white/20.png
  19. BIN
      dotfiles/awesome/lain/icons/cal/white/21.png
  20. BIN
      dotfiles/awesome/lain/icons/cal/white/22.png
  21. BIN
      dotfiles/awesome/lain/icons/cal/white/23.png
  22. BIN
      dotfiles/awesome/lain/icons/cal/white/24.png
  23. BIN
      dotfiles/awesome/lain/icons/cal/white/25.png
  24. BIN
      dotfiles/awesome/lain/icons/cal/white/26.png
  25. BIN
      dotfiles/awesome/lain/icons/cal/white/27.png
  26. BIN
      dotfiles/awesome/lain/icons/cal/white/28.png
  27. BIN
      dotfiles/awesome/lain/icons/cal/white/29.png
  28. BIN
      dotfiles/awesome/lain/icons/cal/white/3.png
  29. BIN
      dotfiles/awesome/lain/icons/cal/white/30.png
  30. BIN
      dotfiles/awesome/lain/icons/cal/white/31.png
  31. BIN
      dotfiles/awesome/lain/icons/cal/white/4.png
  32. BIN
      dotfiles/awesome/lain/icons/cal/white/5.png
  33. BIN
      dotfiles/awesome/lain/icons/cal/white/6.png
  34. BIN
      dotfiles/awesome/lain/icons/cal/white/7.png
  35. BIN
      dotfiles/awesome/lain/icons/cal/white/8.png
  36. BIN
      dotfiles/awesome/lain/icons/cal/white/9.png
  37. BIN
      dotfiles/awesome/lain/icons/layout/default/cascade.png
  38. BIN
      dotfiles/awesome/lain/icons/layout/default/cascadebrowse.png
  39. BIN
      dotfiles/awesome/lain/icons/layout/default/cascadebrowsew.png
  40. BIN
      dotfiles/awesome/lain/icons/layout/default/cascadew.png
  41. BIN
      dotfiles/awesome/lain/icons/layout/default/centerfair.png
  42. BIN
      dotfiles/awesome/lain/icons/layout/default/centerfairw.png
  43. BIN
      dotfiles/awesome/lain/icons/layout/default/centerwork.png
  44. BIN
      dotfiles/awesome/lain/icons/layout/default/centerworkw.png
  45. BIN
      dotfiles/awesome/lain/icons/layout/default/termfair.png
  46. BIN
      dotfiles/awesome/lain/icons/layout/default/termfairw.png
  47. BIN
      dotfiles/awesome/lain/icons/layout/zenburn/cascade.png
  48. BIN
      dotfiles/awesome/lain/icons/layout/zenburn/cascadebrowse.png
  49. BIN
      dotfiles/awesome/lain/icons/layout/zenburn/centerfair.png
  50. BIN
      dotfiles/awesome/lain/icons/layout/zenburn/centerwork.png
  51. BIN
      dotfiles/awesome/lain/icons/layout/zenburn/termfair.png
  52. BIN
      dotfiles/awesome/lain/icons/mail.png
  53. BIN
      dotfiles/awesome/lain/icons/no_net.png
  54. BIN
      dotfiles/awesome/lain/icons/openweathermap/01d.png
  55. BIN
      dotfiles/awesome/lain/icons/openweathermap/01n.png
  56. BIN
      dotfiles/awesome/lain/icons/openweathermap/02d.png
  57. BIN
      dotfiles/awesome/lain/icons/openweathermap/02n.png
  58. BIN
      dotfiles/awesome/lain/icons/openweathermap/03d.png
  59. BIN
      dotfiles/awesome/lain/icons/openweathermap/03n.png
  60. BIN
      dotfiles/awesome/lain/icons/openweathermap/04d.png
  61. 1
      dotfiles/awesome/lain/icons/openweathermap/04n.png
  62. BIN
      dotfiles/awesome/lain/icons/openweathermap/09d.png
  63. 1
      dotfiles/awesome/lain/icons/openweathermap/09n.png
  64. BIN
      dotfiles/awesome/lain/icons/openweathermap/10d.png
  65. 1
      dotfiles/awesome/lain/icons/openweathermap/10n.png
  66. BIN
      dotfiles/awesome/lain/icons/openweathermap/11d.png
  67. 1
      dotfiles/awesome/lain/icons/openweathermap/11n.png
  68. BIN
      dotfiles/awesome/lain/icons/openweathermap/13d.png
  69. 1
      dotfiles/awesome/lain/icons/openweathermap/13n.png
  70. BIN
      dotfiles/awesome/lain/icons/openweathermap/50d.png
  71. 1
      dotfiles/awesome/lain/icons/openweathermap/50n.png
  72. 3
      dotfiles/awesome/lain/icons/openweathermap/README.md
  73. BIN
      dotfiles/awesome/lain/icons/openweathermap/na.png
  74. BIN
      dotfiles/awesome/lain/icons/redshift/redshift_off.png
  75. BIN
      dotfiles/awesome/lain/icons/redshift/redshift_on.png
  76. BIN
      dotfiles/awesome/lain/icons/taskwarrior/task.png
  77. BIN
      dotfiles/awesome/lain/icons/taskwarrior/tasksmall.png
  78. 21
      dotfiles/awesome/lain/init.lua
  79. 80
      dotfiles/awesome/lain/layout/cascade.lua
  80. 167
      dotfiles/awesome/lain/layout/cascadetile.lua
  81. 163
      dotfiles/awesome/lain/layout/centerfair.lua
  82. 131
      dotfiles/awesome/lain/layout/centerwork.lua
  83. 20
      dotfiles/awesome/lain/layout/init.lua
  84. 138
      dotfiles/awesome/lain/layout/termfair.lua
  85. 108
      dotfiles/awesome/lain/layout/uselessfair.lua
  86. 123
      dotfiles/awesome/lain/layout/uselesspiral.lua
  87. 226
      dotfiles/awesome/lain/layout/uselesstile.lua
  88. 387
      dotfiles/awesome/lain/scripts/dfs
  89. 68
      dotfiles/awesome/lain/scripts/mpdcover
  90. 713
      dotfiles/awesome/lain/util/dkjson.lua
  91. 229
      dotfiles/awesome/lain/util/init.lua
  92. 69
      dotfiles/awesome/lain/util/markup.lua
  93. 102
      dotfiles/awesome/lain/util/separators.lua
  94. 41
      dotfiles/awesome/lain/widgets/abase.lua
  95. 68
      dotfiles/awesome/lain/widgets/alsa.lua
  96. 179
      dotfiles/awesome/lain/widgets/alsabar.lua
  97. 39
      dotfiles/awesome/lain/widgets/base.lua
  98. 149
      dotfiles/awesome/lain/widgets/bat.lua
  99. 62
      dotfiles/awesome/lain/widgets/borderbox.lua
  100. 140
      dotfiles/awesome/lain/widgets/calendar.lua
  101. Some files were not shown because too many files have changed in this diff Show More

143
dotfiles/awesome/README.rst

@ -0,0 +1,143 @@
===================
Awesome WM Copycats
===================
--------------------------------
Power themes for Awesome WM 3.5+
--------------------------------
:Author: Luke Bonham <dada [at] archlinux [dot] info>
:Version: git
:License: BY-NC-SA_
:Source: https://github.com/copycat-killer/awesome-copycats
Description
===========
A set of themes with the aim of making Awesome_ appearance awesome too!
Notable features
================
- Autohide widgets (*tell me only when you have to*)
- Autostart applications
- Fast MPD and volume shortcuts (first time you see this trick in Awesome)
- Other shortcuts for copying to the clipboard (goodbye clipboard managers!), toggle wiboxes, widgets popups, screenshots capture, moving and magnifying clients
- Quake drop-down terminal
- Calendar with current day highlighted and months switch with a click
- Elegant notifications for new mails, current song, volume level, hdd critical state, low battery
- OpenWeatherMap integration
- Net carrier status notifier
- Colorful autoupdating icons
- Symbolic tag names
- TXT layoutbox
- PNG wibox bar
- Custom layouts
- No borders when there's only one visible client
- Powerful volume bar
- Menubar menu
- Vi-like client focus
- Nice client border (colors change along with processes status)
- Non-empty tag browsing
- Dynamic useless gaps
- Dynamic tagging
Gallery
=======
**Multicolor** inspired by tip_
.. image:: http://dotshare.it/public/images/uploads/650.png
**Powerarrow Darker** inspired by romockee_
.. image:: http://dotshare.it/public/images/uploads/649.png
**Steamburn** copycatted from ok100_ [porting from dwm]
.. image:: http://dotshare.it/public/images/uploads/648.png
**Blackburn**
.. image:: http://dotshare.it/public/images/uploads/553.png
**Dremora**
.. image:: http://dotshare.it/public/images/uploads/652.png
**Rainbow**
.. image:: http://dotshare.it/public/images/uploads/606.png
**Holo** requested by amouly_
.. image:: http://dotshare.it/public/images/uploads/651.png
**Copland** inspired by foozer_
.. image:: http://dotshare.it/public/images/uploads/655.png
Installation
============
Using git you can have the full master branch: ::
git clone --recursive https://github.com/copycat-killer/awesome-copycats.git
then, move the contents of `awesome-copycats` to `~/.config/awesome`.
Otherwise, download the latest two masters of ``awesome-copycats`` and ``lain`` (1_ and 2_), extract the first one, extract the second one into the first one, and put the contents of the first one into your Awesome directory.
Usage
=====
Switch a theme this way: ::
cd ~/.config/awesome
cp rc.lua.theme rc.lua
Alternatively, you can use `switch-theme.sh`_, which will also update to the latest commit.
Then customize your ``rc.lua`` and restart Awesome (``Mod4 + ctrl + r``).
Notes
=====
Only compatible with **stable** versions of Lua and Awesome (git/unstable versions are *not* supported).
Complements are provided by lain_: be sure to meet its dependencies_.
Fonts are Terminus_ (Multicolor, Powerarrow Darker) and Tamsyn_ (other ones).
Every theme has a colorscheme_.
Blackburn and Dremora use Icons_: be sure to have bitmaps enabled if running under Debian_ or Ubuntu_.
Feel free to email me if you have any request.
Notable forks
=============
Does your fork look very nice? You can send it to me!
The best ones will be linked here.
.. _BY-NC-SA: http://creativecommons.org/licenses/by-nc-sa/4.0/
.. _Awesome: http://awesome.naquadah.org/
.. _tip: https://bbs.archlinux.org/profile.php?id=51327
.. _romockee: https://github.com/romockee/powerarrow
.. _ok100: http://ok100.deviantart.com/art/DWM-January-2013-348656846
.. _amouly: https://bbs.archlinux.org/viewtopic.php?pid=1307158#p1307158
.. _foozer: http://dotshare.it/dots/499/
.. _1: https://github.com/copycat-killer/awesome-copycats/archive/master.zip
.. _2: https://github.com/copycat-killer/lain/archive/master.zip
.. _`switch-theme.sh`: https://github.com/copycat-killer/awesome-copycats/issues/36
.. _lain: https://github.com/copycat-killer/lain
.. _dependencies: https://github.com/copycat-killer/lain/wiki
.. _Terminus: http://terminus-font.sourceforge.net/
.. _Tamsyn: http://www.fial.com/~scott/tamsyn-font/
.. _colorscheme: https://github.com/copycat-killer/dots/tree/master/.colors
.. _Icons: https://github.com/copycat-killer/dots/tree/master/.fonts
.. _Debian: http://weiwu.sdf.org/100921.html
.. _Ubuntu: https://wiki.ubuntu.com/Fonts#Enabling_Bitmapped_Fonts

57
dotfiles/awesome/eminent/init.lua

@ -0,0 +1,57 @@
------------------------------------------
-- Effortless wmii-style dynamic tagging.
------------------------------------------
-- Lucas de Vries <lucas@glacicle.org>
-- Licensed under the WTFPL version 2
-- * http://sam.zoy.org/wtfpl/COPYING
-----------------------------------------
-- Cut version
-----------------------------------------
-- Grab environment
local ipairs = ipairs
local awful = require("awful")
local table = table
local capi = {
screen = screen,
}
-- Eminent: Effortless wmii-style dynamic tagging
module("eminent")
-- Grab the original functions we're replacing
local deflayout = nil
local orig = {
new = awful.tag.new,
taglist = awful.widget.taglist.new,
filter = awful.widget.taglist.filter.all,
}
-- Return tags with stuff on them, mark others hidden
function gettags(screen)
local tags = {}
for k, t in ipairs(capi.screen[screen]:tags()) do
if t.selected or #t:clients() > 0 then
awful.tag.setproperty(t, "hide", false)
table.insert(tags, t)
else
awful.tag.setproperty(t, "hide", true)
end
end
return tags
end
-- Pre-create tags
awful.tag.new = function (names, screen, layout)
deflayout = layout and layout[1] or layout
return orig.new(names, screen, layout)
end
-- Taglist label functions
awful.widget.taglist.filter.all = function (t, args)
if t.selected or #t:clients() > 0 then
return orig.filter(t, args)
end
end

47
dotfiles/awesome/lain/README.rst

@ -0,0 +1,47 @@
Lain
====
--------------------------------------------------
Layouts, widgets and utilities for Awesome WM 3.5+
--------------------------------------------------
:Author: Luke Bonham <dada [at] archlinux [dot] info>
:Version: git
:License: GNU-GPL2_
:Source: https://github.com/copycat-killer/lain
Description
-----------
Successor of awesome-vain_, this module provides new layouts, a set of widgets and utility functions, in order to improve Awesome_ usability and configurability.
Read the wiki_ for all the info.
Contributions
-------------
Any contribution is welcome! Feel free to make a pull request.
Just make sure that:
- Your code fits with the general style of the module. In particular, you should use the same indentation pattern that the code uses, and also avoid adding space at the ends of lines.
- Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions or using ``lain.helpers``. If something is unclear, and you can't write it in such a way that it will be clear, explain it with a comment.
- You test your changes before submitting to make sure that not only your code works, but did not break other parts of the module too!
- You eventually update ``wiki`` submodule with a thorough section.
Contributed widgets have to be put in ``lain/widgets/contrib``.
Screenshots
-----------
.. image:: http://i.imgur.com/8D9A7lW.png
.. image:: http://i.imgur.com/9Iv3OR3.png
.. image:: http://i.imgur.com/STCPcaJ.png
.. _GNU-GPL2: http://www.gnu.org/licenses/gpl-2.0.html
.. _awesome-vain: https://github.com/vain/awesome-vain
.. _Awesome: http://awesome.naquadah.org/
.. _wiki: https://github.com/copycat-killer/lain/wiki

72
dotfiles/awesome/lain/asyncshell.lua

@ -0,0 +1,72 @@
--[[
Licensed under GNU General Public License v2
* (c) 2015, worron
* (c) 2013, Alexander Yakushev
--]]
-- Asynchronous io.popen for Awesome WM.
-- How to use:
-- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end)
-- Grab environment
local awful = require('awful')
-- Initialize tables for module
asyncshell = { request_table = {}, id_counter = 0 }
-- Request counter
local function next_id()
asyncshell.id_counter = (asyncshell.id_counter + 1) % 10000
return asyncshell.id_counter
end
-- Remove given request
function asyncshell.clear(id)
if asyncshell.request_table[id] then
if asyncshell.request_table[id].timer then
asyncshell.request_table[id].timer:stop()
asyncshell.request_table[id].timer = nil
end
asyncshell.request_table[id] = nil
end
end
-- Sends an asynchronous request for an output of the shell command
-- @param command Command to be executed and taken output from
-- @param callback Function to be called when the command finishes
-- @param timeout Maximum amount of time to wait for the result (optional)
function asyncshell.request(command, callback, timeout)
local id = next_id()
asyncshell.request_table[id] = { callback = callback }
local formatted_command = string.gsub(command, '"','\"')
local req = string.format(
"echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &",
id, formatted_command
)
awful.util.spawn_with_shell(req)
if timeout then
asyncshell.request_table[id].timer = timer({ timeout = timeout })
asyncshell.request_table[id].timer:connect_signal("timeout", function() asyncshell.clear(id) end)
asyncshell.request_table[id].timer:start()
end
end
-- Calls the remembered callback function on the output of the shell command
-- @param id Request ID
-- @param output Shell command output to be delievered
function asyncshell.deliver(id, output)
local output = string.sub(output, 2, -2)
if asyncshell.request_table[id] then
asyncshell.request_table[id].callback(output)
asyncshell.clear(id)
end
end
return asyncshell

116
dotfiles/awesome/lain/helpers.lua

@ -0,0 +1,116 @@
--[[
Licensed under GNU General Public License v2
* (c) 2013, Luke Bonham
--]]
local debug = require("debug")
local capi = { timer = timer }
local io = { open = io.open,
lines = io.lines,
popen = io.popen }
local rawget = rawget
-- Lain helper functions for internal use
-- lain.helpers
local helpers = {}
helpers.lain_dir = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
helpers.icons_dir = helpers.lain_dir .. 'icons/'
helpers.scripts_dir = helpers.lain_dir .. 'scripts/'
-- {{{ Modules loader
function helpers.wrequire(table, key)
local module = rawget(table, key)
return module or require(table._NAME .. '.' .. key)
end
-- }}}
-- {{{ File operations
-- see if the file exists and is readable
function helpers.file_exists(file)
local f = io.open(file)
if f then
local s = f:read()
f:close()
f = s
end
return f ~= nil
end
-- get all lines from a file, returns an empty
-- list/table if the file does not exist
function helpers.lines_from(file)
if not helpers.file_exists(file) then return {} end
lines = {}
for line in io.lines(file) do
lines[#lines + 1] = line
end
return lines
end
-- get first line of a file, return nil if
-- the file does not exist
function helpers.first_line(file)
return helpers.lines_from(file)[1]
end
-- get first non empty line from a file,
-- returns nil otherwise
function helpers.first_nonempty_line(file)
for k,v in pairs(helpers.lines_from(file)) do
if #v then return v end
end
return nil
end
-- }}}
-- {{{ Timer maker
helpers.timer_table = {}
function helpers.newtimer(name, timeout, fun, nostart)
helpers.timer_table[name] = capi.timer({ timeout = timeout })
helpers.timer_table[name]:connect_signal("timeout", fun)
helpers.timer_table[name]:start()
if not nostart then
helpers.timer_table[name]:emit_signal("timeout")
end
end
-- }}}
-- {{{ Pipe operations
-- read the full output of a pipe (command)
function helpers.read_pipe(cmd)
local f = assert(io.popen(cmd))
local output = f:read("*all")
f:close()
return output
end
-- }}}
-- {{{ A map utility
helpers.map_table = {}
function helpers.set_map(element, value)
helpers.map_table[element] = value
end
function helpers.get_map(element)
return helpers.map_table[element]
end
-- }}}
return helpers

BIN
dotfiles/awesome/lain/icons/cal/white/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

BIN
dotfiles/awesome/lain/icons/cal/white/10.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/11.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/12.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/14.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/15.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/17.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/18.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/19.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/20.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/21.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/22.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/23.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/24.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/25.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/26.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/27.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/28.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/29.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/30.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/31.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/8.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
dotfiles/awesome/lain/icons/cal/white/9.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
dotfiles/awesome/lain/icons/layout/default/cascade.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

BIN
dotfiles/awesome/lain/icons/layout/default/cascadebrowse.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

BIN
dotfiles/awesome/lain/icons/layout/default/cascadebrowsew.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

BIN
dotfiles/awesome/lain/icons/layout/default/cascadew.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

BIN
dotfiles/awesome/lain/icons/layout/default/centerfair.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

BIN
dotfiles/awesome/lain/icons/layout/default/centerfairw.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

BIN
dotfiles/awesome/lain/icons/layout/default/centerwork.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

BIN
dotfiles/awesome/lain/icons/layout/default/centerworkw.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

BIN
dotfiles/awesome/lain/icons/layout/default/termfair.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

BIN
dotfiles/awesome/lain/icons/layout/default/termfairw.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

BIN
dotfiles/awesome/lain/icons/layout/zenburn/cascade.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

BIN
dotfiles/awesome/lain/icons/layout/zenburn/cascadebrowse.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

BIN
dotfiles/awesome/lain/icons/layout/zenburn/centerfair.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

BIN
dotfiles/awesome/lain/icons/layout/zenburn/centerwork.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

BIN
dotfiles/awesome/lain/icons/layout/zenburn/termfair.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

BIN
dotfiles/awesome/lain/icons/mail.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

BIN
dotfiles/awesome/lain/icons/no_net.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
dotfiles/awesome/lain/icons/openweathermap/01d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
dotfiles/awesome/lain/icons/openweathermap/01n.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
dotfiles/awesome/lain/icons/openweathermap/02d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
dotfiles/awesome/lain/icons/openweathermap/02n.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
dotfiles/awesome/lain/icons/openweathermap/03d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
dotfiles/awesome/lain/icons/openweathermap/03n.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
dotfiles/awesome/lain/icons/openweathermap/04d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

1
dotfiles/awesome/lain/icons/openweathermap/04n.png

@ -0,0 +1 @@
04d.png

BIN
dotfiles/awesome/lain/icons/openweathermap/09d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

1
dotfiles/awesome/lain/icons/openweathermap/09n.png

@ -0,0 +1 @@
09d.png

BIN
dotfiles/awesome/lain/icons/openweathermap/10d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

1
dotfiles/awesome/lain/icons/openweathermap/10n.png

@ -0,0 +1 @@
10d.png

BIN
dotfiles/awesome/lain/icons/openweathermap/11d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

1
dotfiles/awesome/lain/icons/openweathermap/11n.png

@ -0,0 +1 @@
11d.png

BIN
dotfiles/awesome/lain/icons/openweathermap/13d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

1
dotfiles/awesome/lain/icons/openweathermap/13n.png

@ -0,0 +1 @@
13d.png

BIN
dotfiles/awesome/lain/icons/openweathermap/50d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

1
dotfiles/awesome/lain/icons/openweathermap/50n.png

@ -0,0 +1 @@
50d.png

3
dotfiles/awesome/lain/icons/openweathermap/README.md

@ -0,0 +1,3 @@
[Plain Weather Icons](http://merlinthered.deviantart.com/art/plain-weather-icons-157162192), created by [MerlinTheRed](http://merlinthered.deviantart.com/).
<a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"><img src="http://i.creativecommons.org/l/by-nc-sa/2.5/80x15.png" align="right"></a>

BIN
dotfiles/awesome/lain/icons/openweathermap/na.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
dotfiles/awesome/lain/icons/redshift/redshift_off.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

BIN
dotfiles/awesome/lain/icons/redshift/redshift_on.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

BIN
dotfiles/awesome/lain/icons/taskwarrior/task.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
dotfiles/awesome/lain/icons/taskwarrior/tasksmall.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

21
dotfiles/awesome/lain/init.lua

@ -0,0 +1,21 @@
--[[
Lain
Layouts, widgets and utilities for Awesome WM
Licensed under GNU General Public License v2
* (c) 2013, Luke Bonham
--]]
package.loaded.lain = nil
local lain =
{
layout = require("lain.layout"),
util = require("lain.util"),
widgets = require("lain.widgets")
}
return lain

80
dotfiles/awesome/lain/layout/cascade.lua

@ -0,0 +1,80 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, projektile
* (c) 2013, Luke Bonham
* (c) 2010-2012, Peter Hofmann
--]]
local tag = require("awful.tag")
local beautiful = require("beautiful")
local cascade =
{
name = "cascade",
nmaster = 0,
offset_x = 32,
offset_y = 8
}
function cascade.arrange(p)
-- Cascade windows.
-- A global border can be defined with
-- beautiful.global_border_width.
local global_border = tonumber(beautiful.global_border_width) or 0
if global_border < 0 then global_border = 0 end
-- Themes border width requires an offset.
local bw = tonumber(beautiful.border_width) or 0
-- Screen.
local wa = p.workarea
local cls = p.clients
wa.height = wa.height - ((global_border * 2) + (bw * 2))
wa.width = wa.width - ((global_border * 2) + (bw * 2))
wa.x = wa.x + global_border
wa.y = wa.y + global_border
-- Opening a new window will usually force all existing windows to
-- get resized. This wastes a lot of CPU time. So let's set a lower
-- bound to "how_many": This wastes a little screen space but you'll
-- get a much better user experience.
local t = tag.selected(p.screen)
local num_c
if cascade.nmaster > 0
then
num_c = cascade.nmaster
else
num_c = tag.getnmaster(t)
end
local how_many = #cls
if how_many < num_c
then
how_many = num_c
end
local current_offset_x = cascade.offset_x * (how_many - 1)
local current_offset_y = cascade.offset_y * (how_many - 1)
-- Iterate.
for i = 1,#cls,1
do
local c = cls[i]
local g = {}
g.x = wa.x + (how_many - i) * cascade.offset_x
g.y = wa.y + (i - 1) * cascade.offset_y
g.width = wa.width - current_offset_x
g.height = wa.height - current_offset_y
c:geometry(g)
end
end
return cascade

167
dotfiles/awesome/lain/layout/cascadetile.lua

@ -0,0 +1,167 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, projektile
* (c) 2013, Luke Bonham
* (c) 2010-2012, Peter Hofmann
--]]
local tag = require("awful.tag")
local beautiful = require("beautiful")
local tonumber = tonumber
local cascadetile =
{
name = "cascadetile",
nmaster = 0,
ncol = 0,
mwfact = 0,
offset_x = 5,
offset_y = 32,
extra_padding = 0
}
function cascadetile.arrange(p)
-- Layout with one fixed column meant for a master window. Its
-- width is calculated according to mwfact. Other clients are
-- cascaded or "tabbed" in a slave column on the right.
-- It's a bit hard to demonstrate the behaviour with ASCII-images...
--
-- (1) (2) (3) (4)
-- +----------+---+ +----------+---+ +----------+---+ +----------+---+
-- | | | | | 3 | | | 4 | | +---+|
-- | | | -> | | | -> | +---++ -> | +---+|+
-- | 1 | 2 | | 1 +---++ | 1 | 3 || | 1 +---+|+|
-- | | | | | 2 || | +---++| | +---+|+ |
-- | | | | | || | | 2 | | | | 2 |+ |
-- +----------+---+ +---------+---++ +--------+---+-+ +------+---+---+
-- A useless gap (like the dwm patch) can be defined with
-- beautiful.useless_gap_width.
local useless_gap = tonumber(beautiful.useless_gap_width) or 0
if useless_gap < 0 then useless_gap = 0 end
-- A global border can be defined with
-- beautiful.global_border_width
local global_border = tonumber(beautiful.global_border_width) or 0
if global_border < 0 then global_border = 0 end
-- Themes border width requires an offset
local bw = tonumber(beautiful.border_width) or 0
-- Screen.
local wa = p.workarea
local cls = p.clients
-- Borders are factored in.
wa.height = wa.height - ((global_border * 2) + (bw * 2))
wa.width = wa.width - ((global_border * 2) + (bw * 2))
-- Width of main column?
local t = tag.selected(p.screen)
local mwfact
if cascadetile.mwfact > 0
then
mwfact = cascadetile.mwfact
else
mwfact = tag.getmwfact(t)
end
-- Make slave windows overlap main window? Do this if ncol is 1.
local overlap_main
if cascadetile.ncol > 0
then
overlap_main = cascadetile.ncol
else
overlap_main = tag.getncol(t)
end
-- Minimum space for slave windows? See cascade.lua.
local num_c
if cascadetile.nmaster > 0
then
num_c = cascadetile.nmaster
else
num_c = tag.getnmaster(t)
end
local how_many = #cls - 1
if how_many < num_c
then
how_many = num_c
end
local current_offset_x = cascadetile.offset_x * (how_many - 1)
local current_offset_y = cascadetile.offset_y * (how_many - 1)
if #cls > 0
then
-- Main column, fixed width and height.
local c = cls[#cls]
local g = {}
local mainwid = wa.width * mwfact
local slavewid = wa.width - mainwid
if overlap_main == 1
then
g.width = wa.width
-- The size of the main window may be reduced a little bit.
-- This allows you to see if there are any windows below the
-- main window.
-- This only makes sense, though, if the main window is
-- overlapping everything else.
g.width = g.width - cascadetile.extra_padding
else
g.width = mainwid
end
g.height = wa.height
g.x = wa.x + global_border
g.y = wa.y + global_border
if useless_gap > 0
then
-- Reduce width once and move window to the right. Reduce
-- height twice, however.
g.width = g.width - useless_gap
g.height = g.height - 2 * useless_gap
g.x = g.x + useless_gap
g.y = g.y + useless_gap
-- When there's no window to the right, add an additional
-- gap.
if overlap_main == 1
then
g.width = g.width - useless_gap
end
end
c:geometry(g)
-- Remaining clients stacked in slave column, new ones on top.
if #cls > 1
then
for i = (#cls - 1),1,-1
do
c = cls[i]
g = {}
g.width = slavewid - current_offset_x
g.height = wa.height - current_offset_y
g.x = wa.x + mainwid + (how_many - i) * cascadetile.offset_x
g.y = wa.y + (i - 1) * cascadetile.offset_y + global_border
if useless_gap > 0
then
g.width = g.width - 2 * useless_gap
g.height = g.height - 2 * useless_gap
g.x = g.x + useless_gap
g.y = g.y + useless_gap
end
c:geometry(g)
end
end
end
end
return cascadetile

163
dotfiles/awesome/lain/layout/centerfair.lua

@ -0,0 +1,163 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, projektile
* (c) 2013, Luke Bonham
* (c) 2010, Nicolas Estibals
* (c) 2010-2012, Peter Hofmann
--]]
local tag = require("awful.tag")
local beautiful = require("beautiful")
local math = { ceil = math.ceil,
floor = math.floor,
max = math.max }
local tonumber = tonumber
local centerfair = { name = "centerfair" }
function centerfair.arrange(p)
-- Layout with fixed number of vertical columns (read from nmaster).
-- Cols are centerded until there is nmaster columns, then windows
-- are stacked in the slave columns, with at most ncol clients per
-- column if possible.
-- with nmaster=3 and ncol=1 you'll have
-- (1) (2) (3)
-- +---+---+---+ +-+---+---+-+ +---+---+---+
-- | | | | | | | | | | | | |
-- | | 1 | | -> | | 1 | 2 | | -> | 1 | 2 | 3 | ->
-- | | | | | | | | | | | | |
-- +---+---+---+ +-+---+---+-+ +---+---+---+
-- (4) (5)
-- +---+---+---+ +---+---+---+
-- | | | 3 | | | 2 | 4 |
-- + 1 + 2 +---+ -> + 1 +---+---+
-- | | | 4 | | | 3 | 5 |
-- +---+---+---+ +---+---+---+
-- A useless gap (like the dwm patch) can be defined with
-- beautiful.useless_gap_width .
local useless_gap = tonumber(beautiful.useless_gap_width) or 0
if useless_gap < 0 then useless_gap = 0 end
-- A global border can be defined with
-- beautiful.global_border_width
local global_border = tonumber(beautiful.global_border_width) or 0
if global_border < 0 then global_border = 0 end
-- Themes border width requires an offset
local bw = tonumber(beautiful.border_width) or 0
-- Screen.
local wa = p.workarea
local cls = p.clients
-- Borders are factored in.
wa.height = wa.height - ((global_border * 2) + (bw * 2))
wa.width = wa.width - ((global_border * 2) + (bw * 2))
-- How many vertical columns? Read from nmaster on the tag.
local t = tag.selected(p.screen)
local num_x = centerfair.nmaster or tag.getnmaster(t)
local ncol = centerfair.ncol or tag.getncol(t)
if num_x <= 2 then num_x = 2 end
local width = math.floor((wa.width-(num_x+1)*useless_gap) / num_x)
local offset_y = wa.y + useless_gap
if #cls < num_x
then
-- Less clients than the number of columns, let's center it!
local offset_x = wa.x + useless_gap + (wa.width - #cls*width - (#cls+1)*useless_gap) / 2
local g = {}
g.width = width
g.height = wa.height - 2*useless_gap - 2
g.y = offset_y + global_border
for i = 1, #cls do
g.x = offset_x + (#cls - i) * (width + useless_gap + 2) + global_border
cls[i]:geometry(g)
end
else
-- More clients than the number of columns, let's arrange it!
local offset_x = wa.x
if useless_gap > 0 then
offset_x = offset_x
end
-- Master client deserves a special treatement
local g = {}
g.width = wa.width - (num_x - 1) * width - num_x * 2*useless_gap - 2
g.height = wa.height - 2*useless_gap - 2
g.x = offset_x + useless_gap + global_border
g.y = offset_y + global_border
cls[#cls]:geometry(g)
-- Treat the other clients
-- Compute distribution of clients among columns
local num_y ={}
do
local remaining_clients = #cls-1
local ncol_min = math.ceil(remaining_clients/(num_x-1))
if ncol >= ncol_min
then
for i = (num_x-1), 1, -1 do
if (remaining_clients-i+1) < ncol
then
num_y[i] = remaining_clients-i + 1
else
num_y[i] = ncol
end
remaining_clients = remaining_clients - num_y[i]
end
else
local rem = remaining_clients % (num_x-1)
if rem ==0
then
for i = 1, num_x-1 do
num_y[i] = ncol_min
end
else
for i = 1, num_x-1 do
num_y[i] = ncol_min - 1
end
for i = 0, rem-1 do
num_y[num_x-1-i] = num_y[num_x-1-i] + 1
end
end
end
end
-- Compute geometry of the other clients
local nclient = #cls-1 -- we start with the 2nd client
g.x = g.x + g.width+useless_gap + 2
g.width = width
if useless_gap > 0 then
g.width = g.width + useless_gap - 2
end
for i = 1, (num_x-1) do
to_remove = 2
g.height = math.floor((wa.height - (num_y[i] * useless_gap)) / num_y[i])
g.y = offset_y + global_border
for j = 0, (num_y[i]-2) do
cls[nclient]:geometry(g)
nclient = nclient - 1
g.y = g.y + g.height+useless_gap + 2
to_remove = to_remove + 2
end
g.height = wa.height - num_y[i]*useless_gap - (num_y[i]-1)*g.height - useless_gap - to_remove
cls[nclient]:geometry(g)
nclient = nclient - 1
g.x = g.x+g.width+useless_gap + 2
end
end
end
return centerfair

131
dotfiles/awesome/lain/layout/centerwork.lua

@ -0,0 +1,131 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, projektile
* (c) 2013, Luke Bonham
* (c) 2010-2012, Peter Hofmann
--]]
local awful = require("awful")
local beautiful = require("beautiful")
local tonumber = tonumber
local math = { floor = math.floor }
local centerwork =
{
name = "centerwork",
top_left = 0,
top_right = 1,
bottom_left = 2,
bottom_right = 3
}
function centerwork.arrange(p)
-- A useless gap (like the dwm patch) can be defined with
-- beautiful.useless_gap_width .
local useless_gap = tonumber(beautiful.useless_gap_width) or 0
-- A global border can be defined with
-- beautiful.global_border_width
local global_border = tonumber(beautiful.global_border_width) or 0
if global_border < 0 then global_border = 0 end
-- Themes border width requires an offset
local bw = tonumber(beautiful.border_width) or 0
-- Screen.
local wa = p.workarea
local cls = p.clients
-- Borders are factored in.
wa.height = wa.height - ((global_border * 2) + (bw * 2))
wa.width = wa.width - ((global_border * 2) + (bw * 2))
-- Width of main column?
local t = awful.tag.selected(p.screen)
local mwfact = awful.tag.getmwfact(t)
if #cls > 0
then
-- Main column, fixed width and height.
local c = cls[#cls]
local g = {}
local mainwid = math.floor(wa.width * mwfact)
local slavewid = wa.width - mainwid
local slaveLwid = math.floor(slavewid / 2)
local slaveRwid = slavewid - slaveLwid
local slaveThei = math.floor(wa.height / 2)
local slaveBhei = wa.height - slaveThei
g.height = wa.height - 2 * useless_gap
g.width = mainwid
g.x = wa.x + slaveLwid + global_border
g.y = wa.y + useless_gap + global_border
c:geometry(g)
-- Auxiliary windows.
if #cls > 1
then
local at = 0
for i = (#cls - 1),1,-1
do
-- It's all fixed. If there are more than 5 clients,
-- those additional clients will float. This is
-- intentional.
if at == 4
then
break
end
c = cls[i]
g = {}
if at == centerwork.top_left
then
-- top left
g.x = wa.x + useless_gap + global_border
g.y = wa.y + useless_gap + global_border
g.width = slaveLwid - 2 * useless_gap
g.height = slaveThei - useless_gap
elseif at == centerwork.top_right
then
-- top right
g.x = wa.x + slaveLwid + mainwid + useless_gap + global_border
g.y = wa.y + useless_gap + global_border
g.width = slaveRwid - 2 * useless_gap
g.height = slaveThei - useless_gap
elseif at == centerwork.bottom_left
then
-- bottom left
g.x = wa.x + useless_gap + global_border
g.y = wa.y + slaveThei + useless_gap + global_border
g.width = slaveLwid - 2 * useless_gap
g.height = slaveBhei - 2 * useless_gap
elseif at == centerwork.bottom_right
then
-- bottom right
g.x = wa.x + slaveLwid + mainwid + useless_gap + global_border
g.y = wa.y + slaveThei + useless_gap + global_border
g.width = slaveRwid - 2 * useless_gap
g.height = slaveBhei - 2 * useless_gap
end
c:geometry(g)
at = at + 1
end
-- Set remaining clients to floating.
for i = (#cls - 1 - 4),1,-1
do
c = cls[i]
awful.client.floating.set(c, true)
end
end
end
end
return centerwork

20
dotfiles/awesome/lain/layout/init.lua

@ -0,0 +1,20 @@
--[[
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
--]]
local wrequire = require("lain.helpers").wrequire
local setmetatable = setmetatable
local layout = { _NAME = "lain.layout" }
return setmetatable(layout, { __index = wrequire })

138
dotfiles/awesome/lain/layout/termfair.lua

@ -0,0 +1,138 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, projektile
* (c) 2013, Luke Bonham
* (c) 2010-2012, Peter Hofmann
--]]
local tag = require("awful.tag")
local beautiful = require("beautiful")
local math = { ceil = math.ceil,
floor = math.floor,
max = math.max }
local tonumber = tonumber
local termfair = { name = "termfair" }
function termfair.arrange(p)
-- Layout with fixed number of vertical columns (read from nmaster).
-- New windows align from left to right. When a row is full, a now
-- one above it is created. Like this:
-- (1) (2) (3)
-- +---+---+---+ +---+---+---+ +---+---+---+
-- | | | | | | | | | | | |
-- | 1 | | | -> | 2 | 1 | | -> | 3 | 2 | 1 | ->
-- | | | | | | | | | | | |
-- +---+---+---+ +---+---+---+ +---+---+---+
-- (4) (5) (6)
-- +---+---+---+ +---+---+---+ +---+---+---+
-- | 4 | | | | 5 | 4 | | | 6 | 5 | 4 |
-- +---+---+---+ -> +---+---+---+ -> +---+---+---+
-- | 3 | 2 | 1 | | 3 | 2 | 1 | | 3 | 2 | 1 |
-- +---+---+---+ +---+---+---+ +---+---+---+
-- A useless gap (like the dwm patch) can be defined with
-- beautiful.useless_gap_width.
local useless_gap = tonumber(beautiful.useless_gap_width) or 0
if useless_gap < 0 then useless_gap = 0 end
-- A global border can be defined with
-- beautiful.global_border_width
local global_border = tonumber(beautiful.global_border_width) or 0
if global_border < 0 then global_border = 0 end
-- Themes border width requires an offset
local bw = tonumber(beautiful.border_width) or 0
-- Screen.
local wa = p.workarea
local cls = p.clients
-- Borders are factored in.
wa.height = wa.height - ((global_border * 2) + (bw * 2))
wa.width = wa.width - ((global_border * 2) + (bw * 2))
-- How many vertical columns?
local t = tag.selected(p.screen)
local num_x = termfair.nmaster or tag.getnmaster(t)
-- Do at least "desired_y" rows.
local desired_y = termfair.ncol or tag.getncol(t)
if #cls > 0
then
local num_y = math.max(math.ceil(#cls / num_x), desired_y)
local cur_num_x = num_x
local at_x = 0
local at_y = 0
local remaining_clients = #cls
local width = math.floor(wa.width / num_x)
local height = math.floor(wa.height / num_y)
-- We start the first row. Left-align by limiting the number of
-- available slots.
if remaining_clients < num_x
then
cur_num_x = remaining_clients
end
-- Iterate in reversed order.
for i = #cls,1,-1
do
-- Get x and y position.
local c = cls[i]
local this_x = cur_num_x - at_x - 1
local this_y = num_y - at_y - 1
-- Calc geometry.
local g = {}
if this_x == (num_x - 1)
then
g.width = wa.width - (num_x - 1) * width - useless_gap
else
g.width = width - useless_gap
end
if this_y == (num_y - 1)
then
g.height = wa.height - (num_y - 1) * height - useless_gap
else
g.height = height - useless_gap
end
g.x = wa.x + this_x * width + global_border
g.y = wa.y + this_y * height + global_border
if useless_gap > 0
then
-- All clients tile evenly.
g.x = g.x + (useless_gap / 2)
g.y = g.y + (useless_gap / 2)
end
c:geometry(g)
remaining_clients = remaining_clients - 1
-- Next grid position.
at_x = at_x + 1
if at_x == num_x
then
-- Row full, create a new one above it.
at_x = 0
at_y = at_y + 1
-- We start a new row. Left-align.
if remaining_clients < num_x
then
cur_num_x = remaining_clients
end
end
end
end
end
return termfair

108
dotfiles/awesome/lain/layout/uselessfair.lua

@ -0,0 +1,108 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, projektile, worron
* (c) 2013, Luke Bonham
* (c) 2012, Josh Komoroske
* (c) 2010-2012, Peter Hofmann
--]]
local beautiful = require("beautiful")
local ipairs = ipairs
local math = { ceil = math.ceil, sqrt = math.sqrt, floor = math.floor, max = math.max }
local tonumber = tonumber
local uselessfair = {}
-- Transformation functions
local function swap(geometry)
return { x = geometry.y, y = geometry.x, width = geometry.height, height = geometry.width }
end
-- Client geometry correction depending on useless gap and window border
local function size_correction(c, geometry, useless_gap)
geometry.width = math.max(geometry.width - 2 * c.border_width - useless_gap, 1)
geometry.height = math.max(geometry.height - 2 * c.border_width - useless_gap, 1)
geometry.x = geometry.x + useless_gap / 2
geometry.y = geometry.y + useless_gap / 2
end
-- Main tiling function
local function fair(p, orientation)
-- Theme vars
local useless_gap = beautiful.useless_gap_width or 0
local global_border = beautiful.global_border_width or 0
-- Aliases
local wa = p.workarea
local cls = p.clients
-- Nothing to tile here
if #cls == 0 then return end
-- Workarea size correction depending on useless gap and global border
wa.height = wa.height - 2 * global_border - useless_gap
wa.width = wa.width - 2 * global_border - useless_gap
wa.x = wa.x + useless_gap / 2 + global_border
wa.y = wa.y + useless_gap / 2 + global_border
-- Geometry calculation
local row, col = 0, 0
local rows = math.ceil(math.sqrt(#cls))
local cols = math.ceil(#cls / rows)
for i, c in ipairs(cls) do
local g = {}
-- find tile orientation for current client and swap geometry if need
local need_swap = (orientation == "east" and #cls <= 2) or (orientation == "south" and #cls > 2)
local area = need_swap and swap(wa) or wa
-- calculate geometry
if #cls < (cols * rows) and row == cols - 1 then
g.width = area.width / (rows - ((cols * rows) - #cls))
else
g.width = area.width / rows
end
g.height = area.height / cols
g.x = area.x + col * g.width
g.y = area.y + row * g.height
-- turn back to real if geometry was swapped
if need_swap then g = swap(g) end
-- window size correction depending on useless gap and window border
size_correction(c, g, useless_gap)
-- set geometry
c:geometry(g)
-- update tile grid coordinates
col = i % rows
row = math.floor(i / rows)
end
end
-- Layout constructor
local function construct_layout(name, direction)
return {
name = name,
-- @p screen The screen number to tile
arrange = function(p) return fair(p, direction) end
}
end
-- Build layouts with different tile direction
uselessfair.vertical = construct_layout("uselessfair", "south")
uselessfair.horizontal = construct_layout("uselessfairh", "east")
-- Module aliase
uselessfair.arrange = uselessfair.vertical.arrange
uselessfair.name = uselessfair.vertical.name
return uselessfair

123
dotfiles/awesome/lain/layout/uselesspiral.lua

@ -0,0 +1,123 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, projektile
* (c) 2013, Luke Bonham
* (c) 2009, Uli Schlachter
* (c) 2008, Julien Danjolu
--]]
local beautiful = require("beautiful")
local ipairs = ipairs
local tonumber = tonumber
local math = require("math")
local uselesspiral = {}
local function spiral(p, spiral)
-- A useless gap (like the dwm patch) can be defined with
-- beautiful.useless_gap_width.
local useless_gap = tonumber(beautiful.useless_gap_width) or 0
if useless_gap < 0 then useless_gap = 0 end
-- A global border can be defined with
-- beautiful.global_border_width
local global_border = tonumber(beautiful.global_border_width) or 0
if global_border < 0 then global_border = 0 end
-- Themes border width requires an offset
local bw = tonumber(beautiful.border_width) or 0
-- get our orientation right
local wa = p.workarea
local cls = p.clients
local n = #cls -- number of windows total; k = which window number
wa.height = wa.height - ((global_border * 2) + (bw * 2))
wa.width = wa.width - ((global_border * 2) + (bw * 2))
local static_wa = wa
for k, c in ipairs(cls) do
if k < n then
if k % 2 == 0 then
wa.height = (wa.height / 2)
else
wa.width = (wa.width / 2)
end
end
if k % 4 == 0 and spiral then
wa.x = wa.x - wa.width
elseif k % 2 == 0 or
(k % 4 == 3 and k < n and spiral) then
wa.x = wa.x + wa.width
end
if k % 4 == 1 and k ~= 1 and spiral then
wa.y = wa.y - wa.height
elseif k % 2 == 1 and k ~= 1 or
(k % 4 == 0 and k < n and spiral) then
wa.y = wa.y + wa.height
end
local wa2 = {}
wa2.x = wa.x + (useless_gap / 2) + global_border
wa2.y = wa.y + (useless_gap / 2) + global_border
wa2.height = wa.height - (useless_gap / 2)
wa2.width = wa.width - (useless_gap / 2)
-- Useless gap.
if useless_gap > 0
then
-- Top and left clients are shrinked by two steps and
-- get moved away from the border. Other clients just
-- get shrinked in one direction.
top = false
left = false
if wa2.y == static_wa.y then
top = true
end
if wa2.x == static_wa.x then
left = true
end
if top then
wa2.height = wa2.height - useless_gap
wa2.y = wa2.y - (useless_gap / 2)
else
wa2.height = wa2.height - (useless_gap / 2)
end
if left then
wa2.width = wa2.width - useless_gap
wa2.x = wa2.x - (useless_gap / 2)
else
wa2.width = wa2.width - (useless_gap / 2)
end
end
-- End of useless gap.
c:geometry(wa2)
end
end
--- Dwindle layout
uselesspiral.dwindle = {}
uselesspiral.dwindle.name = "uselessdwindle"
function uselesspiral.dwindle.arrange(p)
return spiral(p, false)
end
--- Spiral layout
uselesspiral.name = "uselesspiral"
function uselesspiral.arrange(p)
return spiral(p, true)
end
return uselesspiral

226
dotfiles/awesome/lain/layout/uselesstile.lua

@ -0,0 +1,226 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, projektile, worron
* (c) 2013, Luke Bonham
* (c) 2009, Donald Ephraim Curtis
* (c) 2008, Julien Danjolu
--]]
local tag = require("awful.tag")
local beautiful = require("beautiful")
local ipairs = ipairs
local math = { floor = math.floor,
ceil = math.ceil,
max = math.max,
min = math.min }
local tonumber = tonumber
local uselesstile = {}
-- Transformation functions
local function flip(canvas, geometry)
return {
-- vertical only
x = 2 * canvas.x + canvas.width - geometry.x - geometry.width,
y = geometry.y,
width = geometry.width,
height = geometry.height
}
end
local function swap(geometry)
return { x = geometry.y, y = geometry.x, width = geometry.height, height = geometry.width }
end
-- Find geometry for secondary windows column
local function cut_column(wa, n, index)
local width = wa.width / n
local area = { x = wa.x + (index - 1) * width, y = wa.y, width = width, height = wa.height }
return area
end
-- Find geometry for certain window in column
local function cut_row(wa, factor, index, used)
local height = wa.height * factor.window[index] / factor.total
local area = { x = wa.x, y = wa.y + used, width = wa.width, height = height }
return area
end
-- Client geometry correction depending on useless gap and window border
local function size_correction(c, geometry, useless_gap)
geometry.width = math.max(geometry.width - 2 * c.border_width - useless_gap, 1)
geometry.height = math.max(geometry.height - 2 * c.border_width - useless_gap, 1)
geometry.x = geometry.x + useless_gap / 2
geometry.y = geometry.y + useless_gap / 2
end
-- Check size factor for group of clients and calculate total
local function calc_factor(n, winfactors)
local factor = { window = winfactors, total = 0, min = 1 }
for i = 1, n do
if not factor.window[i] then
factor.window[i] = factor.min
else
factor.min = math.min(factor.window[i], factor.min)
if factor.window[i] < 0.05 then factor.window[i] = 0.05 end
end
factor.total = factor.total + factor.window[i]
end
return factor
end
-- Tile group of clients in given area
-- @canvas need for proper transformation only
-- @winfactors table with clients size factors
local function tile_column(canvas, area, list, useless_gap, transformation, winfactors)
local used = 0
local factor = calc_factor(#list, winfactors)
for i, c in ipairs(list) do
local g = cut_row(area, factor, i, used)
used = used + g.height
-- swap workarea dimensions
if transformation.flip then g = flip(canvas, g) end
if transformation.swap then g = swap(g) end
-- useless gap and border correction
size_correction(c, g, useless_gap)
c:geometry(g)
end
end
--Main tile function
local function tile(p, orientation)
-- Theme vars
local useless_gap = beautiful.useless_gap_width or 0
local global_border = beautiful.global_border_width or 0
-- Aliases
local wa = p.workarea
local cls = p.clients
local t = tag.selected(p.screen)
-- Nothing to tile here
if #cls == 0 then return end
-- Get tag prop
local nmaster = math.min(tag.getnmaster(t), #cls)
local mwfact = tag.getmwfact(t)
if nmaster == 0 then
mwfact = 0
elseif nmaster == #cls then
mwfact = 1
end
-- clients size factor
local data = tag.getdata(t).windowfact
if not data then
data = {}
tag.getdata(t).windowfact = data
end
-- Workarea size correction depending on useless gap and global border
wa.height = wa.height - 2 * global_border - useless_gap
wa.width = wa.width - 2 * global_border - useless_gap
wa.x = wa.x + useless_gap / 2 + global_border
wa.y = wa.y + useless_gap / 2 + global_border
-- Find which transformation we need for given orientation
local transformation = {
swap = orientation == 'top' or orientation == 'bottom',
flip = orientation == 'left' or orientation == 'top'
}
-- Swap workarea dimensions if orientation vertical
if transformation.swap then wa = swap(wa) end
-- Split master and other windows
local cls_master, cls_other = {}, {}
for i, c in ipairs(cls) do
if i <= nmaster then
table.insert(cls_master, c)
else
table.insert(cls_other, c)
end
end
-- Tile master windows
local master_area = {
x = wa.x,
y = wa.y,
width = nmaster > 0 and wa.width * mwfact or 0,
height = wa.height
}
if not data[0] then data[0] = {} end
tile_column(wa, master_area, cls_master, useless_gap, transformation, data[0])
-- Tile other windows
local other_area = {
x = wa.x + master_area.width,
y = wa.y,
width = wa.width - master_area.width,
height = wa.height
}
-- get column number for other windows
local ncol = math.min(tag.getncol(t), #cls_other)
if ncol == 0 then ncol = 1 end
-- split other windows to column groups
local last_small_column = ncol - #cls_other % ncol
local rows_min = math.floor(#cls_other / ncol)
local client_index = 1
for i = 1, ncol do
local position = transformation.flip and ncol - i + 1 or i
local rows = i <= last_small_column and rows_min or rows_min + 1
local column = {}
for j = 1, rows do
table.insert(column, cls_other[client_index])
client_index = client_index + 1
end
-- and tile
local column_area = cut_column(other_area, ncol, position)
if not data[i] then data[i] = {} end
tile_column(wa, column_area, column, useless_gap, transformation, data[i])
end
end
-- Layout constructor
local function construct_layout(name, orientation)
return {
name = name,
-- @p screen number to tile
arrange = function(p) return tile(p, orientation) end
}
end
-- Build layouts with different tile direction
uselesstile.right = construct_layout("uselesstile", "right")
uselesstile.left = construct_layout("uselesstileleft", "left")
uselesstile.bottom = construct_layout("uselesstilebottom", "bottom")
uselesstile.top = construct_layout("uselesstiletop", "top")
-- Module aliase
uselesstile.arrange = uselesstile.right.arrange
uselesstile.name = uselesstile.right.name
return uselesstile

387
dotfiles/awesome/lain/scripts/dfs

@ -0,0 +1,387 @@
#!/bin/bash
#
# 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)]"
NARROW_MODE=0
WEB_OUTPUT=0
while [ $# -gt 0 ]; do
case "$1" in
"-h" )
echo $USAGE
exit
;;
"-d" )
DEBUG=1
;;
"-n" )
NARROW_MODE=1
;;
"-w" )
WEB_OUTPUT=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
# -------------------------------------------------------------------------
# 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++)
{
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
}'

68
dotfiles/awesome/lain/scripts/mpdcover

@ -0,0 +1,68 @@
#!/bin/bash
#
# A simple cover fetcher script for current playing song on mpd.
#
# Original author: Wolfgang Mueller
#
# Adapted for Lain internal use.
# https://github.com/copycat-killer/lain
#
# You can use, edit and redistribute this script in any way you like.
#
# Dependencies: imagemagick.
#
# Usage: mpdcover <music_directory> <song_file> <cover_resize> <default_art>
# Configuration-------------------------------------------------------
# Music directory
MUSIC_DIR=$1
# Song file
file=$2
# Regex expression used for image search
IMG_REG="(Front|front|Cover|cover|Art|art|Folder|folder)\.(jpg|jpeg|png|gif)$"
# Path of temporary resized cover
TEMP_PATH="/tmp/mpdcover.png"
# Resize cover
COVER_RESIZE="$3x$3"
if [ $COVER_RESIZE == "x" ]; then
COVER_RESIZE="100x100"
fi
# The default cover to use (optional)
DEFAULT_ART=$4
# Thumbnail background (transparent)
COVER_BACKGROUND="none"
#--------------------------------------------------------------------
# check if anything is playing at all
[[ -z $file ]] && exit 1
# Art directory
art="$MUSIC_DIR/${file%/*}"
# find every file that matches IMG_REG set the first matching file to be the
# cover.
cover="$(find "$art/" -maxdepth 1 -type f | egrep -i -m1 "$IMG_REG")"
# when no cover is found, use DEFAULT_ART as cover
cover="${cover:=$DEFAULT_ART}"
# check if art is available
if [[ -n $cover ]]; then
if [[ -n $COVER_RESIZE ]]; then
convert "$cover" -scale $COVER_RESIZE -gravity "center" -background "$COVER_BACKGROUND" "$TEMP_PATH"
cover="$TEMP_PATH"
fi
else
rm $TEMP_PATH
fi
exit 0

713
dotfiles/awesome/lain/util/dkjson.lua

@ -0,0 +1,713 @@
-- Module options:
local always_try_using_lpeg = true
local register_global_module_table = false
local global_module_name = 'json'
--[==[
David Kolf's JSON module for Lua 5.1/5.2
Version 2.5
For the documentation see the corresponding readme.txt or visit
<http://dkolf.de/src/dkjson-lua.fsl/>.
You can contact the author by sending an e-mail to 'david' at the
domain 'dkolf.de'.
Copyright (C) 2010-2013 David Heiko Kolf
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]==]
-- global dependencies:
local pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset =
pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset
local error, require, pcall, select = error, require, pcall, select
local floor, huge = math.floor, math.huge
local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat =
string.rep, string.gsub, string.sub, string.byte, string.char,
string.find, string.len, string.format
local strmatch = string.match
local concat = table.concat
local json = { version = "dkjson 2.5" }
if register_global_module_table then
_G[global_module_name] = json
end
local _ENV = nil -- blocking globals in Lua 5.2
pcall (function()
-- Enable access to blocked metatables.
-- Don't worry, this module doesn't change anything in them.
local debmeta = require "debug".getmetatable
if debmeta then getmetatable = debmeta end
end)
json.null = setmetatable ({}, {
__tojson = function () return "null" end
})
local function isarray (tbl)
local max, n, arraylen = 0, 0, 0
for k,v in pairs (tbl) do
if k == 'n' and type(v) == 'number' then
arraylen = v
if v > max then
max = v
end
else
if type(k) ~= 'number' or k < 1 or floor(k) ~= k then
return false
end
if k > max then
max = k
end
n = n + 1
end
end
if max > 10 and max > arraylen and max > n * 2 then
return false -- don't create an array with too many holes
end
return true, max
end
local escapecodes = {
["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f",
["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t"
}
local function escapeutf8 (uchar)
local value = escapecodes[uchar]
if value then
return value
end
local a, b, c, d = strbyte (uchar, 1, 4)
a, b, c, d = a or 0, b or 0, c or 0, d or 0
if a <= 0x7f then
value = a
elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then
value = (a - 0xc0) * 0x40 + b - 0x80
elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then
value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80
elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then
value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80
else
return ""
end
if value <= 0xffff then
return strformat ("\\u%.4x", value)
elseif value <= 0x10ffff then
-- encode as UTF-16 surrogate pair
value = value - 0x10000
local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400)
return strformat ("\\u%.4x\\u%.4x", highsur, lowsur)
else
return ""
end
end
local function fsub (str, pattern, repl)
-- gsub always builds a new string in a buffer, even when no match
-- exists. First using find should be more efficient when most strings
-- don't contain the pattern.
if strfind (str, pattern) then
return gsub (str, pattern, repl)
else
return str
end
end
local function quotestring (value)
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
if strfind (value, "[\194\216\220\225\226\239]") then
value = fsub (value, "\194[\128-\159\173]", escapeutf8)
value = fsub (value, "\216[\128-\132]", escapeutf8)
value = fsub (value, "\220\143", escapeutf8)
value = fsub (value, "\225\158[\180\181]", escapeutf8)
value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8)
value = fsub (value, "\226\129[\160-\175]", escapeutf8)
value = fsub (value, "\239\187\191", escapeutf8)
value = fsub (value, "\239\191[\176-\191]", escapeutf8)
end
return "\"" .. value .. "\""
end
json.quotestring = quotestring
local function replace(str, o, n)
local i, j = strfind (str, o, 1, true)
if i then
return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1)
else
return str
end
end
-- locale independent num2str and str2num functions
local decpoint, numfilter
local function updatedecpoint ()
decpoint = strmatch(tostring(0.5), "([^05+])")
-- build a filter that can be used to remove group separators
numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+"
end
updatedecpoint()
local function num2str (num)
return replace(fsub(tostring(num), numfilter, ""), decpoint, ".")
end
local function str2num (str)
local num = tonumber(replace(str, ".", decpoint))
if not num then
updatedecpoint()
num = tonumber(replace(str, ".", decpoint))
end
return num
end
local function addnewline2 (level, buffer, buflen)
buffer[buflen+1] = "\n"
buffer[buflen+2] = strrep (" ", level)
buflen = buflen + 2
return buflen
end
function json.addnewline (state)
if state.indent then
state.bufferlen = addnewline2 (state.level or 0,
state.buffer, state.bufferlen or #(state.buffer))
end
end
local encode2 -- forward declaration
local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state)
local kt = type (key)
if kt ~= 'string' and kt ~= 'number' then
return nil, "type '" .. kt .. "' is not supported as a key by JSON."
end
if prev then
buflen = buflen + 1
buffer[buflen] = ","
end
if indent then
buflen = addnewline2 (level, buffer, buflen)
end
buffer[buflen+1] = quotestring (key)
buffer[buflen+2] = ":"
return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state)
end
local function appendcustom(res, buffer, state)
local buflen = state.bufferlen
if type (res) == 'string' then
buflen = buflen + 1
buffer[buflen] = res
end
return buflen
end
local function exception(reason, value, state, buffer, buflen, defaultmessage)
defaultmessage = defaultmessage or reason
local handler = state.exception
if not handler then
return nil, defaultmessage
else
state.bufferlen = buflen
local ret, msg = handler (reason, value, state, defaultmessage)
if not ret then return nil, msg or defaultmessage end
return appendcustom(ret, buffer, state)
end
end
function json.encodeexception(reason, value, state, defaultmessage)
return quotestring("<" .. defaultmessage .. ">")
end
encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state)
local valtype = type (value)
local valmeta = getmetatable (value)
valmeta = type (valmeta) == 'table' and valmeta -- only tables
local valtojson = valmeta and valmeta.__tojson
if valtojson then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
state.bufferlen = buflen
local ret, msg = valtojson (value, state)
if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end
tables[value] = nil
buflen = appendcustom(ret, buffer, state)
elseif value == nil then
buflen = buflen + 1
buffer[buflen] = "null"
elseif valtype == 'number' then
local s
if value ~= value or value >= huge or -value >= huge then
-- This is the behaviour of the original JSON implementation.
s = "null"
else
s = num2str (value)
end
buflen = buflen + 1
buffer[buflen] = s
elseif valtype == 'boolean' then
buflen = buflen + 1
buffer[buflen] = value and "true" or "false"
elseif valtype == 'string' then
buflen = buflen + 1
buffer[buflen] = quotestring (value)
elseif valtype == 'table' then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
level = level + 1
local isa, n = isarray (value)
if n == 0 and valmeta and valmeta.__jsontype == 'object' then
isa = false
end
local msg
if isa then -- JSON array
buflen = buflen + 1
buffer[buflen] = "["
for i = 1, n do
buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
if i < n then
buflen = buflen + 1
buffer[buflen] = ","
end
end
buflen = buflen + 1
buffer[buflen] = "]"
else -- JSON object
local prev = false
buflen = buflen + 1
buffer[buflen] = "{"
local order = valmeta and valmeta.__jsonorder or globalorder
if order then
local used = {}
n = #order
for i = 1, n do
local k = order[i]
local v = value[k]
if v then
used[k] = true
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
prev = true -- add a seperator before the next element
end
end
for k,v in pairs (value) do
if not used[k] then
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
else -- unordered
for k,v in pairs (value) do
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
if indent then
buflen = addnewline2 (level - 1, buffer, buflen)
end
buflen = buflen + 1
buffer[buflen] = "}"
end
tables[value] = nil
else
return exception ('unsupported type', value, state, buffer, buflen,
"type '" .. valtype .. "' is not supported by JSON.")
end
return buflen
end
function json.encode (value, state)
state = state or {}
local oldbuffer = state.buffer
local buffer = oldbuffer or {}
state.buffer = buffer
updatedecpoint()
local ret, msg = encode2 (value, state.indent, state.level or 0,
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state)
if not ret then
error (msg, 2)
elseif oldbuffer == buffer then
state.bufferlen = ret
return true
else
state.bufferlen = nil
state.buffer = nil
return concat (buffer)
end
end
local function loc (str, where)
local line, pos, linepos = 1, 1, 0
while true do
pos = strfind (str, "\n", pos, true)
if pos and pos < where then
line = line + 1
linepos = pos
pos = pos + 1
else
break
end
end
return "line " .. line .. ", column " .. (where - linepos)
end
local function unterminated (str, what, where)
return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
end
local function scanwhite (str, pos)
while true do
pos = strfind (str, "%S", pos)
if not pos then return nil end
local sub2 = strsub (str, pos, pos + 1)
if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then
-- UTF-8 Byte Order Mark
pos = pos + 3
elseif sub2 == "//" then
pos = strfind (str, "[\n\r]", pos + 2)
if not pos then return nil end
elseif sub2 == "/*" then
pos = strfind (str, "*/", pos + 2)
if not pos then return nil end
pos = pos + 2
else
return pos
end
end
end
local escapechars = {
["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f",
["n"] = "\n", ["r"] = "\r", ["t"] = "\t"
}
local function unichar (value)
if value < 0 then
return nil
elseif value <= 0x007f then
return strchar (value)
elseif value <= 0x07ff then
return strchar (0xc0 + floor(value/0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0xffff then
return strchar (0xe0 + floor(value/0x1000),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0x10ffff then
return strchar (0xf0 + floor(value/0x40000),
0x80 + (floor(value/0x1000) % 0x40),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
else
return nil
end
end
local function scanstring (str, pos)
local lastpos = pos + 1
local buffer, n = {}, 0
while true do
local nextpos = strfind (str, "[\"\\]", lastpos)
if not nextpos then
return unterminated (str, "string", pos)
end
if nextpos > lastpos then
n = n + 1
buffer[n] = strsub (str, lastpos, nextpos - 1)
end
if strsub (str, nextpos, nextpos) == "\"" then
lastpos = nextpos + 1
break
else
local escchar = strsub (str, nextpos + 1, nextpos + 1)
local value
if escchar == "u" then
value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16)
if value then
local value2
if 0xD800 <= value and value <= 0xDBff then
-- we have the high surrogate of UTF-16. Check if there is a
-- low surrogate escaped nearby to combine them.
if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then
value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16)
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
else
value2 = nil -- in case it was out of range for a low surrogate
end
end
end
value = value and unichar (value)
if value then
if value2 then
lastpos = nextpos + 12
else
lastpos = nextpos + 6
end
end
end
end
if not value then
value = escapechars[escchar] or escchar
lastpos = nextpos + 2
end
n = n + 1
buffer[n] = value
end
end
if n == 1 then
return buffer[1], lastpos
elseif n > 1 then
return concat (buffer), lastpos
else
return "", lastpos
end
end
local scanvalue -- forward declaration
local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta)
local len = strlen (str)
local tbl, n = {}, 0
local pos = startpos + 1
if what == 'object' then
setmetatable (tbl, objectmeta)
else
setmetatable (tbl, arraymeta)
end
while true do
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
local char = strsub (str, pos, pos)
if char == closechar then
return tbl, pos + 1
end
local val1, err
val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
if char == ":" then
if val1 == nil then
return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
end
pos = scanwhite (str, pos + 1)
if not pos then return unterminated (str, what, startpos) end
local val2
val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
tbl[val1] = val2
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
else
n = n + 1
tbl[n] = val1
end
if char == "," then
pos = pos + 1
end
end
end
scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
pos = pos or 1
pos = scanwhite (str, pos)
if not pos then
return nil, strlen (str) + 1, "no valid JSON value (reached the end)"
end
local char = strsub (str, pos, pos)
if char == "{" then
return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta)
elseif char == "[" then
return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta)
elseif char == "\"" then
return scanstring (str, pos)
else
local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos)
if pstart then
local number = str2num (strsub (str, pstart, pend))
if number then
return number, pend + 1
end
end
pstart, pend = strfind (str, "^%a%w*", pos)
if pstart then
local name = strsub (str, pstart, pend)
if name == "true" then
return true, pend + 1
elseif name == "false" then
return false, pend + 1
elseif name == "null" then
return nullval, pend + 1
end
end
return nil, pos, "no valid JSON value at " .. loc (str, pos)
end
end
local function optionalmetatables(...)
if select("#", ...) > 0 then
return ...
else
return {__jsontype = 'object'}, {__jsontype = 'array'}
end
end
function json.decode (str, pos, nullval, ...)
local objectmeta, arraymeta = optionalmetatables(...)
return scanvalue (str, pos, nullval, objectmeta, arraymeta)
end
function json.use_lpeg ()
local g = require ("lpeg")
if g.version() == "0.11" then
error "due to a bug in LPeg 0.11, it cannot be used for JSON matching"
end
local pegmatch = g.match
local P, S, R = g.P, g.S, g.R
local function ErrorCall (str, pos, msg, state)
if not state.msg then
state.msg = msg .. " at " .. loc (str, pos)
state.pos = pos
end
return false
end
local function Err (msg)
return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall)
end
local SingleLineComment = P"//" * (1 - S"\n\r")^0
local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/"
local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0
local PlainChar = 1 - S"\"\\\n\r"
local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars
local HexDigit = R("09", "af", "AF")
local function UTF16Surrogate (match, pos, high, low)
high, low = tonumber (high, 16), tonumber (low, 16)
if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then
return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)
else
return false
end
end
local function UTF16BMP (hex)
return unichar (tonumber (hex, 16))
end
local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit))
local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP
local Char = UnicodeEscape + EscapeSequence + PlainChar
local String = P"\"" * g.Cs (Char ^ 0) * (P"\"" + Err "unterminated string")
local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0))
local Fractal = P"." * R"09"^0
local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1
local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num
local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1)
local SimpleValue = Number + String + Constant
local ArrayContent, ObjectContent
-- The functions parsearray and parseobject parse only a single value/pair
-- at a time and store them directly to avoid hitting the LPeg limits.
local function parsearray (str, pos, nullval, state)
local obj, cont
local npos
local t, nt = {}, 0
repeat
obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state)
if not npos then break end
pos = npos
nt = nt + 1
t[nt] = obj
until cont == 'last'
return pos, setmetatable (t, state.arraymeta)
end
local function parseobject (str, pos, nullval, state)
local obj, key, cont
local npos
local t = {}
repeat
key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state)
if not npos then break end
pos = npos
t[key] = obj
until cont == 'last'
return pos, setmetatable (t, state.objectmeta)
end
local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) * Space * (P"]" + Err "']' expected")
local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) * Space * (P"}" + Err "'}' expected")
local Value = Space * (Array + Object + SimpleValue)
local ExpectedValue = Value + Space * Err "value expected"
ArrayContent = Value * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local Pair = g.Cg (Space * String * Space * (P":" + Err "colon expected") * ExpectedValue)
ObjectContent = Pair * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local DecodeValue = ExpectedValue * g.Cp ()
function json.decode (str, pos, nullval, ...)
local state = {}
state.objectmeta, state.arraymeta = optionalmetatables(...)
local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state)
if state.msg then
return nil, state.pos, state.msg
else
return obj, retpos
end
end
-- use this function only once:
json.use_lpeg = function () return json end
json.using_lpeg = true
return json -- so you can get the module using json = require "dkjson".use_lpeg()
end
if always_try_using_lpeg then
pcall (json.use_lpeg)
end
return json

229
dotfiles/awesome/lain/util/init.lua

@ -0,0 +1,229 @@
--[[
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
--]]
local awful = require("awful")
local beautiful = require("beautiful")
local math = { sqrt = math.sqrt }
local mouse = mouse
local pairs = pairs
local string = { gsub = string.gsub }
local client = client
local screen = screen
local tonumber = tonumber
local wrequire = require("lain.helpers").wrequire
local setmetatable = setmetatable
-- Lain utilities submodule
-- lain.util
local util = { _NAME = "lain.util" }
-- Like awful.menu.clients, but only show clients of currently selected
-- tags.
function util.menu_clients_current_tags(menu, args)
-- List of currently selected tags.
local cls_tags = awful.tag.selectedlist(mouse.screen)
-- Final list of menu items.
local cls_t = {}
if cls_tags == nil then return nil end
-- For each selected tag get all clients of that tag and add them to
-- the menu. A click on a menu item will raise that client.
for i = 1,#cls_tags
do
local t = cls_tags[i]
local cls = t:clients()
for k, c in pairs(cls)
do
cls_t[#cls_t + 1] = { awful.util.escape(c.name) or "",
function ()
c.minimized = false
client.focus = c
c:raise()
end,
c.icon }
end
end
-- No clients? Then quit.
if #cls_t <= 0 then return nil end
-- menu may contain some predefined values, otherwise start with a
-- fresh menu.
if not menu then menu = {} end
-- Set the list of items and show the menu.
menu.items = cls_t
local m = awful.menu.new(menu)
m:show(args)
return m
end
-- Magnify a client: Set it to "float" and resize it.
function util.magnify_client(c)
if not awful.client.floating.get(c) then
awful.client.floating.set(c, true)
local mg = screen[mouse.screen].geometry
local tag = awful.tag.selected(mouse.screen)
local mwfact = awful.tag.getmwfact(tag)
local g = {}
g.width = math.sqrt(mwfact) * mg.width
g.height = math.sqrt(mwfact) * mg.height
g.x = mg.x + (mg.width - g.width) / 2
g.y = mg.y + (mg.height - g.height) / 2
c:geometry(g)
else
awful.client.floating.set(c, false)
end
end
-- Read the nice value of pid from /proc.
local function get_nice_value(pid)
local n = first_line('/proc/' .. pid .. '/stat')
if n == nil
then
-- This should not happen. But I don't want to crash, either.
return 0
end
-- Remove pid and tcomm. This is necessary because tcomm may contain
-- nasty stuff such as whitespace or additional parentheses...
n = string.gsub(n, '.*%) ', '')
-- Field number 17 now is the nice value.
fields = split(n, ' ')
return tonumber(fields[17])
end
-- To be used as a signal handler for "focus"
-- This requires beautiful.border_focus{,_highprio,_lowprio}.
function util.niceborder_focus(c)
local n = get_nice_value(c.pid)
if n == 0
then
c.border_color = beautiful.border_focus
elseif n < 0
then
c.border_color = beautiful.border_focus_highprio
else
c.border_color = beautiful.border_focus_lowprio
end
end
-- To be used as a signal handler for "unfocus"
-- This requires beautiful.border_normal{,_highprio,_lowprio}.
function util.niceborder_unfocus(c)
local n = get_nice_value(c.pid)
if n == 0
then
c.border_color = beautiful.border_normal
elseif n < 0
then
c.border_color = beautiful.border_normal_highprio
else
c.border_color = beautiful.border_normal_lowprio
end
end
-- Non-empty tag browsing
-- direction in {-1, 1} <-> {previous, next} non-empty tag
function util.tag_view_nonempty(direction, sc)
local s = sc or mouse.screen or 1
local scr = screen[s]
for i = 1, #awful.tag.gettags(s) do
awful.tag.viewidx(direction,s)
if #awful.client.visible(s) > 0 then
return
end
end
end
-- {{{ Dynamic tagging
--
-- Add a new tag
function util.add_tag(mypromptbox)
awful.prompt.run({prompt="New tag name: "}, mypromptbox[mouse.screen].widget,
function(text)
if text:len() > 0 then
props = { selected = true }
tag = awful.tag.add(new_name, props)
tag.name = text
tag:emit_signal("property::name")
end
end)
end
-- Rename current tag
-- @author: minism
function util.rename_tag(mypromptbox)
local tag = awful.tag.selected(mouse.screen)
awful.prompt.run({prompt="Rename tag: "}, mypromptbox[mouse.screen].widget,
function(text)
if text:len() > 0 then
tag.name = text
tag:emit_signal("property::name")
end
end)
end
-- Move current tag
-- pos in {-1, 1} <-> {previous, next} tag position
function util.move_tag(pos)
local tag = awful.tag.selected(mouse.screen)
local idx = awful.tag.getidx(tag)
if tonumber(pos) <= -1 then
awful.tag.move(idx - 1, tag)
else
awful.tag.move(idx + 1, tag)
end
end
-- Remove current tag (if empty)
-- Any rule set on the tag shall be broken
function util.remove_tag()
local tag = awful.tag.selected(mouse.screen)
local prevtag = awful.tag.gettags(mouse.screen)[awful.tag.getidx(tag) - 1]
awful.tag.delete(tag, prevtag)
end
--
-- }}}
-- On the fly useless gaps change
function util.useless_gaps_resize(thatmuch)
beautiful.useless_gap_width = tonumber(beautiful.useless_gap_width) + thatmuch
awful.layout.arrange(mouse.screen)
end
-- On the fly global border change
function util.global_border_resize(thatmuch)
beautiful.global_border_width = tonumber(beautiful.global_border_width) + thatmuch
awful.layout.arrange(mouse.screen)
end
-- Check if an element exist on a table
function util.element_in_table(element, tbl)
for _, i in pairs(tbl) do
if i == element then
return true
end
end
return false
end
return setmetatable(util, { __index = wrequire })

69
dotfiles/awesome/lain/util/markup.lua

@ -0,0 +1,69 @@
--[[
Licensed under MIT License
* (c) 2013, Luke Bonham
* (c) 2009, Uli Schlachter
* (c) 2009, Majic
--]]
local beautiful = require("beautiful")
local tostring = tostring
local setmetatable = setmetatable
-- Lain markup util submodule
-- lain.util.markup
local markup = {}
local fg = {}
local bg = {}
-- Convenience tags.
function markup.bold(text) return '<b>' .. tostring(text) .. '</b>' end
function markup.italic(text) return '<i>' .. tostring(text) .. '</i>' end
function markup.strike(text) return '<s>' .. tostring(text) .. '</s>' end
function markup.underline(text) return '<u>' .. tostring(text) .. '</u>' end
function markup.monospace(text) return '<tt>' .. tostring(text) .. '</tt>' end
function markup.big(text) return '<big>' .. tostring(text) .. '</big>' end
function markup.small(text) return '<small>' .. tostring(text) .. '</small>' end
-- Set the font.
function markup.font(font, text)
return '<span font="' .. tostring(font) .. '">' .. tostring(text) ..'</span>'
end
-- Set the foreground.
function fg.color(color, text)
return '<span foreground="' .. tostring(color) .. '">' .. tostring(text) .. '</span>'
end
-- Set the background.
function bg.color(color, text)
return '<span background="' .. tostring(color) .. '">' .. tostring(text) .. '</span>'
end
-- Context: focus
function fg.focus(text) return fg.color(beautiful.fg_focus, text) end
function bg.focus(text) return bg.color(beautiful.bg_focus, text) end
function markup.focus(text) return bg.focus(fg.focus(text)) end
-- Context: normal
function fg.normal(text) return fg.color(beautiful.fg_normal, text) end
function bg.normal(text) return bg.color(beautiful.bg_normal, text) end
function markup.normal(text) return bg.normal(fg.normal(text)) end
-- Context: urgent
function fg.urgent(text) return fg.color(beautiful.fg_urgent, text) end
function bg.urgent(text) return bg.color(beautiful.bg_urgent, text) end
function markup.urgent(text) return bg.urgent(fg.urgent(text)) end
markup.fg = fg
markup.bg = bg
-- link markup.{fg,bg}(...) calls to markup.{fg,bg}.color(...)
setmetatable(markup.fg, { __call = function(_, ...) return markup.fg.color(...) end })
setmetatable(markup.bg, { __call = function(_, ...) return markup.bg.color(...) end })
-- link markup(...) calls to markup.fg.color(...)
return setmetatable(markup, { __call = function(_, ...) return markup.fg.color(...) end })

102
dotfiles/awesome/lain/util/separators.lua

@ -0,0 +1,102 @@
--[[
Licensed under GNU General Public License v2
* (c) 2015, Luke Bonham
* (c) 2015, plotnikovanton
--]]
local wibox = require("wibox")
local beautiful = require("beautiful")
local gears = require("gears")
-- Lain Cairo separators util submodule
-- lain.util.separators
local separators = {}
local height = beautiful.awful_widget_height or 0
local width = beautiful.separators_width or 9
-- [[ Arrow
-- Right
function separators.arrow_right(col1, col2)
local widget = wibox.widget.base.make_widget()
widget.fit = function(m, w, h) return width, height end
widget.draw = function(mycross, wibox, cr, width, height)
if col2 ~= "alpha" then
cr:set_source_rgb(gears.color.parse_color(col2))
cr:new_path()
cr:move_to(0, 0)
cr:line_to(width, height/2)
cr:line_to(width, 0)
cr:close_path()
cr:fill()
cr:new_path()
cr:move_to(0, height)
cr:line_to(width, height/2)
cr:line_to(width, height)
cr:close_path()
cr:fill()
end
if col1 ~= "alpha" then
cr:set_source_rgb(gears.color.parse_color(col1))
cr:new_path()
cr:move_to(0, 0)
cr:line_to(width, height/2)
cr:line_to(0, height)
cr:close_path()
cr:fill()
end
end
return widget
end
-- Left
function separators.arrow_left(col1, col2)
local widget = wibox.widget.base.make_widget()
widget.fit = function(m, w, h) return width, height end
widget.draw = function(mycross, wibox, cr, width, height)
if col1 ~= "alpha" then
cr:set_source_rgb(gears.color.parse_color(col1))
cr:new_path()
cr:move_to(width, 0)
cr:line_to(0, height/2)
cr:line_to(0, 0)
cr:close_path()
cr:fill()
cr:new_path()
cr:move_to(width, height)
cr:line_to(0, height/2)
cr:line_to(0, height)
cr:close_path()
cr:fill()
end
if 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:fill()
end
end
return widget
end
-- ]]
return separators

41
dotfiles/awesome/lain/widgets/abase.lua

@ -0,0 +1,41 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, Luke Bonham
--]]
local newtimer = require("lain.helpers").newtimer
local async = require("lain.asyncshell")
local wibox = require("wibox")
local setmetatable = setmetatable
-- Basic template for custom widgets
-- Asynchronous version
-- lain.widgets.abase
local function worker(args)
local abase = {}
local args = args or {}
local timeout = args.timeout or 5
local cmd = args.cmd or ""
local settings = args.settings or function() end
abase.widget = wibox.widget.textbox('')
function abase.update()
async.request(cmd, function(f)
output = f
widget = abase.widget
settings()
end)
end
newtimer(cmd, timeout, abase.update)
return setmetatable(abase, { __index = abase.widget })
end
return setmetatable({}, { __call = function(_, ...) return worker(...) end })

68
dotfiles/awesome/lain/widgets/alsa.lua

@ -0,0 +1,68 @@
--[[
Licensed under GNU General Public License v2
* (c) 2013, Luke Bonham
* (c) 2010, Adrian C. <anrxc@sysphere.org>
--]]
local newtimer = require("lain.helpers").newtimer
local read_pipe = require("lain.helpers").read_pipe
local wibox = require("wibox")
local string = { match = string.match,
format = string.format }
local setmetatable = setmetatable
-- ALSA volume
-- lain.widgets.alsa
local alsa = {}
local function worker(args)
local args = args or {}
local timeout = args.timeout or 5
local settings = args.settings or function() end
alsa.cmd = args.cmd or "amixer"
alsa.channel = args.channel or "Master"
alsa.widget = wibox.widget.textbox('')
function alsa.update()
local mixer = read_pipe(string.format("%s get %s", alsa.cmd, alsa.channel))
volume_now = {}
volume_now.level, volume_now.status = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
if volume_now.level == nil
then
volume_now.level = "0"
volume_now.status = "off"
end
if volume_now.status == ""
then
if volume_now.level == "0"
then
volume_now.status = "off"
else
volume_now.status = "on"
end
end
widget = alsa.widget
settings()
end
timer_id = string.format("alsa-%s-%s", alsa.cmd, alsa.channel)
newtimer(timer_id, timeout, alsa.update)
return setmetatable(alsa, { __index = alsa.widget })
end
return setmetatable(alsa, { __call = function(_, ...) return worker(...) end })

179
dotfiles/awesome/lain/widgets/alsabar.lua

@ -0,0 +1,179 @@
--[[
Licensed under GNU General Public License v2
* (c) 2013, Luke Bonham
* (c) 2013, Rman
--]]
local newtimer = require("lain.helpers").newtimer
local read_pipe = require("lain.helpers").read_pipe
local awful = require("awful")
local beautiful = require("beautiful")
local naughty = require("naughty")
local math = { modf = math.modf }
local mouse = mouse
local string = { format = string.format,
match = string.match,
rep = string.rep }
local tonumber = tonumber
local setmetatable = setmetatable
-- ALSA volume bar
-- lain.widgets.alsabar
local alsabar = {
channel = "Master",
step = "2%",
colors = {
background = beautiful.bg_normal,
mute = "#EB8F8F",
unmute = "#A4CE8A"
},
terminal = terminal or "xterm",
mixer = terminal .. " -e alsamixer",
notifications = {
font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")),
font_size = "11",
color = beautiful.fg_normal,
bar_size = 18,
screen = 1
},
_current_level = 0,
_muted = false
}
function alsabar.notify()
alsabar.update()
local preset = {
title = "",
text = "",
timeout = 5,
screen = alsabar.notifications.screen,
font = alsabar.notifications.font .. " " ..
alsabar.notifications.font_size,
fg = alsabar.notifications.color
}
if alsabar._muted
then
preset.title = alsabar.channel .. " - Muted"
else
preset.title = alsabar.channel .. " - " .. alsabar._current_level .. "%"
end
int = math.modf((alsabar._current_level / 100) * alsabar.notifications.bar_size)
preset.text = "["
.. string.rep("|", int)
.. string.rep(" ", alsabar.notifications.bar_size - int)
.. "]"
if alsabar.followmouse then
preset.screen = mouse.screen
end
if alsabar._notify ~= nil then
alsabar._notify = naughty.notify ({
replaces_id = alsabar._notify.id,
preset = preset,
})
else
alsabar._notify = naughty.notify ({
preset = preset,
})
end
end
local function worker(args)
local args = args or {}
local timeout = args.timeout or 5
local settings = args.settings or function() end
local width = args.width or 63
local height = args.heigth or 1
local ticks = args.ticks or false
local ticks_size = args.ticks_size or 7
local vertical = args.vertical or false
alsabar.cmd = args.cmd or "amixer"
alsabar.channel = args.channel or alsabar.channel
alsabar.step = args.step or alsabar.step
alsabar.colors = args.colors or alsabar.colors
alsabar.notifications = args.notifications or alsabar.notifications
alsabar.followmouse = args.followmouse or false
alsabar.bar = awful.widget.progressbar()
alsabar.bar:set_background_color(alsabar.colors.background)
alsabar.bar:set_color(alsabar.colors.unmute)
alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
alsabar.bar:set_width(width)
alsabar.bar:set_height(height)
alsabar.bar:set_ticks(ticks)
alsabar.bar:set_ticks_size(ticks_size)
alsabar.bar:set_vertical(vertical)
function alsabar.update()
-- Get mixer control contents
local mixer = read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.channel))
-- Capture mixer control state: [5%] ... ... [on]
local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
if volu == nil then
volu = 0
mute = "off"
end
alsabar._current_level = tonumber(volu)
alsabar.bar:set_value(alsabar._current_level / 100)
if not mute and tonumber(volu) == 0 or mute == "off"
then
alsabar._muted = true
alsabar.tooltip:set_text (" [Muted] ")
alsabar.bar:set_color(alsabar.colors.mute)
else
alsabar._muted = false
alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu))
alsabar.bar:set_color(alsabar.colors.unmute)
end
volume_now = {}
volume_now.level = tonumber(volu)
volume_now.status = mute
settings()
end
alsabar.bar:buttons (awful.util.table.join (
awful.button ({}, 1, function()
awful.util.spawn(alsabar.mixer)
end),
awful.button ({}, 3, function()
awful.util.spawn(string.format("%s set %s toggle", alsabar.cmd, alsabar.channel))
alsabar.update()
end),
awful.button ({}, 4, function()
awful.util.spawn(string.format("%s set %s %s+", alsabar.cmd, alsabar.channel, alsabar.step))
alsabar.update()
end),
awful.button ({}, 5, function()
awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step))
alsabar.update()
end)
))
timer_id = string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel)
newtimer(timer_id, timeout, alsabar.update)
return alsabar
end
return setmetatable(alsabar, { __call = function(_, ...) return worker(...) end })

39
dotfiles/awesome/lain/widgets/base.lua

@ -0,0 +1,39 @@
--[[
Licensed under GNU General Public License v2
* (c) 2014, Luke Bonham
--]]
local newtimer = require("lain.helpers").newtimer
local read_pipe = require("lain.helpers").read_pipe
local wibox = require("wibox")
local setmetatable = setmetatable
-- Basic template for custom widgets
-- lain.widgets.base
local function worker(args)
local base = {}
local args = args or {}
local timeout = args.timeout or 5
local cmd = args.cmd or ""
local settings = args.settings or function() end
base.widget = wibox.widget.textbox('')
function base.update()
output = read_pipe(cmd)
widget = base.widget
settings()
end
newtimer(cmd, timeout, base.update)
return setmetatable(base, { __index = base.widget })
end
return setmetatable({}, { __call = function(_, ...) return worker(...) end })

149
dotfiles/awesome/lain/widgets/bat.lua

@ -0,0 +1,149 @@
--[[
Licensed under GNU General Public License v2
* (c) 2013, Luke Bonham
* (c) 2010-2012, Peter Hofmann
--]]
local newtimer = require("lain.helpers").newtimer
local first_line = require("lain.helpers").first_line
local naughty = require("naughty")
local wibox = require("wibox")
local math = { floor = math.floor }
local string = { format = string.format }
local tonumber = tonumber
local setmetatable = setmetatable
-- Battery infos
-- lain.widgets.bat
local bat = {}
local function worker(args)
local args = args or {}
local timeout = args.timeout or 30
local battery = args.battery or "BAT0"
local notify = args.notify or "on"
local settings = args.settings or function() end
bat.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"
}
function update()
bat_now = {
status = "Not present",
perc = "N/A",
time = "N/A",
watt = "N/A"
}
local bstr = "/sys/class/power_supply/" .. battery
local present = first_line(bstr .. "/present")
if present == "1"
then
local rate = first_line(bstr .. "/power_now") or
first_line(bstr .. "/current_now")
local ratev = first_line(bstr .. "/voltage_now")
local rem = first_line(bstr .. "/energy_now") or
first_line(bstr .. "/charge_now")
local tot = first_line(bstr .. "/energy_full") or
first_line(bstr .. "/charge_full")
bat_now.status = first_line(bstr .. "/status") or "N/A"
rate = tonumber(rate) or 1
ratev = tonumber(ratev)
rem = tonumber(rem)
tot = tonumber(tot)
local time_rat = 0
if bat_now.status == "Charging"
then
time_rat = (tot - rem) / rate
elseif bat_now.status == "Discharging"
then
time_rat = rem / rate
end
local hrs = math.floor(time_rat)
if hrs < 0 then hrs = 0 elseif hrs > 23 then hrs = 23 end
local min = math.floor((time_rat - hrs) * 60)
if min < 0 then min = 0 elseif min > 59 then min = 59 end
bat_now.time = string.format("%02d:%02d", hrs, min)
bat_now.perc = first_line(bstr .. "/capacity")
if not bat_now.perc then
local perc = (rem / tot) * 100
if perc <= 100 then
bat_now.perc = string.format("%d", perc)
elseif perc > 100 then
bat_now.perc = "100"
elseif perc < 0 then
bat_now.perc = "0"
end
end
if rate ~= nil and ratev ~= nil then
bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12)
else
bat_now.watt = "N/A"
end
end
widget = bat.widget
settings()
-- notifications for low and critical states
if bat_now.status == "Discharging" and notify == "on" and bat_now.perc ~= nil
then
local nperc = tonumber(bat_now.perc) or 100
if nperc <= 5
then
bat.id = naughty.notify({
preset = bat_notification_critical_preset,
replaces_id = bat.id,
}).id
elseif nperc <= 15
then
bat.id = naughty.notify({
preset = bat_notification_low_preset,
replaces_id = bat.id,
}).id
end
end
end
newtimer(battery, timeout, update)
return bat.widget
end
return setmetatable(bat, { __call = function(_, ...) return worker(...) end })

62
dotfiles/awesome/lain/widgets/borderbox.lua

@ -0,0 +1,62 @@
--[[
Licensed under GNU General Public License v2
* (c) 2013, Luke Bonham
* (c) 2010-2012, Peter Hofmann
--]]
local wibox = require("awful.wibox")
local setmetatable = setmetatable
-- Creates a thin wibox at a position relative to another wibox
-- lain.widgets.borderbox
local borderbox = {}
local function worker(relbox, s, args)
local where = args.position or 'top'
local color = args.color or '#FFFFFF'
local size = args.size or 1
local box = nil
local wiboxarg = {
position = nil,
bg = color
}
if where == 'top'
then
wiboxarg.width = relbox.width
wiboxarg.height = size
box = wibox(wiboxarg)
box.x = relbox.x
box.y = relbox.y - size
elseif where == 'bottom'
then
wiboxarg.width = relbox.width
wiboxarg.height = size
box = wibox(wiboxarg)
box.x = relbox.x
box.y = relbox.y + relbox.height
elseif where == 'left'
then
wiboxarg.width = size
wiboxarg.height = relbox.height
box = wibox(wiboxarg)
box.x = relbox.x - size
box.y = relbox.y
elseif where == 'right'
then
wiboxarg.width = size
wiboxarg.height = relbox.height
box = wibox(wiboxarg)
box.x = relbox.x + relbox.width
box.y = relbox.y
end
box.screen = s
return box
end
return setmetatable(borderbox, { __call = function(_, ...) return worker(...) end })

140
dotfiles/awesome/lain/widgets/calendar.lua

@ -0,0 +1,140 @@
--[[
Licensed under GNU General Public License v2
* (c) 2013, Luke Bonham
--]]
local icons_dir = require("lain.helpers").icons_dir
local awful = require("awful")
local beautiful = require("beautiful")
local naughty = require("naughty")
local io = { popen = io.popen }
local os = { date = os.date }
local mouse = mouse
local tonumber = tonumber
local setmetatable = setmetatable
-- Calendar notification
-- lain.widgets.calendar
local calendar = {}
local cal_notification = nil
function calendar:hide()
if cal_notification ~= nil then
naughty.destroy(cal_notification)
cal_notification = nil
end
end
function calendar:show(t_out, inc_offset, scr)
calendar:hide()
local offs = inc_offset or 0
local tims = t_out or 0
local f, c_text
local today = tonumber(os.date('%d'))
local init_t = calendar.cal .. ' ' .. calendar.post_cal .. ' ' ..
' | sed -r -e "s/_\\x08//g" | sed -r -e "s/(^| )('
calendar.offset = calendar.offset + offs
if offs == 0 or calendar.offset == 0
then -- current month showing, today highlighted
calendar.offset = 0
calendar.notify_icon = calendar.icons .. today .. ".png"
-- bg and fg inverted to highlight today
f = io.popen( init_t .. today ..
')($| )/\\1<b><span foreground=\\"'
.. calendar.bg ..
'\\" background=\\"'
.. calendar.fg ..
'\\">\\2<\\/span><\\/b>\\3/"' )
else -- no current month showing, no day to highlight
local month = tonumber(os.date('%m'))
local year = tonumber(os.date('%Y'))
month = month + calendar.offset
if month > 12 then
month = month % 12
year = year + 1
if month <= 0 then
month = 12
end
elseif month < 1 then
month = month + 12
year = year - 1
if month <= 0 then
month = 1
end
end
calendar.notify_icon = nil
f = io.popen(calendar.cal .. ' ' .. month .. ' ' .. year .. ' ' ..
calendar.post_cal)
end
c_text = "<tt><span font='" .. calendar.font .. " "
.. calendar.font_size .. "'><b>"
.. f:read() .. "</b>\n\n"
.. f:read() .. "\n"
.. f:read("*all"):gsub("\n*$", "")
.. "</span></tt>"
f:close()
if calendar.followmouse then
scrp = mouse.screen
else
scrp = scr or calendar.scr_pos
end
cal_notification = naughty.notify({
text = c_text,
icon = calendar.notify_icon,
position = calendar.position,
fg = calendar.fg,
bg = calendar.bg,
timeout = tims,
screen = scrp
})
end
function calendar:attach(widget, args)
local args = args or {}
calendar.cal = args.cal or "/usr/bin/cal"
calendar.post_cal = args.post_cal or ""
calendar.icons = args.icons or icons_dir .. "cal/white/"
calendar.font = args.font or beautiful.font:sub(beautiful.font:find(""),
beautiful.font:find(" "))
calendar.font_size = tonumber(args.font_size) or 11
calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF"
calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF"
calendar.position = args.position or "top_right"
calendar.scr_pos = args.scr_pos or 1
calendar.followmouse = args.followmouse or false
calendar.offset = 0
calendar.notify_icon = nil
widget:connect_signal("mouse::enter", function () calendar:show(0, 0, calendar.scr_pos) end)
widget:connect_signal("mouse::leave", function () calendar:hide() end)
widget:buttons(awful.util.table.join(awful.button({ }, 1, function ()
calendar:show(0, -1, calendar.scr_pos) end),
awful.button({ }, 3, function ()
calendar:show(0, 1, calendar.scr_pos) end),
awful.button({ }, 4, function ()
calendar:show(0, -1, calendar.scr_pos) end),
awful.button({ }, 5, function ()
calendar:show(0, 1, calendar.scr_pos) end)))
end
return setmetatable(calendar, { __call = function(_, ...) return create(...) end })

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save