initial commit

This commit is contained in:
Surferlul 2021-07-04 00:06:52 +02:00
commit 64387e3e5f
135 changed files with 9410 additions and 0 deletions

9
.build.yml Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1 @@
../widgets/cmus_all.lua

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,3 @@
Sphinx >= 3
sphinx_rtd_theme
sphinxcontrib-luadomain

37
docs/source/caching.rst Normal file
View 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
View File

@ -0,0 +1 @@
../../CHANGELOG.rst

38
docs/source/conf.py Normal file
View 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
View 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" } })

View File

@ -0,0 +1 @@
../../CONTRIBUTING.rst

83
docs/source/copying.rst Normal file
View 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
View 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
View 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
View 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
View 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
View 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.

View 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
View 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
View 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
View 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 = {
["\""] = "&quot;",
["&"] = "&amp;",
["'"] = "&apos;",
["<"] = "&lt;",
[">"] = "&gt;"
}
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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,3 @@
Based on Zenburn
modified by Surferlul

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

158
themes/zenburn/theme.lua Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 B

100
tools/headergen Executable file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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)
-- }}}

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