initial commit
9
.build.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
image: alpine/edge
|
||||||
|
packages:
|
||||||
|
- luacheck
|
||||||
|
sources:
|
||||||
|
- https://github.com/vicious-widgets/vicious
|
||||||
|
tasks:
|
||||||
|
- check: |
|
||||||
|
cd vicious
|
||||||
|
luacheck --config=tools/luacheckrc .
|
151
CHANGELOG.rst
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
Changelog
|
||||||
|
=========
|
||||||
|
|
||||||
|
Changes in 2.5.0
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
|
||||||
|
- ``vicious.call`` freezing awesome when used with asynchronous widget types
|
||||||
|
|
||||||
|
Added:
|
||||||
|
|
||||||
|
- ``vicious.call_async`` asynchronous analogous to ``vicious.call``
|
||||||
|
|
||||||
|
Moved:
|
||||||
|
|
||||||
|
- Most of the documentation in READMEs to ``docs/``
|
||||||
|
- ``Changes.md`` to ``CHANGELOG.rst``
|
||||||
|
- ``CONTRIBUTING.md`` to ``CONTRIBUTING.rst``
|
||||||
|
- Meta helpers to ``tools/``
|
||||||
|
|
||||||
|
Changes in 2.4.2
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Feature: [hwmontemp] Bring back sysfs path cache
|
||||||
|
|
||||||
|
Changes in 2.4.1
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
|
||||||
|
- [pkg] Fallback the number of lines before packages listing to 0.
|
||||||
|
This fixes crashes on Arch, FreeBSD and Mandriva.
|
||||||
|
- [mdir] Remove trailing semicolon at the end of command.
|
||||||
|
|
||||||
|
Changes in 2.4.0
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. important::
|
||||||
|
|
||||||
|
``volume`` now uses 🔉 and 🔈 instead of ♫ and ♩ to show mute state.
|
||||||
|
This BREAKS backward compatibility if users substitute custom symbols
|
||||||
|
from these default.
|
||||||
|
|
||||||
|
Added:
|
||||||
|
|
||||||
|
- notmuch_all, cpu_freebsd widget types.
|
||||||
|
- [cmus_all] Promote to ``widgets/``.
|
||||||
|
- [wifiiw_linux] Expose BSSID.
|
||||||
|
- [wifi_linux] Expose frequency and transmission power.
|
||||||
|
- ``spawn`` as a fallback for ``awful.spawn`` in case Vicious is used as
|
||||||
|
a stand-alone library. This wrapper, however, does NOT provide the facilities
|
||||||
|
to asynchronously spawn new processes. It also lacks a few features such as
|
||||||
|
parsing ``stderr`` and returning PID.
|
||||||
|
- ``helpers.setasyncall`` to avoid writing redundant workers for asynchronous
|
||||||
|
widget types. Note that these workers are only needed in case Vicious is used
|
||||||
|
as a stand-alone library.
|
||||||
|
- ``helpers.setcall`` for registering functions as widget types.
|
||||||
|
- ``headergen`` script for automatic generation of copyright notices.
|
||||||
|
- ``templates`` for the ease of adding new widget types.
|
||||||
|
- ``CONTRIBUTING.md`` which guide contributors through the steps
|
||||||
|
of filing an issue or submitting a patch.
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
|
||||||
|
- Deprecate the use of ``io.popen`` in following widgets:
|
||||||
|
|
||||||
|
- wifi_linux, wifiiw_linux, hwmontemp_linux, hddtemp_linux
|
||||||
|
- bat_freebsd, mem_freebsd, net_freebsd, thermal_freebsd, uptime_freebsd,
|
||||||
|
- cpu_freebsd, cpufreq_freebsd, fanspeed_freebsd
|
||||||
|
- bat_openbsd
|
||||||
|
- volume, gmail, mdir, mpd, fs
|
||||||
|
|
||||||
|
- [mpd] Lua 5.3 compatibility (for real this time); also correct a typo
|
||||||
|
- [mbox] Update the deprecated ``string.gfind`` to ``string.gmatch``
|
||||||
|
- [pkg,weather,contrib/btc] Allow function call without Awesome
|
||||||
|
- [pkg] Use more updated front-ends for Debian/Ubuntu (apt) and Fedora (dnf)
|
||||||
|
- [os] Splitted os_all into os_linux and os_bsd (and refactored to async)
|
||||||
|
- Tweak ``.luacheckrc`` to suit functional style and soft-limit text width to 80
|
||||||
|
- Update copyright headers for libraries and widget types
|
||||||
|
|
||||||
|
Removed:
|
||||||
|
|
||||||
|
- ``helpers.sysctl`` and ``helpers.sysctl_table`` were removed in favour of
|
||||||
|
``helpers.sysctl_async``.
|
||||||
|
|
||||||
|
Changes in 2.3.3
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Feature: Add battery widget type for OpenBSD
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
|
||||||
|
- [mpd] Lua 5.3 compatibility
|
||||||
|
- [bat_freebsd] Update battery state symbols
|
||||||
|
|
||||||
|
Changes in 2.3.2
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Features:
|
||||||
|
|
||||||
|
- Support stacked graphs
|
||||||
|
- [hwmontemp_linux] Provide name-based access to hwmon sensors via sysfs
|
||||||
|
- [mpd_all] Expose more informations and format time in [hh:]mm:ss
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
|
||||||
|
- Improve defaults and mechanism for data caching
|
||||||
|
- Escape XML entities in results by default
|
||||||
|
- [weather_all] Update NOAA link and use Awesome asynchronous API
|
||||||
|
- [mem_linux] Use MemAvailable to calculate free amount
|
||||||
|
- [mem_freebsd] Correct calculation and switch to swapinfo for swap
|
||||||
|
- [bat_freebsd] Add critical charging state
|
||||||
|
- [fs_all] Fix shell quoting of option arguments
|
||||||
|
|
||||||
|
Moreover, ``.luacheckrc`` was added and ``README.md`` was refomatted
|
||||||
|
for the ease of development.
|
||||||
|
|
||||||
|
Changes in 2.3.1
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
|
||||||
|
- widgets can be a function again (regression introduced in 2.3.0)
|
||||||
|
|
||||||
|
Changes in 2.3.0
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Features:
|
||||||
|
|
||||||
|
- add btc widget
|
||||||
|
- add cmus widget
|
||||||
|
- alsa mixer also accept multiple arguments
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
|
||||||
|
- pkg now uses non-blocking asynchronous api
|
||||||
|
|
||||||
|
Changes in 2.2.0
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Notable changes:
|
||||||
|
|
||||||
|
- moved development from git.sysphere.org/vicious to github.com/Mic92/vicious
|
||||||
|
- official freebsd support
|
||||||
|
- escape variables before passing to shell
|
||||||
|
- support for gear timers
|
||||||
|
- fix weather widget url
|
||||||
|
- add :lua:func:`vicious.call` method to obtain data outside of widgets
|
||||||
|
|
||||||
|
For older versions please see ``git log``.
|
344
CONTRIBUTING.rst
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
Contribution Guidelines
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Filing an Issue
|
||||||
|
---------------
|
||||||
|
|
||||||
|
* Ensure the bug was not already reported by searching GitHub Issues.
|
||||||
|
* If you're unable to find an open issue addressing the problem,
|
||||||
|
open a new one. Be sure to include a title and clear description,
|
||||||
|
as much relevant information as possible, such as Awesome errors,
|
||||||
|
and a config sample or an executable test case
|
||||||
|
(using Vicious as a stand-alone library)
|
||||||
|
demonstrating the expected behavior that is not occurring.
|
||||||
|
|
||||||
|
Please re-read your issue once again to avoid a couple of common mistakes
|
||||||
|
(you can and should use this as a checklist):
|
||||||
|
|
||||||
|
* Is the description of the issue itself sufficient?
|
||||||
|
Make sure that it's obvious
|
||||||
|
|
||||||
|
* What the problem is
|
||||||
|
* How it could be fixed
|
||||||
|
* How your proposed solution would look like
|
||||||
|
|
||||||
|
* Have you provide the versions of Vicious and related software?
|
||||||
|
We would like to how you installed Vicious, which OS you're using,
|
||||||
|
the version of the software or what kind of hardware you are trying
|
||||||
|
to get information from.
|
||||||
|
* Is the issue already documented?
|
||||||
|
* Does the issue involve one problem, and one problem only?
|
||||||
|
Some people seem to think there is a limit of issues they can or should open.
|
||||||
|
There is no limit of issues they can or should open.
|
||||||
|
While it may seem appealing to be able to dump all your issues
|
||||||
|
into one ticket, that means that someone who solves one of your issues
|
||||||
|
cannot mark the issue as closed.
|
||||||
|
* Is anyone going to need the feature? Only post features that you
|
||||||
|
(or an incapacitated friend you can personally talk to) require.
|
||||||
|
Do not post features because they seem like a good idea.
|
||||||
|
If they're really useful, they'll be requested by someone who requires them.
|
||||||
|
|
||||||
|
Requesting for Merging a Patch
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
#. `Fork this repository`_
|
||||||
|
#. Check out the source code with::
|
||||||
|
|
||||||
|
git clone https://github.com/YOUR_GITHUB_USERNAME/vicious.git
|
||||||
|
cd vicious
|
||||||
|
|
||||||
|
#. Start working on your patch. If you want to add a new widget type,
|
||||||
|
see the ``templates`` directory for a more detailed guide.
|
||||||
|
#. Have a look at ``helpers.lua`` and ``spawn.lua``
|
||||||
|
for possible helper functions.
|
||||||
|
#. Make sure your code follows the coding conventions below and check the code
|
||||||
|
with ``luacheck``. This *should fail* at first, but you can continually
|
||||||
|
re-run it until you're done::
|
||||||
|
|
||||||
|
luacheck --config tools/luacheckrc .
|
||||||
|
|
||||||
|
#. Make sure your code works under all Lua versions claimed supported
|
||||||
|
by Vicious, namely 5.1, 5.2 and 5.3.
|
||||||
|
#. Update the copyright notices of the files you modified. Vicious is
|
||||||
|
collectively licensed under GPLv2+, and to protect the freedom of the users,
|
||||||
|
copyright holders need to be properly documented.
|
||||||
|
#. Try to note your changes under ``CHANGELOG.rst``. If you find it is
|
||||||
|
difficult to phrase the changes, you can leave it for us.
|
||||||
|
#. Add_ the changes, commit_ them and push_ the result, like this::
|
||||||
|
|
||||||
|
git add widgets/bar_baz.lua README.md
|
||||||
|
git commit -m '[bar_baz] Add widget type'
|
||||||
|
git add helpers.lua CHANGELOG.rst
|
||||||
|
git commit -m '[helpers] Fix foo'
|
||||||
|
git push
|
||||||
|
|
||||||
|
#. Finally, `create a pull request`_. We'll then review and merge it.
|
||||||
|
|
||||||
|
In any case, thank you very much for your contributions!
|
||||||
|
|
||||||
|
Coding Conventions
|
||||||
|
------------------
|
||||||
|
|
||||||
|
This section introduces a guideline for writing idiomatic, robust
|
||||||
|
and future-proof widget type code.
|
||||||
|
|
||||||
|
Whitespace in Expressions and Statements
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Avoid extraneous whitespace in the following situations:
|
||||||
|
|
||||||
|
* Immediately inside parentheses or brackets. Braces, however, are exceptions
|
||||||
|
to this rule:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
foo(bar[1], { baz = 2 }) -- yes
|
||||||
|
foo( bar[ 1 ], {baz = 2} ) -- no
|
||||||
|
|
||||||
|
* Immediately before a comma, semicolon, or colon.
|
||||||
|
* Immediately before the open parenthesis, braces, quote, etc.
|
||||||
|
that starts the argument list of a function call; or the open bracket
|
||||||
|
that starts an indexing. In other words, prefer these:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
foo(bar, baz)
|
||||||
|
foo{ bar, baz }
|
||||||
|
foo"bar"
|
||||||
|
foo[[bar]]
|
||||||
|
foo[bar]
|
||||||
|
|
||||||
|
* Trailing at the end of line or (newline) at the end of file.
|
||||||
|
|
||||||
|
Always surround these binary operators with a single space on either side:
|
||||||
|
assignment (``=``), comparisons, Booleans (``and``, ``or``, ``not``).
|
||||||
|
If operators with different priorities are used, consider adding whitespace
|
||||||
|
around the operators with the lowest priorities. Use your own judgment;
|
||||||
|
however, never use more than one space, and always have
|
||||||
|
the same amount of whitespace on both sides of a binary operator.
|
||||||
|
|
||||||
|
Indentation
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
Use 4 *spaces* per indentation level.
|
||||||
|
|
||||||
|
Continuation lines should align wrapped elements either vertically
|
||||||
|
inside parentheses, brackets and braces, or using a hanging indent
|
||||||
|
(the opening parenthesis of a parenthesized statement is the last
|
||||||
|
non-whitespace character of the line, with subsequent lines being indented
|
||||||
|
until the closing parenthesis), e.g.
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
-- Vertically aligned
|
||||||
|
long_function_call{ foo, bar,
|
||||||
|
baz }
|
||||||
|
|
||||||
|
-- Hanging indentation
|
||||||
|
long_function_call(
|
||||||
|
foo, bar
|
||||||
|
baz)
|
||||||
|
|
||||||
|
The closing brace or bracket on multi-line constructs may either line up under
|
||||||
|
the first character of the line that starts the construct, as in:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
long_function_call{
|
||||||
|
foo = 1, bar = 2,
|
||||||
|
baz = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
In this case, and this case only, the trailing comma is acceptable
|
||||||
|
to avoid diff noises when more values are added,
|
||||||
|
but since Vicious often deal with system APIs which rarely ever change,
|
||||||
|
it's occasionally helpful to do so.
|
||||||
|
|
||||||
|
Trailing right parentheses, however, are not allowed.
|
||||||
|
|
||||||
|
Maximum Line Length
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
If possible, try to limit all *code* lines to a maximum
|
||||||
|
of 80 characters. In case you find some lines in your patch would be
|
||||||
|
more readable exceeding this limit, feel free to discuss with us.
|
||||||
|
Comments and long strings need not to follow this restriction however.
|
||||||
|
|
||||||
|
As one might have noticed, the syntactic sugars ``f{<fields>}``
|
||||||
|
(for ``f({<fields>})``) and ``f'<string>'``
|
||||||
|
(or ``f"<string>"``/``f[[<string>]]``, for ``f('<string>')``)
|
||||||
|
are especially preferred to squeeze the line length to this limit.
|
||||||
|
|
||||||
|
Blank Lines
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
Surround function definitions with a single blank line. Extra blank lines
|
||||||
|
may be used (sparingly) to separate groups of related functions.
|
||||||
|
Blank lines may be omitted between a bunch of related one-liners
|
||||||
|
(e.g. a set of dummy implementations).
|
||||||
|
Use blank lines in functions, sparingly, to indicate logical sections.
|
||||||
|
|
||||||
|
Requiring Libraries
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
All standard libraries should be localized before used
|
||||||
|
for the matter of performance.
|
||||||
|
|
||||||
|
``require``'s should always be put at the top of the source file,
|
||||||
|
just after the copyright header, and before module globals and constants,
|
||||||
|
and grouped in the following order:
|
||||||
|
|
||||||
|
1. Standard libraries
|
||||||
|
2. Related third-party libraries
|
||||||
|
3. Local libraries
|
||||||
|
|
||||||
|
For example,
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
local type = type
|
||||||
|
local table = { concat = table.concat, insert = table.insert }
|
||||||
|
|
||||||
|
local awful = require("awful")
|
||||||
|
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
|
||||||
|
String Quotes
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
In Lua, single-quoted strings and double-quoted strings are the same,
|
||||||
|
so the choice is totally up to you, but please be consistent within a module.
|
||||||
|
When a string contains single or double quote characters, however,
|
||||||
|
use the other one to avoid backslashes in the string. It improves readability:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
'"key": "value"' -- good
|
||||||
|
"\"key\": \"value\"" -- no good
|
||||||
|
|
||||||
|
It is preferable to add a newline immediately after the opening long bracket:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
foo = [[
|
||||||
|
this is a really,
|
||||||
|
really,
|
||||||
|
really long text]]
|
||||||
|
|
||||||
|
Naming Conventions
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Avoid using the characters ``l`` (lowercase letter el),
|
||||||
|
``O`` (uppercase letter oh), or ``I`` (uppercase letter eye)
|
||||||
|
as single character variable names. In some fonts, these characters
|
||||||
|
are indistinguishable from the 1's and 0's.
|
||||||
|
|
||||||
|
Constants
|
||||||
|
"""""""""
|
||||||
|
|
||||||
|
Constants are usually defined on a module level
|
||||||
|
and written in all capital letters with underscores separating words.
|
||||||
|
Examples include ``MAX_OVERFLOW`` and ``TOTAL``.
|
||||||
|
|
||||||
|
Function and Variable Names
|
||||||
|
"""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
Function names should be lowercase, with words separated by underscores
|
||||||
|
as necessary to improve readability.
|
||||||
|
|
||||||
|
Variable names follow the same convention as function names.
|
||||||
|
|
||||||
|
When you find it difficult to give descriptive names,
|
||||||
|
use the functions and variable anonymously.
|
||||||
|
|
||||||
|
Performance Tips
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Vicious is meant to be run as part of the Awesome window manager,
|
||||||
|
thus any little overhead may defect the responsiveness of the UI.
|
||||||
|
While Lua is famous for its performance, there are a few things
|
||||||
|
one can do to make use of all of its power.
|
||||||
|
|
||||||
|
**Never** use global variables. This includes the standard libraries,
|
||||||
|
which, again, must be localized before use. Remember, every widget type
|
||||||
|
is to be called repeatedly every few seconds.
|
||||||
|
|
||||||
|
Use closures when possible:
|
||||||
|
|
||||||
|
* Define constants on the module level.
|
||||||
|
* Avoid re-fetching the values that are not not meant to change.
|
||||||
|
|
||||||
|
However, declare a variable only when you need it, to avoid declaring it
|
||||||
|
without an initial value (and therefore you seldom forget to initialize it).
|
||||||
|
Moreover, you shorten the scope of the variable, which increases readability.
|
||||||
|
|
||||||
|
Copyright Header
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Vicious is released under the GNU GNU General Public License
|
||||||
|
version 2 or later and each contributor holds the copyright
|
||||||
|
on their contributions. To make this collective control effective,
|
||||||
|
each source file must include a notice of the following format
|
||||||
|
denoting the name of all authors
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
-- <one line to give the program's name and a brief idea of what it does.>
|
||||||
|
-- Copyright (C) <year> <name of author> <<email that can be use for contact>>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Comments
|
||||||
|
^^^^^^^^
|
||||||
|
|
||||||
|
Comments that contradict the code are worse than no comments.
|
||||||
|
Always make a priority of keeping the comments up-to-date when the code changes!
|
||||||
|
|
||||||
|
You should use two spaces after a sentence-ending period
|
||||||
|
in multi-sentence comments, except after the final sentence.
|
||||||
|
|
||||||
|
Block Comments
|
||||||
|
""""""""""""""
|
||||||
|
|
||||||
|
Block comments generally apply to some (or all) code that follows them,
|
||||||
|
and are indented to the same level as that code. Each line of a block comment
|
||||||
|
starts with ``--`` and a single space, unless text inside the comment
|
||||||
|
is indented, or it is to comment out code.
|
||||||
|
|
||||||
|
Paragraphs inside a block comment are separated by a line containing
|
||||||
|
``--`` only. The best example is the copyright notice in the section above.
|
||||||
|
|
||||||
|
The ``--[[...]]`` style may only be used for commenting out source code.
|
||||||
|
|
||||||
|
Inline Comments
|
||||||
|
"""""""""""""""
|
||||||
|
|
||||||
|
An inline comment is a comment on the same line as a statement.
|
||||||
|
Inline comments should be separated by at least two spaces from the statement.
|
||||||
|
They should start with ``--`` and one single space.
|
||||||
|
|
||||||
|
Influences
|
||||||
|
----------
|
||||||
|
|
||||||
|
These contributing guideline are heavily influenced by that of ``youtube-dl``,
|
||||||
|
PEP 8, Programming in Lua and the performance tips in Lua Programming Gems.
|
||||||
|
|
||||||
|
.. _Fork this repository: https://github.com/vicious-widgets/vicious/fork
|
||||||
|
.. _Add: https://git-scm.com/docs/git-add
|
||||||
|
.. _commit: https://git-scm.com/docs/git-commit
|
||||||
|
.. _push: https://git-scm.com/docs/git-push
|
||||||
|
.. _create a pull request:
|
||||||
|
https://help.github.com/articles/creating-a-pull-request
|
339
LICENSE
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
30
README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Vicious
|
||||||
|
|
||||||
|
Vicious is a modular widget library for window managers, but mostly
|
||||||
|
catering to users of the *awesome* window manager. It was derived from
|
||||||
|
the old *Wicked* widget library, and has some of the old *Wicked* widget
|
||||||
|
types, a few of them rewritten, and a good number of new ones.
|
||||||
|
|
||||||
|
Vicious widget types are a framework for creating your own
|
||||||
|
widgets. Vicious contains modules that gather data about your system,
|
||||||
|
and a few *awesome* helper functions that make it easier to register
|
||||||
|
timers, suspend widgets and so on. Vicious doesn't depend on any third party
|
||||||
|
Lua libraries, but may depend on additional system utilities (see widget
|
||||||
|
description).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Please see our [online documentation] for detail instructions.
|
||||||
|
It is also available under the `docs` directory for offline reference.
|
||||||
|
|
||||||
|
## Copying
|
||||||
|
|
||||||
|
Vicious is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 2 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Please refer to our documentation for the full [list of authors].
|
||||||
|
|
||||||
|
[online documentation]: https://vicious.rtfd.io
|
||||||
|
[list of authors]: https://vicious.rtfd.io/copying.html
|
35
TODO
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#-*- mode: org -*-
|
||||||
|
#+TYP_TODO: TODO MAYBE CANCEL WAITING NEXT NOTE DONE
|
||||||
|
#+STARTUP: showall
|
||||||
|
#+STARTUP: hidestars
|
||||||
|
|
||||||
|
|
||||||
|
* Vicious
|
||||||
|
** TODO Implement intelligent multigraph support
|
||||||
|
** TODO Expand raid to grab data for all available devices
|
||||||
|
** TODO Consider commiting power drain support to bat.lua
|
||||||
|
** TODO Document contrib widgets in contrib/README
|
||||||
|
** TODO Complete the hddtemp fix
|
||||||
|
- In certain setups regexp does not match all devices
|
||||||
|
- The regexp catches the first device name, but last stats
|
||||||
|
- Shortening the match introduced new problems IIRC
|
||||||
|
** TODO Add fan speed to thermal.lua
|
||||||
|
** TODO Fix contrib/sensors for Ian
|
||||||
|
- > it does work and provides the lm_sensors
|
||||||
|
> information but only for one cpu core.
|
||||||
|
** TODO Return values of type number in NET and FS
|
||||||
|
- Note: tonumber() strips decimal points
|
||||||
|
** MAYBE Simplify scrolling using negative margins + fixed width
|
||||||
|
** TODO Try to simplify truncating with a fixed width
|
||||||
|
** NOTE Changelog header
|
||||||
|
---------------------------------------------------
|
||||||
|
Full changelog is available online:
|
||||||
|
http://git.sysphere.org/vicious/log/?showmsg=1
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
* Git
|
||||||
|
** DONE Git hook post-update not executed on git push
|
||||||
|
** DONE Git post-update hook does not leave info/refs with correct permissions
|
||||||
|
** DONE Git persmission are incorrect since 1.6.5, does not honor umask
|
||||||
|
** TODO Git smart http transport with cgit
|
49
contrib/ac_linux.lua
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
-- contrib/ac_linux.lua
|
||||||
|
-- Copyright (C) 2012 jinleileiking <jinleileiking@gmail.com>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local string = { format = string.format }
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
local math = {
|
||||||
|
min = math.min,
|
||||||
|
floor = math.floor
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
local ac_linux = {}
|
||||||
|
|
||||||
|
-- {{{ AC widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
local ac = helpers.pathtotable("/sys/class/power_supply/"..warg)
|
||||||
|
|
||||||
|
local state = ac.online
|
||||||
|
if state == nil then
|
||||||
|
return {"N/A"}
|
||||||
|
elseif state == "1\n" then
|
||||||
|
return {"On"}
|
||||||
|
else
|
||||||
|
return {"Off"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
return setmetatable(ac_linux, { __call = function(_, ...) return worker(...) end })
|
93
contrib/ati_linux.lua
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
-- contrib/ati_linux.lua
|
||||||
|
-- Copyright (C) 2013 NormalRa <normalrawr gmail com>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local io = { open = io.open }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
local string = {
|
||||||
|
sub = string.sub,
|
||||||
|
match = string.match,
|
||||||
|
gmatch = string.gmatch
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- ATI: provides various info about ATI GPU status
|
||||||
|
-- vicious.contrib.ati
|
||||||
|
local ati_linux = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Define variables
|
||||||
|
local _units = { clock = { ["khz"] = 1, ["mhz"] = 1000 },
|
||||||
|
voltage = { ["v"] = 1, ["mv"] = 1000 } }
|
||||||
|
local _reps = {
|
||||||
|
["sclk"] = { name = "engine_clock", units = _units.clock, mul = 10 },
|
||||||
|
["mclk"] = { name = "memory_clock", units = _units.clock, mul = 10 },
|
||||||
|
["vddc"] = { name = "voltage", units = _units.voltage },
|
||||||
|
["voltage"] = { name = "voltage", units = _units.voltage },
|
||||||
|
["current engine clock"] = { name = "engine_clock", units = _units.clock },
|
||||||
|
["current memory clock"] = { name = "memory_clock", units = _units.clock }
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ ATI widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
if not warg then return end
|
||||||
|
|
||||||
|
local pm = helpers.pathtotable("/sys/class/drm/"..warg.."/device")
|
||||||
|
local _data = {}
|
||||||
|
|
||||||
|
-- Get power info
|
||||||
|
_data["{method}"] =
|
||||||
|
pm.power_method and string.sub(pm.power_method, 1, -2) or "N/A"
|
||||||
|
_data["{dpm_state}"] =
|
||||||
|
pm.power_dpm_state and string.sub(pm.power_dpm_state, 1, -2) or "N/A"
|
||||||
|
_data["{dpm_perf_level}"] =
|
||||||
|
pm.power_dpm_force_performance_level and
|
||||||
|
string.sub(pm.power_dpm_force_performance_level, 1, -2) or "N/A"
|
||||||
|
_data["{profile}"] =
|
||||||
|
pm.power_profile and string.sub(pm.power_profile, 1, -2) or "N/A"
|
||||||
|
|
||||||
|
local f = io.open("/sys/kernel/debug/dri/64/radeon_pm_info", "r")
|
||||||
|
if f then -- Get ATI info from the debug filesystem
|
||||||
|
for line in f:lines() do
|
||||||
|
for k, unit in string.gmatch(line, "(%a+[%a%s]*):[%s]+([%d]+)") do
|
||||||
|
unit = tonumber(unit)
|
||||||
|
|
||||||
|
_data["{dpm_power_level}"] = -- DPM active?
|
||||||
|
tonumber(string.match(line, "power level ([%d])")) or "N/A"
|
||||||
|
|
||||||
|
if _reps[k] then
|
||||||
|
for u, v in pairs(_reps[k].units) do
|
||||||
|
_data["{".._reps[k].name.." "..u.."}"] =
|
||||||
|
(unit * (_reps[k].mul or 1)) / v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
return _data
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(ati_linux, { __call = function(_, ...) return worker(...) end })
|
93
contrib/batpmu_linux.lua
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
-- contrib/batpmu_linux.lua
|
||||||
|
-- Copyright (C) 2010 Adrian C. <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local io = { open = io.open }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local math = {
|
||||||
|
min = math.min,
|
||||||
|
floor = math.floor
|
||||||
|
}
|
||||||
|
local string = {
|
||||||
|
find = string.find,
|
||||||
|
match = string.match,
|
||||||
|
format = string.format
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Batpmu: provides state, charge and remaining time for a requested battery using PMU
|
||||||
|
-- vicious.contrib.batpmu
|
||||||
|
local batpmu_linux = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Battery widget type
|
||||||
|
local function worker(format, batid)
|
||||||
|
local battery_state = {
|
||||||
|
["full"] = "↯",
|
||||||
|
["unknown"] = "⌁",
|
||||||
|
["00000013"] = "+",
|
||||||
|
["00000011"] = "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Get /proc/pmu/battery* state
|
||||||
|
local f = io.open("/proc/pmu/" .. batid)
|
||||||
|
-- Handler for incompetent users
|
||||||
|
if not f then return {battery_state["unknown"], 0, "N/A"} end
|
||||||
|
local statefile = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Get /proc/pmu/info data
|
||||||
|
local f = io.open("/proc/pmu/info")
|
||||||
|
local infofile = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Check if the battery is present
|
||||||
|
if infofile == nil or string.find(infofile, "Battery count[%s]+:[%s]0") then
|
||||||
|
return {battery_state["unknown"], 0, "N/A"}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Get capacity and charge information
|
||||||
|
local capacity = string.match(statefile, "max_charge[%s]+:[%s]([%d]+).*")
|
||||||
|
local remaining = string.match(statefile, "charge[%s]+:[%s]([%d]+).*")
|
||||||
|
|
||||||
|
-- Calculate percentage
|
||||||
|
local percent = math.min(math.floor(remaining / capacity * 100), 100)
|
||||||
|
|
||||||
|
|
||||||
|
-- Get timer information
|
||||||
|
local timer = string.match(statefile, "time rem%.[%s]+:[%s]([%d]+).*")
|
||||||
|
if timer == "0" then return {battery_state["full"], percent, "N/A"} end
|
||||||
|
|
||||||
|
-- Get state information
|
||||||
|
local state = string.match(statefile, "flags[%s]+:[%s]([%d]+).*")
|
||||||
|
local state = battery_state[state] or battery_state["unknown"]
|
||||||
|
|
||||||
|
-- Calculate remaining (charging or discharging) time
|
||||||
|
local hoursleft = math.floor(tonumber(timer) / 3600)
|
||||||
|
local minutesleft = math.floor((tonumber(timer) / 60) % 60)
|
||||||
|
local time = string.format("%02d:%02d", hoursleft, minutesleft)
|
||||||
|
|
||||||
|
return {state, percent, time}
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(batpmu_linux, { __call = function(_, ...) return worker(...) end })
|
100
contrib/batproc_linux.lua
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
-- contrib/batproc_linux.lua
|
||||||
|
-- Copyright (C) 2010 Adrian C. <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local io = { open = io.open }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local math = {
|
||||||
|
min = math.min,
|
||||||
|
floor = math.floor
|
||||||
|
}
|
||||||
|
local string = {
|
||||||
|
find = string.find,
|
||||||
|
match = string.match,
|
||||||
|
format = string.format
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Batproc: provides state, charge, and remaining time for a requested battery using procfs
|
||||||
|
-- vicious.contrib.batproc
|
||||||
|
local batproc_linux = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Battery widget type
|
||||||
|
local function worker(format, batid)
|
||||||
|
local battery_state = {
|
||||||
|
["full"] = "↯",
|
||||||
|
["unknown"] = "⌁",
|
||||||
|
["charged"] = "↯",
|
||||||
|
["charging"] = "+",
|
||||||
|
["discharging"] = "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Get /proc/acpi/battery info
|
||||||
|
local f = io.open("/proc/acpi/battery/"..batid.."/info")
|
||||||
|
-- Handler for incompetent users
|
||||||
|
if not f then return {battery_state["unknown"], 0, "N/A"} end
|
||||||
|
local infofile = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Check if the battery is present
|
||||||
|
if infofile == nil or string.find(infofile, "present:[%s]+no") then
|
||||||
|
return {battery_state["unknown"], 0, "N/A"}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get capacity information
|
||||||
|
local capacity = string.match(infofile, "last full capacity:[%s]+([%d]+).*")
|
||||||
|
|
||||||
|
|
||||||
|
-- Get /proc/acpi/battery state
|
||||||
|
local f = io.open("/proc/acpi/battery/"..batid.."/state")
|
||||||
|
local statefile = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Get state information
|
||||||
|
local state = string.match(statefile, "charging state:[%s]+([%a]+).*")
|
||||||
|
local state = battery_state[state] or battery_state["unknown"]
|
||||||
|
|
||||||
|
-- Get charge information
|
||||||
|
local rate = string.match(statefile, "present rate:[%s]+([%d]+).*")
|
||||||
|
local remaining = string.match(statefile, "remaining capacity:[%s]+([%d]+).*")
|
||||||
|
|
||||||
|
|
||||||
|
-- Calculate percentage (but work around broken BAT/ACPI implementations)
|
||||||
|
local percent = math.min(math.floor(remaining / capacity * 100), 100)
|
||||||
|
|
||||||
|
-- Calculate remaining (charging or discharging) time
|
||||||
|
if state == "+" then
|
||||||
|
timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate)
|
||||||
|
elseif state == "-" then
|
||||||
|
timeleft = tonumber(remaining) / tonumber(rate)
|
||||||
|
else
|
||||||
|
return {state, percent, "N/A"}
|
||||||
|
end
|
||||||
|
local hoursleft = math.floor(timeleft)
|
||||||
|
local minutesleft = math.floor((timeleft - hoursleft) * 60 )
|
||||||
|
local time = string.format("%02d:%02d", hoursleft, minutesleft)
|
||||||
|
|
||||||
|
return {state, percent, time}
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(batproc_linux, { __call = function(_, ...) return worker(...) end })
|
70
contrib/btc_all.lua
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
-- contrib/btc_all.lua
|
||||||
|
-- Copyright (C) 2017 0x5b <dragen15051@gmail.com>
|
||||||
|
-- Copyright (C) 2017 Joerg Thalheim <joerg@thalheim.io>
|
||||||
|
-- Copyright (C) 2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local pcall = pcall
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
local spawn = require("vicious.spawn")
|
||||||
|
|
||||||
|
local success, json = pcall(require, "cjson")
|
||||||
|
if not success then
|
||||||
|
json = require("json")
|
||||||
|
end
|
||||||
|
|
||||||
|
local string = {
|
||||||
|
sub = string.sub,
|
||||||
|
upper = string.upper,
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Btc: provides current bitcoin price
|
||||||
|
-- vicious.widgets.btc
|
||||||
|
local btc_all = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{ Bitcoin widget type
|
||||||
|
function btc_all.async(format, warg, callback)
|
||||||
|
-- Default values
|
||||||
|
if not warg then warg = "usd" end
|
||||||
|
|
||||||
|
local btc = { ["{price}"] = "N/A" }
|
||||||
|
local currency_code = string.upper(warg)
|
||||||
|
local url = "https://api.coindesk.com/v1/bpi/currentprice/" .. currency_code .. ".json"
|
||||||
|
local cmd = "curl "..helpers.shellquote(url)
|
||||||
|
|
||||||
|
-- {{ Checking response
|
||||||
|
local function parse(response)
|
||||||
|
-- If 'response' is not json, 'json.decode' will return Error
|
||||||
|
local status, data = pcall(function() return json.decode(response) end)
|
||||||
|
if not status or not data then
|
||||||
|
return btc
|
||||||
|
end
|
||||||
|
|
||||||
|
btc["{price}"] = string.sub(data["bpi"][currency_code]["rate"], 0, -3)
|
||||||
|
return btc
|
||||||
|
end
|
||||||
|
-- }}
|
||||||
|
|
||||||
|
spawn.easy_async(cmd, function(stdout) callback(parse(stdout)) end)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return helpers.setasyncall(btc_all)
|
197
contrib/buildbot_all.lua
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
-- contrib/buildbot_all.lua
|
||||||
|
-- Copyright (C) 2012 Andrzje Bieniek <andyhelp@gmail.com>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local pcall = pcall
|
||||||
|
local json_status, json = pcall(require, "json")
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local pairs = pairs
|
||||||
|
local assert = assert
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
local bb = {} --list of all buildbot builders
|
||||||
|
|
||||||
|
local bs = {OK=1, FAILED=2, RUNNING=3}
|
||||||
|
local bc = {"green", "red", "yellow"}
|
||||||
|
|
||||||
|
local buildbot_all = {}
|
||||||
|
|
||||||
|
BB = {}
|
||||||
|
BB.__index = BB
|
||||||
|
|
||||||
|
function BB.create(url, builder)
|
||||||
|
local b = {}
|
||||||
|
setmetatable(b,BB)
|
||||||
|
b.url = url -- buildbot url
|
||||||
|
b.builder = builder -- builder name
|
||||||
|
b.lastChecked = 0 -- last checked build number
|
||||||
|
b.lastSuccessful = 0 -- last successful build number
|
||||||
|
b.lastResult = nil -- last json parsed result
|
||||||
|
b.lastError = nil -- last error string or nil if no error
|
||||||
|
return b
|
||||||
|
end
|
||||||
|
|
||||||
|
function BB:_queryBuildbot(build_number)
|
||||||
|
local f = io.popen("curl --connect-timeout 1 "..self.url.."/json/builders/"..self.builder.."/builds/"..build_number)
|
||||||
|
local jsbuilder = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
if #jsbuilder == 0 then
|
||||||
|
return false, "can't read from url"
|
||||||
|
end
|
||||||
|
|
||||||
|
local result_status, result = pcall(json.decode, jsbuilder, false)
|
||||||
|
if not result_status then
|
||||||
|
return false, "can't parse json data"
|
||||||
|
end
|
||||||
|
return true, result
|
||||||
|
end
|
||||||
|
|
||||||
|
function BB:_getBuildStatus(result)
|
||||||
|
if #result['text'] > 0 then
|
||||||
|
local text = result['text']
|
||||||
|
if text[1] == "build" and text[2] == "successful" and #text == 2 then
|
||||||
|
--successful
|
||||||
|
return bs.OK
|
||||||
|
else
|
||||||
|
--failed
|
||||||
|
return bs.FAILED
|
||||||
|
end
|
||||||
|
else
|
||||||
|
--in progress
|
||||||
|
return bs.RUNNING
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function queries buildbot to refresh builds status.
|
||||||
|
-- * if build is successful or failed it will not be queried again, number is stored in lasteChecked
|
||||||
|
-- * up to 10 last builds will be checked to find last successful build
|
||||||
|
function BB:refresh()
|
||||||
|
local last_pass_fail = 0
|
||||||
|
local nr = -1
|
||||||
|
local last_result
|
||||||
|
local iter_counter = 0
|
||||||
|
|
||||||
|
self.lastError = nil
|
||||||
|
self.lastResult = nil
|
||||||
|
--- there is a gap to fill in, iterate all not checked builds starting from latest
|
||||||
|
while nr > self.lastChecked or nr == -1 do
|
||||||
|
local r_status, r = self:_queryBuildbot(nr)
|
||||||
|
local s
|
||||||
|
|
||||||
|
if not r_status then
|
||||||
|
self.lastError = r
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
s = self:_getBuildStatus(r)
|
||||||
|
if not last_result then
|
||||||
|
last_result = r
|
||||||
|
end
|
||||||
|
nr = r['number']
|
||||||
|
assert(nr > 0)
|
||||||
|
if last_pass_fail == 0 and (s == bs.OK or s == bs.FAILED) then
|
||||||
|
last_pass_fail = nr
|
||||||
|
end
|
||||||
|
if s == bs.OK then --successful
|
||||||
|
self.lastSuccessful = nr
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
nr = nr - 1
|
||||||
|
iter_counter = iter_counter + 1
|
||||||
|
if iter_counter > 10 then --check max last 10 builds when searching for successful build
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if last_pass_fail ~= 0 then
|
||||||
|
self.lastChecked = last_pass_fail
|
||||||
|
end
|
||||||
|
if last_result then
|
||||||
|
self.lastResult = last_result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function BB:getLastSuccessful()
|
||||||
|
return self.lastSuccessful
|
||||||
|
end
|
||||||
|
|
||||||
|
function BB:getCurrent()
|
||||||
|
return self.lastResult['number']
|
||||||
|
end
|
||||||
|
|
||||||
|
function BB:getCurrentStatus()
|
||||||
|
return self:_getBuildStatus(self.lastResult)
|
||||||
|
end
|
||||||
|
|
||||||
|
function BB:getBuilder()
|
||||||
|
return self.builder
|
||||||
|
end
|
||||||
|
|
||||||
|
function BB:getError()
|
||||||
|
return self.lastError
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function getBuilderStatus(b)
|
||||||
|
local s = "[" .. b:getBuilder()
|
||||||
|
--check if json library was loaded correctly
|
||||||
|
if not json_status then
|
||||||
|
return s .. ".<span color=\"orange\">can't find libluaX.X-json</span>]"
|
||||||
|
end
|
||||||
|
|
||||||
|
local err = b:getError()
|
||||||
|
if err then
|
||||||
|
return s .. ".<span color=\"orange\">" .. err .. "</span>]"
|
||||||
|
end
|
||||||
|
|
||||||
|
if b:getLastSuccessful() ~= 0 then
|
||||||
|
success_build_nr_str = "<span color=\"green\">".. b:getLastSuccessful() .."</span>"
|
||||||
|
else
|
||||||
|
success_build_nr_str = "-"
|
||||||
|
end
|
||||||
|
|
||||||
|
local current_build_color = bc[b:getCurrentStatus()]
|
||||||
|
current_build_nr_str = "<span color=\""..current_build_color.."\">"..b:getCurrent().."</span>"
|
||||||
|
|
||||||
|
if current_build_color ~= "green" then
|
||||||
|
s = s .. "." .. current_build_nr_str
|
||||||
|
end
|
||||||
|
return s .. "." .. success_build_nr_str .. "]"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Buildbot widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
if #bb == 0 then --fill up bb with builders when worker function is run for the first time
|
||||||
|
for i,v in pairs(warg) do
|
||||||
|
bb[#bb+1] = BB.create(v["url"], v["builder"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local str = ""
|
||||||
|
for i,v in pairs(bb) do
|
||||||
|
v:refresh()
|
||||||
|
str = str .. " " .. getBuilderStatus(v)
|
||||||
|
end
|
||||||
|
return {str .. " "}
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
setmetatable(buildbot_all, { __call = function(_, ...) return worker(...) end })
|
||||||
|
|
1
contrib/cmus_all.lua
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../widgets/cmus_all.lua
|
64
contrib/countfiles_all.lua
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
-- contrib/countfiles_all.lua
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local pairs = pairs
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- countfiles: provides a number of files in several directories
|
||||||
|
-- @warg.paths a table with the paths which should be checked
|
||||||
|
-- @warg.pattern a global regex to match files (Default: match all)
|
||||||
|
-- use posix-egrep style instead of the default (less familiar) emacs regex
|
||||||
|
|
||||||
|
-- Be carefull with directories, who contains a mass of files.
|
||||||
|
-- "find" is usally fast, but will also produce delays, if the inodes get to big.
|
||||||
|
-- So if you want to count your music library, you may want to use locate/updatedb instead.
|
||||||
|
|
||||||
|
-- vicious.contrib.countfiles
|
||||||
|
local countfiles_all = {}
|
||||||
|
|
||||||
|
-- {{{ Sum up widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
if not warg then return end
|
||||||
|
-- Initialise counter table
|
||||||
|
local store = {}
|
||||||
|
|
||||||
|
-- Match by default all files
|
||||||
|
warg.pattern = warg.pattern or ".*"
|
||||||
|
|
||||||
|
for key, value in pairs(warg.paths) do
|
||||||
|
local f = io.popen("find '"..value.."'"..
|
||||||
|
" -type f -regextype posix-egrep"..
|
||||||
|
" -regex '"..warg.pattern.."'")
|
||||||
|
|
||||||
|
local lines = 0
|
||||||
|
for line in f:lines() do
|
||||||
|
lines = lines + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
store[key] = (store[key] or 0) + lines
|
||||||
|
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
return store
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
setmetatable(countfiles_all, { __call = function(_, ...) return worker(...) end })
|
87
contrib/dio_linux.lua
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
-- contrib/dio_linux.lua
|
||||||
|
-- Copyright (C) 2010, Adrian C. <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local ipairs = ipairs
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local table = { insert = table.insert }
|
||||||
|
local string = { gmatch = string.gmatch }
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Disk I/O: provides I/O statistics for requested storage devices
|
||||||
|
-- vicious.contrib.dio
|
||||||
|
local dio_linux = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- Initialize function tables
|
||||||
|
local disk_usage = {}
|
||||||
|
local disk_total = {}
|
||||||
|
-- Variable definitions
|
||||||
|
local unit = { ["s"] = 1, ["kb"] = 2, ["mb"] = 2048 }
|
||||||
|
|
||||||
|
-- {{{ Disk I/O widget type
|
||||||
|
local function worker(format, disk)
|
||||||
|
if not disk then return end
|
||||||
|
|
||||||
|
local disk_lines = { [disk] = {} }
|
||||||
|
local disk_stats = helpers.pathtotable("/sys/block/" .. disk)
|
||||||
|
|
||||||
|
if disk_stats.stat then
|
||||||
|
local match = string.gmatch(disk_stats.stat, "[%s]+([%d]+)")
|
||||||
|
for i = 1, 11 do -- Store disk stats
|
||||||
|
table.insert(disk_lines[disk], match())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Ensure tables are initialized correctly
|
||||||
|
local diff_total = { [disk] = {} }
|
||||||
|
if not disk_total[disk] then
|
||||||
|
disk_usage[disk] = {}
|
||||||
|
disk_total[disk] = {}
|
||||||
|
|
||||||
|
while #disk_total[disk] < #disk_lines[disk] do
|
||||||
|
table.insert(disk_total[disk], 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, v in ipairs(disk_lines[disk]) do
|
||||||
|
-- Diskstats are absolute, substract our last reading
|
||||||
|
diff_total[disk][i] = v - disk_total[disk][i]
|
||||||
|
|
||||||
|
-- Store totals
|
||||||
|
disk_total[disk][i] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate and store I/O
|
||||||
|
helpers.uformat(disk_usage[disk], "read", diff_total[disk][3], unit)
|
||||||
|
helpers.uformat(disk_usage[disk], "write", diff_total[disk][7], unit)
|
||||||
|
helpers.uformat(disk_usage[disk], "total", diff_total[disk][7] + diff_total[disk][3], unit)
|
||||||
|
|
||||||
|
-- Store I/O scheduler
|
||||||
|
if disk_stats.queue and disk_stats.queue.scheduler then
|
||||||
|
disk_usage[disk]["{sched}"] = string.gmatch(disk_stats.queue.scheduler, "%[([%a]+)%]")
|
||||||
|
end
|
||||||
|
|
||||||
|
return disk_usage[disk]
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(dio_linux, { __call = function(_, ...) return worker(...) end })
|
31
contrib/init.lua
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
-- contrib/init.lua
|
||||||
|
-- Copyright (C) 2010-2012 Adrian C. (anrxc) <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2011 Joerg T. (Mic92) <jthalheim@gmail.com>
|
||||||
|
-- Copyright (C) 2012 Arvydas Sidorenko <asido4@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Setup environment
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local wrequire = require("vicious.helpers").wrequire
|
||||||
|
|
||||||
|
-- Vicious: widgets for the awesome window manager
|
||||||
|
-- vicious.contrib
|
||||||
|
local contrib = { _NAME = "vicious.contrib" }
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- Load modules at runtime as needed
|
||||||
|
return setmetatable(contrib, { __index = wrequire })
|
63
contrib/mpc_all.lua
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
-- contrib/mpc_all.lua
|
||||||
|
-- Copyright (C) 2009 Lucas de Vries <lucas@glacicle.com>
|
||||||
|
-- Copyright (C) 2010 Adrian C. <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
-- Copyright (C) 2018 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local type = type
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local string = { find = string.find }
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Mpc: provides the currently playing song in MPD
|
||||||
|
-- vicious.contrib.mpc
|
||||||
|
local mpc_all = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ MPC widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
-- Get data from mpd
|
||||||
|
local f = io.popen("mpc")
|
||||||
|
local np = f:read("*line")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Not installed,
|
||||||
|
if np == nil or -- off or stoppped.
|
||||||
|
(string.find(np, "MPD_HOST") or string.find(np, "volume:"))
|
||||||
|
then
|
||||||
|
return {"Stopped"}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if we should scroll, or maybe truncate
|
||||||
|
if warg then
|
||||||
|
if type(warg) == "table" then
|
||||||
|
np = helpers.scroll(np, warg[1], warg[2])
|
||||||
|
else
|
||||||
|
np = helpers.truncate(np, warg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {np}
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(mpc_all, { __call = function(_, ...) return worker(...) end })
|
154
contrib/net_linux.lua
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
-- contrib/net_linux.lua
|
||||||
|
-- Copyright (C) 2009 Henning Glawe <glaweh@debian.org>
|
||||||
|
-- Copyright (C) 2009 Lucas de Vries <lucas@glacicle.com>
|
||||||
|
-- Copyright (C) 2010 Adrian C. <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
-- Copyright (C) 2017 Roberto <empijei@users.noreply.github.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local pairs = pairs
|
||||||
|
local tonumber = tonumber
|
||||||
|
local os = { time = os.time }
|
||||||
|
local io = { lines = io.lines }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local string = { match = string.match }
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Net: provides usage statistics for all network interfaces
|
||||||
|
-- vicious.contrib.net
|
||||||
|
local net_linux = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- Initialise function tables
|
||||||
|
local nets = {}
|
||||||
|
-- Variable definitions
|
||||||
|
local unit = { ["b"] = 1, ["kb"] = 1024,
|
||||||
|
["mb"] = 1024^2, ["gb"] = 1024^3
|
||||||
|
}
|
||||||
|
|
||||||
|
-- {{{ Net widget type
|
||||||
|
local function worker(format, tignorelist)
|
||||||
|
local args = {}
|
||||||
|
local tignore = {}
|
||||||
|
local total_rx = 0
|
||||||
|
local total_tx = 0
|
||||||
|
local any_up = 0
|
||||||
|
|
||||||
|
if not tignorelist then
|
||||||
|
tignorelist = {"lo", "wmaster0"}
|
||||||
|
end
|
||||||
|
for k, i in pairs(tignorelist) do
|
||||||
|
tignore[i] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get NET stats
|
||||||
|
for line in io.lines("/proc/net/dev") do
|
||||||
|
-- Match wmaster0 as well as rt0 (multiple leading spaces)
|
||||||
|
local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
|
||||||
|
if name ~= nil then
|
||||||
|
-- Received bytes, first value after the name
|
||||||
|
local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
|
||||||
|
-- Transmited bytes, 7 fields from end of the line
|
||||||
|
local send = tonumber(string.match(line,
|
||||||
|
"([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))
|
||||||
|
|
||||||
|
if not tignore[name] then
|
||||||
|
total_rx = total_rx + recv
|
||||||
|
total_tx = total_tx + send
|
||||||
|
end
|
||||||
|
|
||||||
|
helpers.uformat(args, name .. " rx", recv, unit)
|
||||||
|
helpers.uformat(args, name .. " tx", send, unit)
|
||||||
|
|
||||||
|
if nets[name] == nil then
|
||||||
|
-- Default values on the first run
|
||||||
|
nets[name] = {}
|
||||||
|
|
||||||
|
helpers.uformat(args, name .. " down", 0, unit)
|
||||||
|
helpers.uformat(args, name .. " up", 0, unit)
|
||||||
|
args["{"..name.." carrier}"] = 0
|
||||||
|
|
||||||
|
nets[name].time = os.time()
|
||||||
|
else -- Net stats are absolute, substract our last reading
|
||||||
|
local interval = os.time() - nets[name].time > 0 and
|
||||||
|
os.time() - nets[name].time or 1
|
||||||
|
nets[name].time = os.time()
|
||||||
|
|
||||||
|
local down = (recv - nets[name][1]) / interval
|
||||||
|
local up = (send - nets[name][2]) / interval
|
||||||
|
|
||||||
|
helpers.uformat(args, name .. " down", down, unit)
|
||||||
|
helpers.uformat(args, name .. " up", up, unit)
|
||||||
|
|
||||||
|
-- Carrier detection
|
||||||
|
sysnet = helpers.pathtotable("/sys/class/net/" .. name)
|
||||||
|
|
||||||
|
if sysnet.carrier then
|
||||||
|
ccarrier = tonumber(sysnet.carrier)
|
||||||
|
|
||||||
|
args["{"..name.." carrier}"] = ccarrier
|
||||||
|
if ccarrier == 1 and not tignore[name] then
|
||||||
|
any_up = 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
args["{"..name.." carrier}"] = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Store totals
|
||||||
|
nets[name][1] = recv
|
||||||
|
nets[name][2] = send
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
helpers.uformat(args, "total rx", total_rx, unit)
|
||||||
|
helpers.uformat(args, "total tx", total_tx, unit)
|
||||||
|
|
||||||
|
if nets["total"] == nil then
|
||||||
|
-- Default values on the first run
|
||||||
|
nets["total"] = {}
|
||||||
|
|
||||||
|
helpers.uformat(args, "total down", 0, unit)
|
||||||
|
helpers.uformat(args, "total up", 0, unit)
|
||||||
|
args["{total carrier}"] = 0
|
||||||
|
|
||||||
|
nets["total"].time = os.time()
|
||||||
|
else -- Net stats are absolute, substract our last reading
|
||||||
|
local interval = os.time() - nets["total"].time > 0 and
|
||||||
|
os.time() - nets["total"].time or 1
|
||||||
|
nets["total"].time = os.time()
|
||||||
|
|
||||||
|
local down = (total_rx - nets["total"][1]) / interval
|
||||||
|
local up = (total_tx - nets["total"][2]) / interval
|
||||||
|
|
||||||
|
helpers.uformat(args, "total down", down, unit)
|
||||||
|
helpers.uformat(args, "total up", up, unit)
|
||||||
|
args["{total carrier}"] = any_up
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Store totals
|
||||||
|
nets["total"][1] = total_rx
|
||||||
|
nets["total"][2] = total_tx
|
||||||
|
|
||||||
|
return args
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(net_linux, { __call = function(_, ...) return worker(...) end })
|
50
contrib/netcfg.lua
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
-- contrib/netcfg.lua
|
||||||
|
-- Copyright (C) 2010 Radu A. <admiral0@tuxfamily.org>
|
||||||
|
-- Copyright (C) 2010 Adrian C. (anrxc) <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2012 Arvydas Sidorenko <asido4@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local table = { insert = table.insert }
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Netcfg: provides active netcfg network profiles
|
||||||
|
-- vicious.contrib.netcfg
|
||||||
|
local netcfg = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Netcfg widget type
|
||||||
|
local function worker(format)
|
||||||
|
-- Initialize counters
|
||||||
|
local profiles = {}
|
||||||
|
|
||||||
|
local f = io.popen("ls -1 /var/run/network/profiles")
|
||||||
|
for line in f:lines() do
|
||||||
|
if line ~= nil then
|
||||||
|
table.insert(profiles, line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
return profiles
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(netcfg, { __call = function(_, ...) return worker(...) end })
|
49
contrib/nvinf_all.lua
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
-- contrib/nvinf_all.lua
|
||||||
|
-- Copyright (C) 2015 Ziyuan Guo <s10e.cn@gmail.com>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local string = { gmatch = string.gmatch }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- vicious.widgets.nvinf
|
||||||
|
local nvinf_all = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ NVIDIA infomation widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
if not warg then warg = "0" end
|
||||||
|
local nv_inf = {}
|
||||||
|
local f = io.popen("LC_ALL=C nvidia-settings -q GPUUtilization -q [gpu:"..helpers.shellquote(warg).."]/GPUCoreTemp -q [gpu:"..helpers.shellquote(warg).."]/GPUCurrentClockFreqs -t")
|
||||||
|
local all_info = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
for num in string.gmatch(all_info, "%d+") do
|
||||||
|
nv_inf[#nv_inf + 1] = tonumber(num)
|
||||||
|
end
|
||||||
|
|
||||||
|
return nv_inf
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(nvinf_all, { __call = function(_, ...) return worker(...) end })
|
56
contrib/nvsmi_all.lua
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
-- contrib/nvsmi_all.lua
|
||||||
|
-- Copyright (C) 2014 Adrian C. <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local string = { match = string.match }
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- nvsmi: provides GPU information from nvidia SMI
|
||||||
|
-- vicious.contrib.nvsmi
|
||||||
|
local nvsmi_all = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ GPU Information widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
-- Fallback to querying first device
|
||||||
|
if not warg then warg = "0" end
|
||||||
|
|
||||||
|
-- Get data from smi
|
||||||
|
-- * Todo: support more; MEMORY,UTILIZATION,ECC,POWER,CLOCK,COMPUTE,PIDS,PERFORMANCE
|
||||||
|
local f = io.popen("nvidia-smi -q -d TEMPERATURE -i " .. warg)
|
||||||
|
local smi = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Not installed
|
||||||
|
if smi == nil then return {0} end
|
||||||
|
|
||||||
|
-- Get temperature information
|
||||||
|
local _thermal = string.match(smi, "Gpu[%s]+:[%s]([%d]+)[%s]C")
|
||||||
|
-- Handle devices without data
|
||||||
|
if _thermal == nil then return {0} end
|
||||||
|
|
||||||
|
return {tonumber(_thermal)}
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(nvsmi_all, { __call = function(_, ...) return worker(...) end })
|
121
contrib/openweather_all.lua
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
-- contrib/openweather_all.lua
|
||||||
|
-- Copyright (C) 2013 NormalRa <normalrawr gmail com>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
-- Copyright (C) 2020 Marcel Arpogaus <marcel.arpogaus gmail com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local string = {match = string.match}
|
||||||
|
local math = {ceil = math.ceil, floor = math.floor}
|
||||||
|
local helpers = require "vicious.helpers"
|
||||||
|
local spawn = require "vicious.spawn"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- Openweather: provides weather information for a requested station
|
||||||
|
-- vicious.widgets.openweather
|
||||||
|
local openweather_all = {}
|
||||||
|
|
||||||
|
-- Initialize function tables
|
||||||
|
local _wdirs = {"N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"}
|
||||||
|
local _wdata = {
|
||||||
|
["{city}"] = "N/A",
|
||||||
|
["{wind deg}"] = "N/A",
|
||||||
|
["{wind aim}"] = "N/A",
|
||||||
|
["{wind mps}"] = "N/A",
|
||||||
|
["{wind kmh}"] = "N/A",
|
||||||
|
["{sky}"] = "N/A",
|
||||||
|
["{weather}"] = "N/A",
|
||||||
|
["{temp c}"] = "N/A",
|
||||||
|
["{temp min c}"] = "N/A",
|
||||||
|
["{temp max c}"] = "N/A",
|
||||||
|
["{sunrise}"] = -1,
|
||||||
|
["{sunset}"] = -1,
|
||||||
|
["{humid}"] = "N/A",
|
||||||
|
["{press}"] = "N/A"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- {{{ Openweather widget type
|
||||||
|
local function parse(stdout, stderr, exitreason, exitcode)
|
||||||
|
-- Check if there was a timeout or a problem with the station
|
||||||
|
if stdout == nil or exitcode ~= 0 then return _wdata end
|
||||||
|
|
||||||
|
_wdata["{city}"] = -- City name
|
||||||
|
string.match(stdout, '"name":"([%a%s%-]+)"') or _wdata["{city}"]
|
||||||
|
_wdata["{wind deg}"] = -- Wind degrees
|
||||||
|
string.match(stdout, '"deg":([%d]+)') or _wdata["{wind deg}"]
|
||||||
|
_wdata["{wind mps}"] = -- Wind speed in meters per second
|
||||||
|
string.match(stdout, '"speed":([%d%.]+)') or _wdata["{wind mps}"]
|
||||||
|
_wdata["{sky}"] = -- Sky conditions
|
||||||
|
string.match(stdout, '"main":"([%a]+)"') or _wdata["{sky}"]
|
||||||
|
_wdata["{weather}"] = -- Weather description
|
||||||
|
string.match(stdout, '"description":"([%a%s]+)"') or _wdata["{weather}"]
|
||||||
|
_wdata["{temp c}"] = -- Temperature in celsius
|
||||||
|
string.match(stdout, '"temp":([%-]?[%d%.]+)') or _wdata["{temp c}"]
|
||||||
|
_wdata["{temp min c}"] = -- Minimal Temperature in celsius
|
||||||
|
string.match(stdout, '"temp_min":([%-]?[%d%.]+)') or _wdata["{temp min c}"]
|
||||||
|
_wdata["{temp max c}"] = -- Maximal Temperature in celsius
|
||||||
|
string.match(stdout, '"temp_max":([%-]?[%d%.]+)') or _wdata["{temp max c}"]
|
||||||
|
_wdata["{humid}"] = -- Relative humidity in percent
|
||||||
|
string.match(stdout, '"humidity":([%d]+)') or _wdata["{humid}"]
|
||||||
|
_wdata["{sunrise}"] = -- Sunrise
|
||||||
|
tonumber(string.match(stdout, '"sunrise":([%d]+)')) or _wdata["{sunrise}"]
|
||||||
|
_wdata["{sunset}"] = -- Sunset
|
||||||
|
tonumber(string.match(stdout, '"sunset":([%d]+)')) or _wdata["{sunset}"]
|
||||||
|
_wdata["{press}"] = -- Pressure in hPa
|
||||||
|
string.match(stdout, '"pressure":([%d%.]+)') or _wdata["{press}"]
|
||||||
|
|
||||||
|
-- Wind speed in km/h
|
||||||
|
if _wdata["{wind mps}"] ~= "N/A" then
|
||||||
|
_wdata["{wind mps}"] = math.floor(tonumber(_wdata["{wind mps}"]) + .5)
|
||||||
|
_wdata["{wind kmh}"] = math.ceil(_wdata["{wind mps}"] * 3.6)
|
||||||
|
end -- Temperature in °C
|
||||||
|
if _wdata["{temp c}"] ~= "N/A" then
|
||||||
|
_wdata["{temp c}"] = math.floor(tonumber(_wdata["{temp c}"]) + .5)
|
||||||
|
end -- Calculate wind direction
|
||||||
|
if _wdata["{wind deg}"] ~= "N/A" then
|
||||||
|
_wdata["{wind deg}"] = tonumber(_wdata["{wind deg}"])
|
||||||
|
|
||||||
|
-- Lua tables start at [1]
|
||||||
|
if (_wdata["{wind deg}"] / 45) % 1 == 0 then
|
||||||
|
_wdata["{wind aim}"] = _wdirs[_wdata["{wind deg}"] / 45 + 1]
|
||||||
|
else
|
||||||
|
_wdata["{wind aim}"] = _wdirs[math.ceil(_wdata["{wind deg}"] / 45) +
|
||||||
|
1] ..
|
||||||
|
_wdirs[math.floor(
|
||||||
|
_wdata["{wind deg}"] / 45) + 1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return _wdata
|
||||||
|
end
|
||||||
|
|
||||||
|
function openweather_all.async(format, warg, callback)
|
||||||
|
if not warg then return callback {} end
|
||||||
|
if type(warg) ~= "table" then return callback {} end
|
||||||
|
|
||||||
|
-- Get weather forceast using the city ID code, from:
|
||||||
|
-- * OpenWeatherMap.org
|
||||||
|
local openweather = "http://api.openweathermap.org/data/2.5/weather?id=" ..
|
||||||
|
warg.city_id .. "&appid=" .. warg.app_id ..
|
||||||
|
"&mode=json&units=metric"
|
||||||
|
|
||||||
|
spawn.easy_async("curl --connect-timeout 1 -fsm 3 '" .. openweather .. "'",
|
||||||
|
function(...) callback(parse(...)) end)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return helpers.setasyncall(openweather_all)
|
68
contrib/ossvol_linux.lua
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
-- contrib/ossvol_linux.lua
|
||||||
|
-- Copyright (C) 2010 Adrian C. <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local string = { match = string.match }
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Ossvol: provides volume levels of requested OSS mixers
|
||||||
|
-- vicious.contrib.ossvol
|
||||||
|
local ossvol_linux = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Volume widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
if not warg then return end
|
||||||
|
|
||||||
|
local mixer_state = {
|
||||||
|
["on"] = "♫", -- "",
|
||||||
|
["off"] = "♩" -- "M"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Get mixer control contents
|
||||||
|
local f = io.popen("ossmix -c")
|
||||||
|
local mixer = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Capture mixer control state
|
||||||
|
local volu = tonumber(string.match(mixer, warg .. "[%s]([%d%.]+)"))/0.25
|
||||||
|
local mute = string.match(mixer, "vol%.mute[%s]([%a]+)")
|
||||||
|
-- Handle mixers without data
|
||||||
|
if volu == nil then
|
||||||
|
return {0, mixer_state["off"]}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle mixers without mute
|
||||||
|
if mute == "OFF" and volu == "0"
|
||||||
|
-- Handle mixers that are muted
|
||||||
|
or mute == "ON" then
|
||||||
|
mute = mixer_state["off"]
|
||||||
|
else
|
||||||
|
mute = mixer_state["on"]
|
||||||
|
end
|
||||||
|
|
||||||
|
return {volu, mute}
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(ossvol_linux, { __call = function(_, ...) return worker(...) end })
|
71
contrib/pop_all.lua
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
-- contrib/pop_all.lua
|
||||||
|
-- Copyright (c) 2010 Boris Bolgradov
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
---------------------------------------------------
|
||||||
|
-- This widget type depends on luasocket.
|
||||||
|
--
|
||||||
|
-- Widget arguments are host, port, username and
|
||||||
|
-- password, i.e.:
|
||||||
|
-- {"mail.myhost.com", 110, "John", "132435"}
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local sock_avail, socket = pcall(function()
|
||||||
|
return require("socket")
|
||||||
|
end)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- POP: provides the count of new messages in a POP3 mailbox
|
||||||
|
-- vicious.contrib.pop
|
||||||
|
local pop_all = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ POP3 count widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
if not sock_avail or (not warg or #warg ~= 4) then
|
||||||
|
return {"N/A"}
|
||||||
|
end
|
||||||
|
|
||||||
|
local host, port = warg[1], tonumber(warg[2])
|
||||||
|
local user, pass = warg[3], warg[4]
|
||||||
|
|
||||||
|
local client = socket.tcp()
|
||||||
|
client:settimeout(3)
|
||||||
|
client:connect(host, port)
|
||||||
|
client:receive("*l")
|
||||||
|
client:send("USER " .. user .. "\r\n")
|
||||||
|
client:receive("*l")
|
||||||
|
client:send("PASS " .. pass .. "\r\n")
|
||||||
|
client:receive("*l")
|
||||||
|
client:send("STAT" .. "\r\n")
|
||||||
|
local response = client:receive("*l")
|
||||||
|
client:close()
|
||||||
|
|
||||||
|
if response:find("%+OK") then
|
||||||
|
response = response:match("%+OK (%d+)")
|
||||||
|
end
|
||||||
|
|
||||||
|
return {response}
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(pop_all, { __call = function(_, ...) return worker(...) end })
|
139
contrib/pulse_all.lua
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
-- contrib/pulse_all.lua
|
||||||
|
-- Copyright (C) 2010 MrMagne <mr.magne@yahoo.fr>
|
||||||
|
-- Copyright (C) 2010,2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
-- Copyright (C) 2017 Jonathan McCrohan <jmccrohan@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local type = type
|
||||||
|
local tonumber = tonumber
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local os = { execute = os.execute }
|
||||||
|
local table = { insert = table.insert }
|
||||||
|
local string = {
|
||||||
|
find = string.find,
|
||||||
|
match = string.match,
|
||||||
|
format = string.format,
|
||||||
|
gmatch = string.gmatch
|
||||||
|
}
|
||||||
|
local math = {
|
||||||
|
floor = math.floor,
|
||||||
|
ceil = math.ceil
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Pulse: provides volume levels of requested pulseaudio sinks and methods to change them
|
||||||
|
-- vicious.contrib.pulse
|
||||||
|
local pulse_all = {}
|
||||||
|
|
||||||
|
-- {{{ Helper function
|
||||||
|
local function pacmd(args)
|
||||||
|
local f = io.popen("pacmd "..args)
|
||||||
|
if f == nil then
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
local line = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
return line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function escape(text)
|
||||||
|
local special_chars = { ["."] = "%.", ["-"] = "%-" }
|
||||||
|
return text:gsub("[%.%-]", special_chars)
|
||||||
|
end
|
||||||
|
|
||||||
|
local cached_sinks = {}
|
||||||
|
local function get_sink_name(sink)
|
||||||
|
if type(sink) == "string" then return sink end
|
||||||
|
-- avoid nil keys
|
||||||
|
local key = sink or 1
|
||||||
|
-- Cache requests
|
||||||
|
if not cached_sinks[key] then
|
||||||
|
local line = pacmd("list-sinks")
|
||||||
|
if line == nil then return nil end
|
||||||
|
for s in string.gmatch(line, "name: <(.-)>") do
|
||||||
|
table.insert(cached_sinks, s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return cached_sinks[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Pulseaudio widget type
|
||||||
|
local function worker(format, sink)
|
||||||
|
sink = get_sink_name(sink)
|
||||||
|
if sink == nil then return {0, "unknown"} end
|
||||||
|
|
||||||
|
-- Get sink data
|
||||||
|
local data = pacmd("dump")
|
||||||
|
if sink == nil then return {0, "unknown"} end
|
||||||
|
|
||||||
|
-- If mute return 0 (not "Mute") so we don't break progressbars
|
||||||
|
if string.find(data,"set%-sink%-mute "..escape(sink).." yes") then
|
||||||
|
return {0, "off"}
|
||||||
|
end
|
||||||
|
|
||||||
|
local vol = tonumber(string.match(data, "set%-sink%-volume "..escape(sink).." (0x[%x]+)"))
|
||||||
|
if vol == nil then vol = 0 end
|
||||||
|
volpercent = vol/0x10000*100
|
||||||
|
|
||||||
|
return { volpercent % 1 >= 0.5 and math.ceil(volpercent) or math.floor(volpercent), "on"}
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Volume control helper
|
||||||
|
function pulse_all.add(percent, sink)
|
||||||
|
sink = get_sink_name(sink)
|
||||||
|
if sink == nil then return end
|
||||||
|
|
||||||
|
local data = pacmd("dump")
|
||||||
|
|
||||||
|
local pattern = "set%-sink%-volume "..escape(sink).." (0x[%x]+)"
|
||||||
|
local initial_vol = tonumber(string.match(data, pattern))
|
||||||
|
|
||||||
|
local vol = initial_vol + percent/100*0x10000
|
||||||
|
if vol > 0x10000 then vol = 0x10000 end
|
||||||
|
if vol < 0 then vol = 0 end
|
||||||
|
|
||||||
|
vol = math.ceil(vol)
|
||||||
|
|
||||||
|
local cmd = string.format("pacmd set-sink-volume %s 0x%x >/dev/null", sink, vol)
|
||||||
|
return os.execute(cmd)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pulse_all.toggle(sink)
|
||||||
|
sink = get_sink_name(sink)
|
||||||
|
if sink == nil then return end
|
||||||
|
|
||||||
|
local data = pacmd("dump")
|
||||||
|
local pattern = "set%-sink%-mute "..escape(sink).." (%a%a%a?)"
|
||||||
|
local mute = string.match(data, pattern)
|
||||||
|
|
||||||
|
-- 0 to enable a sink or 1 to mute it.
|
||||||
|
local state = { yes = 0, no = 1}
|
||||||
|
local cmd = string.format("pacmd set-sink-mute %s %d", sink, state[mute])
|
||||||
|
return os.execute(cmd)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(pulse_all, { __call = function(_, ...) return worker(...) end })
|
84
contrib/rss_all.lua
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
-- contrib/rss_all.lua
|
||||||
|
-- Copyright (C) 2009 olcc
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
---------------------------------------------------
|
||||||
|
-- This is now a standalone RSS reader for awesome:
|
||||||
|
-- * http://github.com/olcc/aware
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local pairs = pairs
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- RSS: provides latest world news
|
||||||
|
-- vicious.contrib.rss
|
||||||
|
local rss_all = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ RSS widget type
|
||||||
|
local function worker(format, input)
|
||||||
|
-- input: * feed - feed url
|
||||||
|
-- * object - entity to look for (typically: 'item')
|
||||||
|
-- * fields - fields to read (example: 'link', 'title', 'description')
|
||||||
|
-- output: * count - number of entities found
|
||||||
|
-- * one table for each field, containing wanted values
|
||||||
|
local feed = input.feed
|
||||||
|
local object = input.object
|
||||||
|
local fields = input.fields
|
||||||
|
|
||||||
|
-- Initialise tables
|
||||||
|
local out = {}
|
||||||
|
|
||||||
|
for _, v in pairs(fields) do
|
||||||
|
out[v] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Initialise variables
|
||||||
|
local ob = nil
|
||||||
|
local i,j,k = 1, 1, 0
|
||||||
|
local curl = "curl -A 'Mozilla/4.0' -fsm 5 --connect-timeout 3 "
|
||||||
|
|
||||||
|
-- Get the feed
|
||||||
|
local f = io.popen(curl .. '"' .. feed .. '"')
|
||||||
|
local feed = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
while true do
|
||||||
|
i, j, ob = feed.find(feed, "<" .. object .. ">(.-)</" .. object .. ">", i)
|
||||||
|
if not ob then break end
|
||||||
|
|
||||||
|
for _, v in pairs(fields) do
|
||||||
|
out[v][k] = ob:match("<" .. v .. ">(.*)</" .. v .. ">")
|
||||||
|
end
|
||||||
|
|
||||||
|
k = k+1
|
||||||
|
i = j+1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update the entity count
|
||||||
|
out.count = k
|
||||||
|
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(rss_all, { __call = function(_, ...) return worker(...) end })
|
83
contrib/sensors_linux.lua
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
-- contrib/sensors_linux.lua
|
||||||
|
-- Copyright (C) 2010 Greg D. <jabbas@jabbas.pl>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local table = { insert = table.insert }
|
||||||
|
local string = {
|
||||||
|
gsub = string.gsub,
|
||||||
|
match = string.match
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Sensors: provides access to lm_sensors data
|
||||||
|
-- vicious.contrib.sensors
|
||||||
|
local sensors_linux = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Split helper function
|
||||||
|
local function datasplit(str)
|
||||||
|
-- Splitting strings into associative array
|
||||||
|
-- with some magic to get the values right.
|
||||||
|
str = string.gsub(str, "\n", ":")
|
||||||
|
|
||||||
|
local tbl = {}
|
||||||
|
string.gsub(str, "([^:]*)", function (v)
|
||||||
|
if string.match(v, ".") then
|
||||||
|
table.insert(tbl, v)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local assoc = {}
|
||||||
|
for c = 1, #tbl, 2 do
|
||||||
|
local k = string.gsub(tbl[c], ".*_", "")
|
||||||
|
local v = tonumber(string.match(tbl[c+1], "[%d]+"))
|
||||||
|
assoc[k] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
return assoc
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Sensors widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
-- Get data from all sensors
|
||||||
|
local f = io.popen("LANG=C sensors -uA")
|
||||||
|
local lm_sensors = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
local sensor_data = string.gsub(
|
||||||
|
string.match(lm_sensors, warg..":\n(%s%s.-)\n[^ ]"), " ", "")
|
||||||
|
|
||||||
|
-- One of: crit, max
|
||||||
|
local divisor = "crit"
|
||||||
|
local s_data = datasplit(sensor_data)
|
||||||
|
|
||||||
|
if s_data[divisor] and s_data[divisor] > 0 then
|
||||||
|
s_data.percent = s_data.input / s_data[divisor] * 100
|
||||||
|
end
|
||||||
|
|
||||||
|
return {s_data.input, tonumber(s_data.percent)}
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(sensors_linux, { __call = function(_, ...) return worker(...) end })
|
79
contrib/wpa_all.lua
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
-- contrib/wpa_all.lua
|
||||||
|
-- Copyright (C) 2012 jinleileiking <jinleileiking@gmail.com>
|
||||||
|
-- Copyright (C) 2017 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local math = { ceil = math.ceil }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
local io = {
|
||||||
|
open = io.open,
|
||||||
|
popen = io.popen
|
||||||
|
}
|
||||||
|
local string = {
|
||||||
|
find = string.find,
|
||||||
|
match = string.match
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Wifi: provides wireless information for a requested interface
|
||||||
|
local wpa_all = {}
|
||||||
|
|
||||||
|
local info = {
|
||||||
|
["{ssid}"] = "N/A",
|
||||||
|
["{bssid}"] = "N/A",
|
||||||
|
["{ip}"] = "N/A",
|
||||||
|
["{qual}"] = "N/A",
|
||||||
|
}
|
||||||
|
|
||||||
|
-- {{{ Wireless widget type
|
||||||
|
local function worker(format, warg)
|
||||||
|
if not warg then return info end
|
||||||
|
|
||||||
|
local wpa_cmd = "wpa_cli -i'" .. warg .. "' status 2>&1"
|
||||||
|
local f = io.popen(wpa_cmd)
|
||||||
|
local output = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
if not output then return info end
|
||||||
|
|
||||||
|
state = string.match(output, 'wpa_state=([%a]+)') or 'N/A'
|
||||||
|
info["{bssid}"] = string.match(output, 'bssid=([%d%a:]+)') or 'N/A'
|
||||||
|
info["{ssid}"] = string.match(output, 'ssid=([%a]+)') or 'N/A'
|
||||||
|
info["{ip}"] = string.match(output, 'ip_address=([%d.]+)') or 'N/A'
|
||||||
|
|
||||||
|
if not state == 'COMPLETED' then
|
||||||
|
return info
|
||||||
|
end
|
||||||
|
|
||||||
|
local wpa_cmd = "wpa_cli -i'" .. warg .. "' bss " .. bssid .. " 2>&1"
|
||||||
|
local f = io.popen(wpa_cmd)
|
||||||
|
local output = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
if not output then return info end
|
||||||
|
|
||||||
|
info["{qual}"] = string.match(output, 'qual=([%d]+)')
|
||||||
|
|
||||||
|
return info
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return setmetatable(wpa_all, { __call = function(_, ...) return worker(...) end })
|
20
docs/Makefile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Minimal makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line, and also
|
||||||
|
# from the environment for the first two.
|
||||||
|
SPHINXOPTS ?=
|
||||||
|
SPHINXBUILD ?= sphinx-build
|
||||||
|
SOURCEDIR = source
|
||||||
|
BUILDDIR = build
|
||||||
|
|
||||||
|
# Put it first so that "make" without argument is like "make help".
|
||||||
|
help:
|
||||||
|
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
|
|
||||||
|
.PHONY: help Makefile
|
||||||
|
|
||||||
|
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||||
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
|
%: Makefile
|
||||||
|
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
3
docs/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Sphinx >= 3
|
||||||
|
sphinx_rtd_theme
|
||||||
|
sphinxcontrib-luadomain
|
37
docs/source/caching.rst
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
.. _caching:
|
||||||
|
|
||||||
|
Power and Caching
|
||||||
|
=================
|
||||||
|
|
||||||
|
When a lot of widgets are in use they, and awesome, can generate a lot
|
||||||
|
of wake-ups and also be very expensive for system resources. This is
|
||||||
|
especially important when running on battery power. It was a big problem
|
||||||
|
with awesome v2 and widgets that used shell scripts to gather data,
|
||||||
|
and with widget libraries written in languages like Ruby.
|
||||||
|
|
||||||
|
Lua is an extremely fast and efficient programming language, and Vicious
|
||||||
|
takes advantage of that. But suspending Vicious widgets is one way
|
||||||
|
to prevent them from draining your battery, despite that.
|
||||||
|
|
||||||
|
Update intervals also play a big role, and you can save a lot of power
|
||||||
|
with a smart approach. Don't use intervals like: 5, 10, 30, 60, etc.
|
||||||
|
to avoid harmonics. If you take the 60-second mark as an example,
|
||||||
|
all of your widgets would be executed at that point. Instead think about
|
||||||
|
using only prime numbers, in that case you will have only a few widgets
|
||||||
|
executed at any given time interval. When choosing intervals also consider
|
||||||
|
what a widget actually does. Some widget types read files that reside
|
||||||
|
in memory, others call external utilities and some, like the mbox widget,
|
||||||
|
read big files.
|
||||||
|
|
||||||
|
Vicious can also cache values returned by widget types. Caching enables you
|
||||||
|
to have multiple widgets using the same widget type. With caching its worker
|
||||||
|
function gets executed only once---which is also great for saving power.
|
||||||
|
|
||||||
|
* Some widget types keep internal data and if you call one multiple times
|
||||||
|
without caching, the widget that executes it first would modify stored values.
|
||||||
|
This can lead to problems and give you inconsistent data. Remember it
|
||||||
|
for widget types like CPU and Network usage, which compare the old set
|
||||||
|
of data with the new one to calculate current usage.
|
||||||
|
* Widget types that require a widget argument to be passed should be
|
||||||
|
handled carefully. If you are requesting information for different devices
|
||||||
|
then caching should not be used, because you could get inconsistent data.
|
1
docs/source/changelog.rst
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../CHANGELOG.rst
|
38
docs/source/conf.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# This file only contains a selection of the most common options.
|
||||||
|
# For a full list see the documentation:
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
# Project information
|
||||||
|
project = 'Vicious'
|
||||||
|
copyright = '2020, vicious-widgets'
|
||||||
|
author = 'vicious-widgets'
|
||||||
|
|
||||||
|
# The full version, including alpha/beta/rc tags
|
||||||
|
release = '2.4.2'
|
||||||
|
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings.
|
||||||
|
# They can be extensions coming with Sphinx (named 'sphinx.ext.*')
|
||||||
|
# or your custom ones.
|
||||||
|
extensions = ['sphinx.ext.extlinks', 'sphinxcontrib.luadomain']
|
||||||
|
extlinks = {'github': ('https://github.com/%s', '@')}
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This pattern also affects html_static_path and html_extra_path.
|
||||||
|
exclude_patterns = []
|
||||||
|
|
||||||
|
# Options for HTML output
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
html_show_copyright = False
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets)
|
||||||
|
# here, relative to this directory. They are copied after the builtin
|
||||||
|
# static files, so a file named "default.css" will overwrite the builtin
|
||||||
|
# "default.css".
|
||||||
|
html_static_path = []
|
248
docs/source/contrib.rst
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
Contrib Widget Types
|
||||||
|
====================
|
||||||
|
|
||||||
|
Contrib libraries, or widget types, are extra snippets of code you can use.
|
||||||
|
Some are for less common hardware, and other were contributed by Vicious users.
|
||||||
|
The contrib directory also holds widget types that were obsoleted or rewritten.
|
||||||
|
Contrib widgets will not be imported by init unless you explicitly enable it,
|
||||||
|
or load them in your ``rc.lua``.
|
||||||
|
|
||||||
|
Usage within Awesome
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
To use contrib widgets uncomment the line that loads them in ``init.lua``.
|
||||||
|
Or you can load them in your rc.lua after you require Vicious:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
local vicious = require"vicious"
|
||||||
|
vicious.contrib = require"vicious.contrib"
|
||||||
|
|
||||||
|
Widget Types
|
||||||
|
------------
|
||||||
|
|
||||||
|
Most widget types consist of worker functions that take the ``format`` argument
|
||||||
|
given to :lua:func:`vicious.register` as the first argument,
|
||||||
|
``warg`` as the second, and return a table of values to insert in
|
||||||
|
the format string. But we have not insisted on this coding style in contrib.
|
||||||
|
So widgets like PulseAudio have emerged that are different. These widgets
|
||||||
|
could also depend on Lua libraries that are not distributed with the
|
||||||
|
core Lua distribution. Ease of installation and use does not necessarily
|
||||||
|
have to apply to contributed widgets.
|
||||||
|
|
||||||
|
vicious.contrib.ac
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provide status about the power supply (AC).
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux, requiring ``sysfs``.
|
||||||
|
|
||||||
|
* Argument: the AC device, i.e ``"AC"`` or ``"ACAD"``. The device is linked
|
||||||
|
under ``/sys/class/power_supply/`` and should have a file called ``online``.
|
||||||
|
* Returns ``{"On"}`` if AC is connected, else ``{"Off"}``.
|
||||||
|
If AC doesn't exist, returns ``{"N/A"}``.
|
||||||
|
|
||||||
|
vicious.contrib.ati
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provides various info about ATI GPU status.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux, requiring ``sysfs``.
|
||||||
|
|
||||||
|
* Argument: card ID, e.g. ``"card0"`` (and where possible,
|
||||||
|
uses ``debugfs`` to gather data on radeon power management)
|
||||||
|
* Returns a table with string keys: ``${method}``, ``${dpm_state}``,
|
||||||
|
``${dpm_perf_level}``, ``${profile}``, ``${engine_clock mhz}``,
|
||||||
|
``${engine_clock khz}``, ``${memory_clock mhz}``, ``${memory_clock khz}``,
|
||||||
|
``${voltage v}``, ``${voltage mv}``
|
||||||
|
|
||||||
|
vicious.contrib.batpmu
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.batproc
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.btc
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provides current Bitcoin price in any currency by
|
||||||
|
[code](https://en.wikipedia.org/wiki/ISO_4217).
|
||||||
|
|
||||||
|
|
||||||
|
Platform independent, although requiring ``curl`` and either
|
||||||
|
[lua-cjson](https://github.com/mpx/lua-cjson/) or
|
||||||
|
[luajson](https://github.com/harningt/luajson/).
|
||||||
|
|
||||||
|
* Argument: currency code, e.g. ``"usd"``, ``"rub"`` and other.
|
||||||
|
Default to ``"usd"``.
|
||||||
|
* Returns a table with string key ``${price}``.
|
||||||
|
|
||||||
|
vicious.contrib.buildbot
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provides last build status for configured buildbot builders
|
||||||
|
(http://trac.buildbot.net/).
|
||||||
|
|
||||||
|
Supported platforms: platform independent, though requiring Lua JSON parser
|
||||||
|
[luajson](https://github.com/harningt/luajson/).
|
||||||
|
|
||||||
|
Returns build status in the format:
|
||||||
|
``[<builderName>.<currentBuildNumber>.<lastSuccessfulBuildNumber>]``.
|
||||||
|
If ``<currentBuildNumber>`` is the same as ``<lastSuccessfulBuildNumber>``
|
||||||
|
only one number is displayed. ``<buildNumber>`` colors:
|
||||||
|
red---failed, green---successful, yellow---in progress.
|
||||||
|
|
||||||
|
vicious.contrib.countfiles
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.cmus
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This widget type has been promoted to :ref:`widgets`.
|
||||||
|
|
||||||
|
Provides cmus player information using ``cmus-remote``.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
* Argument: a table whose first field is the socket including host (or nil).
|
||||||
|
* Returns a table with string keys: ``${status}``, ``${artist}``, ``${title}``,
|
||||||
|
``${duration}``, ``${file}``, ``${continue}``, ``${shuffle}``, ``${repeat}``.
|
||||||
|
|
||||||
|
vicious.contrib.dio
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provides I/O statistics for requested storage devices.
|
||||||
|
|
||||||
|
* Argument: the disk as an argument, i.e. ``"sda"``, or a specific
|
||||||
|
partition, i.e. ``"sda/sda2"``
|
||||||
|
* Returns a table with string keys: ``${total_s}``, ``${total_kb}``,
|
||||||
|
``${total_mb}``, ``${read_s}``, ``${read_kb}``, ``${read_mb}``,
|
||||||
|
``${write_s}``, ``${write_kb}``, ``${write_mb}`` and ``${sched}``
|
||||||
|
|
||||||
|
vicious.contrib.mpc
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.netcfg
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.net
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.openweather
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provides weather information for a requested city from OpenWeatherMap (OWM)
|
||||||
|
|
||||||
|
* Argument: a table containing the fields ``city_id`` with the OWM city ID, e.g.
|
||||||
|
``"2643743"`` and ``app_id`` with the the OWM app ID, e.g
|
||||||
|
``"4c57f0c88d9844630327623633ce269cf826ab99"``
|
||||||
|
* Returns a table with string keys: ``${city}``, ``${humid}``, ``${press}``,
|
||||||
|
``${sky}``, ``${sunrise}``, ``${sunset}``, ``${temp c}``, ``${temp max c}``,
|
||||||
|
``${temp min c}``, ``${weather}``, ``${wind aim}``, ``${wind deg}``,
|
||||||
|
``${wind kmh}`` and ``${wind mps}``,
|
||||||
|
|
||||||
|
vicious.contrib.nvinf
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provides GPU utilization, core temperature, clock frequency information about
|
||||||
|
Nvidia GPU from nvidia-settings
|
||||||
|
|
||||||
|
Supported Platforms: platform independent
|
||||||
|
|
||||||
|
* Argument (optional): card ID as an argument, e.g. ``"1"``, default to ID 0
|
||||||
|
* Returns an array containing:
|
||||||
|
|
||||||
|
* ``$1``: Usage of GPU core
|
||||||
|
* ``$2``: Usage of GPU memory
|
||||||
|
* ``$3``: Usage of video engine
|
||||||
|
* ``$4``: Usage of PCIe bandwidth
|
||||||
|
* ``$5``: Uemperature of requested graphics device
|
||||||
|
* ``$6``: Urequency of GPU core
|
||||||
|
* ``$7``: Uemory transfer rate
|
||||||
|
|
||||||
|
vicious.contrib.nvsmi
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provides (very basic) information about Nvidia GPU status from SMI
|
||||||
|
|
||||||
|
Supported platforms: platform independent
|
||||||
|
|
||||||
|
* Argument (optional): card ID as an argument, e.g. ``"1"``, default to ID 0
|
||||||
|
* Returns an array containing temperature of requested graphics device
|
||||||
|
|
||||||
|
vicious.contrib.ossvol
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.pop
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.pulse
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provides volume levels of requested pulseaudio sinks and functions to
|
||||||
|
manipulate them
|
||||||
|
|
||||||
|
* Argument (optional): name of a sink as an optional argument. A number will
|
||||||
|
be interpret as an index, if no argument is given, it will take the
|
||||||
|
first-best. To get a list of available sinks run
|
||||||
|
``pacmd list-sinks | grep 'name:'``.
|
||||||
|
* Returns an array whose only element is the volume level
|
||||||
|
|
||||||
|
vicious.contrib.pulse.add(percent[, sink])
|
||||||
|
""""""""""""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
* ``percent`` is the percentage to increment or decrement the volume
|
||||||
|
from its current value
|
||||||
|
* Returns the exit status of ``pacmd``
|
||||||
|
|
||||||
|
vicious.contrib.pulse.toggle([sink])
|
||||||
|
""""""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
* Toggles mute state
|
||||||
|
* Returns the exit status of ``pacmd``
|
||||||
|
|
||||||
|
vicious.contrib.rss
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.sensors
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
vicious.contrib.wpa
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Provides information about the wifi status.
|
||||||
|
|
||||||
|
Supported Platforms: platform independent, requiring ``wpa_cli``.
|
||||||
|
|
||||||
|
* Argument: the interface, e.g. ``"wlan0"`` or ``"wlan1"``
|
||||||
|
* Returns a table with string keys:
|
||||||
|
``${ssid}``, ``${qual}``, ``${ip}``, ``${bssid}``
|
||||||
|
|
||||||
|
Usage Examples
|
||||||
|
--------------
|
||||||
|
|
||||||
|
PulseAudio Widget
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
vol = wibox.widget.textbox()
|
||||||
|
local sink = "alsa_output.pci-0000_00_1b.0.analog-stereo"
|
||||||
|
vicious.register(vol, vicious.contrib.pulse, " $1%", 2, sink)
|
||||||
|
vol:buttons(awful.util.table.join(
|
||||||
|
awful.button({}, 1, function () awful.util.spawn("pavucontrol") end),
|
||||||
|
awful.button({}, 4, function () vicious.contrib.pulse.add(5, sink) end),
|
||||||
|
awful.button({}, 5, function () vicious.contrib.pulse.add(-5, sink) end)))
|
||||||
|
|
||||||
|
Buildbot Widget
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
buildbotwidget = wibox.widget.textbox()
|
||||||
|
vicious.register(
|
||||||
|
buildbotwidget, vicious.contrib.buildbot, "$1,", 3600,
|
||||||
|
{ { builder="coverage", url="http://buildbot.buildbot.net" },
|
||||||
|
{ builder="tarball-slave", url="http://buildbot.buildbot.net" } })
|
1
docs/source/contributing.rst
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../CONTRIBUTING.rst
|
83
docs/source/copying.rst
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
License and Credits
|
||||||
|
===================
|
||||||
|
|
||||||
|
Wicked was written by:
|
||||||
|
|
||||||
|
* Lucas de Vries <lucas glacicle.com>
|
||||||
|
|
||||||
|
Vicious was originally written by:
|
||||||
|
|
||||||
|
* Adrian C. (anrxc) <anrxc sysphere.org>.
|
||||||
|
|
||||||
|
Vicious is released under `GNU GPLv2+`_ and is currently maintained by:
|
||||||
|
|
||||||
|
* :github:`Jörg Thalheim <Mic92>` <joerg thalheim.io>
|
||||||
|
* :github:`mutlusun` (especially the FreeBSD port)
|
||||||
|
* :github:`Daniel Hahler <blueyed>` <github thequod.de>
|
||||||
|
* :github:`Nguyễn Gia Phong <McSinyx>` <mcsinyx disroot.org>
|
||||||
|
* :github:`Enric Morales <kiike>` <geekingaround enric.me>
|
||||||
|
(especially the OpenBSD port)
|
||||||
|
|
||||||
|
Over the years, Vicious has also received various patches and improvements
|
||||||
|
from the following contributors, listed in alphabetic order:
|
||||||
|
|
||||||
|
* 0x5b <dragen15051 gmail.com>
|
||||||
|
* Adam Lee <adam8157 gmail.com>
|
||||||
|
* Alexander Koch <lynix47 gmail.com>
|
||||||
|
* Amir Mohammad Saied <amirsaied gmail.com>
|
||||||
|
* Andrea Scarpino <me andreascarpino.it>
|
||||||
|
* Andreas Geisenhainer <psycorama datenhalde.de>
|
||||||
|
* Andrew Merenbach <andrew merenbach.com>
|
||||||
|
* Andrzej Bieniek <andyhelp gmail.com>
|
||||||
|
* Arthur Axel 'fREW' Schmidt <git frew.co>
|
||||||
|
* Arvydas Sidorenko <asido4 gmail.com>
|
||||||
|
* Benedikt Sauer <filmor gmail.com>
|
||||||
|
* Beniamin Kalinowski <beniamin.kalinowski gmail.com>
|
||||||
|
* Benoît Zugmeyer <bzugmeyer gmail.com>
|
||||||
|
* blastmaster <blastmaster tuxcode.org>
|
||||||
|
* Brandon Hartshorn <brandonhartshorn gmail.com>
|
||||||
|
* crondog <patches crondog.com>
|
||||||
|
* David Udelson <dru5 cornell.edu>
|
||||||
|
* Dodo The Last <dodo.the.last gmail.com>
|
||||||
|
* Elric Milon <whirm gmx.com>
|
||||||
|
* getzze <getzze gmail.com>
|
||||||
|
* Greg D. <jabbas jabbas.pl>
|
||||||
|
* Hagen Schink <troja84 googlemail.com>
|
||||||
|
* Henning Glawe <glaweh debian.org>
|
||||||
|
* Hiltjo Posthuma <hiltjo codemadness.org>
|
||||||
|
* :github:`James Reed <supplantr>`
|
||||||
|
* Jay Kamat <jaygkamat gmail.com>
|
||||||
|
* Jeremy <jeremy.sainvil gmaill.com>
|
||||||
|
* jinleileiking <jinleileiking gmail.com>
|
||||||
|
* joe di castro <joe joedicastro.com>
|
||||||
|
* Joerg Jaspert <joerg debian.org>
|
||||||
|
* Jonathan McCrohan <jmccrohan gmail.com>
|
||||||
|
* :github:`Juan Carlos Menonita <JuanKman94>`
|
||||||
|
* Juergen Descher <jhdl gmx.net>
|
||||||
|
* Julian Volodia <julianvolodia gmail.com>
|
||||||
|
* Keith Hughitt <keith.hughitt gmail.com>
|
||||||
|
* Lorenzo Gaggini <lg lgaggini.net>
|
||||||
|
* Lyderic Lefever <lyderic.lefever gmail.com>
|
||||||
|
* Martin Striz <striz raynet.cz>
|
||||||
|
* Martin Ueding <dev martin-ueding.de>
|
||||||
|
* Mellich <mellich gmx.net>
|
||||||
|
* Michael Kressibucher <mkressibucher hotmail.com>
|
||||||
|
* Michael Unterkalmsteiner <miciu gmx.de>
|
||||||
|
* niko <nikomomo gmail.com>
|
||||||
|
* Noah Tilton <code tilton.co>
|
||||||
|
* Normal Ra <normalrawr gmail.com>
|
||||||
|
* Perry Hargrave <perry.hargrave gmail.com>
|
||||||
|
* Rémy CLOUARD <shikamaru shikamaru.fr>
|
||||||
|
* :github:`Roberto <empijei>`
|
||||||
|
* Sébastien Luttringer <seblu seblu.net>
|
||||||
|
* Shadowmourne G <s10e live.com>
|
||||||
|
* starenka <starenka0 gmail.com>
|
||||||
|
* Suseika <wlasowegor gmail.com>
|
||||||
|
* Uli Schlachter <psychon znc.in>
|
||||||
|
* Wtfcoder <matt mattfreeman.co.uk>
|
||||||
|
* Xaver Hellauer <xaver hellauer.bayern>
|
||||||
|
* zhrtz <apaterson scramble.io>
|
||||||
|
|
||||||
|
and many others.
|
||||||
|
|
||||||
|
.. _GNU GPLv2+: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
22
docs/source/custom.rst
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
.. _custom-wtype:
|
||||||
|
|
||||||
|
Custom Widget Types
|
||||||
|
===================
|
||||||
|
|
||||||
|
Use any of the existing widget types as a starting point for your own.
|
||||||
|
Write a quick worker function that does the work and plug it in.
|
||||||
|
How data will be formatted, will it be red or blue, should be
|
||||||
|
defined in ``rc.lua`` (or somewhere else, outside the actual module).
|
||||||
|
|
||||||
|
Before writing a widget type you should check if there is already one
|
||||||
|
in the contrib directory of Vicious. The contrib directory contains
|
||||||
|
extra widgets you can use. Some are for less common hardware, and others
|
||||||
|
were contributed by Vicious users. Most of the contrib widgets are obsolete.
|
||||||
|
Contrib widgets will not be imported by init unless you explicitly enable it,
|
||||||
|
or load them in your ``rc.lua``.
|
||||||
|
|
||||||
|
Some users would like to avoid writing new modules. For them Vicious kept
|
||||||
|
the old Wicked functionality, possibility to register their own functions
|
||||||
|
as widget types. By providing them as the second argument to
|
||||||
|
:lua:func:`vicious.register`. Your function can accept ``format`` and ``warg``
|
||||||
|
arguments, just like workers.
|
97
docs/source/examples.rst
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
Usage Examples
|
||||||
|
==============
|
||||||
|
|
||||||
|
Start with a simple widget, like ``date``, then build your setup from there,
|
||||||
|
one widget at a time. Also remember that besides creating and registering
|
||||||
|
widgets you have to add them to a ``wibox`` (statusbar) in order to
|
||||||
|
actually display them.
|
||||||
|
|
||||||
|
Date Widget
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Update every 2 seconds (the default interval),
|
||||||
|
use standard date sequences as the format string:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
datewidget = wibox.widget.textbox()
|
||||||
|
vicious.register(datewidget, vicious.widgets.date, "%b %d, %R")
|
||||||
|
|
||||||
|
Memory Widget
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Update every 13 seconds, append ``MiB`` to 2nd and 3rd returned values
|
||||||
|
and enables caching.
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
memwidget = wibox.widget.textbox()
|
||||||
|
vicious.cache(vicious.widgets.mem)
|
||||||
|
vicious.register(memwidget, vicious.widgets.mem, "$1 ($2MiB/$3MiB)", 13)
|
||||||
|
|
||||||
|
HDD Temperature Widget
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Update every 19 seconds, request the temperature level of ``/dev/sda`` and
|
||||||
|
append *°C* to the returned value. Since the listening port is not provided,
|
||||||
|
default one is used.
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
hddtempwidget = wibox.widget.textbox()
|
||||||
|
vicious.register(hddtempwidget, vicious.widgets.hddtemp, "${/dev/sda} °C", 19)
|
||||||
|
|
||||||
|
Mbox Widget
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Updated every 5 seconds, provide full path to the mbox as argument:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
mboxwidget = wibox.widget.textbox()
|
||||||
|
vicious.register(mboxwidget, vicious.widgets.mbox, "$1", 5,
|
||||||
|
"/home/user/mail/Inbox")
|
||||||
|
|
||||||
|
Battery Widget
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Update every 61 seconds, request the current battery charge level
|
||||||
|
and displays a progressbar, provides ``BAT0`` as battery ID:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
batwidget = wibox.widget.progressbar()
|
||||||
|
|
||||||
|
-- Create wibox with batwidget
|
||||||
|
batbox = wibox.layout.margin(
|
||||||
|
wibox.widget{ { max_value = 1, widget = batwidget,
|
||||||
|
border_width = 0.5, border_color = "#000000",
|
||||||
|
color = { type = "linear",
|
||||||
|
from = { 0, 0 },
|
||||||
|
to = { 0, 30 },
|
||||||
|
stops = { { 0, "#AECF96" },
|
||||||
|
{ 1, "#FF5656" } } } },
|
||||||
|
forced_height = 10, forced_width = 8,
|
||||||
|
direction = 'east', color = beautiful.fg_widget,
|
||||||
|
layout = wibox.container.rotate },
|
||||||
|
1, 1, 3, 3)
|
||||||
|
|
||||||
|
-- Register battery widget
|
||||||
|
vicious.register(batwidget, vicious.widgets.bat, "$2", 61, "BAT0")
|
||||||
|
|
||||||
|
CPU Usage Widget
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Update every 3 seconds, feed the graph with total usage percentage
|
||||||
|
of all CPUs/cores:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
cpuwidget = awful.widget.graph()
|
||||||
|
cpuwidget:set_width(50)
|
||||||
|
cpuwidget:set_background_color"#494B4F"
|
||||||
|
cpuwidget:set_color{ type = "linear", from = { 0, 0 }, to = { 50, 0 },
|
||||||
|
stops = { { 0, "#FF5656" },
|
||||||
|
{ 0.5, "#88A175" },
|
||||||
|
{ 1, "#AECF96" } } }
|
||||||
|
vicious.register(cpuwidget, vicious.widgets.cpu, "$1", 3)
|
137
docs/source/format.rst
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
.. _format-func:
|
||||||
|
|
||||||
|
Format Functions
|
||||||
|
================
|
||||||
|
|
||||||
|
You can use a function instead of a string as the format parameter.
|
||||||
|
Then you are able to check the value returned by the widget type
|
||||||
|
and change it or perform some action. You can change the color of
|
||||||
|
the battery widget when it goes below a certain point, hide widgets
|
||||||
|
when they return a certain value or maybe use ``string.format`` for padding.
|
||||||
|
|
||||||
|
Do not confuse this with just coloring the widget, in those cases
|
||||||
|
standard Pango markup can be inserted into the format string.
|
||||||
|
|
||||||
|
The format function will get the widget as its first argument, table with
|
||||||
|
the values otherwise inserted into the format string as its second argument,
|
||||||
|
and will return the text/data to be used for the widget.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
Hide mpd widget when no song is playing
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
mpdwidget = wibox.widget.textbox()
|
||||||
|
vicious.register(
|
||||||
|
mpdwidget,
|
||||||
|
vicious.widgets.mpd,
|
||||||
|
function (widget, args)
|
||||||
|
if args["{state}"] == "Stop" then
|
||||||
|
return ''
|
||||||
|
else
|
||||||
|
return ('<span color="white">MPD:</span> %s - %s'):format(
|
||||||
|
args["{Artist}"], args["{Title}"])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
Use string.format for padding
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
uptimewidget = wibox.widget.textbox()
|
||||||
|
vicious.register(uptimewidget, vicious.widgets.uptime,
|
||||||
|
function (widget, args)
|
||||||
|
return ("Uptime: %02d %02d:%02d "):format(
|
||||||
|
args[1], args[2], args[3])
|
||||||
|
end, 61)
|
||||||
|
|
||||||
|
When it comes to padding it is also useful to mention how a widget
|
||||||
|
can be configured to have a fixed width. You can set a fixed width on
|
||||||
|
your textbox widgets by changing their ``width`` field (by default width
|
||||||
|
is automatically adapted to text width). The following code forces
|
||||||
|
a fixed width of 50 px to the uptime widget, and aligns its text to the right:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
uptimewidget = wibox.widget.textbox()
|
||||||
|
uptimewidget.width, uptimewidget.align = 50, "right"
|
||||||
|
vicious.register(uptimewidget, vicious.widgets.uptime, "$1 $2:$3", 61)
|
||||||
|
|
||||||
|
Stacked graph
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Stacked graphs are handled specially by Vicious: ``format`` functions passed
|
||||||
|
to the corresponding widget types must return an array instead of a string.
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
cpugraph = wibox.widget.graph()
|
||||||
|
cpugraph:set_stack(true)
|
||||||
|
cpugraph:set_stack_colors{ "red", "yellow", "green", "blue" }
|
||||||
|
vicious.register(cpugraph, vicious.widgets.cpu,
|
||||||
|
function (widget, args)
|
||||||
|
return { args[2], args[3], args[4], args[5] }
|
||||||
|
end, 3)
|
||||||
|
|
||||||
|
The snipet above enables graph stacking/multigraph and plots usage of all four
|
||||||
|
CPU cores on a single graph.
|
||||||
|
|
||||||
|
Substitute widget types' symbols
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
If you are not happy with default symbols used in volume, battery, cpufreq and
|
||||||
|
other widget types, use your own symbols without any need to modify modules.
|
||||||
|
The following example uses a custom table map to modify symbols representing
|
||||||
|
the mixer state: on or off/mute.
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
volumewidget = wibox.widget.textbox()
|
||||||
|
vicious.register(volumewidget, vicious.widgets.volume,
|
||||||
|
function (widget, args)
|
||||||
|
local label = { ["🔉"] = "O", ["🔈"] = "M" }
|
||||||
|
return ("Volume: %d%% State: %s"):format(
|
||||||
|
args[1], label[args[2]])
|
||||||
|
end, 2, "PCM")
|
||||||
|
|
||||||
|
.. _call-example:
|
||||||
|
|
||||||
|
Get data from the widget
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
:lua:func:`vicious.call` could be useful for naughty notification and scripts:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
mybattery = wibox.widget.textbox()
|
||||||
|
vicious.register(mybattery, vicious.widgets.bat, "$2%", 17, "0")
|
||||||
|
mybattery:buttons(awful.util.table.join(awful.button(
|
||||||
|
{}, 1,
|
||||||
|
function ()
|
||||||
|
naughty.notify{ title = "Battery indicator",
|
||||||
|
text = vicious.call(vicious.widgets.bat,
|
||||||
|
"Remaining time: $3", "0") }
|
||||||
|
end)))
|
||||||
|
|
||||||
|
Format functions can be used as well:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
mybattery:buttons(awful.util.table.join(awful.button(
|
||||||
|
{}, 1,
|
||||||
|
function ()
|
||||||
|
naughty.notify{
|
||||||
|
title = "Battery indicator",
|
||||||
|
text = vicious.call(
|
||||||
|
vicious.widgets.bat,
|
||||||
|
function (widget, args)
|
||||||
|
return ("%s: %10sh\n%s: %14d%%\n%s: %12dW"):format(
|
||||||
|
"Remaining time", args[3],
|
||||||
|
"Wear level", args[4],
|
||||||
|
"Present rate", args[5])
|
||||||
|
end, "0") }
|
||||||
|
end)))
|
50
docs/source/index.rst
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
Welcome to Vicious' documentation!
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Vicious is a modular widget library for window managers, but mostly catering
|
||||||
|
to users of the `awesome window manager`_. It was derived from the old
|
||||||
|
*wicked* widget library, and has some of the old *wicked* widget types,
|
||||||
|
a few of them rewritten, and a good number of new ones.
|
||||||
|
|
||||||
|
Vicious widget types are a framework for creating your own widgets.
|
||||||
|
Vicious contains modules that gather data about your system,
|
||||||
|
and a few *awesome* helper functions that make it easier to register timers,
|
||||||
|
suspend widgets and so on. Vicious doesn't depend on any third party Lua_
|
||||||
|
library, but may depend on additional system utilities.
|
||||||
|
|
||||||
|
Table of Contents
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
usage-lua
|
||||||
|
usage-awesome
|
||||||
|
examples
|
||||||
|
widgets
|
||||||
|
contrib
|
||||||
|
custom
|
||||||
|
format
|
||||||
|
caching
|
||||||
|
security
|
||||||
|
contributing
|
||||||
|
copying
|
||||||
|
changelog
|
||||||
|
|
||||||
|
See Also
|
||||||
|
--------
|
||||||
|
|
||||||
|
* Manual pages: `awesome(1)`_, `awesomerc(5)`_
|
||||||
|
* `Awesome declarative layout system`_
|
||||||
|
* `My first awesome`_
|
||||||
|
* `Example awesome configuration`_ (outdated)
|
||||||
|
|
||||||
|
.. _awesome window manager: https://awesomewm.org
|
||||||
|
.. _Lua: https://www.lua.org
|
||||||
|
.. _awesome(1): https://awesomewm.org/doc/manpages/awesome.1.html
|
||||||
|
.. _awesomerc(5): https://awesomewm.org/doc/manpages/awesomerc.5.html
|
||||||
|
.. _Awesome declarative layout system:
|
||||||
|
https://awesomewm.org/apidoc/documentation/03-declarative-layout.md.html
|
||||||
|
.. _My first awesome:
|
||||||
|
https://awesomewm.org/doc/api/documentation/07-my-first-awesome.md.html
|
||||||
|
.. _Example awesome configuration: http://git.sysphere.org/awesome-configs/
|
27
docs/source/security.rst
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Security Notes
|
||||||
|
==============
|
||||||
|
|
||||||
|
At the moment only one widget type (Gmail) requires
|
||||||
|
authentication information in order to get to the data.
|
||||||
|
In the future there could be more, and you should give some thought
|
||||||
|
to the issue of protecting your data. The Gmail widget type by default
|
||||||
|
stores login information in the ``~/.netrc`` file, and you are advised
|
||||||
|
to make sure that file is only readable by the owner. Other than that
|
||||||
|
we can not force all users to conform to one standard,
|
||||||
|
one way of keeping it secure, like in some keyring.
|
||||||
|
|
||||||
|
First let's clear why we simply don't encrypt the login information
|
||||||
|
and store it in ciphertext. By exposing the algorithm anyone can
|
||||||
|
reverse the encryption steps. Some claim even that's better than
|
||||||
|
plaintext but it's just security through obscurity.
|
||||||
|
|
||||||
|
Here are some ideas actually worth your time. Users that have KDE
|
||||||
|
(or parts of it) installed could store their login information into
|
||||||
|
the Kwallet service and request it via DBus from the widget type.
|
||||||
|
It can be done with tools like ``dbus-send`` and ``qdbus``.
|
||||||
|
The Gnome keyring should support the same, so those with parts of Gnome
|
||||||
|
installed could use that keyring.
|
||||||
|
|
||||||
|
Users of GnuPG (and its agent) could consider encrypting the netrc file
|
||||||
|
with their GPG key. Through the GPG Passphrase Agent they could then
|
||||||
|
decrypt the file transparently while their session is active.
|
162
docs/source/usage-awesome.rst
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
Usage within Awesome
|
||||||
|
====================
|
||||||
|
|
||||||
|
To use Vicious with awesome_, install the package from your operating system
|
||||||
|
provider, or download the source code and move it to your awesome
|
||||||
|
configuration directory in ``$XDG_CONFIG_HOME`` (usually ``~/.config``)::
|
||||||
|
|
||||||
|
git clone https://github.com/vicious-widgets/vicious.git
|
||||||
|
mv vicious $XDG_CONFIG_HOME/awesome/
|
||||||
|
|
||||||
|
Vicious will only load modules for widget types you intend to use in
|
||||||
|
your awesome configuration, to avoid having useless modules sitting in
|
||||||
|
your memory.
|
||||||
|
|
||||||
|
Then add the following to the top of your ``rc.lua``:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
local vicious = require("vicious")
|
||||||
|
|
||||||
|
vicious.register
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Once you create a widget (a textbox, graph or a progressbar),
|
||||||
|
call ``vicious.register`` to register it with Vicious:
|
||||||
|
|
||||||
|
.. lua:function:: vicious.register(widget, wtype, format, interval, warg)
|
||||||
|
|
||||||
|
Register a widget.
|
||||||
|
|
||||||
|
:param widget: awesome widget created from
|
||||||
|
``awful.widget`` or ``wibox.widget``
|
||||||
|
|
||||||
|
:param wtype: either of
|
||||||
|
|
||||||
|
* Vicious widget type: any widget type
|
||||||
|
:ref:`provided by Vicious <widgets>` or customly defined.
|
||||||
|
* ``function``: custom function from your own
|
||||||
|
awesome configuration can be registered as widget types
|
||||||
|
(see :ref:`custom-wtype`).
|
||||||
|
|
||||||
|
:param format: either of
|
||||||
|
|
||||||
|
* string: ``$key`` will be replaced by respective value in the table
|
||||||
|
``t`` returned by the widget type, i.e. use ``$1``, ``$2``, etc.
|
||||||
|
to retrieve data from an integer-indexed table (a.k.a. array);
|
||||||
|
``${foo bar}`` will be substituted by ``t["{foo bar}"]``.
|
||||||
|
* ``function (widget, args)`` can be used to manipulate data returned
|
||||||
|
by the widget type (see :ref:`format-func`).
|
||||||
|
|
||||||
|
:param interval: number of seconds between updates of the widget
|
||||||
|
(default: 2). See :ref:`caching` for more information.
|
||||||
|
|
||||||
|
:param warg: arguments to be passed to widget types, e.g. the battery ID.
|
||||||
|
|
||||||
|
``vicious.register`` alone is not much different from awful.widget.watch_,
|
||||||
|
which has been added to Awesome since version 4.0. However, Vicious offers
|
||||||
|
more advanced control of widgets' behavior by providing the following functions.
|
||||||
|
|
||||||
|
vicious.unregister
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. lua:function:: vicious.unregister(widget, keep)
|
||||||
|
|
||||||
|
Unregister a widget.
|
||||||
|
|
||||||
|
:param widget: awesome widget created from
|
||||||
|
``awful.widget`` or ``wibox.widget``
|
||||||
|
:param keep: if true suspend ``widget`` and wait for activation
|
||||||
|
:type keep: bool
|
||||||
|
|
||||||
|
vicious.suspend
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. lua:function:: vicious.suspend()
|
||||||
|
|
||||||
|
Suspend all widgets.
|
||||||
|
|
||||||
|
See `example automation script`_ for the "laptop-mode-tools" start-stop module.
|
||||||
|
|
||||||
|
vicious.activate
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. lua:function:: vicious.activate([widget])
|
||||||
|
|
||||||
|
Restart suspended widget(s).
|
||||||
|
|
||||||
|
:param widget: if provided only that widget will be activated
|
||||||
|
|
||||||
|
vicious.cache
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. lua:function:: vicious.cache(wtype)
|
||||||
|
|
||||||
|
Enable caching of values returned by a widget type.
|
||||||
|
|
||||||
|
vicious.force
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. lua:function:: vicious.force(wtable)
|
||||||
|
|
||||||
|
Force update of given widgets.
|
||||||
|
|
||||||
|
:param wtable: table of one or more widgets to be updated
|
||||||
|
|
||||||
|
vicious.call[_async]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. lua:function:: vicious.call(wtype, format, warg)
|
||||||
|
|
||||||
|
Get formatted data from a synchronous widget type
|
||||||
|
(:ref:`example <call-example>`).
|
||||||
|
|
||||||
|
:param wtype: either of
|
||||||
|
|
||||||
|
* Vicious widget type: any synchronous widget type
|
||||||
|
:ref:`provided by Vicious <widgets>` or customly defined.
|
||||||
|
* ``function``: custom function from your own
|
||||||
|
awesome configuration can be registered as widget types
|
||||||
|
(see :ref:`custom-wtype`).
|
||||||
|
|
||||||
|
:param format: either of
|
||||||
|
|
||||||
|
* string: ``$key`` will be replaced by respective value in the table
|
||||||
|
``t`` returned by the widget type, i.e. use ``$1``, ``$2``, etc.
|
||||||
|
to retrieve data from an integer-indexed table (a.k.a. array);
|
||||||
|
``${foo bar}`` will be substituted by ``t["{foo bar}"]``.
|
||||||
|
* ``function (widget, args)`` can be used to manipulate data returned
|
||||||
|
by the widget type (see :ref:`format-func`).
|
||||||
|
|
||||||
|
:param warg: arguments to be passed to the widget type, e.g. the battery ID.
|
||||||
|
|
||||||
|
:return: ``nil`` if the widget type is asynchronous,
|
||||||
|
otherwise the formatted data from with widget type.
|
||||||
|
|
||||||
|
.. lua:function:: vicious.call_async(wtype, format, warg, callback)
|
||||||
|
|
||||||
|
Get formatted data from an asynchronous widget type.
|
||||||
|
|
||||||
|
:param wtype: any asynchronous widget type
|
||||||
|
:ref:`provided by Vicious <widgets>` or customly defined.
|
||||||
|
|
||||||
|
:param format: either of
|
||||||
|
|
||||||
|
* string: ``$key`` will be replaced by respective value in the table
|
||||||
|
``t`` returned by the widget type, i.e. use ``$1``, ``$2``, etc.
|
||||||
|
to retrieve data from an integer-indexed table (a.k.a. array);
|
||||||
|
``${foo bar}`` will be substituted by ``t["{foo bar}"]``.
|
||||||
|
* ``function (widget, args)`` can be used to manipulate data returned
|
||||||
|
by the widget type (see :ref:`format-func`).
|
||||||
|
|
||||||
|
:param warg: arguments to be passed to the widget type.
|
||||||
|
|
||||||
|
:param callback: function taking the formatted data from with widget type.
|
||||||
|
If the given widget type happens to be synchronous,
|
||||||
|
``nil`` will be passed to ``callback``.
|
||||||
|
|
||||||
|
.. _awesome: https://awesomewm.org/
|
||||||
|
.. _awful.widget.watch:
|
||||||
|
https://awesomewm.org/doc/api/classes/awful.widget.watch.html
|
||||||
|
.. _example automation script:
|
||||||
|
http://sysphere.org/~anrxc/local/sources/lmt-vicious.sh
|
15
docs/source/usage-lua.rst
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Usage as a Lua Library
|
||||||
|
======================
|
||||||
|
|
||||||
|
When provided by an operating system package, or installed from source
|
||||||
|
into the Lua library path, Vicious can be used as a regular Lua_ library,
|
||||||
|
to be used stand-alone or to feed widgets of any window manager
|
||||||
|
(e.g. Ion, WMII). It is compatible with Lua 5.1 and above.
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
> widgets = require("vicious.widgets.init")
|
||||||
|
> print(widgets.volume(nil, "Master")[1])
|
||||||
|
100
|
||||||
|
|
||||||
|
.. _Lua: https://www.lua.org/
|
509
docs/source/widgets.rst
Normal file
@ -0,0 +1,509 @@
|
|||||||
|
.. _widgets:
|
||||||
|
|
||||||
|
Officially Supported Widget Types
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Widget types consist of worker functions that take two arguments
|
||||||
|
``format`` and ``warg`` (in that order), which were previously
|
||||||
|
passed to :lua:func:`vicious.register`, and return a table of values
|
||||||
|
to be formatted by ``format``.
|
||||||
|
|
||||||
|
vicious.widgets.bat
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Provides state, charge, and remaining time for a requested battery.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux (require ``sysfs``),
|
||||||
|
FreeBSD (require ``acpiconf``) and OpenBSD (no extra requirements).
|
||||||
|
|
||||||
|
* ``warg`` (from now on will be called *argument*):
|
||||||
|
|
||||||
|
* On GNU/Linux: battery ID, e.g. ``"BAT0"``
|
||||||
|
* On FreeBSD (optional): battery ID, e.g. ``"batt"`` or ``"0"``
|
||||||
|
* On OpenBSD (optional): ``bat`` followed by battery index,
|
||||||
|
e.g. ``"bat0"`` or ``"bat1"`` on systems with more than one battery
|
||||||
|
|
||||||
|
* Returns an array (integer-indexed table) consisting of:
|
||||||
|
|
||||||
|
* ``$1``: State of requested battery
|
||||||
|
* ``$2``: Charge level in percent
|
||||||
|
* ``$3``: Remaining (charging or discharging) time
|
||||||
|
* ``$4``: Wear level in percent
|
||||||
|
* ``$5``: Current (dis)charge rate in Watt
|
||||||
|
|
||||||
|
vicious.contrib.cmus
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Provides cmus player information using ``cmus-remote``.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
* Argument: a table whose first field is the socket including host (or nil).
|
||||||
|
* Returns a table with string keys: ``${status}``, ``${artist}``, ``${title}``,
|
||||||
|
``${duration}``, ``${file}``, ``${continue}``, ``${shuffle}``, ``${repeat}``.
|
||||||
|
|
||||||
|
vicious.widgets.cpu
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Provides CPU usage for all available CPUs/cores. Since this widget type give
|
||||||
|
CPU utilization between two consecutive calls, it is recommended to enable
|
||||||
|
caching if it is used to register multiple widgets (#71).
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux, FreeBSD, OpenBSD.
|
||||||
|
|
||||||
|
On FreeBSD and Linux returns an array containing:
|
||||||
|
|
||||||
|
* ``$1``: usage of all CPUs/cores
|
||||||
|
* ``$2``, ``$3``, etc. are respectively the usage of 1st, 2nd, etc. CPU/core
|
||||||
|
|
||||||
|
On OpenBSD returns an array containing:
|
||||||
|
|
||||||
|
* ``$1``: usage of all CPUs/cores
|
||||||
|
|
||||||
|
vicious.widgets.cpufreq
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Provides freq, voltage and governor info for a requested CPU.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux, FreeBSD.
|
||||||
|
|
||||||
|
* Argument: CPU ID, e.g. ``"cpu0"`` on GNU/Linux, ``"0"`` on FreeBSD
|
||||||
|
* Returns an array containing:
|
||||||
|
|
||||||
|
* ``$1``: Frequency in MHz
|
||||||
|
* ``$2``: Frequency in GHz
|
||||||
|
* ``$3``: Voltage in mV
|
||||||
|
* ``$4``: Voltage in V
|
||||||
|
* ``$5``: Governor state
|
||||||
|
* On FreeBSD: only the first two are supported
|
||||||
|
(other values will always be ``"N/A"``)
|
||||||
|
|
||||||
|
vicious.widgets.cpuinf
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Provides speed and cache information for all available CPUs/cores.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux.
|
||||||
|
|
||||||
|
Returns a table whose keys using CPU ID as a base, e.g. ``${cpu0 mhz}``,
|
||||||
|
``${cpu0 ghz}``, ``${cpu0 kb}``, ``${cpu0 mb}``, ``${cpu1 mhz}``, etc.
|
||||||
|
|
||||||
|
vicious.widgets.date
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Provides access to Lua's ``os.date``, with optional settings for time format
|
||||||
|
and time offset.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
* ``format`` (optional): a `strftime(3)`_ format specification string
|
||||||
|
(format functions are not supported). If not provided, use the prefered
|
||||||
|
representation for the current locale.
|
||||||
|
* Argument (optional): time offset in seconds, e.g. for different a time zone.
|
||||||
|
If not provided, current time is used.
|
||||||
|
* Returns the output of ``os.date`` formatted by ``format`` *string*.
|
||||||
|
|
||||||
|
vicious.widgets.dio
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Provides I/O statistics for all available storage devices.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux.
|
||||||
|
|
||||||
|
Returns a table with string keys: ``${sda total_s}``, ``${sda total_kb}``,
|
||||||
|
``${sda total_mb}``, ``${sda read_s}``, ``${sda read_kb}``, ``${sda read_mb}``,
|
||||||
|
``${sda write_s}``, ``${sda write_kb}``, ``${sda write_mb}``,
|
||||||
|
``${sda iotime_ms}``, ``${sda iotime_s}``, ``${sdb1 total_s}``, etc.
|
||||||
|
|
||||||
|
vicious.widget.fanspeed
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Provides fanspeed information for specified fans.
|
||||||
|
|
||||||
|
Supported platforms: FreeBSD.
|
||||||
|
|
||||||
|
* Argument: full ``sysctl`` string to one or multiple entries,
|
||||||
|
e.g. ``"dev.acpi_ibm.0.fan_speed"``
|
||||||
|
* Returns speed of specified fan in RPM, ``"N/A"`` on error
|
||||||
|
(probably wrong string)
|
||||||
|
|
||||||
|
vicious.widgets.fs
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Provides usage of disk space.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
* Argument (optional): if true includes remote filesystems, otherwise fallback
|
||||||
|
to default, where only local filesystems are included.
|
||||||
|
* Returns a table with string keys, using mount points as a base,
|
||||||
|
e.g. ``${/ size_mb}``, ``${/ size_gb}``, ``${/ used_mb}``, ``${/ used_gb}``,
|
||||||
|
``${/ used_p}``, ``${/ avail_mb}``, ``${/ avail_gb}``, ``${/ avail_p}``,
|
||||||
|
``${/home size_mb}``, etc.
|
||||||
|
mb and gb refer to mebibyte and gibibyte respectively.
|
||||||
|
|
||||||
|
vicious.widgets.gmail
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Provides count of new and subject of last e-mail on Gmail.
|
||||||
|
|
||||||
|
Supported platform: platform independent, requiring ``curl``.
|
||||||
|
|
||||||
|
This widget expects login information in your ``~/.netrc`` file, e.g.
|
||||||
|
``machine mail.google.com login user password pass``. Use your `app
|
||||||
|
password`_ if you can, or disable `two step verification`_
|
||||||
|
and `allow access for less secure apps`_.
|
||||||
|
|
||||||
|
.. caution::
|
||||||
|
|
||||||
|
Making these settings is a security risk!
|
||||||
|
|
||||||
|
* Arguments (optional): either a number or a table
|
||||||
|
|
||||||
|
* If it is a number, subject will be truncated.
|
||||||
|
* If it is a table whose first field is the maximum length and second field
|
||||||
|
is the widget name (e.g. ``"gmailwidget"``), scrolling will be used.
|
||||||
|
|
||||||
|
* Returns a table with string keys: ``${count}`` and ``${subject}``
|
||||||
|
|
||||||
|
vicious.widgets.hddtemp
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Provides hard drive temperatures using the hddtemp daemon.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux, requiring ``hddtemp`` and ``curl``.
|
||||||
|
|
||||||
|
* Argument (optional): ``hddtemp`` listening port (default: 7634)
|
||||||
|
* Returns a table with string keys, using hard drives as a base, e.g.
|
||||||
|
``${/dev/sda}`` and ``${/dev/sdc}``.
|
||||||
|
|
||||||
|
vicious.widgets.hwmontemp
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Provides name-based access to hwmon devices via sysfs.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux
|
||||||
|
|
||||||
|
* Argument: an array with sensor name and input number
|
||||||
|
(optional, falling back to ``1``), e.g. ``{"radeon", 2}``
|
||||||
|
* Returns a table with just the temperature value: ``$1``
|
||||||
|
* Usage example:
|
||||||
|
|
||||||
|
.. code-block:: lua
|
||||||
|
|
||||||
|
gputemp = wibox.widget.textbox()
|
||||||
|
vicious.register(gputemp, vicious.widgets.hwmontemp, " $1°C", 5, {"radeon"})
|
||||||
|
|
||||||
|
vicious.widgets.mbox
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Provides the subject of last e-mail in a mbox file.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
* Argument: either a string or a table:
|
||||||
|
|
||||||
|
* A string representing the full path to the mbox, or
|
||||||
|
* Array of the form ``{path, maximum_length[, widget_name]}``.
|
||||||
|
If the widget name is provided, scrolling will be used.
|
||||||
|
* Note: the path will be escaped so special variables like ``~`` will not
|
||||||
|
work, use ``os.getenv`` instead to access environment variables.
|
||||||
|
|
||||||
|
* Returns an array whose first value is the subject of the last e-mail.
|
||||||
|
|
||||||
|
vicious.widgets.mboxc
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Provides the count of total, old and new messages in mbox files.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
* Argument: an array full paths to mbox files.
|
||||||
|
* Returns an array containing:
|
||||||
|
|
||||||
|
* ``$1``: Total number of messages
|
||||||
|
* ``$2``: Number of old messages
|
||||||
|
* ``$3``: Number of new messages
|
||||||
|
|
||||||
|
vicious.widgets.mdir
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Provides the number of unread messages in Maildir structures/directories.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
* Argument: an array with full paths to Maildir structures.
|
||||||
|
* Returns an array containing:
|
||||||
|
|
||||||
|
* ``$1``: Number of new messages
|
||||||
|
* ``$2``: Number of *old* messages lacking the *Seen* flag
|
||||||
|
|
||||||
|
vicious.widgets.mem
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Provides RAM and Swap usage statistics.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux, FreeBSD.
|
||||||
|
|
||||||
|
Returns (per platform):
|
||||||
|
* GNU/Linux: an array consisting of:
|
||||||
|
|
||||||
|
* ``$1``: Memory usage in percent
|
||||||
|
* ``$2``: Memory usage in MiB
|
||||||
|
* ``$3``: Total system memory in MiB
|
||||||
|
* ``$4``: Free memory in MiB
|
||||||
|
* ``$5``: Swap usage in percent
|
||||||
|
* ``$6``: Swap usage in MiB
|
||||||
|
* ``$7``: Total system swap in MiB
|
||||||
|
* ``$8``: Free swap in MiB
|
||||||
|
* ``$9``: Memory usage with buffers and cache, in MiB
|
||||||
|
|
||||||
|
* FreeBSD: an array including:
|
||||||
|
|
||||||
|
* ``$1``: Memory usage in percent
|
||||||
|
* ``$2``: Memory usage in MiB
|
||||||
|
* ``$3``: Total system memory in MiB
|
||||||
|
* ``$4``: Free memory in MiB
|
||||||
|
* ``$5``: Swap usage in percent
|
||||||
|
* ``$6``: Swap usage in MiB
|
||||||
|
* ``$7``: Total system swap in MiB
|
||||||
|
* ``$8``: Free swap in MiB
|
||||||
|
* ``$9``: Wired memory in percent
|
||||||
|
* ``$10``: Wired memory in MiB
|
||||||
|
* ``$11``: Unfreeable memory (basically active+inactive+wired) in percent
|
||||||
|
* ``$12``: Unfreeable memory in MiB
|
||||||
|
|
||||||
|
vicious.widgets.mpd
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Provides Music Player Daemon information.
|
||||||
|
|
||||||
|
Supported platforms: platform independent (required tools: ``curl``).
|
||||||
|
|
||||||
|
* Argument: an array including password, hostname and port in that order.
|
||||||
|
``nil`` fields will be fallen back to default
|
||||||
|
(``localhost:6600`` without password).
|
||||||
|
* Returns a table with string keys: ``${volume}``, ``${bitrate}``,
|
||||||
|
``${elapsed}`` (in seconds), ``${duration}`` (in seconds),
|
||||||
|
``${Elapsed}`` (formatted as [hh:]mm:ss),
|
||||||
|
``${Duration}`` (formatted as [hh:]mm:ss), ``${Progress}`` (in percentage),
|
||||||
|
``${random}``, ``${repeat}``, ``${state}``, ``${Artist}``, ``${Title}``,
|
||||||
|
``${Album}``, ``${Genre}`` and optionally ``${Name}`` and ``${file}``.
|
||||||
|
|
||||||
|
vicious.widgets.net
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Provides state and usage statistics of network interfaces.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux, FreeBSD.
|
||||||
|
|
||||||
|
* Argument (FreeBSD only): desired interface, e.g. ``"wlan0"``
|
||||||
|
* Returns (per platform):
|
||||||
|
|
||||||
|
* GNU/Linux: a table with string keys, using net interfaces as a base,
|
||||||
|
e.g. ``${eth0 carrier}``, ``${eth0 rx_b}``, ``${eth0 tx_b}``,
|
||||||
|
``${eth0 rx_kb}``, ``${eth0 tx_kb}``, ``${eth0 rx_mb}``,
|
||||||
|
``${eth0 tx_mb}``, ``${eth0 rx_gb}``, ``${eth0 tx_gb}``,
|
||||||
|
``${eth0 down_b}``, ``${eth0 up_b}``, ``${eth0 down_kb}``,
|
||||||
|
``${eth0 up_kb}``, ``${eth0 down_mb}``, ``${eth0 up_mb}``,
|
||||||
|
``${eth0 down_gb}``, ``${eth0 up_gb}``, ``${eth1 rx_b}``, etc.
|
||||||
|
* FreeBSD: a table with string keys: ``${carrier}``, ``${rx_b}``, ``${tx_b}``,
|
||||||
|
``${rx_kb}``, ``${tx_kb}``, ``${rx_mb}``, ``${tx_mb}``, ``${rx_gb}``,
|
||||||
|
``${tx_gb}``, ``${down_b}``, ``${up_b}``, ``${down_kb}``, ``${up_kb}``,
|
||||||
|
``${down_mb}``, ``${up_mb}``, ``${down_gb}``, ``${up_gb}``.
|
||||||
|
|
||||||
|
vicious.widgets.notmuch
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Provides a message count according to an arbitrary Notmuch query.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
Argument: the query that is passed to Notmuch. For instance:
|
||||||
|
``tag:inbox AND tag:unread`` returns the number of unread messages with
|
||||||
|
tag "inbox".
|
||||||
|
|
||||||
|
Returns a table with string keys containing:
|
||||||
|
|
||||||
|
* ``${count}``: the count of messages that match the query
|
||||||
|
|
||||||
|
|
||||||
|
vicious.widgets.org
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Provides agenda statistics for Emacs org-mode.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
* Argument: an array of full paths to agenda files,
|
||||||
|
which will be parsed as arguments.
|
||||||
|
* Returns an array consisting of
|
||||||
|
|
||||||
|
* ``$1``: Number of tasks you forgot to do
|
||||||
|
* ``$2``: Number of tasks for today
|
||||||
|
* ``$3``: Number of tasks for the next 3 days
|
||||||
|
* ``$4``: Number of tasks to do in the week
|
||||||
|
|
||||||
|
vicious.widgets.os
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Provides operating system information.
|
||||||
|
|
||||||
|
Supported platforms: platform independent.
|
||||||
|
|
||||||
|
Returns an array containing:
|
||||||
|
* ``$1``: Operating system in use
|
||||||
|
* ``$2``: Release version
|
||||||
|
* ``$3``: Username
|
||||||
|
* ``$4``: Hostname
|
||||||
|
* ``$5``: Available system entropy
|
||||||
|
* ``$6``: Available entropy in percent
|
||||||
|
|
||||||
|
vicious.widgets.pkg
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Provides number of pending updates on UNIX systems. Be aware that some package
|
||||||
|
managers need to update their local databases (as root) before showing the
|
||||||
|
correct number of updates.
|
||||||
|
|
||||||
|
Supported platforms: platform independent, although it requires Awesome
|
||||||
|
``awful.spawn`` library for non-blocking spawning.
|
||||||
|
|
||||||
|
* Argument: distribution name, e.g. ``"Arch"``, ``"Arch C"``, ``"Arch S"``,
|
||||||
|
``"Debian"``, ``"Ubuntu"``, ``"Fedora"``, ``"FreeBSD"``, ``"Mandriva"``.
|
||||||
|
* Returns an array including:
|
||||||
|
|
||||||
|
* ``$1``: Number of available updates
|
||||||
|
* ``$2``: Packages available for update
|
||||||
|
|
||||||
|
vicious.widgets.raid
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Provides state information for a requested RAID array.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux.
|
||||||
|
|
||||||
|
* Argument: the RAID array ID.
|
||||||
|
* Returns an array containing:
|
||||||
|
|
||||||
|
* ``$1``: Number of assigned devices
|
||||||
|
* ``$2``: Number of active devices
|
||||||
|
|
||||||
|
vicious.widgets.thermal
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Provides temperature levels of several thermal zones.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux, FreeBSD.
|
||||||
|
|
||||||
|
* Argument (per platform):
|
||||||
|
|
||||||
|
* GNU/Linux: either a string - the thermal zone, e.g. ``"thermal_zone0"``,
|
||||||
|
or a table of the form ``{thermal_zone, data_source[, input_file]}``.
|
||||||
|
Available ``data_source``'s and corresponding default ``input_file``
|
||||||
|
are given in the table below. For instance, if ``"thermal_zone0"``
|
||||||
|
is passed, temperature would be read from
|
||||||
|
``/sys/class/thermal/thermal_zone0/temp``. This widget type is confusing
|
||||||
|
and ugly but it is kept for backward compatibility.
|
||||||
|
* FreeBSD: either a full ``sysctl`` path to a thermal zone, e.g.
|
||||||
|
``"hw.acpi.thermal.tz0.temperature"``, or a table with multiple paths.
|
||||||
|
|
||||||
|
* Returns (per platform):
|
||||||
|
|
||||||
|
* GNU/Linux: an array whose first value is the requested temperature.
|
||||||
|
* FreeBSD: a table whose keys are provided paths thermal zones.
|
||||||
|
|
||||||
|
=============== ======================== ======================
|
||||||
|
``data_source`` Path Default ``input_file``
|
||||||
|
=============== ======================== ======================
|
||||||
|
``"sys"`` /sys/class/thermal/ ``"temp"``
|
||||||
|
``"core"`` /sys/devices/platform/ ``"temp2_input"``
|
||||||
|
``"hwmon"`` /sys/class/hwmon/ ``"temp1_input"``
|
||||||
|
``"proc"`` /proc/acpi/thermal_zone/ ``"temperature"``
|
||||||
|
=============== ======================== ======================
|
||||||
|
|
||||||
|
vicious.widgets.uptime
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Provides system uptime and load information.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux, FreeBSD.
|
||||||
|
|
||||||
|
Returns an array containing:
|
||||||
|
|
||||||
|
* ``$1``: Uptime in days
|
||||||
|
* ``$2``: Uptime in hours
|
||||||
|
* ``$3``: Uptime in minutes
|
||||||
|
* ``$4``: Load average in the past minute
|
||||||
|
* ``$5``: Load average in the past 5 minutes
|
||||||
|
* ``$6``: Load average in the past 15 minutes
|
||||||
|
|
||||||
|
vicious.widgets.volume
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Provides volume levels and state of requested mixers.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux (requiring ``amixer``), FreeBSD.
|
||||||
|
|
||||||
|
* Argument (per platform):
|
||||||
|
|
||||||
|
* GNU/Linux: either a string containing the ALSA mixer control
|
||||||
|
(e.g. ``"Master"``) or a table including command line arguments
|
||||||
|
to be passed to `amixer(1)`_, e.g. ``{"PCM", "-c", "0"}``
|
||||||
|
or ``{"Master", "-D", "pulse"}``
|
||||||
|
* FreeBSD: the mixer control, e.g. ``"vol"``
|
||||||
|
|
||||||
|
* Returns an array consisting of (per platform):
|
||||||
|
|
||||||
|
* GNU/Linux: ``$1`` as the volume level and ``$2`` as the mute state of
|
||||||
|
the requested control
|
||||||
|
* FreeBSD: ``$1`` as the volume level of the *left* channel, ``$2`` as the
|
||||||
|
volume level of the *right* channel and ``$3`` as the mute state of the
|
||||||
|
desired control
|
||||||
|
|
||||||
|
vicious.widgets.weather
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Provides weather information for a requested station.
|
||||||
|
|
||||||
|
Supported platforms: any having Awesome and ``curl`` installed.
|
||||||
|
|
||||||
|
* Argument: the ICAO station code, e.g. ``"LDRI"``
|
||||||
|
* Returns a table with string keys: ``${city}``, ``${wind}``, ``${windmph}``,
|
||||||
|
``${windkmh}``, ``${sky}``, ``${weather}``, ``${tempf}``, ``${tempc}``,
|
||||||
|
``${humid}``, ``${dewf}``, ``${dewc}`` and ``${press}``, ``${when}``
|
||||||
|
|
||||||
|
vicious.widgets.wifi
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Provides wireless information for a requested interface.
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux.
|
||||||
|
|
||||||
|
* Argument: the network interface, e.g. ``"wlan0"``
|
||||||
|
* Returns a table with string keys: ``${ssid}``, ``${mode}``,
|
||||||
|
``${chan}``, ``${rate}`` (Mb/s), ``${freq}`` (MHz),
|
||||||
|
``${txpw}`` (transmission power, in dBm), ``${sign}`` (signal level),
|
||||||
|
``${link}`` and ``${linp}`` (link quality per 70 and per cent)
|
||||||
|
|
||||||
|
vicious.widgets.wifiiw
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Provides wireless information for a requested interface (similar to
|
||||||
|
vicious.widgets.wifi, but uses ``iw`` instead of ``iwconfig``).
|
||||||
|
|
||||||
|
Supported platforms: GNU/Linux.
|
||||||
|
|
||||||
|
* Argument: the network interface, e.g. ``"wlan0"``
|
||||||
|
* Returns a table with string keys: ``${bssid}``, ``${ssid}``,
|
||||||
|
``${mode}``, ``${chan}``, ``${rate}`` (Mb/s), ``${freq}`` (MHz),
|
||||||
|
``${linp}`` (link quality in percent),
|
||||||
|
``${txpw}`` (transmission power, in dBm)
|
||||||
|
and ``${sign}`` (signal level, in dBm)
|
||||||
|
|
||||||
|
.. _strftime(3): https://linux.die.net/man/3/strftime
|
||||||
|
.. _app password: https://support.google.com/accounts/answer/185833?hl=en
|
||||||
|
.. _two step verification: https://support.google.com/accounts/answer/1064203
|
||||||
|
.. _allow access for less secure apps:
|
||||||
|
https://www.google.com/settings/security/lesssecureapps
|
||||||
|
.. _amixer(1): https://linux.die.net/man/1/amixer
|
309
helpers.lua
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
-- helper functions
|
||||||
|
-- Copyright (C) 2009 Benedikt Sauer <filmor@gmail.com>
|
||||||
|
-- Copyright (C) 2009 Henning Glawe <glaweh@debian.org>
|
||||||
|
-- Copyright (C) 2009 Lucas de Vries <lucas@glacicle.com>
|
||||||
|
-- Copyright (C) 2009 Rémy C. <shikamaru@mandriva.org>
|
||||||
|
-- Copyright (C) 2009-2012 Adrian C. (anrxc) <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2011 Joerg T. (Mic92) <jthalheim@gmail.com>
|
||||||
|
-- Copyright (C) 2012 Arvydas Sidorenko <asido4@gmail.com>
|
||||||
|
-- Copyright (C) 2012 Jörg Thalheim <jthalheim@gmail.com>
|
||||||
|
-- Copyright (C) 2014-2015 Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
|
-- Copyright (C) 2017 Joerg Thalheim <joerg@thalheim.io>
|
||||||
|
-- Copyright (C) 2017,2019 mutlusun <mutlusun@github.com>
|
||||||
|
-- Copyright (C) 2017-2018 Jörg Thalheim <joerg@thalheim.io>
|
||||||
|
-- Copyright (C) 2018-2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
-- Copyright (C) 2019 Alexander Koch <lynix47@gmail.com>
|
||||||
|
-- Copyright (C) 2019 Enric Morales <me@enric.me>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local ipairs = ipairs
|
||||||
|
local pairs = pairs
|
||||||
|
local rawget = rawget
|
||||||
|
local require = require
|
||||||
|
local tonumber = tonumber
|
||||||
|
local tostring = tostring
|
||||||
|
local io = { open = io.open, popen = io.popen }
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local getmetatable = getmetatable
|
||||||
|
local string = {
|
||||||
|
upper = string.upper,
|
||||||
|
lower = string.lower,
|
||||||
|
format = string.format,
|
||||||
|
match = string.match,
|
||||||
|
find = string.find,
|
||||||
|
}
|
||||||
|
local table = { concat = table.concat }
|
||||||
|
local pcall = pcall
|
||||||
|
local assert = assert
|
||||||
|
local spawn = require("vicious.spawn")
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Helpers: provides helper functions for vicious widgets
|
||||||
|
-- vicious.helpers
|
||||||
|
local helpers = {}
|
||||||
|
|
||||||
|
-- {{{ Constants definitions
|
||||||
|
local OS_UNSUPPORTED_ERR = "Vicious: platform not supported: %s"
|
||||||
|
local NOT_FOUND_MSG = "module '%s' not found"
|
||||||
|
local NOT_FOUND_ERR = [[
|
||||||
|
Vicious: %s is not available for the current platform or does not exist]]
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Variable definitions
|
||||||
|
local scroller = {}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Helper functions
|
||||||
|
-- {{{ Determine operating system
|
||||||
|
local kernel_name
|
||||||
|
function helpers.getos()
|
||||||
|
if kernel_name ~= nil then
|
||||||
|
return kernel_name
|
||||||
|
end
|
||||||
|
|
||||||
|
local f = io.popen("uname -s")
|
||||||
|
kernel_name = string.lower(f:read("*line"))
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
return kernel_name
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Loader of vicious modules
|
||||||
|
function helpers.wrequire(collection, key)
|
||||||
|
local ret = rawget(collection, key)
|
||||||
|
|
||||||
|
if ret then
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
local ostable = {
|
||||||
|
linux = { "linux", "all" },
|
||||||
|
freebsd = { "freebsd", "bsd", "all" },
|
||||||
|
openbsd = { "openbsd", "bsd", "all" }
|
||||||
|
}
|
||||||
|
|
||||||
|
local platform = ostable[helpers.getos()]
|
||||||
|
assert(platform, OS_UNSUPPORTED_ERR:format(helpers.getos()))
|
||||||
|
|
||||||
|
local basename = collection._NAME .. '.' .. key
|
||||||
|
for i = 1, #platform do
|
||||||
|
local name = basename .. '_' .. platform[i]
|
||||||
|
local status, value = pcall(require, name)
|
||||||
|
if status then
|
||||||
|
ret = value
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This is ugly but AFAWK there is no other way to check for
|
||||||
|
-- the type of error. If other error get caught, raise it.
|
||||||
|
if value:find(NOT_FOUND_MSG:format(name), 1, true) == nil then
|
||||||
|
require(name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(ret, NOT_FOUND_ERR:format(basename))
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Set widget type's __call metamethod to given worker function
|
||||||
|
function helpers.setcall(worker)
|
||||||
|
return setmetatable(
|
||||||
|
{}, { __call = function(_, ...) return worker(...) end })
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Set __call metamethod to widget type table having async key
|
||||||
|
function helpers.setasyncall(wtype)
|
||||||
|
local function worker(format, warg)
|
||||||
|
local ret
|
||||||
|
wtype.async(format, warg, function (data) ret = data end)
|
||||||
|
while ret == nil do end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
local metatable = { __call = function (_, ...) return worker(...) end }
|
||||||
|
return setmetatable(wtype, metatable)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Expose path as a Lua table
|
||||||
|
function helpers.pathtotable(dir)
|
||||||
|
return setmetatable({ _path = dir },
|
||||||
|
{ __index = function(self, index)
|
||||||
|
local path = self._path .. '/' .. index
|
||||||
|
local f = io.open(path)
|
||||||
|
if f then
|
||||||
|
local s = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
if s then
|
||||||
|
return s
|
||||||
|
else
|
||||||
|
local o = { _path = path }
|
||||||
|
setmetatable(o, getmetatable(self))
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Format a string with args
|
||||||
|
function helpers.format(format, args)
|
||||||
|
for var, val in pairs(args) do
|
||||||
|
format = format:gsub("$" .. (tonumber(var) and var or
|
||||||
|
var:gsub("[-+?*]", function(i) return "%"..i end)),
|
||||||
|
val)
|
||||||
|
end
|
||||||
|
|
||||||
|
return format
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Format units to one decimal point
|
||||||
|
function helpers.uformat(array, key, value, unit)
|
||||||
|
for u, v in pairs(unit) do
|
||||||
|
array["{"..key.."_"..u.."}"] = string.format("%.1f", value/v)
|
||||||
|
end
|
||||||
|
|
||||||
|
return array
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Escape a string
|
||||||
|
function helpers.escape(text)
|
||||||
|
local xml_entities = {
|
||||||
|
["\""] = """,
|
||||||
|
["&"] = "&",
|
||||||
|
["'"] = "'",
|
||||||
|
["<"] = "<",
|
||||||
|
[">"] = ">"
|
||||||
|
}
|
||||||
|
|
||||||
|
return text and text:gsub("[\"&'<>]", xml_entities)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Escape a string for safe usage on the command line
|
||||||
|
function helpers.shellquote(arg)
|
||||||
|
local s = tostring(arg)
|
||||||
|
if s == nil then return "" end
|
||||||
|
-- use single quotes, and put single quotes into double quotes
|
||||||
|
-- the string $'b is then quoted as '$'"'"'b'"'"'
|
||||||
|
return "'" .. s:gsub("'", "'\"'\"'") .. "'"
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Capitalize a string
|
||||||
|
function helpers.capitalize(text)
|
||||||
|
return text and text:gsub("([%w])([%w]*)", function(c, s)
|
||||||
|
return string.upper(c) .. s
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Truncate a string
|
||||||
|
function helpers.truncate(text, maxlen)
|
||||||
|
local txtlen = text:len()
|
||||||
|
|
||||||
|
if txtlen > maxlen then
|
||||||
|
text = text:sub(1, maxlen - 3) .. "..."
|
||||||
|
end
|
||||||
|
|
||||||
|
return text
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Scroll through a string
|
||||||
|
function helpers.scroll(text, maxlen, widget)
|
||||||
|
if not scroller[widget] then
|
||||||
|
scroller[widget] = { i = 1, d = true }
|
||||||
|
end
|
||||||
|
|
||||||
|
local txtlen = text:len()
|
||||||
|
local state = scroller[widget]
|
||||||
|
|
||||||
|
if txtlen > maxlen then
|
||||||
|
if state.d then
|
||||||
|
text = text:sub(state.i, state.i + maxlen) .. "..."
|
||||||
|
state.i = state.i + 3
|
||||||
|
|
||||||
|
if maxlen + state.i >= txtlen then
|
||||||
|
state.d = false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
text = "..." .. text:sub(state.i, state.i + maxlen)
|
||||||
|
state.i = state.i - 3
|
||||||
|
|
||||||
|
if state.i <= 1 then
|
||||||
|
state.d = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return text
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Parse output of sysctl command calling the `parse` function
|
||||||
|
function helpers.sysctl_async(path_table, parse)
|
||||||
|
local ret = {}
|
||||||
|
local path = {}
|
||||||
|
|
||||||
|
for i=1,#path_table do
|
||||||
|
path[i] = helpers.shellquote(path_table[i])
|
||||||
|
end
|
||||||
|
|
||||||
|
path = table.concat(path, " ")
|
||||||
|
|
||||||
|
spawn.with_line_callback("sysctl " .. path, {
|
||||||
|
stdout = function (line)
|
||||||
|
local separators = {
|
||||||
|
freebsd = ": ",
|
||||||
|
linux = " = ",
|
||||||
|
openbsd = "="
|
||||||
|
}
|
||||||
|
local pattern = ("(.+)%s(.+)"):format(separators[helpers.getos()])
|
||||||
|
local key, value = string.match(line, pattern)
|
||||||
|
ret[key] = value
|
||||||
|
end,
|
||||||
|
stderr = function (line)
|
||||||
|
local messages = {
|
||||||
|
openbsd = { "level name .+ in (.+) is invalid" },
|
||||||
|
linux = { "cannot stat /proc/sys/(.+):",
|
||||||
|
"permission denied on key '(.+)'" },
|
||||||
|
freebsd = { "unknown oid '(.+)'" }
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, error_message in ipairs(messages[helpers.getos()]) do
|
||||||
|
local key = line:match(error_message)
|
||||||
|
if key then
|
||||||
|
key = key:gsub("/", ".")
|
||||||
|
ret[key] = "N/A"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
output_done = function () parse(ret) end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return helpers
|
||||||
|
-- }}}
|
356
init.lua
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
-- Vicious module initialization
|
||||||
|
-- Copyright (C) 2009 Lucas de Vries <lucas@glacicle.com>
|
||||||
|
-- Copyright (C) 2009-2013 Adrian C. (anrxc) <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2011-2017 Joerg Thalheim <joerg@thalheim.io>
|
||||||
|
-- Copyright (C) 2012 Arvydas Sidorenko <asido4@gmail.com>
|
||||||
|
-- Copyright (C) 2013 Dodo <dodo.the.last@gmail.com>
|
||||||
|
-- Copyright (C) 2014 blastmaster <blastmaster@tuxcode.org>
|
||||||
|
-- Copyright (C) 2015,2019 Daniel Hahler <github@thequod.de>
|
||||||
|
-- Copyright (C) 2017 James Reed <supplantr@users.noreply.github.com>
|
||||||
|
-- Copyright (C) 2017 getzze <getzze@gmail.com>
|
||||||
|
-- Copyright (C) 2017 mutlusun <mutlusun@github.com>
|
||||||
|
-- Copyright (C) 2018 Beniamin Kalinowski <beniamin.kalinowski@gmail.com>
|
||||||
|
-- Copyright (C) 2018,2020 Nguyễn Gia Phong <mcsinyx@disroot.org>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Setup environment
|
||||||
|
local type = type
|
||||||
|
local pairs = pairs
|
||||||
|
local tonumber = tonumber
|
||||||
|
local timer = type(timer) == "table" and timer or require("gears.timer")
|
||||||
|
local os = { time = os.time }
|
||||||
|
local table = {
|
||||||
|
insert = table.insert,
|
||||||
|
remove = table.remove
|
||||||
|
}
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
|
||||||
|
-- Vicious: widgets for the awesome window manager
|
||||||
|
local vicious = {}
|
||||||
|
vicious.widgets = require("vicious.widgets")
|
||||||
|
--vicious.contrib = require("vicious.contrib")
|
||||||
|
|
||||||
|
-- Initialize tables
|
||||||
|
local timers = {}
|
||||||
|
local registered = {}
|
||||||
|
local widget_cache = {}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Local functions
|
||||||
|
-- {{{ Update a widget
|
||||||
|
local function update(widget, reg, disablecache)
|
||||||
|
-- Check if there are any equal widgets
|
||||||
|
if reg == nil then
|
||||||
|
for w, i in pairs(registered) do
|
||||||
|
if w == widget then
|
||||||
|
for _, r in pairs(i) do
|
||||||
|
update(w, r, disablecache)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local update_time = os.time()
|
||||||
|
|
||||||
|
local function format_data(data)
|
||||||
|
local ret
|
||||||
|
if type(data) == "table" then
|
||||||
|
local escaped_data = {}
|
||||||
|
for k, v in pairs(data) do
|
||||||
|
if type(v) == "string" then
|
||||||
|
escaped_data[k] = helpers.escape(v)
|
||||||
|
else
|
||||||
|
escaped_data[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(reg.format) == "string" then
|
||||||
|
ret = helpers.format(reg.format, escaped_data)
|
||||||
|
elseif type(reg.format) == "function" then
|
||||||
|
ret = reg.format(widget, escaped_data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret or data
|
||||||
|
end
|
||||||
|
|
||||||
|
local function topercent(e) return tonumber(e) and tonumber(e) / 100 end
|
||||||
|
|
||||||
|
local function update_value(data)
|
||||||
|
local fmtd_data = format_data(data)
|
||||||
|
if widget.add_value ~= nil then
|
||||||
|
if widget.get_stack ~= nil and widget:get_stack() then
|
||||||
|
for idx, _ in ipairs(widget:get_stack_colors()) do
|
||||||
|
if fmtd_data[idx] then
|
||||||
|
widget:add_value(topercent(fmtd_data[idx]), idx)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
widget:add_value(topercent(fmtd_data))
|
||||||
|
end
|
||||||
|
elseif widget.set_value ~= nil then
|
||||||
|
widget:set_value(topercent(fmtd_data))
|
||||||
|
elseif widget.set_markup ~= nil then
|
||||||
|
widget:set_markup(fmtd_data)
|
||||||
|
else
|
||||||
|
widget.text = fmtd_data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function update_cache(data, t, cache)
|
||||||
|
-- Update cache
|
||||||
|
if t and cache then
|
||||||
|
cache.time, cache.data = t, data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check for cached output newer than the last update
|
||||||
|
local c = widget_cache[reg.wtype]
|
||||||
|
if c and update_time < c.time + reg.timeout and not disablecache then
|
||||||
|
update_value(c.data)
|
||||||
|
elseif reg.wtype then
|
||||||
|
if type(reg.wtype) == "table" and reg.wtype.async then
|
||||||
|
if not reg.lock then
|
||||||
|
reg.lock = true
|
||||||
|
return reg.wtype.async(reg.format,
|
||||||
|
reg.warg,
|
||||||
|
function(data)
|
||||||
|
update_cache(data, update_time, c)
|
||||||
|
update_value(data)
|
||||||
|
reg.lock=false
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local data = reg.wtype(reg.format, reg.warg)
|
||||||
|
update_cache(data, update_time, c)
|
||||||
|
update_value(data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Register from reg object
|
||||||
|
local function regregister(reg)
|
||||||
|
if not reg.running then
|
||||||
|
if registered[reg.widget] == nil then
|
||||||
|
registered[reg.widget] = {}
|
||||||
|
table.insert(registered[reg.widget], reg)
|
||||||
|
else
|
||||||
|
local already = false
|
||||||
|
|
||||||
|
for w, i in pairs(registered) do
|
||||||
|
if w == reg.widget then
|
||||||
|
for _, v in pairs(i) do
|
||||||
|
if v == reg then
|
||||||
|
already = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if already then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not already then
|
||||||
|
table.insert(registered[reg.widget], reg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Start the timer
|
||||||
|
if reg.timeout > 0 then
|
||||||
|
local tm = timers[reg.timeout] and timers[reg.timeout].timer
|
||||||
|
tm = tm or timer({ timeout = reg.timeout })
|
||||||
|
if tm.connect_signal then
|
||||||
|
tm:connect_signal("timeout", reg.update)
|
||||||
|
else
|
||||||
|
tm:add_signal("timeout", reg.update)
|
||||||
|
end
|
||||||
|
if not timers[reg.timeout] then
|
||||||
|
timers[reg.timeout] = { timer = tm, refs = 1 }
|
||||||
|
else
|
||||||
|
timers[reg.timeout].refs = timers[reg.timeout].refs + 1
|
||||||
|
end
|
||||||
|
if not tm.started then
|
||||||
|
tm:start()
|
||||||
|
end
|
||||||
|
-- Initial update
|
||||||
|
reg.update()
|
||||||
|
end
|
||||||
|
reg.running = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Global functions
|
||||||
|
-- {{{ Register a widget
|
||||||
|
function vicious.register(widget, wtype, format, timeout, warg)
|
||||||
|
local reg = {
|
||||||
|
-- Set properties
|
||||||
|
wtype = wtype,
|
||||||
|
lock = false,
|
||||||
|
format = format,
|
||||||
|
timeout = timeout or 2,
|
||||||
|
warg = warg,
|
||||||
|
widget = widget,
|
||||||
|
}
|
||||||
|
reg.timer = timeout -- For backward compatibility.
|
||||||
|
|
||||||
|
-- Set functions
|
||||||
|
function reg.update()
|
||||||
|
update(widget, reg)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Register a reg object
|
||||||
|
regregister(reg)
|
||||||
|
|
||||||
|
-- Return a reg object for reuse
|
||||||
|
return reg
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Unregister a widget
|
||||||
|
function vicious.unregister(widget, keep, reg)
|
||||||
|
if reg == nil then
|
||||||
|
for w, i in pairs(registered) do
|
||||||
|
if w == widget then
|
||||||
|
for _, v in pairs(i) do
|
||||||
|
reg = vicious.unregister(w, keep, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return reg
|
||||||
|
end
|
||||||
|
|
||||||
|
if not keep then
|
||||||
|
for w, i in pairs(registered) do
|
||||||
|
if w == widget then
|
||||||
|
for k, v in pairs(i) do
|
||||||
|
if v == reg then
|
||||||
|
table.remove(registered[w], k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not reg.running then
|
||||||
|
return reg
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Disconnect from timer
|
||||||
|
local tm = timers[reg.timeout]
|
||||||
|
if tm.timer.disconnect_signal then
|
||||||
|
tm.timer:disconnect_signal("timeout", reg.update)
|
||||||
|
else
|
||||||
|
tm.timer:remove_signal("timeout", reg.update)
|
||||||
|
end
|
||||||
|
reg.running = false
|
||||||
|
-- Stop the timer
|
||||||
|
tm.refs = tm.refs - 1
|
||||||
|
if tm.refs == 0 and tm.timer.started then
|
||||||
|
tm.timer:stop()
|
||||||
|
end
|
||||||
|
|
||||||
|
return reg
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Enable caching of a widget type
|
||||||
|
function vicious.cache(wtype)
|
||||||
|
if wtype ~= nil then
|
||||||
|
if widget_cache[wtype] == nil then
|
||||||
|
widget_cache[wtype] = { data = nil, time = 0 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Force update of widgets
|
||||||
|
function vicious.force(wtable)
|
||||||
|
if type(wtable) == "table" then
|
||||||
|
for _, w in pairs(wtable) do
|
||||||
|
update(w, nil, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Suspend all widgets
|
||||||
|
function vicious.suspend()
|
||||||
|
for w, i in pairs(registered) do
|
||||||
|
for _, v in pairs(i) do
|
||||||
|
vicious.unregister(w, true, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Activate a widget
|
||||||
|
function vicious.activate(widget)
|
||||||
|
for w, i in pairs(registered) do
|
||||||
|
if widget == nil or w == widget then
|
||||||
|
for _, v in pairs(i) do
|
||||||
|
regregister(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Get formatted data from a synchronous widget type
|
||||||
|
function vicious.call(wtype, format, warg)
|
||||||
|
if wtype.async ~= nil then return nil end
|
||||||
|
|
||||||
|
local data = wtype(format, warg)
|
||||||
|
if type(format) == "string" then
|
||||||
|
return helpers.format(format, data)
|
||||||
|
elseif type(format) == "function" then
|
||||||
|
return format(wtype, data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Get formatted data from an asynchronous widget type
|
||||||
|
function vicious.call_async(wtype, format, warg, callback)
|
||||||
|
if wtype.async == nil then
|
||||||
|
callback()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
wtype.async(
|
||||||
|
format, warg,
|
||||||
|
function (data)
|
||||||
|
if type(format) == "string" then
|
||||||
|
callback(helpers.format(format, data))
|
||||||
|
elseif type(format) == "function" then
|
||||||
|
callback(format(wtype, data))
|
||||||
|
else
|
||||||
|
callback()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return vicious
|
||||||
|
-- }}}
|
650
rc.lua
Normal file
@ -0,0 +1,650 @@
|
|||||||
|
-- If LuaRocks is installed, make sure that packages installed through it are
|
||||||
|
-- found (e.g. lgi). If LuaRocks is not installed, do nothing.
|
||||||
|
pcall(require, "luarocks.loader")
|
||||||
|
|
||||||
|
-- Standard awesome library
|
||||||
|
local gears = require("gears")
|
||||||
|
local awful = require("awful")
|
||||||
|
require("awful.autofocus")
|
||||||
|
-- Widget and layout library
|
||||||
|
local wibox = require("wibox")
|
||||||
|
-- Theme handling library
|
||||||
|
local beautiful = require("beautiful")
|
||||||
|
-- Notification library
|
||||||
|
local naughty = require("naughty")
|
||||||
|
local menubar = require("menubar")
|
||||||
|
local hotkeys_popup = require("awful.hotkeys_popup")
|
||||||
|
--local hotkeys = require("awful.hotkeys_popup")
|
||||||
|
--local hotkeys_popup = hotkeys_popup.widget.new({ width = 100, height = 100 })
|
||||||
|
--hotkeys_popup.show_help = hotkeys_popup.widget.show_help
|
||||||
|
-- Enable hotkeys help widget for VIM and other apps
|
||||||
|
-- when client with a matching name is opened:
|
||||||
|
require("awful.hotkeys_popup.keys.vim")
|
||||||
|
--local cairo = require("lgi").cairo
|
||||||
|
|
||||||
|
-- My custom libs
|
||||||
|
local vicious = require("vicious")
|
||||||
|
|
||||||
|
-- {{{ Error handling
|
||||||
|
-- Check if awesome encountered an error during startup and fell back to
|
||||||
|
-- another config (This code will only ever execute for the fallback config)
|
||||||
|
if awesome.startup_errors then
|
||||||
|
naughty.notify({ preset = naughty.config.presets.critical,
|
||||||
|
title = "Oops, there were errors during startup!",
|
||||||
|
text = awesome.startup_errors })
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle runtime errors after startup
|
||||||
|
do
|
||||||
|
local in_error = false
|
||||||
|
awesome.connect_signal("debug::error", function (err)
|
||||||
|
-- Make sure we don't go into an endless error loop
|
||||||
|
if in_error then return end
|
||||||
|
in_error = true
|
||||||
|
|
||||||
|
naughty.notify({ preset = naughty.config.presets.critical,
|
||||||
|
title = "Oops, an error happened!",
|
||||||
|
text = tostring(err) })
|
||||||
|
in_error = false
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Variable definitions
|
||||||
|
-- Themes define colours, icons, font and wallpapers.
|
||||||
|
--beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
|
||||||
|
local theme_path = string.format("%s/.config/awesome/themes/%s/theme.lua", os.getenv("HOME"), "zenburn")
|
||||||
|
beautiful.init(theme_path)
|
||||||
|
beautiful.font = "Indie Flower Bold 12"
|
||||||
|
--local cr = cairo.Context()
|
||||||
|
--beautiful.hotkeys_shape = gears.shape.rect(cr, 10, 10, 10)
|
||||||
|
--beautiful.useless_gap = 3
|
||||||
|
|
||||||
|
|
||||||
|
-- This is used later as the default terminal and editor to run.
|
||||||
|
terminal = "kitty"
|
||||||
|
editor = os.getenv("EDITOR") or "vim"
|
||||||
|
editor_cmd = terminal .. " -e " .. editor
|
||||||
|
|
||||||
|
-- Default modkey.
|
||||||
|
-- Usually, Mod4 is the key with a logo between Control and Alt.
|
||||||
|
-- If you do not like this or do not have such a key,
|
||||||
|
-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
|
||||||
|
-- However, you can use another modifier like Mod1, but it may interact with others.
|
||||||
|
modkey = "Mod4"
|
||||||
|
|
||||||
|
-- Table of layouts to cover with awful.layout.inc, order matters.
|
||||||
|
awful.layout.layouts = {
|
||||||
|
awful.layout.suit.floating,
|
||||||
|
awful.layout.suit.tile,
|
||||||
|
awful.layout.suit.tile.left,
|
||||||
|
awful.layout.suit.tile.bottom,
|
||||||
|
awful.layout.suit.tile.top,
|
||||||
|
awful.layout.suit.fair,
|
||||||
|
awful.layout.suit.fair.horizontal,
|
||||||
|
awful.layout.suit.spiral,
|
||||||
|
awful.layout.suit.spiral.dwindle,
|
||||||
|
awful.layout.suit.max,
|
||||||
|
awful.layout.suit.max.fullscreen,
|
||||||
|
awful.layout.suit.magnifier,
|
||||||
|
awful.layout.suit.corner.nw,
|
||||||
|
-- awful.layout.suit.corner.ne,
|
||||||
|
-- awful.layout.suit.corner.sw,
|
||||||
|
-- awful.layout.suit.corner.se,
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Menu
|
||||||
|
-- Create a launcher widget and a main menu
|
||||||
|
myawesomemenu = {
|
||||||
|
{ "hotkeys", function() hotkeys_popup.show_help(nil, awful.screen.focused()) end },
|
||||||
|
{ "manual", terminal .. " -e man awesome" },
|
||||||
|
{ "edit config", editor_cmd .. " " .. awesome.conffile },
|
||||||
|
{ "restart", awesome.restart },
|
||||||
|
{ "quit", function() awesome.quit() end },
|
||||||
|
}
|
||||||
|
|
||||||
|
mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
|
||||||
|
{ "terminal", terminal }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
|
||||||
|
menu = mymainmenu })
|
||||||
|
|
||||||
|
-- Menubar configuration
|
||||||
|
menubar.utils.terminal = terminal -- Set the terminal for applications that require it
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- Keyboard map indicator and switcher
|
||||||
|
mykeyboardlayout = awful.widget.keyboardlayout()
|
||||||
|
|
||||||
|
-- {{{ Wibar
|
||||||
|
|
||||||
|
-- Create a wibox for each screen and add it
|
||||||
|
local taglist_buttons = gears.table.join(
|
||||||
|
awful.button({ }, 1, function(t) t:view_only() end),
|
||||||
|
awful.button({ modkey }, 1, function(t)
|
||||||
|
if client.focus then
|
||||||
|
client.focus:move_to_tag(t)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
awful.button({ }, 3, awful.tag.viewtoggle),
|
||||||
|
awful.button({ modkey }, 3, function(t)
|
||||||
|
if client.focus then
|
||||||
|
client.focus:toggle_tag(t)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
|
||||||
|
awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
|
||||||
|
)
|
||||||
|
|
||||||
|
local tasklist_buttons = gears.table.join(
|
||||||
|
awful.button({ }, 1, function (c)
|
||||||
|
if c == client.focus then
|
||||||
|
c.minimized = true
|
||||||
|
else
|
||||||
|
c:emit_signal(
|
||||||
|
"request::activate",
|
||||||
|
"tasklist",
|
||||||
|
{raise = true}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
awful.button({ }, 3, function()
|
||||||
|
awful.menu.client_list({ theme = { width = 250 } })
|
||||||
|
end),
|
||||||
|
awful.button({ }, 4, function ()
|
||||||
|
awful.client.focus.byidx(1)
|
||||||
|
end),
|
||||||
|
awful.button({ }, 5, function ()
|
||||||
|
awful.client.focus.byidx(-1)
|
||||||
|
end))
|
||||||
|
|
||||||
|
local function set_wallpaper(s)
|
||||||
|
-- Wallpaper
|
||||||
|
if beautiful.wallpaper then
|
||||||
|
local wallpaper = beautiful.wallpaper
|
||||||
|
-- If wallpaper is a function, call it with the screen
|
||||||
|
if type(wallpaper) == "function" then
|
||||||
|
wallpaper = wallpaper(s)
|
||||||
|
end
|
||||||
|
gears.wallpaper.maximized(wallpaper, s, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
datewidget = wibox.widget.textbox()
|
||||||
|
vicious.register(datewidget, vicious.widgets.date, "%b %d, %R ")
|
||||||
|
|
||||||
|
--memwidget = wibox.widget.textbox()
|
||||||
|
--vicious.cache(vicious.widgets.mem)
|
||||||
|
--vicious.register(memwidget, vicious.widgets.mem, " $2/$3 $1% $6/$7 $5% ", 1)
|
||||||
|
|
||||||
|
-- Create wibox with batwidget
|
||||||
|
batwidget = wibox.widget.progressbar()
|
||||||
|
batbox = wibox.layout.margin(
|
||||||
|
wibox.widget{ { max_value = 1, widget = batwidget,
|
||||||
|
border_width = 0.5, border_color = "#000000",
|
||||||
|
color = { type = "linear",
|
||||||
|
from = { 0, 0 },
|
||||||
|
to = { 0, 30 },
|
||||||
|
stops = { { 0, "#AECF96" },
|
||||||
|
{ 1, "#FF5656" } } } },
|
||||||
|
forced_height = 10, forced_width = 8,
|
||||||
|
direction = 'east', color = beautiful.fg_widget,
|
||||||
|
layout = wibox.container.rotate },
|
||||||
|
1, 4, 1, 1)
|
||||||
|
|
||||||
|
-- Register battery widget
|
||||||
|
vicious.register(batwidget, vicious.widgets.bat, "$2", 1, "BAT1")
|
||||||
|
|
||||||
|
|
||||||
|
cpuwidget = awful.widget.graph()
|
||||||
|
cpuwidget:set_width(50)
|
||||||
|
cpuwidget:set_background_color"#4A3F9800"
|
||||||
|
cpuwidget:set_color{ type = "linear", from = { 0, 0 }, to = { 50, 0 },
|
||||||
|
stops = { { 0, "#4A3F9800" },
|
||||||
|
{ 0.1, "#FF5656" },
|
||||||
|
{ 0.95, "#4A3F9800" } } }
|
||||||
|
vicious.register(cpuwidget, vicious.widgets.cpu, "$1", 1)
|
||||||
|
|
||||||
|
memwidget = awful.widget.graph()
|
||||||
|
memwidget:set_width(50)
|
||||||
|
memwidget:set_background_color"#4A3F9800"
|
||||||
|
memwidget:set_color{ type = "linear", from = { 0, 0 }, to = { 50, 0 },
|
||||||
|
stops = { { 0, "#4A3F9800" },
|
||||||
|
{ 0.1, "#FF5656" },
|
||||||
|
{ 0.95, "#4A3F9800" } } }
|
||||||
|
vicious.register(memwidget, vicious.widgets.mem, "$1", 1)
|
||||||
|
|
||||||
|
swapwidget = awful.widget.graph()
|
||||||
|
swapwidget:set_width(50)
|
||||||
|
swapwidget:set_background_color"#4A3F9800"
|
||||||
|
swapwidget:set_color{ type = "linear", from = { 0, 0 }, to = { 50, 0 },
|
||||||
|
stops = { { 0, "#4A3F9800" },
|
||||||
|
{ 0.1, "#FF5656" },
|
||||||
|
{ 0.95, "#4A3F9800" } } }
|
||||||
|
vicious.register(swapwidget, vicious.widgets.mem, "$5", 1)
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
|
||||||
|
screen.connect_signal("property::geometry", set_wallpaper)
|
||||||
|
|
||||||
|
awful.screen.connect_for_each_screen(function(s)
|
||||||
|
-- Wallpaper
|
||||||
|
set_wallpaper(s)
|
||||||
|
|
||||||
|
-- Each screen has its own tag table.
|
||||||
|
awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])
|
||||||
|
|
||||||
|
-- Create a promptbox for each screen
|
||||||
|
s.mypromptbox = awful.widget.prompt()
|
||||||
|
-- Create an imagebox widget which will contain an icon indicating which layout we're using.
|
||||||
|
-- We need one layoutbox per screen.
|
||||||
|
s.mylayoutbox = awful.widget.layoutbox(s)
|
||||||
|
s.mylayoutbox:buttons(gears.table.join(
|
||||||
|
awful.button({ }, 1, function () awful.layout.inc( 1) end),
|
||||||
|
awful.button({ }, 3, function () awful.layout.inc(-1) end),
|
||||||
|
awful.button({ }, 4, function () awful.layout.inc( 1) end),
|
||||||
|
awful.button({ }, 5, function () awful.layout.inc(-1) end)))
|
||||||
|
-- Create a taglist widget
|
||||||
|
s.mytaglist = awful.widget.taglist {
|
||||||
|
screen = s,
|
||||||
|
filter = awful.widget.taglist.filter.all,
|
||||||
|
buttons = taglist_buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Create a tasklist widget
|
||||||
|
s.mytasklist = awful.widget.tasklist {
|
||||||
|
screen = s,
|
||||||
|
filter = awful.widget.tasklist.filter.currenttags,
|
||||||
|
buttons = tasklist_buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Create the wibox
|
||||||
|
s.mywibox = awful.wibar({ position = "bottom", screen = s })
|
||||||
|
|
||||||
|
-- Add widgets to the wibox
|
||||||
|
s.mywibox:setup {
|
||||||
|
layout = wibox.layout.align.horizontal,
|
||||||
|
{ -- Left widgets
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
mylauncher,
|
||||||
|
s.mytaglist,
|
||||||
|
s.mypromptbox,
|
||||||
|
},
|
||||||
|
s.mytasklist, -- Middle widget
|
||||||
|
{ -- Right widgets
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
wibox.widget.systray(),
|
||||||
|
memwidget,
|
||||||
|
swapwidget,
|
||||||
|
cpuwidget,
|
||||||
|
mykeyboardlayout,
|
||||||
|
datewidget,
|
||||||
|
batbox,
|
||||||
|
s.mylayoutbox,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Mouse bindings
|
||||||
|
root.buttons(gears.table.join(
|
||||||
|
awful.button({ }, 3, function () mymainmenu:toggle() end),
|
||||||
|
awful.button({ }, 4, awful.tag.viewnext),
|
||||||
|
awful.button({ }, 5, awful.tag.viewprev)
|
||||||
|
))
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Key bindings
|
||||||
|
globalkeys = gears.table.join(
|
||||||
|
awful.key({ modkey, }, "s", hotkeys_popup.show_help,
|
||||||
|
{description="show help", group="awesome"}),
|
||||||
|
awful.key({ modkey, }, "Left", awful.tag.viewprev,
|
||||||
|
{description = "view previous", group = "tag"}),
|
||||||
|
awful.key({ modkey, }, "Right", awful.tag.viewnext,
|
||||||
|
{description = "view next", group = "tag"}),
|
||||||
|
awful.key({ modkey, }, "Escape", awful.tag.history.restore,
|
||||||
|
{description = "go back", group = "tag"}),
|
||||||
|
|
||||||
|
awful.key({ modkey, }, "j",
|
||||||
|
function ()
|
||||||
|
awful.client.focus.byidx( 1)
|
||||||
|
end,
|
||||||
|
{description = "focus next by index", group = "client"}
|
||||||
|
),
|
||||||
|
awful.key({ modkey, }, "k",
|
||||||
|
function ()
|
||||||
|
awful.client.focus.byidx(-1)
|
||||||
|
end,
|
||||||
|
{description = "focus previous by index", group = "client"}
|
||||||
|
),
|
||||||
|
awful.key({ modkey, }, "w", function () mymainmenu:show() end,
|
||||||
|
{description = "show main menu", group = "awesome"}),
|
||||||
|
|
||||||
|
-- Layout manipulation
|
||||||
|
awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
|
||||||
|
{description = "swap with next client by index", group = "client"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
|
||||||
|
{description = "swap with previous client by index", group = "client"}),
|
||||||
|
awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
|
||||||
|
{description = "focus the next screen", group = "screen"}),
|
||||||
|
awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
|
||||||
|
{description = "focus the previous screen", group = "screen"}),
|
||||||
|
awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
|
||||||
|
{description = "jump to urgent client", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "Tab",
|
||||||
|
function ()
|
||||||
|
awful.client.focus.history.previous()
|
||||||
|
if client.focus then
|
||||||
|
client.focus:raise()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "go back", group = "client"}),
|
||||||
|
|
||||||
|
-- Standard program
|
||||||
|
awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
|
||||||
|
{description = "open a terminal", group = "launcher"}),
|
||||||
|
awful.key({ modkey, "Control" }, "r", awesome.restart,
|
||||||
|
{description = "reload awesome", group = "awesome"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "q", awesome.quit,
|
||||||
|
{description = "quit awesome", group = "awesome"}),
|
||||||
|
|
||||||
|
awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
|
||||||
|
{description = "increase master width factor", group = "layout"}),
|
||||||
|
awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
|
||||||
|
{description = "decrease master width factor", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
|
||||||
|
{description = "increase the number of master clients", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
|
||||||
|
{description = "decrease the number of master clients", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
|
||||||
|
{description = "increase the number of columns", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
|
||||||
|
{description = "decrease the number of columns", group = "layout"}),
|
||||||
|
awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
|
||||||
|
{description = "select next", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
|
||||||
|
{description = "select previous", group = "layout"}),
|
||||||
|
|
||||||
|
awful.key({ modkey, "Control" }, "n",
|
||||||
|
function ()
|
||||||
|
local c = awful.client.restore()
|
||||||
|
-- Focus restored client
|
||||||
|
if c then
|
||||||
|
c:emit_signal(
|
||||||
|
"request::activate", "key.unminimize", {raise = true}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "restore minimized", group = "client"}),
|
||||||
|
|
||||||
|
-- Prompt
|
||||||
|
awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end,
|
||||||
|
{description = "run prompt", group = "launcher"}),
|
||||||
|
|
||||||
|
awful.key({ modkey }, "x",
|
||||||
|
function ()
|
||||||
|
awful.prompt.run {
|
||||||
|
prompt = "Run Lua code: ",
|
||||||
|
textbox = awful.screen.focused().mypromptbox.widget,
|
||||||
|
exe_callback = awful.util.eval,
|
||||||
|
history_path = awful.util.get_cache_dir() .. "/history_eval"
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
{description = "lua execute prompt", group = "awesome"}),
|
||||||
|
-- Menubar
|
||||||
|
awful.key({ modkey }, "p", function() menubar.show() end,
|
||||||
|
{description = "show the menubar", group = "launcher"})
|
||||||
|
)
|
||||||
|
|
||||||
|
clientkeys = gears.table.join(
|
||||||
|
awful.key({ modkey, }, "f",
|
||||||
|
function (c)
|
||||||
|
c.fullscreen = not c.fullscreen
|
||||||
|
c:raise()
|
||||||
|
end,
|
||||||
|
{description = "toggle fullscreen", group = "client"}),
|
||||||
|
awful.key({ modkey, "Control" }, "s",
|
||||||
|
function (c)
|
||||||
|
awful.titlebar.toggle(c)
|
||||||
|
end,
|
||||||
|
{description = "toggle titlebar", group = "client"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
|
||||||
|
{description = "close", group = "client"}),
|
||||||
|
awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
|
||||||
|
{description = "toggle floating", group = "client"}),
|
||||||
|
awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
|
||||||
|
{description = "move to master", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
|
||||||
|
{description = "move to screen", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
|
||||||
|
{description = "toggle keep on top", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "n",
|
||||||
|
function (c)
|
||||||
|
-- The client currently has the input focus, so it cannot be
|
||||||
|
-- minimized, since minimized clients can't have the focus.
|
||||||
|
c.minimized = true
|
||||||
|
end ,
|
||||||
|
{description = "minimize", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "m",
|
||||||
|
function (c)
|
||||||
|
c.maximized = not c.maximized
|
||||||
|
c:raise()
|
||||||
|
end ,
|
||||||
|
{description = "(un)maximize", group = "client"}),
|
||||||
|
awful.key({ modkey, "Control" }, "m",
|
||||||
|
function (c)
|
||||||
|
c.maximized_vertical = not c.maximized_vertical
|
||||||
|
c:raise()
|
||||||
|
end ,
|
||||||
|
{description = "(un)maximize vertically", group = "client"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "m",
|
||||||
|
function (c)
|
||||||
|
c.maximized_horizontal = not c.maximized_horizontal
|
||||||
|
c:raise()
|
||||||
|
end ,
|
||||||
|
{description = "(un)maximize horizontally", group = "client"})
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Bind all key numbers to tags.
|
||||||
|
-- Be careful: we use keycodes to make it work on any keyboard layout.
|
||||||
|
-- This should map on the top row of your keyboard, usually 1 to 9.
|
||||||
|
for i = 1, 9 do
|
||||||
|
globalkeys = gears.table.join(globalkeys,
|
||||||
|
-- View tag only.
|
||||||
|
awful.key({ modkey }, "#" .. i + 9,
|
||||||
|
function ()
|
||||||
|
local screen = awful.screen.focused()
|
||||||
|
local tag = screen.tags[i]
|
||||||
|
if tag then
|
||||||
|
tag:view_only()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "view tag #"..i, group = "tag"}),
|
||||||
|
-- Toggle tag display.
|
||||||
|
awful.key({ modkey, "Control" }, "#" .. i + 9,
|
||||||
|
function ()
|
||||||
|
local screen = awful.screen.focused()
|
||||||
|
local tag = screen.tags[i]
|
||||||
|
if tag then
|
||||||
|
awful.tag.viewtoggle(tag)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "toggle tag #" .. i, group = "tag"}),
|
||||||
|
-- Move client to tag.
|
||||||
|
awful.key({ modkey, "Shift" }, "#" .. i + 9,
|
||||||
|
function ()
|
||||||
|
if client.focus then
|
||||||
|
local tag = client.focus.screen.tags[i]
|
||||||
|
if tag then
|
||||||
|
client.focus:move_to_tag(tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "move focused client to tag #"..i, group = "tag"}),
|
||||||
|
-- Toggle tag on focused client.
|
||||||
|
awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
|
||||||
|
function ()
|
||||||
|
if client.focus then
|
||||||
|
local tag = client.focus.screen.tags[i]
|
||||||
|
if tag then
|
||||||
|
client.focus:toggle_tag(tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "toggle focused client on tag #" .. i, group = "tag"})
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
clientbuttons = gears.table.join(
|
||||||
|
awful.button({ }, 1, function (c)
|
||||||
|
c:emit_signal("request::activate", "mouse_click", {raise = true})
|
||||||
|
end),
|
||||||
|
awful.button({ modkey }, 1, function (c)
|
||||||
|
c:emit_signal("request::activate", "mouse_click", {raise = true})
|
||||||
|
awful.mouse.client.move(c)
|
||||||
|
end),
|
||||||
|
awful.button({ modkey }, 3, function (c)
|
||||||
|
c:emit_signal("request::activate", "mouse_click", {raise = true})
|
||||||
|
awful.mouse.client.resize(c)
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Set keys
|
||||||
|
root.keys(globalkeys)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Rules
|
||||||
|
-- Rules to apply to new clients (through the "manage" signal).
|
||||||
|
awful.rules.rules = {
|
||||||
|
-- All clients will match this rule.
|
||||||
|
{ rule = { },
|
||||||
|
properties = { border_width = beautiful.border_width,
|
||||||
|
border_color = beautiful.border_normal,
|
||||||
|
focus = awful.client.focus.filter,
|
||||||
|
raise = true,
|
||||||
|
keys = clientkeys,
|
||||||
|
buttons = clientbuttons,
|
||||||
|
screen = awful.screen.preferred,
|
||||||
|
placement = awful.placement.no_overlap+awful.placement.no_offscreen
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Floating clients.
|
||||||
|
{ rule_any = {
|
||||||
|
instance = {
|
||||||
|
"DTA", -- Firefox addon DownThemAll.
|
||||||
|
"copyq", -- Includes session name in class.
|
||||||
|
"pinentry",
|
||||||
|
},
|
||||||
|
class = {
|
||||||
|
"Arandr",
|
||||||
|
"Blueman-manager",
|
||||||
|
"Gpick",
|
||||||
|
"Kruler",
|
||||||
|
"MessageWin", -- kalarm.
|
||||||
|
"Sxiv",
|
||||||
|
"Tor Browser", -- Needs a fixed window size to avoid fingerprinting by screen size.
|
||||||
|
"Wpa_gui",
|
||||||
|
"veromix",
|
||||||
|
"xtightvncviewer"},
|
||||||
|
|
||||||
|
-- Note that the name property shown in xprop might be set slightly after creation of the client
|
||||||
|
-- and the name shown there might not match defined rules here.
|
||||||
|
name = {
|
||||||
|
"Event Tester", -- xev.
|
||||||
|
},
|
||||||
|
role = {
|
||||||
|
"AlarmWindow", -- Thunderbird's calendar.
|
||||||
|
"ConfigManager", -- Thunderbird's about:config.
|
||||||
|
"pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
|
||||||
|
}
|
||||||
|
}, properties = { floating = false }},
|
||||||
|
|
||||||
|
-- Add titlebars to normal clients and dialogs
|
||||||
|
{ rule_any = {type = { "normal", "dialog" }
|
||||||
|
}, properties = { titlebars_enabled = false }
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Set Firefox to always map on the tag named "2" on screen 1.
|
||||||
|
-- { rule = { class = "Firefox" },
|
||||||
|
-- properties = { screen = 1, tag = "2" } },
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Signals
|
||||||
|
-- Signal function to execute when a new client appears.
|
||||||
|
client.connect_signal("manage", function (c)
|
||||||
|
-- Set the windows at the slave,
|
||||||
|
-- i.e. put it at the end of others instead of setting it master.
|
||||||
|
-- if not awesome.startup then awful.client.setslave(c) end
|
||||||
|
|
||||||
|
if awesome.startup
|
||||||
|
and not c.size_hints.user_position
|
||||||
|
and not c.size_hints.program_position then
|
||||||
|
-- Prevent clients from being unreachable after screen count changes.
|
||||||
|
awful.placement.no_offscreen(c)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Add a titlebar if titlebars_enabled is set to true in the rules.
|
||||||
|
client.connect_signal("request::titlebars", function(c)
|
||||||
|
-- buttons for the titlebar
|
||||||
|
local buttons = gears.table.join(
|
||||||
|
awful.button({ }, 1, function()
|
||||||
|
c:emit_signal("request::activate", "titlebar", {raise = true})
|
||||||
|
awful.mouse.client.move(c)
|
||||||
|
end),
|
||||||
|
awful.button({ }, 3, function()
|
||||||
|
c:emit_signal("request::activate", "titlebar", {raise = true})
|
||||||
|
awful.mouse.client.resize(c)
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
awful.titlebar(c) : setup {
|
||||||
|
{ -- Left
|
||||||
|
awful.titlebar.widget.iconwidget(c),
|
||||||
|
buttons = buttons,
|
||||||
|
layout = wibox.layout.fixed.horizontal
|
||||||
|
},
|
||||||
|
{ -- Middle
|
||||||
|
{ -- Title
|
||||||
|
align = "center",
|
||||||
|
widget = awful.titlebar.widget.titlewidget(c)
|
||||||
|
},
|
||||||
|
buttons = buttons,
|
||||||
|
layout = wibox.layout.flex.horizontal
|
||||||
|
},
|
||||||
|
{ -- Right
|
||||||
|
awful.titlebar.widget.floatingbutton (c),
|
||||||
|
awful.titlebar.widget.maximizedbutton(c),
|
||||||
|
awful.titlebar.widget.stickybutton (c),
|
||||||
|
awful.titlebar.widget.ontopbutton (c),
|
||||||
|
awful.titlebar.widget.closebutton (c),
|
||||||
|
layout = wibox.layout.fixed.horizontal()
|
||||||
|
},
|
||||||
|
layout = wibox.layout.align.horizontal
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
--client.connect_signal("property::floating", function(c)
|
||||||
|
-- if c.floating then
|
||||||
|
-- awful.titlebar.show(c)
|
||||||
|
-- else
|
||||||
|
-- awful.titlebar.hide(c)
|
||||||
|
-- end
|
||||||
|
-- end)
|
||||||
|
|
||||||
|
-- Enable sloppy focus, so that focus follows mouse.
|
||||||
|
client.connect_signal("mouse::enter", function(c)
|
||||||
|
c:emit_signal("request::activate", "mouse_enter", {raise = false})
|
||||||
|
end)
|
||||||
|
|
||||||
|
client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
|
||||||
|
client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
|
||||||
|
-- }}}
|
628
rc.lua.save
Normal file
@ -0,0 +1,628 @@
|
|||||||
|
-- If LuaRocks is installed, make sure that packages installed through it are
|
||||||
|
-- found (e.g. lgi). If LuaRocks is not installed, do nothing.
|
||||||
|
pcall(require, "luarocks.loader")
|
||||||
|
|
||||||
|
-- Standard awesome library
|
||||||
|
local gears = require("gears")
|
||||||
|
local awful = require("awful")
|
||||||
|
require("awful.autofocus")
|
||||||
|
-- Widget and layout library
|
||||||
|
local wibox = require("wibox")
|
||||||
|
-- Theme handling library
|
||||||
|
local beautiful = require("beautiful")
|
||||||
|
-- Notification library
|
||||||
|
local naughty = require("naughty")
|
||||||
|
local menubar = require("menubar")
|
||||||
|
local hotkeys_popup = require("awful.hotkeys_popup")
|
||||||
|
-- Enable hotkeys help widget for VIM and other apps
|
||||||
|
-- when client with a matching name is opened:
|
||||||
|
require("awful.hotkeys_popup.keys")
|
||||||
|
|
||||||
|
-- My custom libs
|
||||||
|
local vicious = require("vicious")
|
||||||
|
|
||||||
|
-- {{{ Error handling
|
||||||
|
-- Check if awesome encountered an error during startup and fell back to
|
||||||
|
-- another config (This code will only ever execute for the fallback config)
|
||||||
|
if awesome.startup_errors then
|
||||||
|
naughty.notify({ preset = naughty.config.presets.critical,
|
||||||
|
title = "Oops, there were errors during startup!",
|
||||||
|
text = awesome.startup_errors })
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle runtime errors after startup
|
||||||
|
do
|
||||||
|
local in_error = false
|
||||||
|
awesome.connect_signal("debug::error", function (err)
|
||||||
|
-- Make sure we don't go into an endless error loop
|
||||||
|
if in_error then return end
|
||||||
|
in_error = true
|
||||||
|
|
||||||
|
naughty.notify({ preset = naughty.config.presets.critical,
|
||||||
|
title = "Oops, an error happened!",
|
||||||
|
text = tostring(err) })
|
||||||
|
in_error = false
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Variable definitions
|
||||||
|
-- Themes define colours, icons, font and wallpapers.
|
||||||
|
beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
|
||||||
|
beautiful.font = "Indie Flower Bold 12"
|
||||||
|
|
||||||
|
-- This is used later as the default terminal and editor to run.
|
||||||
|
terminal = "konsole"
|
||||||
|
editor = os.getenv("EDITOR") or "nano"
|
||||||
|
editor_cmd = terminal .. " -e " .. editor
|
||||||
|
|
||||||
|
-- Default modkey.
|
||||||
|
-- Usually, Mod4 is the key with a logo between Control and Alt.
|
||||||
|
-- If you do not like this or do not have such a key,
|
||||||
|
-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
|
||||||
|
-- However, you can use another modifier like Mod1, but it may interact with others.
|
||||||
|
modkey = "Mod4"
|
||||||
|
|
||||||
|
-- Table of layouts to cover with awful.layout.inc, order matters.
|
||||||
|
awful.layout.layouts = {
|
||||||
|
awful.layout.suit.floating,
|
||||||
|
awful.layout.suit.tile,
|
||||||
|
awful.layout.suit.tile.left,
|
||||||
|
awful.layout.suit.tile.bottom,
|
||||||
|
awful.layout.suit.tile.top,
|
||||||
|
awful.layout.suit.fair,
|
||||||
|
awful.layout.suit.fair.horizontal,
|
||||||
|
awful.layout.suit.spiral,
|
||||||
|
awful.layout.suit.spiral.dwindle,
|
||||||
|
awful.layout.suit.max,
|
||||||
|
awful.layout.suit.max.fullscreen,
|
||||||
|
awful.layout.suit.magnifier,
|
||||||
|
awful.layout.suit.corner.nw,
|
||||||
|
-- awful.layout.suit.corner.ne,
|
||||||
|
-- awful.layout.suit.corner.sw,
|
||||||
|
-- awful.layout.suit.corner.se,
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Menu
|
||||||
|
-- Create a launcher widget and a main menu
|
||||||
|
myawesomemenu = {
|
||||||
|
{ "hotkeys", function() hotkeys_popup.show_help(nil, awful.screen.focused()) end },
|
||||||
|
{ "manual", terminal .. " -e man awesome" },
|
||||||
|
{ "edit config", editor_cmd .. " " .. awesome.conffile },
|
||||||
|
{ "restart", awesome.restart },
|
||||||
|
{ "quit", function() awesome.quit() end },
|
||||||
|
}
|
||||||
|
|
||||||
|
mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
|
||||||
|
{ "open terminal", terminal }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
|
||||||
|
menu = mymainmenu })
|
||||||
|
|
||||||
|
-- Menubar configuration
|
||||||
|
menubar.utils.terminal = terminal -- Set the terminal for applications that require it
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- Keyboard map indicator and switcher
|
||||||
|
mykeyboardlayout = awful.widget.keyboardlayout()
|
||||||
|
|
||||||
|
-- {{{ Wibar
|
||||||
|
|
||||||
|
-- Create a wibox for each screen and add it
|
||||||
|
local taglist_buttons = gears.table.join(
|
||||||
|
awful.button({ }, 1, function(t) t:view_only() end),
|
||||||
|
awful.button({ modkey }, 1, function(t)
|
||||||
|
if client.focus then
|
||||||
|
client.focus:move_to_tag(t)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
awful.button({ }, 3, awful.tag.viewtoggle),
|
||||||
|
awful.button({ modkey }, 3, function(t)
|
||||||
|
if client.focus then
|
||||||
|
client.focus:toggle_tag(t)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
|
||||||
|
awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
|
||||||
|
)
|
||||||
|
|
||||||
|
local tasklist_buttons = gears.table.join(
|
||||||
|
awful.button({ }, 1, function (c)
|
||||||
|
if c == client.focus then
|
||||||
|
c.minimized = true
|
||||||
|
else
|
||||||
|
c:emit_signal(
|
||||||
|
"request::activate",
|
||||||
|
"tasklist",
|
||||||
|
{raise = true}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
awful.button({ }, 3, function()
|
||||||
|
awful.menu.client_list({ theme = { width = 250 } })
|
||||||
|
end),
|
||||||
|
awful.button({ }, 4, function ()
|
||||||
|
awful.client.focus.byidx(1)
|
||||||
|
end),
|
||||||
|
awful.button({ }, 5, function ()
|
||||||
|
awful.client.focus.byidx(-1)
|
||||||
|
end))
|
||||||
|
|
||||||
|
local function set_wallpaper(s)
|
||||||
|
-- Wallpaper
|
||||||
|
if beautiful.wallpaper then
|
||||||
|
local wallpaper = beautiful.wallpaper
|
||||||
|
-- If wallpaper is a function, call it with the screen
|
||||||
|
if type(wallpaper) == "function" then
|
||||||
|
wallpaper = wallpaper(s)
|
||||||
|
end
|
||||||
|
gears.wallpaper.maximized(wallpaper, s, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
datewidget = wibox.widget.textbox()
|
||||||
|
vicious.register(datewidget, vicious.widgets.date, "%b %d, %R ")
|
||||||
|
|
||||||
|
--memwidget = wibox.widget.textbox()
|
||||||
|
--vicious.cache(vicious.widgets.mem)
|
||||||
|
--vicious.register(memwidget, vicious.widgets.mem, " $2/$3 $1% $6/$7 $5% ", 1)
|
||||||
|
|
||||||
|
batwidget = wibox.widget.progressbar()
|
||||||
|
|
||||||
|
-- Create wibox with batwidget
|
||||||
|
batbox = wibox.layout.margin(
|
||||||
|
wibox.widget{ { max_value = 1, widget = batwidget,
|
||||||
|
border_width = 0.5, border_color = "#000000",
|
||||||
|
color = { type = "linear",
|
||||||
|
from = { 0, 0 },
|
||||||
|
to = { 0, 30 },
|
||||||
|
stops = { { 0, "#AECF96" },
|
||||||
|
{ 1, "#FF5656" } } } },
|
||||||
|
forced_height = 10, forced_width = 8,
|
||||||
|
direction = 'east', color = beautiful.fg_widget,
|
||||||
|
layout = wibox.container.rotate },
|
||||||
|
1, 4, 1, 1)
|
||||||
|
|
||||||
|
-- Register battery widget
|
||||||
|
vicious.register(batwidget, vicious.widgets.bat, "$2", 1, "BAT0")
|
||||||
|
|
||||||
|
|
||||||
|
cpuwidget = awful.widget.graph()
|
||||||
|
cpuwidget:set_width(50)
|
||||||
|
cpuwidget:set_background_color"#494B4F"
|
||||||
|
cpuwidget:set_color{ type = "linear", from = { 0, 0 }, to = { 50, 0 },
|
||||||
|
stops = { { 0, "#FF5656" },
|
||||||
|
{ 0.5, "#88A175" },
|
||||||
|
{ 1, "#AECF96" } } }
|
||||||
|
vicious.register(cpuwidget, vicious.widgets.cpu, "$1", 1)
|
||||||
|
|
||||||
|
memwidget = awful.widget.graph()
|
||||||
|
memwidget:set_width(50)
|
||||||
|
memwidget:set_background_color"#494B4F"
|
||||||
|
memwidget:set_color{ type = "linear", from = { 0, 0 }, to = { 50, 0 },
|
||||||
|
stops = { { 0, "#FF5656" },
|
||||||
|
{ 0.5, "#88A175" },
|
||||||
|
{ 1, "#AECF96" } } }
|
||||||
|
vicious.register(memwidget, vicious.widgets.mem, "$1", 1)
|
||||||
|
|
||||||
|
swapwidget = awful.widget.graph()
|
||||||
|
swapwidget:set_width(50)
|
||||||
|
swapwidget:set_background_color"#494B4F"
|
||||||
|
swapwidget:set_color{ type = "linear", from = { 0, 0 }, to = { 50, 0 },
|
||||||
|
stops = { { 0, "#FF5656" },
|
||||||
|
{ 0.5, "#88A175" },
|
||||||
|
{ 1, "#AECF96" } } }
|
||||||
|
vicious.register(swapwidget, vicious.widgets.mem, "$5", 1)
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
|
||||||
|
screen.connect_signal("property::geometry", set_wallpaper)
|
||||||
|
|
||||||
|
awful.screen.connect_for_each_screen(function(s)
|
||||||
|
-- Wallpaper
|
||||||
|
set_wallpaper(s)
|
||||||
|
|
||||||
|
-- Each screen has its own tag table.
|
||||||
|
awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])
|
||||||
|
|
||||||
|
-- Create a promptbox for each screen
|
||||||
|
s.mypromptbox = awful.widget.prompt()
|
||||||
|
-- Create an imagebox widget which will contain an icon indicating which layout we're using.
|
||||||
|
-- We need one layoutbox per screen.
|
||||||
|
s.mylayoutbox = awful.widget.layoutbox(s)
|
||||||
|
s.mylayoutbox:buttons(gears.table.join(
|
||||||
|
awful.button({ }, 1, function () awful.layout.inc( 1) end),
|
||||||
|
awful.button({ }, 3, function () awful.layout.inc(-1) end),
|
||||||
|
awful.button({ }, 4, function () awful.layout.inc( 1) end),
|
||||||
|
awful.button({ }, 5, function () awful.layout.inc(-1) end)))
|
||||||
|
-- Create a taglist widget
|
||||||
|
s.mytaglist = awful.widget.taglist {
|
||||||
|
screen = s,
|
||||||
|
filter = awful.widget.taglist.filter.all,
|
||||||
|
buttons = taglist_buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Create a tasklist widget
|
||||||
|
s.mytasklist = awful.widget.tasklist {
|
||||||
|
screen = s,
|
||||||
|
filter = awful.widget.tasklist.filter.currenttags,
|
||||||
|
buttons = tasklist_buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Create the wibox
|
||||||
|
s.mywibox = awful.wibar({ position = "top", screen = s })
|
||||||
|
|
||||||
|
-- Add widgets to the wibox
|
||||||
|
s.mywibox:setup {
|
||||||
|
layout = wibox.layout.align.horizontal,
|
||||||
|
{ -- Left widgets
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
mylauncher,
|
||||||
|
s.mytaglist,
|
||||||
|
s.mypromptbox,
|
||||||
|
},
|
||||||
|
s.mytasklist, -- Middle widget
|
||||||
|
{ -- Right widgets
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
wibox.widget.systray(),
|
||||||
|
memwidget,
|
||||||
|
swapwidget,
|
||||||
|
cpuwidget,
|
||||||
|
mykeyboardlayout,
|
||||||
|
datewidget,
|
||||||
|
batbox,
|
||||||
|
s.mylayoutbox,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Mouse bindings
|
||||||
|
root.buttons(gears.table.join(
|
||||||
|
awful.button({ }, 3, function () mymainmenu:toggle() end),
|
||||||
|
awful.button({ }, 4, awful.tag.viewnext),
|
||||||
|
awful.button({ }, 5, awful.tag.viewprev)
|
||||||
|
))
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Key bindings
|
||||||
|
globalkeys = gears.table.join(
|
||||||
|
awful.key({ modkey, }, "s", hotkeys_popup.show_help,
|
||||||
|
{description="show help", group="awesome"}),
|
||||||
|
awful.key({ modkey, }, "Left", awful.tag.viewprev,
|
||||||
|
{description = "view previous", group = "tag"}),
|
||||||
|
awful.key({ modkey, }, "Right", awful.tag.viewnext,
|
||||||
|
{description = "view next", group = "tag"}),
|
||||||
|
awful.key({ modkey, }, "Escape", awful.tag.history.restore,
|
||||||
|
{description = "go back", group = "tag"}),
|
||||||
|
|
||||||
|
awful.key({ modkey, }, "j",
|
||||||
|
function ()
|
||||||
|
awful.client.focus.byidx( 1)
|
||||||
|
end,
|
||||||
|
{description = "focus next by index", group = "client"}
|
||||||
|
),
|
||||||
|
awful.key({ modkey, }, "k",
|
||||||
|
function ()
|
||||||
|
awful.client.focus.byidx(-1)
|
||||||
|
end,
|
||||||
|
{description = "focus previous by index", group = "client"}
|
||||||
|
),
|
||||||
|
awful.key({ modkey, }, "w", function () mymainmenu:show() end,
|
||||||
|
{description = "show main menu", group = "awesome"}),
|
||||||
|
|
||||||
|
-- Layout manipulation
|
||||||
|
awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
|
||||||
|
{description = "swap with next client by index", group = "client"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
|
||||||
|
{description = "swap with previous client by index", group = "client"}),
|
||||||
|
awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
|
||||||
|
{description = "focus the next screen", group = "screen"}),
|
||||||
|
awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
|
||||||
|
{description = "focus the previous screen", group = "screen"}),
|
||||||
|
awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
|
||||||
|
{description = "jump to urgent client", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "Tab",
|
||||||
|
function ()
|
||||||
|
awful.client.focus.history.previous()
|
||||||
|
if client.focus then
|
||||||
|
client.focus:raise()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "go back", group = "client"}),
|
||||||
|
|
||||||
|
-- Standard program
|
||||||
|
awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
|
||||||
|
{description = "open a terminal", group = "launcher"}),
|
||||||
|
awful.key({ modkey, "Control" }, "r", awesome.restart,
|
||||||
|
{description = "reload awesome", group = "awesome"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "q", awesome.quit,
|
||||||
|
{description = "quit awesome", group = "awesome"}),
|
||||||
|
|
||||||
|
awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
|
||||||
|
{description = "increase master width factor", group = "layout"}),
|
||||||
|
awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
|
||||||
|
{description = "decrease master width factor", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
|
||||||
|
{description = "increase the number of master clients", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
|
||||||
|
{description = "decrease the number of master clients", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
|
||||||
|
{description = "increase the number of columns", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
|
||||||
|
{description = "decrease the number of columns", group = "layout"}),
|
||||||
|
awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
|
||||||
|
{description = "select next", group = "layout"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
|
||||||
|
{description = "select previous", group = "layout"}),
|
||||||
|
|
||||||
|
awful.key({ modkey, "Control" }, "n",
|
||||||
|
function ()
|
||||||
|
local c = awful.client.restore()
|
||||||
|
-- Focus restored client
|
||||||
|
if c then
|
||||||
|
c:emit_signal(
|
||||||
|
"request::activate", "key.unminimize", {raise = true}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "restore minimized", group = "client"}),
|
||||||
|
|
||||||
|
-- Prompt
|
||||||
|
awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end,
|
||||||
|
{description = "run prompt", group = "launcher"}),
|
||||||
|
|
||||||
|
awful.key({ modkey }, "x",
|
||||||
|
function ()
|
||||||
|
awful.prompt.run {
|
||||||
|
prompt = "Run Lua code: ",
|
||||||
|
textbox = awful.screen.focused().mypromptbox.widget,
|
||||||
|
exe_callback = awful.util.eval,
|
||||||
|
history_path = awful.util.get_cache_dir() .. "/history_eval"
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
{description = "lua execute prompt", group = "awesome"}),
|
||||||
|
-- Menubar
|
||||||
|
awful.key({ modkey }, "p", function() menubar.show() end,
|
||||||
|
{description = "show the menubar", group = "launcher"})
|
||||||
|
)
|
||||||
|
|
||||||
|
clientkeys = gears.table.join(
|
||||||
|
awful.key({ modkey, }, "f",
|
||||||
|
function (c)
|
||||||
|
c.fullscreen = not c.fullscreen
|
||||||
|
c:raise()
|
||||||
|
end,
|
||||||
|
{description = "toggle fullscreen", group = "client"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
|
||||||
|
{description = "close", group = "client"}),
|
||||||
|
awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
|
||||||
|
{description = "toggle floating", group = "client"}),
|
||||||
|
awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
|
||||||
|
{description = "move to master", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
|
||||||
|
{description = "move to screen", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
|
||||||
|
{description = "toggle keep on top", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "n",
|
||||||
|
function (c)
|
||||||
|
-- The client currently has the input focus, so it cannot be
|
||||||
|
-- minimized, since minimized clients can't have the focus.
|
||||||
|
c.minimized = true
|
||||||
|
end ,
|
||||||
|
{description = "minimize", group = "client"}),
|
||||||
|
awful.key({ modkey, }, "m",
|
||||||
|
function (c)
|
||||||
|
c.maximized = not c.maximized
|
||||||
|
c:raise()
|
||||||
|
end ,
|
||||||
|
{description = "(un)maximize", group = "client"}),
|
||||||
|
awful.key({ modkey, "Control" }, "m",
|
||||||
|
function (c)
|
||||||
|
c.maximized_vertical = not c.maximized_vertical
|
||||||
|
c:raise()
|
||||||
|
end ,
|
||||||
|
{description = "(un)maximize vertically", group = "client"}),
|
||||||
|
awful.key({ modkey, "Shift" }, "m",
|
||||||
|
function (c)
|
||||||
|
c.maximized_horizontal = not c.maximized_horizontal
|
||||||
|
c:raise()
|
||||||
|
end ,
|
||||||
|
{description = "(un)maximize horizontally", group = "client"})
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Bind all key numbers to tags.
|
||||||
|
-- Be careful: we use keycodes to make it work on any keyboard layout.
|
||||||
|
-- This should map on the top row of your keyboard, usually 1 to 9.
|
||||||
|
for i = 1, 9 do
|
||||||
|
globalkeys = gears.table.join(globalkeys,
|
||||||
|
-- View tag only.
|
||||||
|
awful.key({ modkey }, "#" .. i + 9,
|
||||||
|
function ()
|
||||||
|
local screen = awful.screen.focused()
|
||||||
|
local tag = screen.tags[i]
|
||||||
|
if tag then
|
||||||
|
tag:view_only()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "view tag #"..i, group = "tag"}),
|
||||||
|
-- Toggle tag display.
|
||||||
|
awful.key({ modkey, "Control" }, "#" .. i + 9,
|
||||||
|
function ()
|
||||||
|
local screen = awful.screen.focused()
|
||||||
|
local tag = screen.tags[i]
|
||||||
|
if tag then
|
||||||
|
awful.tag.viewtoggle(tag)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "toggle tag #" .. i, group = "tag"}),
|
||||||
|
-- Move client to tag.
|
||||||
|
awful.key({ modkey, "Shift" }, "#" .. i + 9,
|
||||||
|
function ()
|
||||||
|
if client.focus then
|
||||||
|
local tag = client.focus.screen.tags[i]
|
||||||
|
if tag then
|
||||||
|
client.focus:move_to_tag(tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "move focused client to tag #"..i, group = "tag"}),
|
||||||
|
-- Toggle tag on focused client.
|
||||||
|
awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
|
||||||
|
function ()
|
||||||
|
if client.focus then
|
||||||
|
local tag = client.focus.screen.tags[i]
|
||||||
|
if tag then
|
||||||
|
client.focus:toggle_tag(tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{description = "toggle focused client on tag #" .. i, group = "tag"})
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
clientbuttons = gears.table.join(
|
||||||
|
awful.button({ }, 1, function (c)
|
||||||
|
c:emit_signal("request::activate", "mouse_click", {raise = true})
|
||||||
|
end),
|
||||||
|
awful.button({ modkey }, 1, function (c)
|
||||||
|
c:emit_signal("request::activate", "mouse_click", {raise = true})
|
||||||
|
awful.mouse.client.move(c)
|
||||||
|
end),
|
||||||
|
awful.button({ modkey }, 3, function (c)
|
||||||
|
c:emit_signal("request::activate", "mouse_click", {raise = true})
|
||||||
|
awful.mouse.client.resize(c)
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Set keys
|
||||||
|
root.keys(globalkeys)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Rules
|
||||||
|
-- Rules to apply to new clients (through the "manage" signal).
|
||||||
|
awful.rules.rules = {
|
||||||
|
-- All clients will match this rule.
|
||||||
|
{ rule = { },
|
||||||
|
properties = { border_width = beautiful.border_width,
|
||||||
|
border_color = beautiful.border_normal,
|
||||||
|
focus = awful.client.focus.filter,
|
||||||
|
raise = true,
|
||||||
|
keys = clientkeys,
|
||||||
|
buttons = clientbuttons,
|
||||||
|
screen = awful.screen.preferred,
|
||||||
|
placement = awful.placement.no_overlap+awful.placement.no_offscreen
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Floating clients.
|
||||||
|
{ rule_any = {
|
||||||
|
instance = {
|
||||||
|
"DTA", -- Firefox addon DownThemAll.
|
||||||
|
"copyq", -- Includes session name in class.
|
||||||
|
"pinentry",
|
||||||
|
},
|
||||||
|
class = {
|
||||||
|
"Arandr",
|
||||||
|
"Blueman-manager",
|
||||||
|
"Gpick",
|
||||||
|
"Kruler",
|
||||||
|
"MessageWin", -- kalarm.
|
||||||
|
"Sxiv",
|
||||||
|
"Tor Browser", -- Needs a fixed window size to avoid fingerprinting by screen size.
|
||||||
|
"Wpa_gui",
|
||||||
|
"veromix",
|
||||||
|
"xtightvncviewer"},
|
||||||
|
|
||||||
|
-- Note that the name property shown in xprop might be set slightly after creation of the client
|
||||||
|
-- and the name shown there might not match defined rules here.
|
||||||
|
name = {
|
||||||
|
"Event Tester", -- xev.
|
||||||
|
},
|
||||||
|
role = {
|
||||||
|
"AlarmWindow", -- Thunderbird's calendar.
|
||||||
|
"ConfigManager", -- Thunderbird's about:config.
|
||||||
|
"pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
|
||||||
|
}
|
||||||
|
}, properties = { floating = true }},
|
||||||
|
|
||||||
|
-- Add titlebars to normal clients and dialogs
|
||||||
|
{ rule_any = {type = { "normal", "dialog" }
|
||||||
|
}, properties = { titlebars_enabled = true }
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Set Firefox to always map on the tag named "2" on screen 1.
|
||||||
|
-- { rule = { class = "Firefox" },
|
||||||
|
-- properties = { screen = 1, tag = "2" } },
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Signals
|
||||||
|
-- Signal function to execute when a new client appears.
|
||||||
|
client.connect_signal("manage", function (c)
|
||||||
|
-- Set the windows at the slave,
|
||||||
|
-- i.e. put it at the end of others instead of setting it master.
|
||||||
|
-- if not awesome.startup then awful.client.setslave(c) end
|
||||||
|
|
||||||
|
if awesome.startup
|
||||||
|
and not c.size_hints.user_position
|
||||||
|
and not c.size_hints.program_position then
|
||||||
|
-- Prevent clients from being unreachable after screen count changes.
|
||||||
|
awful.placement.no_offscreen(c)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Add a titlebar if titlebars_enabled is set to true in the rules.
|
||||||
|
client.connect_signal("request::titlebars", function(c)
|
||||||
|
-- buttons for the titlebar
|
||||||
|
local buttons = gears.table.join(
|
||||||
|
awful.button({ }, 1, function()
|
||||||
|
c:emit_signal("request::activate", "titlebar", {raise = true})
|
||||||
|
awful.mouse.client.move(c)
|
||||||
|
end),
|
||||||
|
awful.button({ }, 3, function()
|
||||||
|
c:emit_signal("request::activate", "titlebar", {raise = true})
|
||||||
|
awful.mouse.client.resize(c)
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
|
||||||
|
awful.titlebar(c) : setup {
|
||||||
|
{ -- Left
|
||||||
|
awful.titlebar.widget.iconwidget(c),
|
||||||
|
buttons = buttons,
|
||||||
|
layout = wibox.layout.fixed.horizontal
|
||||||
|
},
|
||||||
|
{ -- Middle
|
||||||
|
{ -- Title
|
||||||
|
align = "center",
|
||||||
|
widget = awful.titlebar.widget.titlewidget(c)
|
||||||
|
},
|
||||||
|
buttons = buttons,
|
||||||
|
layout = wibox.layout.flex.horizontal
|
||||||
|
},
|
||||||
|
{ -- Right
|
||||||
|
awful.titlebar.widget.floatingbutton (c),
|
||||||
|
awful.titlebar.widget.maximizedbutton(c),
|
||||||
|
awful.titlebar.widget.stickybutton (c),
|
||||||
|
awful.titlebar.widget.ontopbutton (c),
|
||||||
|
awful.titlebar.widget.closebutton (c),
|
||||||
|
layout = wibox.layout.fixed.horizontal()
|
||||||
|
},
|
||||||
|
layout = wibox.layout.align.horizontal
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Enable sloppy focus, so that focus follows mouse.
|
||||||
|
client.connect_signal("mouse::enter", function(c)
|
||||||
|
c:emit_signal("request::activate", "mouse_enter", {raise = false})
|
||||||
|
end)
|
||||||
|
|
||||||
|
client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
|
||||||
|
client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
|
||||||
|
-- }}}
|
88
spawn.lua
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
-- wrapper around Awesome awful.spawn with fallback
|
||||||
|
-- Copyright (C) 2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
local status, awful = pcall(require, "awful")
|
||||||
|
if status then
|
||||||
|
local spawn = awful.spawn
|
||||||
|
function spawn.with_line_callback_with_shell(cmd, callbacks)
|
||||||
|
spawn.with_line_callback({ awful.util.shell, "-c", cmd }, callbacks)
|
||||||
|
end
|
||||||
|
return spawn
|
||||||
|
end
|
||||||
|
|
||||||
|
local io = { popen = io.popen }
|
||||||
|
|
||||||
|
-- In case the Awesome library is not available,
|
||||||
|
-- fall back to this synchronous, handicapped API.
|
||||||
|
local spawn = {}
|
||||||
|
|
||||||
|
--- Spawn a program and capture its output line by line.
|
||||||
|
-- @tparam string cmd The command.
|
||||||
|
-- @tab callbacks Table containing callbacks that should be invoked on
|
||||||
|
-- various conditions.
|
||||||
|
-- @tparam[opt] function callbacks.stdout Function that is called with each
|
||||||
|
-- line of output on stdout, e.g. `stdout(line)`.
|
||||||
|
-- @tparam[opt] function callbacks.stderr Function that is supposed to be called
|
||||||
|
-- with each line of output on stderr, but due to limitation of io.popen,
|
||||||
|
-- stderr will be discarded (sorry!).
|
||||||
|
-- @tparam[opt] function callbacks.output_done Function to call when no more
|
||||||
|
-- output is produced.
|
||||||
|
-- @tparam[opt] function callbacks.exit Function to call when the spawned
|
||||||
|
-- process exits. This function gets the exit reason and code as its
|
||||||
|
-- arguments.
|
||||||
|
-- The reason can be "exit" or "signal".
|
||||||
|
-- For "exit", the second argument is the exit code.
|
||||||
|
-- For "signal", the second argument is the signal causing process
|
||||||
|
-- termination.
|
||||||
|
-- @treturn boolean|nil true if cmd terminated successfully, or nil otherwise
|
||||||
|
function spawn.with_line_callback_with_shell(cmd, callbacks)
|
||||||
|
local stdout_callback, stdout = callbacks.stdout, io.popen(cmd)
|
||||||
|
if stdout_callback then
|
||||||
|
for line in stdout:lines() do stdout_callback(line) end
|
||||||
|
end
|
||||||
|
if callbacks.output_done then callbacks.output_done() end
|
||||||
|
|
||||||
|
local success, reason, code = stdout:close() -- this requires Lua 5.2
|
||||||
|
if callbacks.exit then callbacks.exit(reason, code) end
|
||||||
|
return success
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Spawn a program and capture its output.
|
||||||
|
-- @tparam string cmd The command.
|
||||||
|
-- @tab callback Function with the following arguments
|
||||||
|
-- @tparam string callback.stdout Output on stdout.
|
||||||
|
-- @tparam string callback.stderr Output on stderr,
|
||||||
|
-- which will be an empty due to limitation of io.popen.
|
||||||
|
-- @tparam string callback.exitreason Exit reason ("exit" or "signal").
|
||||||
|
-- @tparam integer callback.exitcode Exit code (exit code or signal number,
|
||||||
|
-- depending on "exitreason").
|
||||||
|
-- @treturn boolean|nil true if cmd terminated successfully, or nil otherwise
|
||||||
|
function spawn.easy_async_with_shell(cmd, callback)
|
||||||
|
local out_stream = io.popen(cmd)
|
||||||
|
local stdout = out_stream:read("*all")
|
||||||
|
local success, reason, code = out_stream:close() -- requiring Lua 5.2
|
||||||
|
callback(stdout, "", reason, code)
|
||||||
|
return success
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Since io.popen always use a shell
|
||||||
|
spawn.easy_async = spawn.easy_async_with_shell
|
||||||
|
spawn.with_line_callback = spawn.with_line_callback_with_shell
|
||||||
|
|
||||||
|
return spawn
|
||||||
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
48
templates/README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Widget type templates
|
||||||
|
|
||||||
|
Before writing a new widget type, make sure to ask yourself if anyone is going
|
||||||
|
to need the feature. Only widget types that you (or an incapacitated friend
|
||||||
|
you can personally talk to) require would be merged. Do not file PRs because
|
||||||
|
they seem like a good idea. If they're really useful, they'll be requested
|
||||||
|
in the issue tracker.
|
||||||
|
|
||||||
|
Additionally, too simple widget types (e.g. an one-liner) and those that
|
||||||
|
are not modular enough are very unlikely to be merged. By *modular*, we mean
|
||||||
|
|
||||||
|
> constructed with standardized units or dimensions
|
||||||
|
> allowing flexibility and variety in use
|
||||||
|
|
||||||
|
If all the above conditions are met, you can start from one of the templates
|
||||||
|
in this directory:
|
||||||
|
|
||||||
|
* `sync.lua`: synchronous widget type that does not fork
|
||||||
|
* `async.lua`: asynchronous widget type for fetching informations using
|
||||||
|
a command-line utility. As a rule of thumb, if your widget type uses
|
||||||
|
`io.popen`, you would need to refactor it to use async facilities.
|
||||||
|
|
||||||
|
Your widget types should be placed in `widgets`: the `contrib` directory
|
||||||
|
exists only for historical reasons and is barely maintained anymore.
|
||||||
|
The filenames should be of the form `<name>_<platform>.lua`, whereas
|
||||||
|
|
||||||
|
* `<name>` is a single (alphanumeric) word, preferably in lowercase
|
||||||
|
* `<platform>` is the OS that the widget type works on.
|
||||||
|
At the time of writing these are supported:
|
||||||
|
- `freebsd`: FreeBSD
|
||||||
|
- `openbsd`: OpenBSD
|
||||||
|
- `bsd`: all \*BSDs listed above
|
||||||
|
- `linux`: GNU/Linux
|
||||||
|
- `all`: all of the above
|
||||||
|
|
||||||
|
Please be aware of `luacheck`, which may help you during the progress.
|
||||||
|
From `widgets`, run
|
||||||
|
|
||||||
|
luacheck --config .luacheckrc ..
|
||||||
|
|
||||||
|
After finishing the widget type, you should document its usage in the project's
|
||||||
|
`README.md`. Try to provide at least
|
||||||
|
|
||||||
|
* A brief description
|
||||||
|
* The list of supported platforms
|
||||||
|
* Type and structures of the arguments that the widget type passes
|
||||||
|
(`format` and `warg`), with unused parameters omitted
|
||||||
|
* Type and structure of the return value
|
28
templates/async.lua
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-- template for asynchronous widet types
|
||||||
|
-- Copyright (C) 2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
local helpers = require"vicious.helpers"
|
||||||
|
|
||||||
|
return helpers.setasyncall{
|
||||||
|
async = function (format, warg, callback)
|
||||||
|
-- In here there should be some asynchronous function
|
||||||
|
-- from vicious.spawn or helpers.sysctl_async
|
||||||
|
-- that call callback on the result.
|
||||||
|
end }
|
||||||
|
|
||||||
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
25
templates/sync.lua
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
-- template for synchronous widet types
|
||||||
|
-- Copyright (C) 2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
local helpers = require"vicious.helpers"
|
||||||
|
|
||||||
|
return helpers.setcall(function (format, warg)
|
||||||
|
-- Do the processing and return a table here.
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
3
themes/zenburn/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Based on Zenburn
|
||||||
|
|
||||||
|
modified by Surferlul
|
BIN
themes/zenburn/artix_wallpaper.png
Normal file
After Width: | Height: | Size: 2.6 MiB |
BIN
themes/zenburn/layouts/cornerne.png
Normal file
After Width: | Height: | Size: 193 B |
BIN
themes/zenburn/layouts/cornernw.png
Normal file
After Width: | Height: | Size: 190 B |
BIN
themes/zenburn/layouts/cornerse.png
Normal file
After Width: | Height: | Size: 197 B |
BIN
themes/zenburn/layouts/cornersw.png
Normal file
After Width: | Height: | Size: 195 B |
BIN
themes/zenburn/layouts/dwindle.png
Normal file
After Width: | Height: | Size: 196 B |
BIN
themes/zenburn/layouts/fairh.png
Normal file
After Width: | Height: | Size: 191 B |
BIN
themes/zenburn/layouts/fairv.png
Normal file
After Width: | Height: | Size: 193 B |
BIN
themes/zenburn/layouts/floating.png
Normal file
After Width: | Height: | Size: 189 B |
BIN
themes/zenburn/layouts/fullscreen.png
Normal file
After Width: | Height: | Size: 199 B |
BIN
themes/zenburn/layouts/magnifier.png
Normal file
After Width: | Height: | Size: 191 B |
BIN
themes/zenburn/layouts/max.png
Normal file
After Width: | Height: | Size: 271 B |
BIN
themes/zenburn/layouts/spiral.png
Normal file
After Width: | Height: | Size: 196 B |
BIN
themes/zenburn/layouts/tile.png
Normal file
After Width: | Height: | Size: 189 B |
BIN
themes/zenburn/layouts/tilebottom.png
Normal file
After Width: | Height: | Size: 186 B |
BIN
themes/zenburn/layouts/tileleft.png
Normal file
After Width: | Height: | Size: 188 B |
BIN
themes/zenburn/layouts/tiletop.png
Normal file
After Width: | Height: | Size: 186 B |
BIN
themes/zenburn/taglist/squarefz.png
Normal file
After Width: | Height: | Size: 168 B |
BIN
themes/zenburn/taglist/squarez.png
Normal file
After Width: | Height: | Size: 171 B |
158
themes/zenburn/theme.lua
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
----------------------------------------
|
||||||
|
-- "idk what yet" awesome theme --
|
||||||
|
-- By Lukas B. (Surferlul) --
|
||||||
|
-- based on "Zenburn" awesome theme --
|
||||||
|
-- By Adrian C. (anrxc) --
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
local themes_path = require("gears.filesystem").get_themes_dir()
|
||||||
|
local dpi = require("beautiful.xresources").apply_dpi
|
||||||
|
local beautiful = require("beautiful")
|
||||||
|
|
||||||
|
-- {{{ Main
|
||||||
|
local theme = {}
|
||||||
|
theme.wallpaper = "/home/surferlul/.config/awesome/themes/zenburn/artix_wallpaper.png"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
|
||||||
|
-- {{{ Styles
|
||||||
|
theme.font = "sans 8"
|
||||||
|
|
||||||
|
-- {{{ Colors
|
||||||
|
theme.fg_normal = "#EDEDDD"
|
||||||
|
theme.fg_focus = "#F0DFAF"
|
||||||
|
theme.fg_urgent = "#CC9393"
|
||||||
|
theme.bg_normal = "#4A3F9833"
|
||||||
|
theme.bg_focus = "#080811CC"
|
||||||
|
theme.bg_urgent = "#916A9D33"
|
||||||
|
theme.bg_systray = theme.bg_normal
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
theme.hotkeys_bg = "#111122"
|
||||||
|
theme.hotkeys_fg = "#EEEEFF"
|
||||||
|
theme.hotkeys_label_fg = "#111122"
|
||||||
|
theme.hotkeys_modifiers_fg = "#DD7777"
|
||||||
|
theme.hotkeys_description_font = "Indie Flower Bold 10"
|
||||||
|
theme.hotkeys_border_width = 1
|
||||||
|
theme.hotkeys_border_color = "#6f6f6f55"
|
||||||
|
|
||||||
|
theme.menubar_bg_normal = "#11112299"
|
||||||
|
theme.menubar_fg_normal = "#FFBBBB"
|
||||||
|
theme.menubar_bg_focus = "#333344FF"
|
||||||
|
theme.menubar_fg_focus = "#BBBBFF"
|
||||||
|
|
||||||
|
theme.menu_bg_normal = "#11112299"
|
||||||
|
theme.menu_fg_normal = "#FFBBBB"
|
||||||
|
theme.menu_bg_focus = "#333344FF"
|
||||||
|
theme.menu_fg_focus = "#BBBBFF"
|
||||||
|
|
||||||
|
-- {{{ Borders
|
||||||
|
theme.useless_gap = dpi(2)
|
||||||
|
theme.border_width = dpi(1)
|
||||||
|
theme.border_normal = "#6F6F6F55"
|
||||||
|
theme.border_focus = "#6F6F6F55"
|
||||||
|
theme.border_marked = "#CC939355"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Titlebars
|
||||||
|
theme.titlebar_bg_focus = "#3F3F3F"
|
||||||
|
theme.titlebar_bg_normal = "#3F3F3F"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- There are other variable sets
|
||||||
|
-- overriding the default one when
|
||||||
|
-- defined, the sets are:
|
||||||
|
-- [taglist|tasklist]_[bg|fg]_[focus|urgent|occupied|empty|volatile]
|
||||||
|
-- titlebar_[normal|focus]
|
||||||
|
-- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color]
|
||||||
|
-- Example:
|
||||||
|
--theme.taglist_bg_focus = "#CC9393"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Widgets
|
||||||
|
-- You can add as many variables as
|
||||||
|
-- you wish and access them by using
|
||||||
|
-- beautiful.variable in your rc.lua
|
||||||
|
--theme.fg_widget = "#AECF96"
|
||||||
|
--theme.fg_center_widget = "#88A175"
|
||||||
|
--theme.fg_end_widget = "#FF5656"
|
||||||
|
--theme.bg_widget = "#494B4F"
|
||||||
|
--theme.border_widget = "#3F3F3F"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Mouse finder
|
||||||
|
theme.mouse_finder_color = "#CC9393"
|
||||||
|
-- mouse_finder_[timeout|animate_timeout|radius|factor]
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Menu
|
||||||
|
-- Variables set for theming the menu:
|
||||||
|
-- menu_[bg|fg]_[normal|focus]
|
||||||
|
-- menu_[border_color|border_width]
|
||||||
|
theme.menu_height = dpi(15)
|
||||||
|
theme.menu_width = dpi(100)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Icons
|
||||||
|
-- {{{ Taglist
|
||||||
|
theme.taglist_squares_sel = themes_path .. "zenburn/taglist/squarefz.png"
|
||||||
|
theme.taglist_squares_unsel = themes_path .. "zenburn/taglist/squarez.png"
|
||||||
|
--theme.taglist_squares_resize = "false"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Misc
|
||||||
|
theme.awesome_icon = themes_path .. "zenburn/awesome-icon.png"
|
||||||
|
theme.menu_submenu_icon = themes_path .. "default/submenu.png"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Layout
|
||||||
|
theme.layout_tile = themes_path .. "zenburn/layouts/tile.png"
|
||||||
|
theme.layout_tileleft = themes_path .. "zenburn/layouts/tileleft.png"
|
||||||
|
theme.layout_tilebottom = themes_path .. "zenburn/layouts/tilebottom.png"
|
||||||
|
theme.layout_tiletop = themes_path .. "zenburn/layouts/tiletop.png"
|
||||||
|
theme.layout_fairv = themes_path .. "zenburn/layouts/fairv.png"
|
||||||
|
theme.layout_fairh = themes_path .. "zenburn/layouts/fairh.png"
|
||||||
|
theme.layout_spiral = themes_path .. "zenburn/layouts/spiral.png"
|
||||||
|
theme.layout_dwindle = themes_path .. "zenburn/layouts/dwindle.png"
|
||||||
|
theme.layout_max = themes_path .. "zenburn/layouts/max.png"
|
||||||
|
theme.layout_fullscreen = themes_path .. "zenburn/layouts/fullscreen.png"
|
||||||
|
theme.layout_magnifier = themes_path .. "zenburn/layouts/magnifier.png"
|
||||||
|
theme.layout_floating = themes_path .. "zenburn/layouts/floating.png"
|
||||||
|
theme.layout_cornernw = themes_path .. "zenburn/layouts/cornernw.png"
|
||||||
|
theme.layout_cornerne = themes_path .. "zenburn/layouts/cornerne.png"
|
||||||
|
theme.layout_cornersw = themes_path .. "zenburn/layouts/cornersw.png"
|
||||||
|
theme.layout_cornerse = themes_path .. "zenburn/layouts/cornerse.png"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Titlebar
|
||||||
|
theme.titlebar_close_button_focus = themes_path .. "zenburn/titlebar/close_focus.png"
|
||||||
|
theme.titlebar_close_button_normal = themes_path .. "zenburn/titlebar/close_normal.png"
|
||||||
|
|
||||||
|
theme.titlebar_minimize_button_normal = themes_path .. "default/titlebar/minimize_normal.png"
|
||||||
|
theme.titlebar_minimize_button_focus = themes_path .. "default/titlebar/minimize_focus.png"
|
||||||
|
|
||||||
|
theme.titlebar_ontop_button_focus_active = themes_path .. "zenburn/titlebar/ontop_focus_active.png"
|
||||||
|
theme.titlebar_ontop_button_normal_active = themes_path .. "zenburn/titlebar/ontop_normal_active.png"
|
||||||
|
theme.titlebar_ontop_button_focus_inactive = themes_path .. "zenburn/titlebar/ontop_focus_inactive.png"
|
||||||
|
theme.titlebar_ontop_button_normal_inactive = themes_path .. "zenburn/titlebar/ontop_normal_inactive.png"
|
||||||
|
|
||||||
|
theme.titlebar_sticky_button_focus_active = themes_path .. "zenburn/titlebar/sticky_focus_active.png"
|
||||||
|
theme.titlebar_sticky_button_normal_active = themes_path .. "zenburn/titlebar/sticky_normal_active.png"
|
||||||
|
theme.titlebar_sticky_button_focus_inactive = themes_path .. "zenburn/titlebar/sticky_focus_inactive.png"
|
||||||
|
theme.titlebar_sticky_button_normal_inactive = themes_path .. "zenburn/titlebar/sticky_normal_inactive.png"
|
||||||
|
|
||||||
|
theme.titlebar_floating_button_focus_active = themes_path .. "zenburn/titlebar/floating_focus_active.png"
|
||||||
|
theme.titlebar_floating_button_normal_active = themes_path .. "zenburn/titlebar/floating_normal_active.png"
|
||||||
|
theme.titlebar_floating_button_focus_inactive = themes_path .. "zenburn/titlebar/floating_focus_inactive.png"
|
||||||
|
theme.titlebar_floating_button_normal_inactive = themes_path .. "zenburn/titlebar/floating_normal_inactive.png"
|
||||||
|
|
||||||
|
theme.titlebar_maximized_button_focus_active = themes_path .. "zenburn/titlebar/maximized_focus_active.png"
|
||||||
|
theme.titlebar_maximized_button_normal_active = themes_path .. "zenburn/titlebar/maximized_normal_active.png"
|
||||||
|
theme.titlebar_maximized_button_focus_inactive = themes_path .. "zenburn/titlebar/maximized_focus_inactive.png"
|
||||||
|
theme.titlebar_maximized_button_normal_inactive = themes_path .. "zenburn/titlebar/maximized_normal_inactive.png"
|
||||||
|
-- }}}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return theme
|
||||||
|
|
||||||
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
BIN
themes/zenburn/titlebar/close_focus.png
Normal file
After Width: | Height: | Size: 187 B |
BIN
themes/zenburn/titlebar/close_normal.png
Normal file
After Width: | Height: | Size: 116 B |
BIN
themes/zenburn/titlebar/floating_focus_active.png
Normal file
After Width: | Height: | Size: 187 B |
BIN
themes/zenburn/titlebar/floating_focus_inactive.png
Normal file
After Width: | Height: | Size: 112 B |
BIN
themes/zenburn/titlebar/floating_normal_active.png
Normal file
After Width: | Height: | Size: 116 B |
BIN
themes/zenburn/titlebar/floating_normal_inactive.png
Normal file
After Width: | Height: | Size: 90 B |
BIN
themes/zenburn/titlebar/maximized_focus_active.png
Normal file
After Width: | Height: | Size: 196 B |
BIN
themes/zenburn/titlebar/maximized_focus_inactive.png
Normal file
After Width: | Height: | Size: 110 B |
BIN
themes/zenburn/titlebar/maximized_normal_active.png
Normal file
After Width: | Height: | Size: 121 B |
BIN
themes/zenburn/titlebar/maximized_normal_inactive.png
Normal file
After Width: | Height: | Size: 112 B |
BIN
themes/zenburn/titlebar/ontop_focus_active.png
Normal file
After Width: | Height: | Size: 191 B |
BIN
themes/zenburn/titlebar/ontop_focus_inactive.png
Normal file
After Width: | Height: | Size: 106 B |
BIN
themes/zenburn/titlebar/ontop_normal_active.png
Normal file
After Width: | Height: | Size: 118 B |
BIN
themes/zenburn/titlebar/ontop_normal_inactive.png
Normal file
After Width: | Height: | Size: 107 B |
BIN
themes/zenburn/titlebar/sticky_focus_active.png
Normal file
After Width: | Height: | Size: 187 B |
BIN
themes/zenburn/titlebar/sticky_focus_inactive.png
Normal file
After Width: | Height: | Size: 103 B |
BIN
themes/zenburn/titlebar/sticky_normal_active.png
Normal file
After Width: | Height: | Size: 116 B |
BIN
themes/zenburn/titlebar/sticky_normal_inactive.png
Normal file
After Width: | Height: | Size: 86 B |
100
tools/headergen
Executable file
@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/env lua
|
||||||
|
-- copyright header generator
|
||||||
|
-- Copyright (C) 2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
local ipairs = ipairs
|
||||||
|
local pairs = pairs
|
||||||
|
local tonumber = tonumber
|
||||||
|
local io = { open = io.open, popen = io.popen }
|
||||||
|
local os = { exit = os.exit }
|
||||||
|
local table = {
|
||||||
|
concat = table.concat,
|
||||||
|
insert = table.insert,
|
||||||
|
sort = table.sort
|
||||||
|
}
|
||||||
|
|
||||||
|
local HEADER = [[-- %s
|
||||||
|
%s
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
%s]]
|
||||||
|
local COMMAND = "git log --date=format:%Y --format='%ad %an <%ae>' "
|
||||||
|
|
||||||
|
if #arg == 0 then
|
||||||
|
print'usage: headergen lua-source-files'
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, filename in ipairs(arg) do
|
||||||
|
local fi = io.open(filename)
|
||||||
|
local content = fi:read'*a'
|
||||||
|
fi:close()
|
||||||
|
|
||||||
|
local holders = {}
|
||||||
|
local output = io.popen(COMMAND .. filename)
|
||||||
|
for line in output:lines() do
|
||||||
|
local year, author = line:match'(%d+)%s+(.+)'
|
||||||
|
if holders[author] == nil then holders[author] = {} end
|
||||||
|
holders[author][year] = true
|
||||||
|
end
|
||||||
|
output:close()
|
||||||
|
|
||||||
|
local copyrights = {}
|
||||||
|
for author, years in pairs(holders) do
|
||||||
|
local time = {}
|
||||||
|
for year, _ in pairs(years) do table.insert(time, tonumber(year)) end
|
||||||
|
table.sort(time)
|
||||||
|
|
||||||
|
local copyright = { 'Copyright (C) ' }
|
||||||
|
for _, current in ipairs(time) do
|
||||||
|
local prev = tonumber(copyright[#copyright])
|
||||||
|
if prev == nil then
|
||||||
|
table.insert(copyright, current)
|
||||||
|
elseif current - 1 ~= prev then
|
||||||
|
table.insert(copyright, ',')
|
||||||
|
table.insert(copyright, current)
|
||||||
|
elseif copyright[#copyright - 1] == '-' then
|
||||||
|
copyright[#copyright] = current
|
||||||
|
else
|
||||||
|
table.insert(copyright, '-')
|
||||||
|
table.insert(copyright, current)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(copyrights,
|
||||||
|
('-- %s %s'):format(table.concat(copyright), author))
|
||||||
|
end
|
||||||
|
|
||||||
|
local fo = io.open(filename, 'w')
|
||||||
|
table.sort(copyrights)
|
||||||
|
fo:write(HEADER:format(filename, table.concat(copyrights, '\n'), content))
|
||||||
|
fo:close()
|
||||||
|
end
|
23
tools/luacheckrc
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
-- Only allow symbols available in all Lua versions
|
||||||
|
std = "min"
|
||||||
|
|
||||||
|
-- Global objects defined by the C code
|
||||||
|
read_globals = {
|
||||||
|
"timer", -- deprecated, but used in older versions.
|
||||||
|
}
|
||||||
|
|
||||||
|
include_files = {
|
||||||
|
"*.lua", -- libraries
|
||||||
|
"widgets/*.lua", -- officially supported widget types
|
||||||
|
"templates/*.lua", -- officially supported widget types
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Warnings to be ignored
|
||||||
|
ignore = {
|
||||||
|
"212", -- Unused argument.
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Not enforced, but preferable
|
||||||
|
max_code_line_length = 80
|
||||||
|
|
||||||
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
1
vicious
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 150864a76d4b18c97da1459f355c6a86540a0863
|
94
widgets/bat_freebsd.lua
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
-- battery widget type for FreeBSD
|
||||||
|
-- Copyright (C) 2017-2019 mutlusun <mutlusun@github.com>
|
||||||
|
-- Copyright (C) 2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local math = { floor = math.floor }
|
||||||
|
local string = {
|
||||||
|
gmatch = string.gmatch,
|
||||||
|
format = string.format
|
||||||
|
}
|
||||||
|
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
local spawn = require("vicious.spawn")
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- Battery: provides battery level of requested battery
|
||||||
|
-- vicious.widgets.battery_freebsd
|
||||||
|
local bat_freebsd = {}
|
||||||
|
|
||||||
|
-- {{{ Battery widget type
|
||||||
|
local function parse(stdout, stderr, exitreason, exitcode)
|
||||||
|
local bat_info = {}
|
||||||
|
for line in string.gmatch(stdout, "[^\n]+") do
|
||||||
|
for key,value in string.gmatch(line, "(.+):%s+(.+)") do
|
||||||
|
bat_info[key] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- current state
|
||||||
|
-- see: https://github.com/freebsd/freebsd/blob/master/usr.sbin/acpi/acpiconf/acpiconf.c
|
||||||
|
local battery_state = {
|
||||||
|
["high"] = "↯",
|
||||||
|
["charging"] = "+",
|
||||||
|
["critical charging"] = "+",
|
||||||
|
["discharging"] = "-",
|
||||||
|
["critical discharging"] = "!",
|
||||||
|
["critical"] = "!",
|
||||||
|
}
|
||||||
|
local state = battery_state[bat_info["State"]] or "N/A"
|
||||||
|
|
||||||
|
-- battery capacity in percent
|
||||||
|
local percent = tonumber(bat_info["Remaining capacity"]:match"[%d]+")
|
||||||
|
|
||||||
|
-- use remaining (charging or discharging) time calculated by acpiconf
|
||||||
|
local time = bat_info["Remaining time"]
|
||||||
|
if time == "unknown" then
|
||||||
|
time = "∞"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- calculate wear level from (last full / design) capacity
|
||||||
|
local wear = "N/A"
|
||||||
|
if bat_info["Last full capacity"] and bat_info["Design capacity"] then
|
||||||
|
local l_full = tonumber(bat_info["Last full capacity"]:match"[%d]+")
|
||||||
|
local design = tonumber(bat_info["Design capacity"]:match"[%d]+")
|
||||||
|
wear = math.floor(l_full / design * 100)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- dis-/charging rate as presented by battery
|
||||||
|
local rate = bat_info["Present rate"]:match"([%d]+)%smW"
|
||||||
|
rate = string.format("%2.1f", tonumber(rate / 1000))
|
||||||
|
|
||||||
|
-- returns
|
||||||
|
-- * state (high "↯", discharging "-", charging "+", N/A "⌁" }
|
||||||
|
-- * remaining_capacity (percent)
|
||||||
|
-- * remaining_time, by battery
|
||||||
|
-- * wear level (percent)
|
||||||
|
-- * present_rate (mW)
|
||||||
|
return {state, percent, time, wear, rate}
|
||||||
|
end
|
||||||
|
|
||||||
|
function bat_freebsd.async(format, warg, callback)
|
||||||
|
local battery = warg or "batt"
|
||||||
|
spawn.easy_async("acpiconf -i " .. helpers.shellquote(battery),
|
||||||
|
function (...) callback(parse(...)) end)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return helpers.setasyncall(bat_freebsd)
|
109
widgets/bat_linux.lua
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
-- battery widget type for GNU/Linux
|
||||||
|
-- Copyright (C) 2010 Adrian C. <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2013 NormalRa <normalrawr@gmail.com>
|
||||||
|
-- Copyright (C) 2017 David Udelson <dru5@cornell.edu>
|
||||||
|
-- Copyright (C) 2017 Roberto <empijei@users.noreply.github.com>
|
||||||
|
-- Copyright (C) 2017 mutlusun <mutlusun@github.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local tonumber = tonumber
|
||||||
|
local string = { format = string.format }
|
||||||
|
local math = {
|
||||||
|
min = math.min,
|
||||||
|
floor = math.floor
|
||||||
|
}
|
||||||
|
|
||||||
|
local helpers = require"vicious.helpers"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Battery widget type
|
||||||
|
return helpers.setcall(function (format, warg)
|
||||||
|
if not warg then return end
|
||||||
|
|
||||||
|
local battery = helpers.pathtotable("/sys/class/power_supply/"..warg)
|
||||||
|
local battery_state = {
|
||||||
|
["Full\n"] = "↯",
|
||||||
|
["Unknown\n"] = "⌁",
|
||||||
|
["Charged\n"] = "↯",
|
||||||
|
["Charging\n"] = "+",
|
||||||
|
["Discharging\n"] = "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Get current power usage in watt
|
||||||
|
local curpower = "N/A"
|
||||||
|
if battery.power_now then
|
||||||
|
curpower = string.format("%.2f", tonumber(battery.power_now) /1000000)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if the battery is present
|
||||||
|
if battery.present ~= "1\n" then
|
||||||
|
return {battery_state["Unknown\n"], 0, "N/A", 0, curpower}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get state information
|
||||||
|
local state = battery_state[battery.status] or battery_state["Unknown\n"]
|
||||||
|
|
||||||
|
-- Get capacity information
|
||||||
|
local remaining, capacity, capacity_design
|
||||||
|
if battery.charge_now then
|
||||||
|
remaining, capacity = battery.charge_now, battery.charge_full
|
||||||
|
capacity_design = battery.charge_full_design or capacity
|
||||||
|
elseif battery.energy_now then
|
||||||
|
remaining, capacity = battery.energy_now, battery.energy_full
|
||||||
|
capacity_design = battery.energy_full_design or capacity
|
||||||
|
else
|
||||||
|
return {battery_state["Unknown\n"], 0, "N/A", 0, curpower}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate capacity and wear percentage (but work around broken BAT/ACPI implementations)
|
||||||
|
local percent = math.min(math.floor(remaining / capacity * 100), 100)
|
||||||
|
local wear = math.floor(100 - capacity / capacity_design * 100)
|
||||||
|
|
||||||
|
-- Get charge information
|
||||||
|
local rate
|
||||||
|
if battery.current_now then
|
||||||
|
rate = tonumber(battery.current_now)
|
||||||
|
elseif battery.power_now then
|
||||||
|
rate = tonumber(battery.power_now)
|
||||||
|
else
|
||||||
|
return {state, percent, "N/A", wear, curpower}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate remaining (charging or discharging) time
|
||||||
|
local time = "N/A"
|
||||||
|
|
||||||
|
if rate ~= nil and rate ~= 0 then
|
||||||
|
local timeleft
|
||||||
|
if state == "+" then
|
||||||
|
timeleft = (tonumber(capacity)-tonumber(remaining)) / tonumber(rate)
|
||||||
|
elseif state == "-" then
|
||||||
|
timeleft = tonumber(remaining) / tonumber(rate)
|
||||||
|
else
|
||||||
|
return {state, percent, time, wear, curpower}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate time
|
||||||
|
local hoursleft = math.floor(timeleft)
|
||||||
|
local minutesleft = math.floor((timeleft - hoursleft) * 60 )
|
||||||
|
|
||||||
|
time = string.format("%02d:%02d", hoursleft, minutesleft)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {state, percent, time, wear, curpower}
|
||||||
|
end)
|
||||||
|
-- }}}
|
94
widgets/bat_openbsd.lua
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
-- battery widget type for OpenBSD
|
||||||
|
-- Copyright (C) 2019 Enric Morales <me@enric.me>
|
||||||
|
-- Copyright (C) 2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local pairs = pairs
|
||||||
|
local tonumber = tonumber
|
||||||
|
local table = {
|
||||||
|
insert = table.insert
|
||||||
|
}
|
||||||
|
|
||||||
|
local math = {
|
||||||
|
floor = math.floor,
|
||||||
|
modf = math.modf
|
||||||
|
}
|
||||||
|
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
local bat_openbsd = {}
|
||||||
|
function bat_openbsd.async(format, warg, callback)
|
||||||
|
local battery_id = warg or "bat0"
|
||||||
|
|
||||||
|
local fields = {
|
||||||
|
charging_rate = ("hw.sensors.acpi%s.power0"):format(battery_id),
|
||||||
|
last_full_capacity = ("hw.sensors.acpi%s.watthour0"):format(battery_id),
|
||||||
|
remaining_capacity = ("hw.sensors.acpi%s.watthour3"):format(battery_id),
|
||||||
|
design_capacity = ("hw.sensors.acpi%s.watthour4"):format(battery_id),
|
||||||
|
state = ("hw.sensors.acpi%s.raw0"):format(battery_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
local sysctl_args = {}
|
||||||
|
for _, v in pairs(fields) do table.insert(sysctl_args, v) end
|
||||||
|
|
||||||
|
local battery = {}
|
||||||
|
helpers.sysctl_async(sysctl_args, function (ret)
|
||||||
|
for k, v in pairs(fields) do
|
||||||
|
-- discard the description that comes after the values
|
||||||
|
battery[k] = tonumber(ret[v]:match("(.-) "))
|
||||||
|
end
|
||||||
|
|
||||||
|
local states = {
|
||||||
|
[0] = "↯", -- not charging
|
||||||
|
[1] = "-", -- discharging
|
||||||
|
[2] = "!", -- critical
|
||||||
|
[3] = "+", -- charging
|
||||||
|
[4] = "N/A", -- unknown status
|
||||||
|
[255] = "N/A" -- unimplemented by the driver
|
||||||
|
}
|
||||||
|
local state = states[battery.state]
|
||||||
|
|
||||||
|
local charge = tonumber(battery.remaining_capacity
|
||||||
|
/ battery.last_full_capacity * 100)
|
||||||
|
|
||||||
|
local remaining_time
|
||||||
|
if battery.charging_rate < 1 then
|
||||||
|
remaining_time = "∞"
|
||||||
|
else
|
||||||
|
local raw_time = battery.remaining_capacity / battery.rate
|
||||||
|
local hours, hour_fraction = math.modf(raw_time)
|
||||||
|
local minutes = math.floor(60 * hour_fraction)
|
||||||
|
remaining_time = ("%d:%0.2d"):format(hours, minutes)
|
||||||
|
end
|
||||||
|
|
||||||
|
local wear = math.floor(battery.last_full_capacity,
|
||||||
|
battery.design_capacity)
|
||||||
|
|
||||||
|
-- Pass the following arguments to callback function:
|
||||||
|
-- * battery state symbol (↯, -, !, + or N/A)
|
||||||
|
-- * remaining capacity (in percent)
|
||||||
|
-- * remaining time, as reported by the battery
|
||||||
|
-- * wear level (in percent)
|
||||||
|
-- * present_rate (in Watts/hour)
|
||||||
|
return callback({ state, charge, remaining_time,
|
||||||
|
wear, battery.charging_rate })
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return helpers.setasyncall(bat_openbsd)
|
66
widgets/cmus_all.lua
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
-- cmus music player widget type
|
||||||
|
-- Copyright (C) 2017 JuanKman94 <juan.carlos.menonita@gmail.com>
|
||||||
|
-- Copyright (C) 2017 Joerg Thalheim <joerg@thalheim.io>
|
||||||
|
-- Copyright (C) 2018-2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local type = type
|
||||||
|
local tonumber = tonumber
|
||||||
|
local os = { getenv = os.getenv }
|
||||||
|
|
||||||
|
local helpers = require"vicious.helpers"
|
||||||
|
local spawn = require"vicious.spawn"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
local CMUS_SOCKET = helpers.shellquote(os.getenv"CMUS_SOCKET")
|
||||||
|
|
||||||
|
-- Cmus: provides CMUS information
|
||||||
|
-- vicious.widgets.cmus
|
||||||
|
return helpers.setasyncall{
|
||||||
|
async = function (format, warg, callback)
|
||||||
|
local server = ""
|
||||||
|
if type(warg) == "table" then
|
||||||
|
server = " --server " .. helpers.shellquote(warg.host or warg[1])
|
||||||
|
elseif CMUS_SOCKET ~= nil then
|
||||||
|
server = " --server " .. CMUS_SOCKET
|
||||||
|
end
|
||||||
|
|
||||||
|
local cmus_state = { ["{duration}"] = 0, ["{file}"] = "N/A",
|
||||||
|
["{status}"] = "N/A", ["{title}"] = "N/A",
|
||||||
|
["{artist}"] = "N/A", ["{continue}"] = "off",
|
||||||
|
["{shuffle}"] = "off", ["{repeat}"] = "off" }
|
||||||
|
|
||||||
|
spawn.with_line_callback("cmus-remote --query" .. server, {
|
||||||
|
stdout = function (line)
|
||||||
|
for module, value in line:gmatch"([%w]+) (.*)$" do
|
||||||
|
if module == "file" or module == "status" then
|
||||||
|
cmus_state["{"..module.."}"] = value
|
||||||
|
elseif module == "duration" then
|
||||||
|
cmus_state["{"..module.."}"] = tonumber(value)
|
||||||
|
else
|
||||||
|
local k, v = value:gmatch("([%w]+) (.*)$")()
|
||||||
|
if module == "tag" then
|
||||||
|
cmus_state["{"..k.."}"] = v
|
||||||
|
elseif module == "set" and v == "true" then
|
||||||
|
cmus_state["{"..k.."}"] = "on"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
output_done = function () callback(cmus_state) end })
|
||||||
|
end }
|
89
widgets/cpu_freebsd.lua
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
-- CPU usage widget type for FreeBSD
|
||||||
|
-- Copyright (C) 2017,2019 mutlusun <mutlusun@github.com>
|
||||||
|
-- Copyright (C) 2019 Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local math = { floor = math.floor }
|
||||||
|
local string = { gmatch = string.gmatch }
|
||||||
|
|
||||||
|
local helpers = require("vicious.helpers")
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- Cpu: provides CPU usage for all available CPUs/cores
|
||||||
|
-- vicious.widgets.cpu_freebsd
|
||||||
|
local cpu_freebsd = {}
|
||||||
|
|
||||||
|
-- Initialize function tables
|
||||||
|
local cpu_total = {}
|
||||||
|
local cpu_idle = {}
|
||||||
|
|
||||||
|
-- {{{ CPU widget type
|
||||||
|
function cpu_freebsd.async(format, warg, callback)
|
||||||
|
local matches = {}
|
||||||
|
local tmp_total = {}
|
||||||
|
local tmp_idle = {}
|
||||||
|
local tmp_usage = {}
|
||||||
|
|
||||||
|
helpers.sysctl_async({ "kern.cp_times" }, function(ret)
|
||||||
|
-- Read input data
|
||||||
|
for v in string.gmatch(ret["kern.cp_times"], "([%d]+)") do
|
||||||
|
table.insert(matches, v)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set first value of function tables
|
||||||
|
if #cpu_total == 0 then -- check for empty table
|
||||||
|
for i = 1, #matches / 5 + 1 do
|
||||||
|
cpu_total[i] = 0
|
||||||
|
cpu_idle[i] = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i = 1, #matches / 5 + 1 do
|
||||||
|
tmp_total[i] = 0
|
||||||
|
tmp_idle[i] = 0
|
||||||
|
tmp_usage[i] = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- CPU usage
|
||||||
|
for i, v in ipairs(matches) do
|
||||||
|
local index = math.floor((i-1) / 5) + 2 -- current cpu
|
||||||
|
|
||||||
|
tmp_total[1] = tmp_total[1] + v
|
||||||
|
tmp_total[index] = tmp_total[index] + v
|
||||||
|
|
||||||
|
if (i-1) % 5 == 4 then
|
||||||
|
tmp_idle[1] = tmp_idle[1] + v
|
||||||
|
tmp_idle[index] = tmp_idle[index] + v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, #tmp_usage do
|
||||||
|
tmp_usage[i] = tmp_total[i] - cpu_total[i]
|
||||||
|
tmp_usage[i] = math.floor(
|
||||||
|
(tmp_usage[i] - (tmp_idle[i] - cpu_idle[i]))
|
||||||
|
/ tmp_usage[i] * 100)
|
||||||
|
end
|
||||||
|
|
||||||
|
cpu_total = tmp_total
|
||||||
|
cpu_idle = tmp_idle
|
||||||
|
|
||||||
|
return callback(tmp_usage)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
return helpers.setasyncall(cpu_freebsd)
|
86
widgets/cpu_linux.lua
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
-- CPU usage widget type for GNU/Linux
|
||||||
|
-- Copyright (C) 2009 Lucas de Vries <lucas@glacicle.com>
|
||||||
|
-- Copyright (C) 2011 Adrian C. <anrxc@sysphere.org>
|
||||||
|
-- Copyright (C) 2011 Jörg Thalheim <jthalheim@gmail.com>
|
||||||
|
-- Copyright (C) 2017 mutlusun <mutlusun@github.com>
|
||||||
|
--
|
||||||
|
-- This file is part of Vicious.
|
||||||
|
--
|
||||||
|
-- Vicious is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 2 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- Vicious is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
-- {{{ Grab environment
|
||||||
|
local ipairs = ipairs
|
||||||
|
local io = { open = io.open }
|
||||||
|
local math = { floor = math.floor }
|
||||||
|
local table = { insert = table.insert }
|
||||||
|
local string = {
|
||||||
|
sub = string.sub,
|
||||||
|
gmatch = string.gmatch
|
||||||
|
}
|
||||||
|
|
||||||
|
local helpers = require"vicious.helpers"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- Initialize function tables
|
||||||
|
local cpu_usage = {}
|
||||||
|
local cpu_total = {}
|
||||||
|
local cpu_active = {}
|
||||||
|
|
||||||
|
-- {{{ CPU widget type
|
||||||
|
return helpers.setcall(function ()
|
||||||
|
local cpu_lines = {}
|
||||||
|
|
||||||
|
-- Get CPU stats
|
||||||
|
local f = io.open("/proc/stat")
|
||||||
|
for line in f:lines() do
|
||||||
|
if string.sub(line, 1, 3) ~= "cpu" then break end
|
||||||
|
|
||||||
|
cpu_lines[#cpu_lines+1] = {}
|
||||||
|
|
||||||
|
for i in string.gmatch(line, "[%s]+([^%s]+)") do
|
||||||
|
table.insert(cpu_lines[#cpu_lines], i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Ensure tables are initialized correctly
|
||||||
|
for i = #cpu_total + 1, #cpu_lines do
|
||||||
|
cpu_total[i] = 0
|
||||||
|
cpu_usage[i] = 0
|
||||||
|
cpu_active[i] = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, v in ipairs(cpu_lines) do
|
||||||
|
-- Calculate totals
|
||||||
|
local total_new = 0
|
||||||
|
for j = 1, #v do
|
||||||
|
total_new = total_new + v[j]
|
||||||
|
end
|
||||||
|
local active_new = total_new - (v[4] + v[5])
|
||||||
|
|
||||||
|
-- Calculate percentage
|
||||||
|
local diff_total = total_new - cpu_total[i]
|
||||||
|
local diff_active = active_new - cpu_active[i]
|
||||||
|
|
||||||
|
if diff_total == 0 then diff_total = 1E-6 end
|
||||||
|
cpu_usage[i] = math.floor((diff_active / diff_total) * 100)
|
||||||
|
|
||||||
|
-- Store totals
|
||||||
|
cpu_total[i] = total_new
|
||||||
|
cpu_active[i] = active_new
|
||||||
|
end
|
||||||
|
|
||||||
|
return cpu_usage
|
||||||
|
end)
|
||||||
|
-- }}}
|