mirror of https://github.com/lcpz/lain.git
commit
b8adf93221
|
@ -0,0 +1,339 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||||
|
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.
|
||||||
|
|
||||||
|
{description}
|
||||||
|
Copyright (C) {year} {fullname}
|
||||||
|
|
||||||
|
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.
|
|
@ -43,5 +43,5 @@ Screenshots
|
||||||
|
|
||||||
.. _GNU-GPL2: http://www.gnu.org/licenses/gpl-2.0.html
|
.. _GNU-GPL2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||||
.. _awesome-vain: https://github.com/vain/awesome-vain
|
.. _awesome-vain: https://github.com/vain/awesome-vain
|
||||||
.. _Awesome: http://awesome.naquadah.org/
|
.. _Awesome: https://github.com/awesomeWM/awesome
|
||||||
.. _wiki: https://github.com/copycat-killer/lain/wiki
|
.. _wiki: https://github.com/copycat-killer/lain/wiki
|
||||||
|
|
|
@ -52,7 +52,7 @@ function asyncshell.request(command, callback, timeout)
|
||||||
id, formatted_command
|
id, formatted_command
|
||||||
)
|
)
|
||||||
|
|
||||||
if type(awful.spawn) == 'table' then
|
if type(awful.spawn) == 'table' and awful.spawn.with_shell then
|
||||||
awful.spawn.with_shell(req)
|
awful.spawn.with_shell(req)
|
||||||
else
|
else
|
||||||
awful.util.spawn_with_shell(req)
|
awful.util.spawn_with_shell(req)
|
||||||
|
|
16
helpers.lua
16
helpers.lua
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
local debug = require("debug")
|
local debug = require("debug")
|
||||||
|
|
||||||
|
local assert = assert
|
||||||
local capi = { timer = (type(timer) == 'table' and timer or require ("gears.timer")) }
|
local capi = { timer = (type(timer) == 'table' and timer or require ("gears.timer")) }
|
||||||
local io = { open = io.open,
|
local io = { open = io.open,
|
||||||
lines = io.lines,
|
lines = io.lines,
|
||||||
|
@ -93,9 +94,9 @@ function helpers.newtimer(_name, timeout, fun, nostart)
|
||||||
local name = timeout
|
local name = timeout
|
||||||
if not helpers.timer_table[name] then
|
if not helpers.timer_table[name] then
|
||||||
helpers.timer_table[name] = capi.timer({ timeout = timeout })
|
helpers.timer_table[name] = capi.timer({ timeout = timeout })
|
||||||
|
helpers.timer_table[name]:start()
|
||||||
end
|
end
|
||||||
helpers.timer_table[name]:connect_signal("timeout", fun)
|
helpers.timer_table[name]:connect_signal("timeout", fun)
|
||||||
helpers.timer_table[name]:start()
|
|
||||||
if not nostart then
|
if not nostart then
|
||||||
helpers.timer_table[name]:emit_signal("timeout")
|
helpers.timer_table[name]:emit_signal("timeout")
|
||||||
end
|
end
|
||||||
|
@ -105,7 +106,7 @@ end
|
||||||
|
|
||||||
-- {{{ Pipe operations
|
-- {{{ Pipe operations
|
||||||
|
|
||||||
-- read the full output of a pipe (command)
|
-- read the full output of a command output
|
||||||
function helpers.read_pipe(cmd)
|
function helpers.read_pipe(cmd)
|
||||||
local f = assert(io.popen(cmd))
|
local f = assert(io.popen(cmd))
|
||||||
local output = f:read("*all")
|
local output = f:read("*all")
|
||||||
|
@ -113,6 +114,16 @@ function helpers.read_pipe(cmd)
|
||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- return line iterator of a command output
|
||||||
|
function helpers.pipelines(...)
|
||||||
|
local f = assert(io.popen(...))
|
||||||
|
return function () -- iterator
|
||||||
|
local data = f:read()
|
||||||
|
if data == nil then f:close() end
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- {{{ A map utility
|
-- {{{ A map utility
|
||||||
|
@ -148,4 +159,5 @@ function helpers.spairs(t)
|
||||||
end
|
end
|
||||||
--}}}
|
--}}}
|
||||||
|
|
||||||
|
|
||||||
return helpers
|
return helpers
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package = "lain"
|
||||||
|
version = "git"
|
||||||
|
source = {
|
||||||
|
url = "https://github.com/copycat-killer/lain",
|
||||||
|
tag = "git"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Layout, widgets and utilities for Awesome WM",
|
||||||
|
detailed = [[
|
||||||
|
Successor of awesome-vain, this module provides new layouts, a set of widgets and utility functions, in order to improve Awesome usability and configurability.
|
||||||
|
|
||||||
|
Optional dependencies: alsa-utils (for alsamixer); curl; imagemagick.
|
||||||
|
]],
|
||||||
|
homepage = "https://github.com/copycat-killer/lain",
|
||||||
|
license = "GPL v2"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1",
|
||||||
|
"awesome >= 3.5",
|
||||||
|
"alsa-utils",
|
||||||
|
"curl",
|
||||||
|
"imagemagick"
|
||||||
|
}
|
||||||
|
supported_platforms = { "linux" }
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = { lain = "init.lua" }
|
||||||
|
}
|
12
scripts/dfs
12
scripts/dfs
|
@ -11,10 +11,11 @@
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Decoding options
|
# Decoding options
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
USAGE="Usage: $0 [-h(elp)] | [-n(arrow mode)] | [-w(eb output)]"
|
USAGE="Usage: $0 [-h(elp)] | [-n(arrow mode)] | [-w(eb output) | --type=<fstype> | --exclude-type=<fstype>]"
|
||||||
|
|
||||||
NARROW_MODE=0
|
NARROW_MODE=0
|
||||||
WEB_OUTPUT=0
|
WEB_OUTPUT=0
|
||||||
|
DF_OPTIONS=""
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
@ -31,6 +32,12 @@ NARROW_MODE=1
|
||||||
"-w" )
|
"-w" )
|
||||||
WEB_OUTPUT=1
|
WEB_OUTPUT=1
|
||||||
;;
|
;;
|
||||||
|
--type=*)
|
||||||
|
DF_OPTIONS+=" $1"
|
||||||
|
;;
|
||||||
|
--exclude-type=*)
|
||||||
|
DF_OPTIONS+=" $1"
|
||||||
|
;;
|
||||||
* )
|
* )
|
||||||
echo $USAGE
|
echo $USAGE
|
||||||
exit
|
exit
|
||||||
|
@ -58,6 +65,9 @@ AWK_COMMAND="/usr/bin/env gawk"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
# Add additional df options
|
||||||
|
DF_COMMAND+=$DF_OPTIONS
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Grabbing "df" result
|
# Grabbing "df" result
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
|
@ -98,7 +98,7 @@ function util.mc(c)
|
||||||
g.height = math.sqrt(mwfact) * mg.height
|
g.height = math.sqrt(mwfact) * mg.height
|
||||||
g.x = mg.x + (mg.width - g.width) / 2
|
g.x = mg.x + (mg.width - g.width) / 2
|
||||||
g.y = mg.y + (mg.height - g.height) / 2
|
g.y = mg.y + (mg.height - g.height) / 2
|
||||||
c:geometry(g)
|
if c then c:geometry(g) end -- if c is still a valid object
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Read the nice value of pid from /proc.
|
-- Read the nice value of pid from /proc.
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
|
||||||
|
--[[
|
||||||
|
|
||||||
|
Licensed under GNU General Public License v2
|
||||||
|
* (c) 2016, Luke Bonham
|
||||||
|
|
||||||
|
--]]
|
||||||
|
|
||||||
|
local awful = require("awful")
|
||||||
|
local capi = { client = client,
|
||||||
|
mouse = mouse,
|
||||||
|
screen = screen,
|
||||||
|
timer = timer }
|
||||||
|
local string = string
|
||||||
|
|
||||||
|
local pairs = pairs
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
local tostring = tostring
|
||||||
|
|
||||||
|
-- Quake-like Dropdown application spawn
|
||||||
|
-- Original version: https://awesomewm.org/wiki/Drop-down_terminal#Another_solution
|
||||||
|
local quake = {}
|
||||||
|
|
||||||
|
-- If you have a rule like "awful.client.setslave" for your terminals,
|
||||||
|
-- ensure you use an exception for QuakeDD. Otherwise, you may
|
||||||
|
-- run into problems with focus.
|
||||||
|
|
||||||
|
function quake:display()
|
||||||
|
-- First, we locate the client
|
||||||
|
local client = nil
|
||||||
|
local i = 0
|
||||||
|
for c in awful.client.iterate(function (c)
|
||||||
|
-- c.name may be changed!
|
||||||
|
return c.instance == self.name
|
||||||
|
end, nil, self.screen)
|
||||||
|
do
|
||||||
|
i = i + 1
|
||||||
|
if i == 1 then
|
||||||
|
client = c
|
||||||
|
else
|
||||||
|
-- Additional matching clients, let's remove the sticky bit
|
||||||
|
-- which may persist between awesome restarts. We don't close
|
||||||
|
-- them as they may be valuable. They will just turn into
|
||||||
|
-- normal clients.
|
||||||
|
c.sticky = false
|
||||||
|
c.ontop = false
|
||||||
|
c.above = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not client and not self.visible then return end
|
||||||
|
|
||||||
|
if not client then
|
||||||
|
-- The client does not exist, we spawn it
|
||||||
|
awful.util.spawn(string.format("%s %s %s", self.app,
|
||||||
|
string.format(self.argname, self.name), self.extra),
|
||||||
|
false, self.screen)
|
||||||
|
self.notexist = true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Resize
|
||||||
|
awful.client.floating.set(client, true)
|
||||||
|
client.border_width = self.border
|
||||||
|
client.size_hints_honor = false
|
||||||
|
if self.notexist then
|
||||||
|
client:geometry(self.geometry)
|
||||||
|
self.notexist = false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Not sticky and on top
|
||||||
|
client.ontop = true
|
||||||
|
client.above = true
|
||||||
|
client.skip_taskbar = true
|
||||||
|
client.sticky = false
|
||||||
|
|
||||||
|
-- Toggle display
|
||||||
|
if self.visible then
|
||||||
|
client.hidden = false
|
||||||
|
client:raise()
|
||||||
|
self.last_tag = tostring(awful.tag.selected(self.screen))
|
||||||
|
client:tags({awful.tag.selected(self.screen)})
|
||||||
|
capi.client.focus = client
|
||||||
|
else
|
||||||
|
client.hidden = true
|
||||||
|
local ctags = client:tags()
|
||||||
|
for i, t in pairs(ctags) do
|
||||||
|
ctags[i] = nil
|
||||||
|
end
|
||||||
|
client:tags(ctags)
|
||||||
|
end
|
||||||
|
|
||||||
|
return client
|
||||||
|
end
|
||||||
|
|
||||||
|
function quake:new(config)
|
||||||
|
local conf = config or {}
|
||||||
|
|
||||||
|
conf.app = conf.app or "xterm" -- application to spawn
|
||||||
|
conf.name = conf.name or "QuakeDD" -- window name
|
||||||
|
conf.argname = conf.argname or "-name %s" -- how to specify window name
|
||||||
|
conf.extra = conf.extra or "" -- extra arguments
|
||||||
|
conf.visible = conf.visible or false -- initially not visible
|
||||||
|
conf.screen = conf.screen or capi.mouse.screen
|
||||||
|
conf.border = conf.border or 1
|
||||||
|
|
||||||
|
-- If width or height <= 1 this is a proportion of the workspace
|
||||||
|
wibox_height = conf.wibox_height or 18 -- statusbar weight
|
||||||
|
height = conf.height or 0.25 -- height
|
||||||
|
width = conf.width or 1 -- width
|
||||||
|
vert = conf.vert or "top" -- top, bottom or center
|
||||||
|
horiz = conf.horiz or "center" -- left, right or center
|
||||||
|
|
||||||
|
-- Compute size
|
||||||
|
local geom = capi.screen[conf.screen].workarea
|
||||||
|
if width <= 1 then width = geom.width * width end
|
||||||
|
if height <= 1 then height = geom.height * height end
|
||||||
|
local x, y
|
||||||
|
if horiz == "left" then x = geom.x
|
||||||
|
elseif horiz == "right" then x = geom.width + geom.x - width
|
||||||
|
else x = geom.x + (geom.width - width)/2 end
|
||||||
|
if vert == "top" then y = geom.y
|
||||||
|
elseif vert == "bottom" then y = geom.height + geom.y - height
|
||||||
|
else y = geom.y + (geom.height - height)/2 end
|
||||||
|
conf.geometry = { x = x, y = y + wibox_height, width = width, height = height }
|
||||||
|
|
||||||
|
local console = setmetatable(conf, { __index = quake })
|
||||||
|
capi.client.connect_signal("manage", function(c)
|
||||||
|
if c.instance == console.name and c.screen == console.screen then
|
||||||
|
console:display()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
capi.client.connect_signal("unmanage", function(c)
|
||||||
|
if c.instance == console.name and c.screen == console.screen then
|
||||||
|
console.visible = false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- "Reattach" currently running quake application. This is in case awesome is restarted.
|
||||||
|
local reattach = capi.timer { timeout = 0 }
|
||||||
|
reattach:connect_signal("timeout", function()
|
||||||
|
reattach:stop()
|
||||||
|
console:display()
|
||||||
|
end)
|
||||||
|
reattach:start()
|
||||||
|
|
||||||
|
return console
|
||||||
|
end
|
||||||
|
|
||||||
|
function quake:toggle()
|
||||||
|
current_tag = awful.tag.selected(self.screen)
|
||||||
|
if self.last_tag ~= tostring(current_tag) and self.visible then
|
||||||
|
awful.client.movetotag(current_tag, self:display())
|
||||||
|
else
|
||||||
|
self.visible = not self.visible
|
||||||
|
self:display()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
setmetatable(quake, { __call = function(_, ...) return quake:new(...) end })
|
||||||
|
|
||||||
|
return quake
|
|
@ -28,12 +28,18 @@ local function worker(args)
|
||||||
|
|
||||||
alsa.cmd = args.cmd or "amixer"
|
alsa.cmd = args.cmd or "amixer"
|
||||||
alsa.channel = args.channel or "Master"
|
alsa.channel = args.channel or "Master"
|
||||||
|
alsa.togglechannel = args.togglechannel
|
||||||
alsa.widget = wibox.widget.textbox('')
|
alsa.widget = wibox.widget.textbox('')
|
||||||
|
|
||||||
function alsa.update()
|
function alsa.update()
|
||||||
mixer = read_pipe(string.format("%s get %s", alsa.cmd, alsa.channel))
|
mixer = read_pipe(string.format("%s get %s", alsa.cmd, alsa.channel))
|
||||||
l,s = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
|
l,s = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
|
||||||
|
|
||||||
|
-- HDMIs can have a channel different from Master for toggling mute
|
||||||
|
if alsa.togglechannel then
|
||||||
|
s = string.match(read_pipe(string.format("%s get %s", alsa.cmd, alsa.togglechannel)), "%[(%a+)%]")
|
||||||
|
end
|
||||||
|
|
||||||
if alsa.last_level ~= l or alsa.last_status ~= s then
|
if alsa.last_level ~= l or alsa.last_status ~= s then
|
||||||
volume_now = { level = l, status = s }
|
volume_now = { level = l, status = s }
|
||||||
alsa.last_level = l
|
alsa.last_level = l
|
||||||
|
|
|
@ -27,7 +27,7 @@ local setmetatable = setmetatable
|
||||||
-- lain.widgets.alsabar
|
-- lain.widgets.alsabar
|
||||||
local alsabar = {
|
local alsabar = {
|
||||||
channel = "Master",
|
channel = "Master",
|
||||||
step = "2%",
|
step = "1%",
|
||||||
|
|
||||||
colors = {
|
colors = {
|
||||||
background = beautiful.bg_normal,
|
background = beautiful.bg_normal,
|
||||||
|
@ -104,6 +104,7 @@ local function worker(args)
|
||||||
|
|
||||||
alsabar.cmd = args.cmd or "amixer"
|
alsabar.cmd = args.cmd or "amixer"
|
||||||
alsabar.channel = args.channel or alsabar.channel
|
alsabar.channel = args.channel or alsabar.channel
|
||||||
|
alsabar.togglechannel = args.togglechannel
|
||||||
alsabar.step = args.step or alsabar.step
|
alsabar.step = args.step or alsabar.step
|
||||||
alsabar.colors = args.colors or alsabar.colors
|
alsabar.colors = args.colors or alsabar.colors
|
||||||
alsabar.notifications = args.notifications or alsabar.notifications
|
alsabar.notifications = args.notifications or alsabar.notifications
|
||||||
|
@ -127,9 +128,14 @@ local function worker(args)
|
||||||
-- Capture mixer control state: [5%] ... ... [on]
|
-- Capture mixer control state: [5%] ... ... [on]
|
||||||
local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
|
local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
|
||||||
|
|
||||||
|
-- HDMIs can have a channel different from Master for toggling mute
|
||||||
|
if alsabar.togglechannel then
|
||||||
|
mute = string.match(read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.togglechannel)), "%[(%a+)%]")
|
||||||
|
end
|
||||||
|
|
||||||
if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted)
|
if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted)
|
||||||
then
|
then
|
||||||
alsabar._current_level = tonumber(volu)
|
alsabar._current_level = tonumber(volu) or alsabar._current_level
|
||||||
alsabar.bar:set_value(alsabar._current_level / 100)
|
alsabar.bar:set_value(alsabar._current_level / 100)
|
||||||
if not mute and tonumber(volu) == 0 or mute == "off"
|
if not mute and tonumber(volu) == 0 or mute == "off"
|
||||||
then
|
then
|
||||||
|
@ -149,19 +155,23 @@ local function worker(args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
alsabar.bar:buttons (awful.util.table.join (
|
alsabar.bar:buttons(awful.util.table.join (
|
||||||
awful.button ({}, 1, function()
|
awful.button({}, 1, function()
|
||||||
awful.util.spawn(alsabar.mixer)
|
awful.util.spawn(alsabar.mixer)
|
||||||
end),
|
end),
|
||||||
awful.button ({}, 3, function()
|
awful.button({}, 2, function()
|
||||||
|
awful.util.spawn(string.format("%s set %s 100%%", alsabar.cmd, alsabar.channel))
|
||||||
|
pulsebar.update()
|
||||||
|
end),
|
||||||
|
awful.button({}, 3, function()
|
||||||
awful.util.spawn(string.format("%s set %s toggle", alsabar.cmd, alsabar.channel))
|
awful.util.spawn(string.format("%s set %s toggle", alsabar.cmd, alsabar.channel))
|
||||||
alsabar.update()
|
alsabar.update()
|
||||||
end),
|
end),
|
||||||
awful.button ({}, 4, function()
|
awful.button({}, 4, function()
|
||||||
awful.util.spawn(string.format("%s set %s %s+", alsabar.cmd, alsabar.channel, alsabar.step))
|
awful.util.spawn(string.format("%s set %s %s+", alsabar.cmd, alsabar.channel, alsabar.step))
|
||||||
alsabar.update()
|
alsabar.update()
|
||||||
end),
|
end),
|
||||||
awful.button ({}, 5, function()
|
awful.button({}, 5, function()
|
||||||
awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step))
|
awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step))
|
||||||
alsabar.update()
|
alsabar.update()
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -26,8 +26,8 @@ local function worker(args)
|
||||||
base.widget = wibox.widget.textbox('')
|
base.widget = wibox.widget.textbox('')
|
||||||
|
|
||||||
function base.update()
|
function base.update()
|
||||||
if output ~= base.prev then
|
|
||||||
output = read_pipe(cmd)
|
output = read_pipe(cmd)
|
||||||
|
if output ~= base.prev then
|
||||||
widget = base.widget
|
widget = base.widget
|
||||||
settings()
|
settings()
|
||||||
base.prev = output
|
base.prev = output
|
||||||
|
|
|
@ -13,10 +13,14 @@ local first_line = require("lain.helpers").first_line
|
||||||
local naughty = require("naughty")
|
local naughty = require("naughty")
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
|
||||||
local math = { floor = math.floor, min = math.min }
|
local math = { abs = math.abs,
|
||||||
|
floor = math.floor,
|
||||||
|
log10 = math.log10,
|
||||||
|
min = math.min }
|
||||||
local string = { format = string.format }
|
local string = { format = string.format }
|
||||||
local tonumber = tonumber
|
|
||||||
|
|
||||||
|
local type = type
|
||||||
|
local tonumber = tonumber
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
-- Battery infos
|
-- Battery infos
|
||||||
|
@ -50,7 +54,7 @@ local function worker(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
bat_now = {
|
bat_now = {
|
||||||
status = "Not present",
|
status = "N/A",
|
||||||
ac_status = "N/A",
|
ac_status = "N/A",
|
||||||
perc = "N/A",
|
perc = "N/A",
|
||||||
time = "N/A",
|
time = "N/A",
|
||||||
|
@ -58,24 +62,26 @@ local function worker(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
bat_now.n_status = {}
|
bat_now.n_status = {}
|
||||||
|
bat_now.n_perc = {}
|
||||||
for i = 1, #batteries do
|
for i = 1, #batteries do
|
||||||
bat_now.n_status[i] = "Not present"
|
bat_now.n_status[i] = "N/A"
|
||||||
|
bat_now.n_perc[i] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function update()
|
function bat.update()
|
||||||
local sum_rate_current = 0
|
local sum_rate_current = 0
|
||||||
local sum_rate_voltage = 0
|
local sum_rate_voltage = 0
|
||||||
local sum_rate_power = 0
|
local sum_rate_power = 0
|
||||||
|
local sum_rate_energy = 0
|
||||||
local sum_energy_now = 0
|
local sum_energy_now = 0
|
||||||
local sum_energy_full = 0
|
local sum_energy_full = 0
|
||||||
local sum_energy_percentage = 0
|
local pspath = "/sys/class/power_supply/"
|
||||||
|
|
||||||
for i, battery in ipairs(batteries) do
|
for i, battery in ipairs(batteries) do
|
||||||
local bstr = "/sys/class/power_supply/" .. battery
|
local bstr = pspath .. battery
|
||||||
local present = first_line(bstr .. "/present")
|
local present = first_line(bstr .. "/present")
|
||||||
|
|
||||||
if present == "1"
|
if tonumber(present) == 1 then
|
||||||
then
|
|
||||||
-- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW]
|
-- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW]
|
||||||
local rate_current = tonumber(first_line(bstr .. "/current_now"))
|
local rate_current = tonumber(first_line(bstr .. "/current_now"))
|
||||||
local rate_voltage = tonumber(first_line(bstr .. "/voltage_now"))
|
local rate_voltage = tonumber(first_line(bstr .. "/voltage_now"))
|
||||||
|
@ -92,64 +98,74 @@ local function worker(args)
|
||||||
local energy_percentage = tonumber(first_line(bstr .. "/capacity")) or
|
local energy_percentage = tonumber(first_line(bstr .. "/capacity")) or
|
||||||
math.floor((energy_now / energy_full) * 100)
|
math.floor((energy_now / energy_full) * 100)
|
||||||
|
|
||||||
if bat_now.n_status[i] ~= "Charging" and bat_now.n_status[i] ~= "Discharging"
|
|
||||||
then
|
|
||||||
bat_now.n_status[i] = first_line(bstr .. "/status") or "N/A"
|
bat_now.n_status[i] = first_line(bstr .. "/status") or "N/A"
|
||||||
end
|
bat_now.n_perc[i] = energy_percentage or bat_now.n_perc[i]
|
||||||
|
|
||||||
sum_rate_current = sum_rate_current + (rate_current or 0)
|
sum_rate_current = sum_rate_current + (rate_current or 0)
|
||||||
sum_rate_voltage = sum_rate_voltage + rate_voltage
|
sum_rate_voltage = sum_rate_voltage + (rate_voltage or 0)
|
||||||
sum_rate_power = sum_rate_power + (rate_power or ((rate_voltage * rate_current) / 1e6))
|
sum_rate_power = sum_rate_power + (rate_power or 0)
|
||||||
sum_energy_now = sum_energy_now + energy_now
|
sum_rate_energy = sum_rate_energy + (rate_power or (((rate_voltage or 0) * (rate_current or 0)) / 1e6))
|
||||||
sum_energy_full = sum_energy_full + energy_full
|
sum_energy_now = sum_energy_now + (energy_now or 0)
|
||||||
sum_energy_percentage = sum_energy_percentage + energy_percentage
|
sum_energy_full = sum_energy_full + (energy_full or 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
bat_now.status = bat_now.n_status[1]
|
bat_now.status = bat_now.n_status[1]
|
||||||
bat_now.ac_status = first_line(string.format("/sys/class/power_supply/%s/online", ac)) or "N/A"
|
bat_now.ac_status = tonumber(first_line(string.format("%s%s/online", pspath, ac))) or "N/A"
|
||||||
|
|
||||||
-- update {perc,time,watt} iff rate > 0 and battery not full
|
if bat_now.status ~= "N/A" then
|
||||||
if (sum_rate_current > 0 or sum_rate_power > 0) and not (bat_now.status == "Full")
|
-- update {perc,time,watt} iff battery not full and rate > 0
|
||||||
then
|
if bat_now.status ~= "Full" and (sum_rate_power > 0 or sum_rate_current > 0) then
|
||||||
local rate_time = 0
|
local rate_time = 0
|
||||||
|
local div = (sum_rate_power > 0 and sum_rate_power) or sum_rate_current
|
||||||
|
|
||||||
if bat_now.status == "Charging" then
|
if bat_now.status == "Charging" then
|
||||||
rate_time = (sum_energy_full - sum_energy_now) / (sum_rate_power or sum_rate_current)
|
rate_time = (sum_energy_full - sum_energy_now) / div
|
||||||
elseif bat_now.status == "Discharging" then
|
else -- Discharging
|
||||||
rate_time = sum_energy_now / (sum_rate_power or sum_rate_current)
|
rate_time = sum_energy_now / div
|
||||||
|
end
|
||||||
|
|
||||||
|
if 0 < rate_time and rate_time < 0.01 then -- check for magnitude discrepancies (#199)
|
||||||
|
rate_time_magnitude = math.abs(math.floor(math.log10(rate_time)))
|
||||||
|
rate_time = rate_time * 10^(rate_time_magnitude - 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local hours = math.floor(rate_time)
|
local hours = math.floor(rate_time)
|
||||||
local minutes = math.floor((rate_time - hours) * 60)
|
local minutes = math.floor((rate_time - hours) * 60)
|
||||||
local watt = sum_rate_power / 1e6
|
bat_now.perc = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100))
|
||||||
|
|
||||||
bat_now.perc = string.format("%d", math.min(100, sum_energy_percentage / #batteries))
|
|
||||||
bat_now.time = string.format("%02d:%02d", hours, minutes)
|
bat_now.time = string.format("%02d:%02d", hours, minutes)
|
||||||
bat_now.watt = string.format("%.2fW", watt)
|
bat_now.watt = tonumber(string.format("%.2f", sum_rate_energy / 1e6))
|
||||||
|
elseif bat_now.status ~= "Full" and sum_rate_power == 0 and bat_now.ac_status == 1 then
|
||||||
|
bat_now.perc = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100))
|
||||||
|
bat_now.time = "00:00"
|
||||||
|
bat_now.watt = 0
|
||||||
|
elseif bat_now.status == "Full" then
|
||||||
|
bat_now.perc = 100
|
||||||
|
bat_now.time = "00:00"
|
||||||
|
bat_now.watt = 0
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
widget = bat.widget
|
widget = bat.widget
|
||||||
settings()
|
settings()
|
||||||
|
|
||||||
-- notifications for low and critical states
|
-- notifications for low and critical states
|
||||||
if bat_now.status == "Discharging" and notify == "on" and bat_now.perc then
|
if notify == "on" and type(bat_now.perc) == "number" and bat_now.status == "Discharging" then
|
||||||
local nperc = tonumber(bat_now.perc) or 100
|
if bat_now.perc <= 5 then
|
||||||
if nperc <= 5 then
|
|
||||||
bat.id = naughty.notify({
|
bat.id = naughty.notify({
|
||||||
preset = bat_notification_critical_preset,
|
preset = bat_notification_critical_preset,
|
||||||
replaces_id = bat.id,
|
replaces_id = bat.id
|
||||||
}).id
|
}).id
|
||||||
elseif nperc <= 15 then
|
elseif bat_now.perc <= 15 then
|
||||||
bat.id = naughty.notify({
|
bat.id = naughty.notify({
|
||||||
preset = bat_notification_low_preset,
|
preset = bat_notification_low_preset,
|
||||||
replaces_id = bat.id,
|
replaces_id = bat.id
|
||||||
}).id
|
}).id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
newtimer(battery, timeout, update)
|
newtimer(battery, timeout, bat.update)
|
||||||
|
|
||||||
return setmetatable(bat, { __index = bat.widget })
|
return setmetatable(bat, { __index = bat.widget })
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,15 +27,15 @@ local setmetatable = setmetatable
|
||||||
local calendar = {}
|
local calendar = {}
|
||||||
local cal_notification = nil
|
local cal_notification = nil
|
||||||
|
|
||||||
function calendar:hide()
|
function calendar.hide()
|
||||||
if cal_notification ~= nil then
|
if cal_notification ~= nil then
|
||||||
naughty.destroy(cal_notification)
|
naughty.destroy(cal_notification)
|
||||||
cal_notification = nil
|
cal_notification = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function calendar:show(t_out, inc_offset, scr)
|
function calendar.show(t_out, inc_offset, scr)
|
||||||
calendar:hide()
|
calendar.hide()
|
||||||
|
|
||||||
local f, c_text
|
local f, c_text
|
||||||
local offs = inc_offset or 0
|
local offs = inc_offset or 0
|
||||||
|
@ -96,7 +96,7 @@ function calendar:show(t_out, inc_offset, scr)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function calendar:attach(widget, args)
|
function calendar.attach(widget, args)
|
||||||
local args = args or {}
|
local args = args or {}
|
||||||
|
|
||||||
calendar.cal = args.cal or "/usr/bin/cal"
|
calendar.cal = args.cal or "/usr/bin/cal"
|
||||||
|
@ -116,16 +116,16 @@ function calendar:attach(widget, args)
|
||||||
calendar.offset = 0
|
calendar.offset = 0
|
||||||
calendar.notify_icon = nil
|
calendar.notify_icon = nil
|
||||||
|
|
||||||
widget:connect_signal("mouse::enter", function () calendar:show(0, 0, calendar.scr_pos) end)
|
widget:connect_signal("mouse::enter", function () calendar.show(0, 0, calendar.scr_pos) end)
|
||||||
widget:connect_signal("mouse::leave", function () calendar:hide() end)
|
widget:connect_signal("mouse::leave", function () calendar.hide() end)
|
||||||
widget:buttons(awful.util.table.join(awful.button({ }, 1, function ()
|
widget:buttons(awful.util.table.join(awful.button({ }, 1, function ()
|
||||||
calendar:show(0, -1, calendar.scr_pos) end),
|
calendar.show(0, -1, calendar.scr_pos) end),
|
||||||
awful.button({ }, 3, function ()
|
awful.button({ }, 3, function ()
|
||||||
calendar:show(0, 1, calendar.scr_pos) end),
|
calendar.show(0, 1, calendar.scr_pos) end),
|
||||||
awful.button({ }, 4, function ()
|
awful.button({ }, 4, function ()
|
||||||
calendar:show(0, -1, calendar.scr_pos) end),
|
calendar.show(0, -1, calendar.scr_pos) end),
|
||||||
awful.button({ }, 5, function ()
|
awful.button({ }, 5, function ()
|
||||||
calendar:show(0, 1, calendar.scr_pos) end)))
|
calendar.show(0, 1, calendar.scr_pos) end)))
|
||||||
end
|
end
|
||||||
|
|
||||||
return setmetatable(calendar, { __call = function(_, ...) return create(...) end })
|
return setmetatable(calendar, { __call = function(_, ...) return create(...) end })
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
|
|
||||||
--[[
|
|
||||||
|
|
||||||
Licensed under GNU General Public License v2
|
|
||||||
* (c) 2014, Aaron Lebo
|
|
||||||
|
|
||||||
--]]
|
|
||||||
|
|
||||||
local newtimer = require("lain.helpers").newtimer
|
|
||||||
local json = require("lain.util").dkjson
|
|
||||||
|
|
||||||
local wibox = require("wibox")
|
|
||||||
|
|
||||||
local string = { format = string.format }
|
|
||||||
local tonumber = tonumber
|
|
||||||
|
|
||||||
-- Crypto currencies widget
|
|
||||||
-- lain.widgets.contrib.ccurr
|
|
||||||
local ccurr = {}
|
|
||||||
|
|
||||||
-- Currently gets
|
|
||||||
-- * BTC/USD
|
|
||||||
-- * DOGE/USD
|
|
||||||
-- using Coinbase and Cryptsy APIs.
|
|
||||||
|
|
||||||
-- requires http://dkolf.de/src/dkjson-lua.fsl/home
|
|
||||||
-- based upon http://awesome.naquadah.org/wiki/Bitcoin_Price_Widget
|
|
||||||
|
|
||||||
local function get(url)
|
|
||||||
local f = io.popen('curl -m 5 -s "' .. url .. '"')
|
|
||||||
if not f then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
local s = f:read("*all")
|
|
||||||
f:close()
|
|
||||||
return s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function parse(j)
|
|
||||||
local obj, pos, err = json.decode(j, 1, nil)
|
|
||||||
if err then
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
return obj
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function worker(args)
|
|
||||||
local args = args or {}
|
|
||||||
local timeout = args.timeout or 600
|
|
||||||
local btc_url = args.btc_url or "https://coinbase.com/api/v1/prices/buy"
|
|
||||||
local doge_url = args.doge_url or "http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=132"
|
|
||||||
local settings = args.settings or function() end
|
|
||||||
|
|
||||||
ccurr.widget = wibox.widget.textbox('')
|
|
||||||
|
|
||||||
local function update()
|
|
||||||
price_now = {
|
|
||||||
btc = "N/A",
|
|
||||||
doge = "N/A"
|
|
||||||
}
|
|
||||||
|
|
||||||
btc = parse(get(btc_url))
|
|
||||||
doge = parse(get(doge_url))
|
|
||||||
|
|
||||||
if btc and doge then
|
|
||||||
price_now.btc = tonumber(btc["subtotal"]["amount"])
|
|
||||||
price_now.doge = tonumber(doge["return"]["markets"]["DOGE"]["lasttradeprice"])
|
|
||||||
price_now.doge = string.format("%.4f", price_now.btc * price_now.doge)
|
|
||||||
end
|
|
||||||
|
|
||||||
widget = ccurr.widget
|
|
||||||
settings()
|
|
||||||
end
|
|
||||||
|
|
||||||
newtimer("ccurr", timeout, update)
|
|
||||||
|
|
||||||
return ccurr.widget
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(ccurr, { __call = function(_, ...) return worker(...) end })
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
|
||||||
|
--[[
|
||||||
|
|
||||||
|
Licensed under GNU General Public License v2
|
||||||
|
* (c) 2016, Alexandre Terrien
|
||||||
|
|
||||||
|
--]]
|
||||||
|
|
||||||
|
local helpers = require("lain.helpers")
|
||||||
|
local json = require("lain.util.dkjson")
|
||||||
|
local pread = require("awful.util").pread
|
||||||
|
local naughty = require("naughty")
|
||||||
|
local wibox = require("wibox")
|
||||||
|
local mouse = mouse
|
||||||
|
local os = { getenv = os.getenv }
|
||||||
|
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
|
-- Google Play Music Desktop infos
|
||||||
|
-- lain.widget.contrib.gpmdp
|
||||||
|
local gpmdp = {}
|
||||||
|
|
||||||
|
local function worker(args)
|
||||||
|
local args = args or {}
|
||||||
|
local timeout = args.timeout or 2
|
||||||
|
local notify = args.notify or "off"
|
||||||
|
local followmouse = args.followmouse or false
|
||||||
|
local file_location = args.file_location or
|
||||||
|
os.getenv("HOME") .. "/.config/Google Play Music Desktop Player/json_store/playback.json"
|
||||||
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
|
gpmdp.widget = wibox.widget.textbox('')
|
||||||
|
|
||||||
|
gpmdp_notification_preset = {
|
||||||
|
title = "Now playing",
|
||||||
|
timeout = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
helpers.set_map("gpmdp_current", nil)
|
||||||
|
|
||||||
|
function gpmdp.update()
|
||||||
|
file, err = io.open(file_location, "r")
|
||||||
|
if not file
|
||||||
|
then
|
||||||
|
gpm_now = { running = false, playing = false }
|
||||||
|
else
|
||||||
|
dict, pos, err = json.decode(file:read "*a", 1, nil)
|
||||||
|
file:close()
|
||||||
|
gpm_now = {}
|
||||||
|
gpm_now.artist = dict.song.artist
|
||||||
|
gpm_now.album = dict.song.album
|
||||||
|
gpm_now.title = dict.song.title
|
||||||
|
gpm_now.cover_url = dict.song.albumArt
|
||||||
|
gpm_now.playing = dict.playing
|
||||||
|
end
|
||||||
|
|
||||||
|
if (pread("pidof 'Google Play Music Desktop Player'") ~= '') then
|
||||||
|
gpm_now.running = true
|
||||||
|
else
|
||||||
|
gpm_now.running = false
|
||||||
|
end
|
||||||
|
|
||||||
|
gpmdp_notification_preset.text = string.format("%s (%s) - %s", gpm_now.artist, gpm_now.album, gpm_now.title)
|
||||||
|
widget = gpmdp.widget
|
||||||
|
settings()
|
||||||
|
|
||||||
|
if gpm_now.playing
|
||||||
|
then
|
||||||
|
if notify == "on" and gpm_now.title ~= helpers.get_map("gpmdp_current")
|
||||||
|
then
|
||||||
|
helpers.set_map("gpmdp_current", gpm_now.title)
|
||||||
|
os.execute("curl " .. gpm_now.cover_url .. " -o /tmp/gpmcover.png")
|
||||||
|
|
||||||
|
if followmouse then
|
||||||
|
gpmdp_notification_preset.screen = mouse.screen
|
||||||
|
end
|
||||||
|
|
||||||
|
gpmdp.id = naughty.notify({
|
||||||
|
preset = gpmdp_notification_preset,
|
||||||
|
icon = "/tmp/gpmcover.png",
|
||||||
|
replaces_id = gpmdp.id,
|
||||||
|
}).id
|
||||||
|
end
|
||||||
|
elseif not gpm_now.running
|
||||||
|
then
|
||||||
|
helpers.set_map("gpmdp_current", nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
helpers.newtimer("gpmdp", timeout, gpmdp.update)
|
||||||
|
|
||||||
|
return setmetatable(gpmdp, { __index = gpmdp.widget })
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(gpmdp, { __call = function(_, ...) return worker(...) end })
|
|
@ -19,7 +19,7 @@ local setmetatable = setmetatable
|
||||||
-- Keyboard layout switcher
|
-- Keyboard layout switcher
|
||||||
-- lain.widgets.contrib.kblayout
|
-- lain.widgets.contrib.kblayout
|
||||||
|
|
||||||
local function worker (args)
|
local function worker(args)
|
||||||
local kbdlayout = {}
|
local kbdlayout = {}
|
||||||
kbdlayout.widget = wibox.widget.textbox('')
|
kbdlayout.widget = wibox.widget.textbox('')
|
||||||
|
|
||||||
|
@ -36,21 +36,21 @@ local function worker (args)
|
||||||
awful.button({ }, 1, function () kbdlayout.next() end),
|
awful.button({ }, 1, function () kbdlayout.next() end),
|
||||||
awful.button({ }, 3, function () kbdlayout.prev() end)))
|
awful.button({ }, 3, function () kbdlayout.prev() end)))
|
||||||
|
|
||||||
local function run_settings (layout, variant)
|
local function run_settings(layout, variant)
|
||||||
widget = kbdlayout.widget
|
widget = kbdlayout.widget
|
||||||
kbdlayout_now = { layout=string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
|
kbdlayout_now = { layout=string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
|
||||||
variant=variant }
|
variant=variant }
|
||||||
settings()
|
settings()
|
||||||
end
|
end
|
||||||
|
|
||||||
function kbdlayout.update ()
|
function kbdlayout.update()
|
||||||
local status = read_pipe('setxkbmap -query')
|
local status = read_pipe('setxkbmap -query')
|
||||||
|
|
||||||
run_settings(string.match(status, "layout:%s*([^\n]*)"),
|
run_settings(string.match(status, "layout:%s*([^\n]*)"),
|
||||||
string.match(status, "variant:%s*([^\n]*)"))
|
string.match(status, "variant:%s*([^\n]*)"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function kbdlayout.set (i)
|
function kbdlayout.set(i)
|
||||||
idx = ((i - 1) % #layouts) + 1 -- Make sure to wrap around as needed.
|
idx = ((i - 1) % #layouts) + 1 -- Make sure to wrap around as needed.
|
||||||
local to_execute = 'setxkbmap ' .. layouts[idx].layout
|
local to_execute = 'setxkbmap ' .. layouts[idx].layout
|
||||||
|
|
||||||
|
@ -67,11 +67,11 @@ local function worker (args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kbdlayout.next ()
|
function kbdlayout.next()
|
||||||
kbdlayout.set(idx + 1)
|
kbdlayout.set(idx + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function kbdlayout.prev ()
|
function kbdlayout.prev()
|
||||||
kbdlayout.set(idx - 1)
|
kbdlayout.set(idx - 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ local active = false -- true if redshift is active
|
||||||
local running = false -- true if redshift was initialized
|
local running = false -- true if redshift was initialized
|
||||||
local update_fnct = function() end -- Function that is run each time redshift is toggled. See redshift:attach().
|
local update_fnct = function() end -- Function that is run each time redshift is toggled. See redshift:attach().
|
||||||
|
|
||||||
|
|
||||||
local function init()
|
local function init()
|
||||||
-- As there is no way to determine if redshift was previously
|
-- As there is no way to determine if redshift was previously
|
||||||
-- toggled off (i.e Awesome on-the-fly restart), kill redshift to make sure
|
-- toggled off (i.e Awesome on-the-fly restart), kill redshift to make sure
|
||||||
|
|
|
@ -25,29 +25,34 @@ local task = {}
|
||||||
|
|
||||||
local task_notification = nil
|
local task_notification = nil
|
||||||
|
|
||||||
function task:hide()
|
function findLast(haystack, needle)
|
||||||
|
local i=haystack:match(".*"..needle.."()")
|
||||||
|
if i==nil then return nil else return i-1 end
|
||||||
|
end
|
||||||
|
|
||||||
|
function task.hide()
|
||||||
if task_notification ~= nil then
|
if task_notification ~= nil then
|
||||||
naughty.destroy(task_notification)
|
naughty.destroy(task_notification)
|
||||||
task_notification = nil
|
task_notification = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function task:show(scr_pos)
|
function task.show(scr_pos)
|
||||||
task:hide()
|
task.hide()
|
||||||
|
|
||||||
local f, c_text
|
local f, c_text, scrp
|
||||||
|
|
||||||
if task.followmouse then
|
if task.followmouse then
|
||||||
local scrp = mouse.screen
|
scrp = mouse.screen
|
||||||
else
|
else
|
||||||
local scrp = scr_pos or task.scr_pos
|
scrp = scr_pos or task.scr_pos
|
||||||
end
|
end
|
||||||
|
|
||||||
f = io.popen('task')
|
f = io.popen('task ' .. task.cmdline)
|
||||||
c_text = "<span font='"
|
c_text = "<span font='"
|
||||||
.. task.font .. " "
|
.. task.font .. " "
|
||||||
.. task.font_size .. "'>"
|
.. task.font_size .. "'>"
|
||||||
.. f:read("*all"):gsub("\n*$", "")
|
.. awful.util.escape(f:read("*all"):gsub("\n*$", ""))
|
||||||
.. "</span>"
|
.. "</span>"
|
||||||
f:close()
|
f:close()
|
||||||
|
|
||||||
|
@ -62,7 +67,7 @@ function task:show(scr_pos)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
function task:prompt_add()
|
function task.prompt_add()
|
||||||
awful.prompt.run({ prompt = "Add task: " },
|
awful.prompt.run({ prompt = "Add task: " },
|
||||||
mypromptbox[mouse.screen].widget,
|
mypromptbox[mouse.screen].widget,
|
||||||
function (...)
|
function (...)
|
||||||
|
@ -70,7 +75,7 @@ function task:prompt_add()
|
||||||
c_text = "\n<span font='"
|
c_text = "\n<span font='"
|
||||||
.. task.font .. " "
|
.. task.font .. " "
|
||||||
.. task.font_size .. "'>"
|
.. task.font_size .. "'>"
|
||||||
.. f:read("*all")
|
.. awful.util.escape(f:read("*all"))
|
||||||
.. "</span>"
|
.. "</span>"
|
||||||
f:close()
|
f:close()
|
||||||
|
|
||||||
|
@ -87,7 +92,7 @@ function task:prompt_add()
|
||||||
awful.util.getdir("cache") .. "/history_task_add")
|
awful.util.getdir("cache") .. "/history_task_add")
|
||||||
end
|
end
|
||||||
|
|
||||||
function task:prompt_search()
|
function task.prompt_search()
|
||||||
awful.prompt.run({ prompt = "Search task: " },
|
awful.prompt.run({ prompt = "Search task: " },
|
||||||
mypromptbox[mouse.screen].widget,
|
mypromptbox[mouse.screen].widget,
|
||||||
function (...)
|
function (...)
|
||||||
|
@ -102,7 +107,7 @@ function task:prompt_search()
|
||||||
c_text = "<span font='"
|
c_text = "<span font='"
|
||||||
.. task.font .. " "
|
.. task.font .. " "
|
||||||
.. task.font_size .. "'>"
|
.. task.font_size .. "'>"
|
||||||
.. c_text
|
.. awful.util.escape(c_text)
|
||||||
.. "</span>"
|
.. "</span>"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -121,24 +126,25 @@ function task:prompt_search()
|
||||||
awful.util.getdir("cache") .. "/history_task")
|
awful.util.getdir("cache") .. "/history_task")
|
||||||
end
|
end
|
||||||
|
|
||||||
function task:attach(widget, args)
|
function task.attach(widget, args)
|
||||||
local args = args or {}
|
local args = args or {}
|
||||||
|
|
||||||
task.font_size = tonumber(args.font_size) or 12
|
task.font_size = tonumber(args.font_size) or 12
|
||||||
task.font = beautiful.font:sub(beautiful.font:find(""),
|
task.font = args.font or beautiful.font:sub(beautiful.font:find(""),
|
||||||
beautiful.font:find(" "))
|
findLast(beautiful.font, " "))
|
||||||
task.fg = args.fg or beautiful.fg_normal or "#FFFFFF"
|
task.fg = args.fg or beautiful.fg_normal or "#FFFFFF"
|
||||||
task.bg = args.bg or beautiful.bg_normal or "#FFFFFF"
|
task.bg = args.bg or beautiful.bg_normal or "#FFFFFF"
|
||||||
task.position = args.position or "top_right"
|
task.position = args.position or "top_right"
|
||||||
task.timeout = args.timeout or 7
|
task.timeout = args.timeout or 7
|
||||||
task.scr_pos = args.scr_pos or 1
|
task.scr_pos = args.scr_pos or 1
|
||||||
task.followmouse = args.followmouse or false
|
task.followmouse = args.followmouse or false
|
||||||
|
task.cmdline = args.cmdline or "next"
|
||||||
|
|
||||||
task.notify_icon = icons_dir .. "/taskwarrior/task.png"
|
task.notify_icon = icons_dir .. "/taskwarrior/task.png"
|
||||||
task.notify_icon_small = icons_dir .. "/taskwarrior/tasksmall.png"
|
task.notify_icon_small = icons_dir .. "/taskwarrior/tasksmall.png"
|
||||||
|
|
||||||
widget:connect_signal("mouse::enter", function () task:show(task.scr_pos) end)
|
widget:connect_signal("mouse::enter", function () task.show(task.scr_pos) end)
|
||||||
widget:connect_signal("mouse::leave", function () task:hide() end)
|
widget:connect_signal("mouse::leave", function () task.hide() end)
|
||||||
end
|
end
|
||||||
|
|
||||||
return setmetatable(task, { __call = function(_, ...) return create(...) end })
|
return setmetatable(task, { __call = function(_, ...) return create(...) end })
|
||||||
|
|
|
@ -16,7 +16,6 @@ local tonumber = tonumber
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
local smapi = {}
|
local smapi = {}
|
||||||
|
|
||||||
local apipath = "/sys/devices/platform/smapi"
|
local apipath = "/sys/devices/platform/smapi"
|
||||||
|
|
||||||
-- Most are readable values, but some can be written to (not implemented, yet?)
|
-- Most are readable values, but some can be written to (not implemented, yet?)
|
||||||
|
|
|
@ -28,26 +28,29 @@ local setmetatable = setmetatable
|
||||||
local fs = {}
|
local fs = {}
|
||||||
local fs_notification = nil
|
local fs_notification = nil
|
||||||
|
|
||||||
function fs:hide()
|
function fs.hide()
|
||||||
if fs_notification ~= nil then
|
if fs_notification ~= nil then
|
||||||
naughty.destroy(fs_notification)
|
naughty.destroy(fs_notification)
|
||||||
fs_notification = nil
|
fs_notification = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs:show(t_out)
|
function fs.show(seconds, options, scr)
|
||||||
fs:hide()
|
fs.hide()
|
||||||
|
|
||||||
local ws = helpers.read_pipe(helpers.scripts_dir .. "dfs"):gsub("\n*$", "")
|
local cmd = (options and string.format("dfs %s", options)) or "dfs"
|
||||||
|
local ws = helpers.read_pipe(helpers.scripts_dir .. cmd):gsub("\n*$", "")
|
||||||
|
|
||||||
if fs.followmouse then
|
if fs.followmouse then
|
||||||
fs.notification_preset.screen = mouse.screen
|
fs.notification_preset.screen = mouse.screen
|
||||||
|
elseif scr then
|
||||||
|
fs.notification_preset.screen = scr
|
||||||
end
|
end
|
||||||
|
|
||||||
fs_notification = naughty.notify({
|
fs_notification = naughty.notify({
|
||||||
preset = fs.notification_preset,
|
preset = fs.notification_preset,
|
||||||
text = ws,
|
text = ws,
|
||||||
timeout = t_out
|
timeout = seconds or 5
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -58,6 +61,8 @@ local function worker(args)
|
||||||
local args = args or {}
|
local args = args or {}
|
||||||
local timeout = args.timeout or 600
|
local timeout = args.timeout or 600
|
||||||
local partition = args.partition or "/"
|
local partition = args.partition or "/"
|
||||||
|
local showpopup = args.showpopup or "on"
|
||||||
|
local notify = args.notify or "on"
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
|
||||||
fs.followmouse = args.followmouse or false
|
fs.followmouse = args.followmouse or false
|
||||||
|
@ -92,10 +97,11 @@ local function worker(args)
|
||||||
fs_now.size_mb = tonumber(fs_info[partition .. " size_mb"]) or 0
|
fs_now.size_mb = tonumber(fs_info[partition .. " size_mb"]) or 0
|
||||||
fs_now.size_gb = tonumber(fs_info[partition .. " size_gb"]) or 0
|
fs_now.size_gb = tonumber(fs_info[partition .. " size_gb"]) or 0
|
||||||
|
|
||||||
|
notification_preset = fs.notification_preset
|
||||||
widget = fs.widget
|
widget = fs.widget
|
||||||
settings()
|
settings()
|
||||||
|
|
||||||
if fs_now.used >= 99 and not helpers.get_map(partition)
|
if notify == "on" and fs_now.used >= 99 and not helpers.get_map(partition)
|
||||||
then
|
then
|
||||||
naughty.notify({
|
naughty.notify({
|
||||||
title = "warning",
|
title = "warning",
|
||||||
|
@ -110,8 +116,10 @@ local function worker(args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if showpopup == "on" then
|
||||||
fs.widget:connect_signal('mouse::enter', function () fs:show(0) end)
|
fs.widget:connect_signal('mouse::enter', function () fs:show(0) end)
|
||||||
fs.widget:connect_signal('mouse::leave', function () fs:hide() end)
|
fs.widget:connect_signal('mouse::leave', function () fs:hide() end)
|
||||||
|
end
|
||||||
|
|
||||||
helpers.newtimer(partition, timeout, update)
|
helpers.newtimer(partition, timeout, update)
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,7 @@ local function worker(args)
|
||||||
|
|
||||||
helpers.set_map(mail, 0)
|
helpers.set_map(mail, 0)
|
||||||
|
|
||||||
if not is_plain
|
if not is_plain then
|
||||||
then
|
|
||||||
password = helpers.read_pipe(password):gsub("\n", "")
|
password = helpers.read_pipe(password):gsub("\n", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,7 @@ local function worker(args)
|
||||||
maildir.widget = wibox.widget.textbox('')
|
maildir.widget = wibox.widget.textbox('')
|
||||||
|
|
||||||
function update()
|
function update()
|
||||||
if ext_mail_cmd ~= nil
|
if ext_mail_cmd then
|
||||||
then
|
|
||||||
awful.util.spawn(ext_mail_cmd)
|
awful.util.spawn(ext_mail_cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -75,6 +74,7 @@ local function worker(args)
|
||||||
p:close()
|
p:close()
|
||||||
|
|
||||||
newmail = "no mail"
|
newmail = "no mail"
|
||||||
|
|
||||||
-- Count the total number of mails irrespective of where it was found
|
-- Count the total number of mails irrespective of where it was found
|
||||||
total = 0
|
total = 0
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ local function worker(args)
|
||||||
|
|
||||||
mem_now.used = mem_now.total - (mem_now.free + mem_now.buf + mem_now.cache)
|
mem_now.used = mem_now.total - (mem_now.free + mem_now.buf + mem_now.cache)
|
||||||
mem_now.swapused = mem_now.swap - mem_now.swapf
|
mem_now.swapused = mem_now.swap - mem_now.swapf
|
||||||
|
mem_now.perc = math.floor(mem_now.used / mem_now.total * 100)
|
||||||
|
|
||||||
widget = mem.widget
|
widget = mem.widget
|
||||||
settings()
|
settings()
|
||||||
|
|
|
@ -37,6 +37,7 @@ local function worker(args)
|
||||||
local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
|
local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
|
||||||
local cover_size = args.cover_size or 100
|
local cover_size = args.cover_size or 100
|
||||||
local default_art = args.default_art or ""
|
local default_art = args.default_art or ""
|
||||||
|
local notify = args.notify or "on"
|
||||||
local followmouse = args.followmouse or false
|
local followmouse = args.followmouse or false
|
||||||
local echo_cmd = args.echo_cmd or "echo"
|
local echo_cmd = args.echo_cmd or "echo"
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
|
@ -57,6 +58,12 @@ local function worker(args)
|
||||||
function mpd.update()
|
function mpd.update()
|
||||||
async.request(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh, function (f)
|
async.request(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh, function (f)
|
||||||
mpd_now = {
|
mpd_now = {
|
||||||
|
random_mode = false,
|
||||||
|
single_mode = false,
|
||||||
|
repeat_mode = false,
|
||||||
|
consume_mode = false,
|
||||||
|
pls_pos = "N/A",
|
||||||
|
pls_len = "N/A",
|
||||||
state = "N/A",
|
state = "N/A",
|
||||||
file = "N/A",
|
file = "N/A",
|
||||||
name = "N/A",
|
name = "N/A",
|
||||||
|
@ -79,6 +86,12 @@ local function worker(args)
|
||||||
elseif k == "Date" then mpd_now.date = escape_f(v)
|
elseif k == "Date" then mpd_now.date = escape_f(v)
|
||||||
elseif k == "Time" then mpd_now.time = v
|
elseif k == "Time" then mpd_now.time = v
|
||||||
elseif k == "elapsed" then mpd_now.elapsed = string.match(v, "%d+")
|
elseif k == "elapsed" then mpd_now.elapsed = string.match(v, "%d+")
|
||||||
|
elseif k == "song" then mpd_now.pls_pos = v
|
||||||
|
elseif k == "playlistlength" then mpd_now.pls_len = v
|
||||||
|
elseif k == "repeat" then mpd_now.repeat_mode = v ~= "0"
|
||||||
|
elseif k == "single" then mpd_now.single_mode = v ~= "0"
|
||||||
|
elseif k == "random" then mpd_now.random_mode = v ~= "0"
|
||||||
|
elseif k == "consume" then mpd_now.consume_mode = v ~= "0"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -90,7 +103,7 @@ local function worker(args)
|
||||||
|
|
||||||
if mpd_now.state == "play"
|
if mpd_now.state == "play"
|
||||||
then
|
then
|
||||||
if mpd_now.title ~= helpers.get_map("current mpd track")
|
if notify == "on" and mpd_now.title ~= helpers.get_map("current mpd track")
|
||||||
then
|
then
|
||||||
helpers.set_map("current mpd track", mpd_now.title)
|
helpers.set_map("current mpd track", mpd_now.title)
|
||||||
|
|
||||||
|
|
|
@ -128,12 +128,12 @@ local function worker(args)
|
||||||
net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ',', '.')
|
net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ',', '.')
|
||||||
net_now.received = string.gsub(string.format('%.1f', net_now.received), ',', '.')
|
net_now.received = string.gsub(string.format('%.1f', net_now.received), ',', '.')
|
||||||
|
|
||||||
widget = net.widget
|
|
||||||
settings()
|
|
||||||
|
|
||||||
net.last_t = total_t
|
net.last_t = total_t
|
||||||
net.last_r = total_r
|
net.last_r = total_r
|
||||||
end
|
end
|
||||||
|
|
||||||
|
widget = net.widget
|
||||||
|
settings()
|
||||||
end
|
end
|
||||||
|
|
||||||
helpers.newtimer(iface, timeout, update)
|
helpers.newtimer(iface, timeout, update)
|
||||||
|
|
|
@ -10,7 +10,8 @@ local read_pipe = require("lain.helpers").read_pipe
|
||||||
local newtimer = require("lain.helpers").newtimer
|
local newtimer = require("lain.helpers").newtimer
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
|
||||||
local string = { match = string.match,
|
local string = { gmatch = string.gmatch,
|
||||||
|
match = string.match,
|
||||||
format = string.format }
|
format = string.format }
|
||||||
|
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
|
@ -25,7 +26,7 @@ local function worker(args)
|
||||||
local settings = args.settings or function() end
|
local settings = args.settings or function() end
|
||||||
local scallback = args.scallback
|
local scallback = args.scallback
|
||||||
|
|
||||||
pulseaudio.cmd = args.cmd or string.format("pacmd list-sinks | sed -n -e '0,/*/d' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p'")
|
pulseaudio.cmd = args.cmd or string.format("pacmd list-sinks | sed -n -e '0,/*/d' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'")
|
||||||
pulseaudio.widget = wibox.widget.textbox('')
|
pulseaudio.widget = wibox.widget.textbox('')
|
||||||
|
|
||||||
function pulseaudio.update()
|
function pulseaudio.update()
|
||||||
|
@ -33,9 +34,19 @@ local function worker(args)
|
||||||
local s = read_pipe(pulseaudio.cmd)
|
local s = read_pipe(pulseaudio.cmd)
|
||||||
|
|
||||||
volume_now = {}
|
volume_now = {}
|
||||||
volume_now.left = tonumber(string.match(s, ":.-(%d+)%%"))
|
volume_now.index = string.match(s, "index: (%S+)") or "N/A"
|
||||||
volume_now.right = tonumber(string.match(s, ":.-(%d+)%%"))
|
volume_now.sink = string.match(s, "device.string = \"(%S+)\"") or "N/A"
|
||||||
volume_now.muted = string.match(s, "muted: (%S+)")
|
volume_now.muted = string.match(s, "muted: (%S+)") or "N/A"
|
||||||
|
|
||||||
|
local ch = 1
|
||||||
|
volume_now.channel = {}
|
||||||
|
for v in string.gmatch(s, ":.-(%d+)%%") do
|
||||||
|
volume_now.channel[ch] = v
|
||||||
|
ch = ch + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
volume_now.left = volume_now.channel[1] or "N/A"
|
||||||
|
volume_now.right = volume_now.channel[2] or "N/A"
|
||||||
|
|
||||||
widget = pulseaudio.widget
|
widget = pulseaudio.widget
|
||||||
settings()
|
settings()
|
||||||
|
|
|
@ -27,6 +27,7 @@ local setmetatable = setmetatable
|
||||||
-- lain.widgets.pulsebar
|
-- lain.widgets.pulsebar
|
||||||
local pulsebar = {
|
local pulsebar = {
|
||||||
sink = 0,
|
sink = 0,
|
||||||
|
step = "1%",
|
||||||
|
|
||||||
colors = {
|
colors = {
|
||||||
background = beautiful.bg_normal,
|
background = beautiful.bg_normal,
|
||||||
|
@ -105,6 +106,7 @@ local function worker(args)
|
||||||
pulsebar.colors = args.colors or pulsebar.colors
|
pulsebar.colors = args.colors or pulsebar.colors
|
||||||
pulsebar.notifications = args.notifications or pulsebar.notifications
|
pulsebar.notifications = args.notifications or pulsebar.notifications
|
||||||
pulsebar.sink = args.sink or 0
|
pulsebar.sink = args.sink or 0
|
||||||
|
pulsebar.step = args.step or pulsebar.step
|
||||||
pulsebar.followmouse = args.followmouse or false
|
pulsebar.followmouse = args.followmouse or false
|
||||||
|
|
||||||
pulsebar.bar = awful.widget.progressbar()
|
pulsebar.bar = awful.widget.progressbar()
|
||||||
|
@ -148,9 +150,25 @@ local function worker(args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
pulsebar.bar:buttons (awful.util.table.join (
|
pulsebar.bar:buttons(awful.util.table.join (
|
||||||
awful.button ({}, 1, function()
|
awful.button({}, 1, function()
|
||||||
awful.util.spawn(pulsebar.mixer)
|
awful.util.spawn(pulsebar.mixer)
|
||||||
|
end),
|
||||||
|
awful.button({}, 2, function()
|
||||||
|
awful.util.spawn(string.format("pactl set-sink-volume %d 100%%", pulsebar.sink))
|
||||||
|
pulsebar.update()
|
||||||
|
end),
|
||||||
|
awful.button({}, 3, function()
|
||||||
|
awful.util.spawn(string.format("pactl set-sink-mute %d toggle", pulsebar.sink))
|
||||||
|
pulsebar.update()
|
||||||
|
end),
|
||||||
|
awful.button({}, 4, function()
|
||||||
|
awful.util.spawn(string.format("pactl set-sink-volume %d +%s", pulsebar.sink, pulsebar.step))
|
||||||
|
pulsebar.update()
|
||||||
|
end),
|
||||||
|
awful.button({}, 5, function()
|
||||||
|
awful.util.spawn(string.format("pactl set-sink-volume %d -%s", pulsebar.sink, pulsebar.step))
|
||||||
|
pulsebar.update()
|
||||||
end)
|
end)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ local function worker(args)
|
||||||
local pos, err
|
local pos, err
|
||||||
weather_now, pos, err = json.decode(f, 1, nil)
|
weather_now, pos, err = json.decode(f, 1, nil)
|
||||||
|
|
||||||
if not err and weather_now and tonumber(weather_now["cod"]) == 200 then
|
if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then
|
||||||
weather.notification_text = ''
|
weather.notification_text = ''
|
||||||
for i = 1, weather_now["cnt"] do
|
for i = 1, weather_now["cnt"] do
|
||||||
weather.notification_text = weather.notification_text ..
|
weather.notification_text = weather.notification_text ..
|
||||||
|
@ -128,7 +128,7 @@ local function worker(args)
|
||||||
local pos, err, icon
|
local pos, err, icon
|
||||||
weather_now, pos, err = json.decode(f, 1, nil)
|
weather_now, pos, err = json.decode(f, 1, nil)
|
||||||
|
|
||||||
if not err and weather_now and tonumber(weather_now["cod"]) == 200 then
|
if not err and type(weather_now) == "table" and tonumber(weather_now["cod"]) == 200 then
|
||||||
-- weather icon based on localtime
|
-- weather icon based on localtime
|
||||||
local now = os.time()
|
local now = os.time()
|
||||||
local sunrise = tonumber(weather_now["sys"]["sunrise"])
|
local sunrise = tonumber(weather_now["sys"]["sunrise"])
|
||||||
|
|
2
wiki
2
wiki
|
@ -1 +1 @@
|
||||||
Subproject commit 25dd1a2ec44da832d06ded29f393d716e4b54783
|
Subproject commit d0df450d05655c5d8f724c42dc6b5d18b3676a60
|
Loading…
Reference in New Issue