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
|
||||
.. _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
|
||||
|
|
|
@ -52,7 +52,7 @@ function asyncshell.request(command, callback, timeout)
|
|||
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)
|
||||
else
|
||||
awful.util.spawn_with_shell(req)
|
||||
|
|
16
helpers.lua
16
helpers.lua
|
@ -8,6 +8,7 @@
|
|||
|
||||
local debug = require("debug")
|
||||
|
||||
local assert = assert
|
||||
local capi = { timer = (type(timer) == 'table' and timer or require ("gears.timer")) }
|
||||
local io = { open = io.open,
|
||||
lines = io.lines,
|
||||
|
@ -93,9 +94,9 @@ function helpers.newtimer(_name, timeout, fun, nostart)
|
|||
local name = timeout
|
||||
if not helpers.timer_table[name] then
|
||||
helpers.timer_table[name] = capi.timer({ timeout = timeout })
|
||||
helpers.timer_table[name]:start()
|
||||
end
|
||||
helpers.timer_table[name]:connect_signal("timeout", fun)
|
||||
helpers.timer_table[name]:start()
|
||||
if not nostart then
|
||||
helpers.timer_table[name]:emit_signal("timeout")
|
||||
end
|
||||
|
@ -105,7 +106,7 @@ end
|
|||
|
||||
-- {{{ Pipe operations
|
||||
|
||||
-- read the full output of a pipe (command)
|
||||
-- read the full output of a command output
|
||||
function helpers.read_pipe(cmd)
|
||||
local f = assert(io.popen(cmd))
|
||||
local output = f:read("*all")
|
||||
|
@ -113,6 +114,16 @@ function helpers.read_pipe(cmd)
|
|||
return output
|
||||
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
|
||||
|
@ -148,4 +159,5 @@ function helpers.spairs(t)
|
|||
end
|
||||
--}}}
|
||||
|
||||
|
||||
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
|
||||
# -------------------------------------------------------------------------
|
||||
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
|
||||
WEB_OUTPUT=0
|
||||
DF_OPTIONS=""
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
|
@ -31,6 +32,12 @@ NARROW_MODE=1
|
|||
"-w" )
|
||||
WEB_OUTPUT=1
|
||||
;;
|
||||
--type=*)
|
||||
DF_OPTIONS+=" $1"
|
||||
;;
|
||||
--exclude-type=*)
|
||||
DF_OPTIONS+=" $1"
|
||||
;;
|
||||
* )
|
||||
echo $USAGE
|
||||
exit
|
||||
|
@ -58,6 +65,9 @@ AWK_COMMAND="/usr/bin/env gawk"
|
|||
;;
|
||||
esac
|
||||
|
||||
# Add additional df options
|
||||
DF_COMMAND+=$DF_OPTIONS
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Grabbing "df" result
|
||||
# -------------------------------------------------------------------------
|
||||
|
|
|
@ -98,7 +98,7 @@ function util.mc(c)
|
|||
g.height = math.sqrt(mwfact) * mg.height
|
||||
g.x = mg.x + (mg.width - g.width) / 2
|
||||
g.y = mg.y + (mg.height - g.height) / 2
|
||||
c:geometry(g)
|
||||
if c then c:geometry(g) end -- if c is still a valid object
|
||||
end
|
||||
|
||||
-- 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
|
|
@ -26,14 +26,20 @@ local function worker(args)
|
|||
local timeout = args.timeout or 5
|
||||
local settings = args.settings or function() end
|
||||
|
||||
alsa.cmd = args.cmd or "amixer"
|
||||
alsa.channel = args.channel or "Master"
|
||||
alsa.widget = wibox.widget.textbox('')
|
||||
alsa.cmd = args.cmd or "amixer"
|
||||
alsa.channel = args.channel or "Master"
|
||||
alsa.togglechannel = args.togglechannel
|
||||
alsa.widget = wibox.widget.textbox('')
|
||||
|
||||
function alsa.update()
|
||||
mixer = read_pipe(string.format("%s get %s", alsa.cmd, alsa.channel))
|
||||
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
|
||||
volume_now = { level = l, status = s }
|
||||
alsa.last_level = l
|
||||
|
|
|
@ -27,7 +27,7 @@ local setmetatable = setmetatable
|
|||
-- lain.widgets.alsabar
|
||||
local alsabar = {
|
||||
channel = "Master",
|
||||
step = "2%",
|
||||
step = "1%",
|
||||
|
||||
colors = {
|
||||
background = beautiful.bg_normal,
|
||||
|
@ -104,6 +104,7 @@ local function worker(args)
|
|||
|
||||
alsabar.cmd = args.cmd or "amixer"
|
||||
alsabar.channel = args.channel or alsabar.channel
|
||||
alsabar.togglechannel = args.togglechannel
|
||||
alsabar.step = args.step or alsabar.step
|
||||
alsabar.colors = args.colors or alsabar.colors
|
||||
alsabar.notifications = args.notifications or alsabar.notifications
|
||||
|
@ -127,9 +128,14 @@ local function worker(args)
|
|||
-- Capture mixer control state: [5%] ... ... [on]
|
||||
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)
|
||||
then
|
||||
alsabar._current_level = tonumber(volu)
|
||||
alsabar._current_level = tonumber(volu) or alsabar._current_level
|
||||
alsabar.bar:set_value(alsabar._current_level / 100)
|
||||
if not mute and tonumber(volu) == 0 or mute == "off"
|
||||
then
|
||||
|
@ -149,19 +155,23 @@ local function worker(args)
|
|||
end
|
||||
end
|
||||
|
||||
alsabar.bar:buttons (awful.util.table.join (
|
||||
awful.button ({}, 1, function()
|
||||
alsabar.bar:buttons(awful.util.table.join (
|
||||
awful.button({}, 1, function()
|
||||
awful.util.spawn(alsabar.mixer)
|
||||
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))
|
||||
alsabar.update()
|
||||
end),
|
||||
awful.button ({}, 4, function()
|
||||
awful.button({}, 4, function()
|
||||
awful.util.spawn(string.format("%s set %s %s+", alsabar.cmd, alsabar.channel, alsabar.step))
|
||||
alsabar.update()
|
||||
end),
|
||||
awful.button ({}, 5, function()
|
||||
awful.button({}, 5, function()
|
||||
awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step))
|
||||
alsabar.update()
|
||||
end)
|
||||
|
|
|
@ -26,8 +26,8 @@ local function worker(args)
|
|||
base.widget = wibox.widget.textbox('')
|
||||
|
||||
function base.update()
|
||||
output = read_pipe(cmd)
|
||||
if output ~= base.prev then
|
||||
output = read_pipe(cmd)
|
||||
widget = base.widget
|
||||
settings()
|
||||
base.prev = output
|
||||
|
|
114
widgets/bat.lua
114
widgets/bat.lua
|
@ -13,10 +13,14 @@ local first_line = require("lain.helpers").first_line
|
|||
local naughty = require("naughty")
|
||||
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 tonumber = tonumber
|
||||
|
||||
local type = type
|
||||
local tonumber = tonumber
|
||||
local setmetatable = setmetatable
|
||||
|
||||
-- Battery infos
|
||||
|
@ -50,7 +54,7 @@ local function worker(args)
|
|||
}
|
||||
|
||||
bat_now = {
|
||||
status = "Not present",
|
||||
status = "N/A",
|
||||
ac_status = "N/A",
|
||||
perc = "N/A",
|
||||
time = "N/A",
|
||||
|
@ -58,28 +62,30 @@ local function worker(args)
|
|||
}
|
||||
|
||||
bat_now.n_status = {}
|
||||
bat_now.n_perc = {}
|
||||
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
|
||||
|
||||
function update()
|
||||
function bat.update()
|
||||
local sum_rate_current = 0
|
||||
local sum_rate_voltage = 0
|
||||
local sum_rate_power = 0
|
||||
local sum_energy_now = 0
|
||||
local sum_energy_full = 0
|
||||
local sum_energy_percentage = 0
|
||||
local sum_rate_power = 0
|
||||
local sum_rate_energy = 0
|
||||
local sum_energy_now = 0
|
||||
local sum_energy_full = 0
|
||||
local pspath = "/sys/class/power_supply/"
|
||||
|
||||
for i, battery in ipairs(batteries) do
|
||||
local bstr = "/sys/class/power_supply/" .. battery
|
||||
local bstr = pspath .. battery
|
||||
local present = first_line(bstr .. "/present")
|
||||
|
||||
if present == "1"
|
||||
then
|
||||
if tonumber(present) == 1 then
|
||||
-- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW]
|
||||
local rate_current = tonumber(first_line(bstr .. "/current_now"))
|
||||
local rate_voltage = tonumber(first_line(bstr .. "/voltage_now"))
|
||||
local rate_power = tonumber(first_line(bstr .. "/power_now"))
|
||||
local rate_current = tonumber(first_line(bstr .. "/current_now"))
|
||||
local rate_voltage = tonumber(first_line(bstr .. "/voltage_now"))
|
||||
local rate_power = tonumber(first_line(bstr .. "/power_now"))
|
||||
|
||||
-- energy_now(P)[uWh], charge_now(I)[uAh]
|
||||
local energy_now = tonumber(first_line(bstr .. "/energy_now") or
|
||||
|
@ -92,64 +98,74 @@ local function worker(args)
|
|||
local energy_percentage = tonumber(first_line(bstr .. "/capacity")) or
|
||||
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"
|
||||
end
|
||||
bat_now.n_status[i] = first_line(bstr .. "/status") or "N/A"
|
||||
bat_now.n_perc[i] = energy_percentage or bat_now.n_perc[i]
|
||||
|
||||
sum_rate_current = sum_rate_current + (rate_current or 0)
|
||||
sum_rate_voltage = sum_rate_voltage + rate_voltage
|
||||
sum_rate_power = sum_rate_power + (rate_power or ((rate_voltage * rate_current) / 1e6))
|
||||
sum_energy_now = sum_energy_now + energy_now
|
||||
sum_energy_full = sum_energy_full + energy_full
|
||||
sum_energy_percentage = sum_energy_percentage + energy_percentage
|
||||
sum_rate_current = sum_rate_current + (rate_current or 0)
|
||||
sum_rate_voltage = sum_rate_voltage + (rate_voltage or 0)
|
||||
sum_rate_power = sum_rate_power + (rate_power or 0)
|
||||
sum_rate_energy = sum_rate_energy + (rate_power or (((rate_voltage or 0) * (rate_current or 0)) / 1e6))
|
||||
sum_energy_now = sum_energy_now + (energy_now or 0)
|
||||
sum_energy_full = sum_energy_full + (energy_full or 0)
|
||||
end
|
||||
end
|
||||
|
||||
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 (sum_rate_current > 0 or sum_rate_power > 0) and not (bat_now.status == "Full")
|
||||
then
|
||||
local rate_time = 0
|
||||
if bat_now.status ~= "N/A" then
|
||||
-- update {perc,time,watt} iff battery not full and rate > 0
|
||||
if bat_now.status ~= "Full" and (sum_rate_power > 0 or sum_rate_current > 0) then
|
||||
local rate_time = 0
|
||||
local div = (sum_rate_power > 0 and sum_rate_power) or sum_rate_current
|
||||
|
||||
if bat_now.status == "Charging" then
|
||||
rate_time = (sum_energy_full - sum_energy_now) / (sum_rate_power or sum_rate_current)
|
||||
elseif bat_now.status == "Discharging" then
|
||||
rate_time = sum_energy_now / (sum_rate_power or sum_rate_current)
|
||||
if bat_now.status == "Charging" then
|
||||
rate_time = (sum_energy_full - sum_energy_now) / div
|
||||
else -- Discharging
|
||||
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
|
||||
|
||||
local hours = math.floor(rate_time)
|
||||
local minutes = math.floor((rate_time - hours) * 60)
|
||||
bat_now.perc = math.floor(math.min(100, (sum_energy_now / sum_energy_full) * 100))
|
||||
bat_now.time = string.format("%02d:%02d", hours, minutes)
|
||||
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
|
||||
|
||||
local hours = math.floor(rate_time)
|
||||
local minutes = math.floor((rate_time - hours) * 60)
|
||||
local watt = sum_rate_power / 1e6
|
||||
|
||||
bat_now.perc = string.format("%d", math.min(100, sum_energy_percentage / #batteries))
|
||||
bat_now.time = string.format("%02d:%02d", hours, minutes)
|
||||
bat_now.watt = string.format("%.2fW", watt)
|
||||
end
|
||||
|
||||
widget = bat.widget
|
||||
settings()
|
||||
|
||||
-- notifications for low and critical states
|
||||
if bat_now.status == "Discharging" and notify == "on" and bat_now.perc then
|
||||
local nperc = tonumber(bat_now.perc) or 100
|
||||
if nperc <= 5 then
|
||||
if notify == "on" and type(bat_now.perc) == "number" and bat_now.status == "Discharging" then
|
||||
if bat_now.perc <= 5 then
|
||||
bat.id = naughty.notify({
|
||||
preset = bat_notification_critical_preset,
|
||||
replaces_id = bat.id,
|
||||
replaces_id = bat.id
|
||||
}).id
|
||||
elseif nperc <= 15 then
|
||||
elseif bat_now.perc <= 15 then
|
||||
bat.id = naughty.notify({
|
||||
preset = bat_notification_low_preset,
|
||||
replaces_id = bat.id,
|
||||
replaces_id = bat.id
|
||||
}).id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newtimer(battery, timeout, update)
|
||||
newtimer(battery, timeout, bat.update)
|
||||
|
||||
return setmetatable(bat, { __index = bat.widget })
|
||||
end
|
||||
|
|
|
@ -27,15 +27,15 @@ local setmetatable = setmetatable
|
|||
local calendar = {}
|
||||
local cal_notification = nil
|
||||
|
||||
function calendar:hide()
|
||||
function calendar.hide()
|
||||
if cal_notification ~= nil then
|
||||
naughty.destroy(cal_notification)
|
||||
cal_notification = nil
|
||||
end
|
||||
end
|
||||
|
||||
function calendar:show(t_out, inc_offset, scr)
|
||||
calendar:hide()
|
||||
function calendar.show(t_out, inc_offset, scr)
|
||||
calendar.hide()
|
||||
|
||||
local f, c_text
|
||||
local offs = inc_offset or 0
|
||||
|
@ -96,7 +96,7 @@ function calendar:show(t_out, inc_offset, scr)
|
|||
})
|
||||
end
|
||||
|
||||
function calendar:attach(widget, args)
|
||||
function calendar.attach(widget, args)
|
||||
local args = args or {}
|
||||
|
||||
calendar.cal = args.cal or "/usr/bin/cal"
|
||||
|
@ -116,16 +116,16 @@ function calendar:attach(widget, args)
|
|||
calendar.offset = 0
|
||||
calendar.notify_icon = nil
|
||||
|
||||
widget:connect_signal("mouse::enter", function () calendar:show(0, 0, calendar.scr_pos) end)
|
||||
widget:connect_signal("mouse::leave", function () calendar:hide() end)
|
||||
widget:connect_signal("mouse::enter", function () calendar.show(0, 0, calendar.scr_pos) end)
|
||||
widget:connect_signal("mouse::leave", function () calendar.hide() end)
|
||||
widget:buttons(awful.util.table.join(awful.button({ }, 1, function ()
|
||||
calendar:show(0, -1, calendar.scr_pos) end),
|
||||
calendar.show(0, -1, calendar.scr_pos) end),
|
||||
awful.button({ }, 3, function ()
|
||||
calendar:show(0, 1, calendar.scr_pos) end),
|
||||
calendar.show(0, 1, calendar.scr_pos) end),
|
||||
awful.button({ }, 4, function ()
|
||||
calendar:show(0, -1, calendar.scr_pos) end),
|
||||
calendar.show(0, -1, calendar.scr_pos) end),
|
||||
awful.button({ }, 5, function ()
|
||||
calendar:show(0, 1, calendar.scr_pos) end)))
|
||||
calendar.show(0, 1, calendar.scr_pos) end)))
|
||||
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
|
||||
-- lain.widgets.contrib.kblayout
|
||||
|
||||
local function worker (args)
|
||||
local function worker(args)
|
||||
local kbdlayout = {}
|
||||
kbdlayout.widget = wibox.widget.textbox('')
|
||||
|
||||
|
@ -36,21 +36,21 @@ local function worker (args)
|
|||
awful.button({ }, 1, function () kbdlayout.next() end),
|
||||
awful.button({ }, 3, function () kbdlayout.prev() end)))
|
||||
|
||||
local function run_settings (layout, variant)
|
||||
local function run_settings(layout, variant)
|
||||
widget = kbdlayout.widget
|
||||
kbdlayout_now = { layout=string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
|
||||
variant=variant }
|
||||
settings()
|
||||
end
|
||||
|
||||
function kbdlayout.update ()
|
||||
function kbdlayout.update()
|
||||
local status = read_pipe('setxkbmap -query')
|
||||
|
||||
run_settings(string.match(status, "layout:%s*([^\n]*)"),
|
||||
string.match(status, "variant:%s*([^\n]*)"))
|
||||
end
|
||||
|
||||
function kbdlayout.set (i)
|
||||
function kbdlayout.set(i)
|
||||
idx = ((i - 1) % #layouts) + 1 -- Make sure to wrap around as needed.
|
||||
local to_execute = 'setxkbmap ' .. layouts[idx].layout
|
||||
|
||||
|
@ -67,11 +67,11 @@ local function worker (args)
|
|||
end
|
||||
end
|
||||
|
||||
function kbdlayout.next ()
|
||||
function kbdlayout.next()
|
||||
kbdlayout.set(idx + 1)
|
||||
end
|
||||
|
||||
function kbdlayout.prev ()
|
||||
function kbdlayout.prev()
|
||||
kbdlayout.set(idx - 1)
|
||||
end
|
||||
|
||||
|
|
|
@ -16,11 +16,10 @@ local setmetatable = setmetatable
|
|||
-- lain.widgets.contrib.redshift
|
||||
local redshift = {}
|
||||
|
||||
local attached = false -- true if attached to a widget
|
||||
local active = false -- true if redshift is active
|
||||
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 attached = false -- true if attached to a widget
|
||||
local active = false -- true if redshift is active
|
||||
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 function init()
|
||||
-- As there is no way to determine if redshift was previously
|
||||
|
|
|
@ -25,29 +25,34 @@ local task = {}
|
|||
|
||||
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
|
||||
naughty.destroy(task_notification)
|
||||
task_notification = nil
|
||||
end
|
||||
end
|
||||
|
||||
function task:show(scr_pos)
|
||||
task:hide()
|
||||
function task.show(scr_pos)
|
||||
task.hide()
|
||||
|
||||
local f, c_text
|
||||
local f, c_text, scrp
|
||||
|
||||
if task.followmouse then
|
||||
local scrp = mouse.screen
|
||||
scrp = mouse.screen
|
||||
else
|
||||
local scrp = scr_pos or task.scr_pos
|
||||
scrp = scr_pos or task.scr_pos
|
||||
end
|
||||
|
||||
f = io.popen('task')
|
||||
f = io.popen('task ' .. task.cmdline)
|
||||
c_text = "<span font='"
|
||||
.. task.font .. " "
|
||||
.. task.font_size .. "'>"
|
||||
.. f:read("*all"):gsub("\n*$", "")
|
||||
.. awful.util.escape(f:read("*all"):gsub("\n*$", ""))
|
||||
.. "</span>"
|
||||
f:close()
|
||||
|
||||
|
@ -62,7 +67,7 @@ function task:show(scr_pos)
|
|||
})
|
||||
end
|
||||
|
||||
function task:prompt_add()
|
||||
function task.prompt_add()
|
||||
awful.prompt.run({ prompt = "Add task: " },
|
||||
mypromptbox[mouse.screen].widget,
|
||||
function (...)
|
||||
|
@ -70,7 +75,7 @@ function task:prompt_add()
|
|||
c_text = "\n<span font='"
|
||||
.. task.font .. " "
|
||||
.. task.font_size .. "'>"
|
||||
.. f:read("*all")
|
||||
.. awful.util.escape(f:read("*all"))
|
||||
.. "</span>"
|
||||
f:close()
|
||||
|
||||
|
@ -87,7 +92,7 @@ function task:prompt_add()
|
|||
awful.util.getdir("cache") .. "/history_task_add")
|
||||
end
|
||||
|
||||
function task:prompt_search()
|
||||
function task.prompt_search()
|
||||
awful.prompt.run({ prompt = "Search task: " },
|
||||
mypromptbox[mouse.screen].widget,
|
||||
function (...)
|
||||
|
@ -102,7 +107,7 @@ function task:prompt_search()
|
|||
c_text = "<span font='"
|
||||
.. task.font .. " "
|
||||
.. task.font_size .. "'>"
|
||||
.. c_text
|
||||
.. awful.util.escape(c_text)
|
||||
.. "</span>"
|
||||
end
|
||||
|
||||
|
@ -121,24 +126,25 @@ function task:prompt_search()
|
|||
awful.util.getdir("cache") .. "/history_task")
|
||||
end
|
||||
|
||||
function task:attach(widget, args)
|
||||
function task.attach(widget, args)
|
||||
local args = args or {}
|
||||
|
||||
task.font_size = tonumber(args.font_size) or 12
|
||||
task.font = beautiful.font:sub(beautiful.font:find(""),
|
||||
beautiful.font:find(" "))
|
||||
task.font = args.font or beautiful.font:sub(beautiful.font:find(""),
|
||||
findLast(beautiful.font, " "))
|
||||
task.fg = args.fg or beautiful.fg_normal or "#FFFFFF"
|
||||
task.bg = args.bg or beautiful.bg_normal or "#FFFFFF"
|
||||
task.position = args.position or "top_right"
|
||||
task.timeout = args.timeout or 7
|
||||
task.scr_pos = args.scr_pos or 1
|
||||
task.followmouse = args.followmouse or false
|
||||
task.cmdline = args.cmdline or "next"
|
||||
|
||||
task.notify_icon = icons_dir .. "/taskwarrior/task.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::leave", function () task:hide() end)
|
||||
widget:connect_signal("mouse::enter", function () task.show(task.scr_pos) end)
|
||||
widget:connect_signal("mouse::leave", function () task.hide() end)
|
||||
end
|
||||
|
||||
return setmetatable(task, { __call = function(_, ...) return create(...) end })
|
||||
|
|
|
@ -16,7 +16,6 @@ local tonumber = tonumber
|
|||
local setmetatable = setmetatable
|
||||
|
||||
local smapi = {}
|
||||
|
||||
local apipath = "/sys/devices/platform/smapi"
|
||||
|
||||
-- Most are readable values, but some can be written to (not implemented, yet?)
|
||||
|
|
|
@ -28,26 +28,29 @@ local setmetatable = setmetatable
|
|||
local fs = {}
|
||||
local fs_notification = nil
|
||||
|
||||
function fs:hide()
|
||||
function fs.hide()
|
||||
if fs_notification ~= nil then
|
||||
naughty.destroy(fs_notification)
|
||||
fs_notification = nil
|
||||
end
|
||||
end
|
||||
|
||||
function fs:show(t_out)
|
||||
fs:hide()
|
||||
function fs.show(seconds, options, scr)
|
||||
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
|
||||
fs.notification_preset.screen = mouse.screen
|
||||
elseif scr then
|
||||
fs.notification_preset.screen = scr
|
||||
end
|
||||
|
||||
fs_notification = naughty.notify({
|
||||
preset = fs.notification_preset,
|
||||
text = ws,
|
||||
timeout = t_out
|
||||
timeout = seconds or 5
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -58,6 +61,8 @@ local function worker(args)
|
|||
local args = args or {}
|
||||
local timeout = args.timeout or 600
|
||||
local partition = args.partition or "/"
|
||||
local showpopup = args.showpopup or "on"
|
||||
local notify = args.notify or "on"
|
||||
local settings = args.settings or function() end
|
||||
|
||||
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_gb = tonumber(fs_info[partition .. " size_gb"]) or 0
|
||||
|
||||
notification_preset = fs.notification_preset
|
||||
widget = fs.widget
|
||||
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
|
||||
naughty.notify({
|
||||
title = "warning",
|
||||
|
@ -110,8 +116,10 @@ local function worker(args)
|
|||
end
|
||||
end
|
||||
|
||||
fs.widget:connect_signal('mouse::enter', function () fs:show(0) end)
|
||||
fs.widget:connect_signal('mouse::leave', function () fs:hide() end)
|
||||
if showpopup == "on" then
|
||||
fs.widget:connect_signal('mouse::enter', function () fs:show(0) end)
|
||||
fs.widget:connect_signal('mouse::leave', function () fs:hide() end)
|
||||
end
|
||||
|
||||
helpers.newtimer(partition, timeout, update)
|
||||
|
||||
|
|
|
@ -41,8 +41,7 @@ local function worker(args)
|
|||
|
||||
helpers.set_map(mail, 0)
|
||||
|
||||
if not is_plain
|
||||
then
|
||||
if not is_plain then
|
||||
password = helpers.read_pipe(password):gsub("\n", "")
|
||||
end
|
||||
|
||||
|
|
|
@ -39,8 +39,7 @@ local function worker(args)
|
|||
maildir.widget = wibox.widget.textbox('')
|
||||
|
||||
function update()
|
||||
if ext_mail_cmd ~= nil
|
||||
then
|
||||
if ext_mail_cmd then
|
||||
awful.util.spawn(ext_mail_cmd)
|
||||
end
|
||||
|
||||
|
@ -75,6 +74,7 @@ local function worker(args)
|
|||
p:close()
|
||||
|
||||
newmail = "no mail"
|
||||
|
||||
-- Count the total number of mails irrespective of where it was found
|
||||
total = 0
|
||||
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
|
||||
--]]
|
||||
|
||||
local newtimer = require("lain.helpers").newtimer
|
||||
local newtimer = require("lain.helpers").newtimer
|
||||
|
||||
local wibox = require("wibox")
|
||||
local wibox = require("wibox")
|
||||
|
||||
local io = { lines = io.lines }
|
||||
local math = { floor = math.floor }
|
||||
local string = { gmatch = string.gmatch }
|
||||
local io = { lines = io.lines }
|
||||
local math = { floor = math.floor }
|
||||
local string = { gmatch = string.gmatch }
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local setmetatable = setmetatable
|
||||
|
||||
-- Memory usage (ignoring caches)
|
||||
-- lain.widgets.mem
|
||||
|
@ -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.swapused = mem_now.swap - mem_now.swapf
|
||||
mem_now.perc = math.floor(mem_now.used / mem_now.total * 100)
|
||||
|
||||
widget = mem.widget
|
||||
settings()
|
||||
|
|
|
@ -14,13 +14,13 @@ local escape_f = require("awful.util").escape
|
|||
local naughty = require("naughty")
|
||||
local wibox = require("wibox")
|
||||
|
||||
local os = { execute = os.execute,
|
||||
getenv = os.getenv }
|
||||
local math = { floor = math.floor }
|
||||
local os = { execute = os.execute,
|
||||
getenv = os.getenv }
|
||||
local math = { floor = math.floor }
|
||||
local mouse = mouse
|
||||
local string = { format = string.format,
|
||||
match = string.match,
|
||||
gmatch = string.gmatch }
|
||||
local string = { format = string.format,
|
||||
match = string.match,
|
||||
gmatch = string.gmatch }
|
||||
|
||||
local setmetatable = setmetatable
|
||||
|
||||
|
@ -37,6 +37,7 @@ local function worker(args)
|
|||
local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
|
||||
local cover_size = args.cover_size or 100
|
||||
local default_art = args.default_art or ""
|
||||
local notify = args.notify or "on"
|
||||
local followmouse = args.followmouse or false
|
||||
local echo_cmd = args.echo_cmd or "echo"
|
||||
local settings = args.settings or function() end
|
||||
|
@ -57,28 +58,40 @@ local function worker(args)
|
|||
function mpd.update()
|
||||
async.request(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh, function (f)
|
||||
mpd_now = {
|
||||
state = "N/A",
|
||||
file = "N/A",
|
||||
name = "N/A",
|
||||
artist = "N/A",
|
||||
title = "N/A",
|
||||
album = "N/A",
|
||||
date = "N/A",
|
||||
time = "N/A",
|
||||
elapsed = "N/A"
|
||||
random_mode = false,
|
||||
single_mode = false,
|
||||
repeat_mode = false,
|
||||
consume_mode = false,
|
||||
pls_pos = "N/A",
|
||||
pls_len = "N/A",
|
||||
state = "N/A",
|
||||
file = "N/A",
|
||||
name = "N/A",
|
||||
artist = "N/A",
|
||||
title = "N/A",
|
||||
album = "N/A",
|
||||
date = "N/A",
|
||||
time = "N/A",
|
||||
elapsed = "N/A"
|
||||
}
|
||||
|
||||
for line in string.gmatch(f, "[^\n]+") do
|
||||
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
|
||||
if k == "state" then mpd_now.state = v
|
||||
elseif k == "file" then mpd_now.file = v
|
||||
elseif k == "Name" then mpd_now.name = escape_f(v)
|
||||
elseif k == "Artist" then mpd_now.artist = escape_f(v)
|
||||
elseif k == "Title" then mpd_now.title = escape_f(v)
|
||||
elseif k == "Album" then mpd_now.album = escape_f(v)
|
||||
elseif k == "Date" then mpd_now.date = escape_f(v)
|
||||
elseif k == "Time" then mpd_now.time = v
|
||||
elseif k == "elapsed" then mpd_now.elapsed = string.match(v, "%d+")
|
||||
if k == "state" then mpd_now.state = v
|
||||
elseif k == "file" then mpd_now.file = v
|
||||
elseif k == "Name" then mpd_now.name = escape_f(v)
|
||||
elseif k == "Artist" then mpd_now.artist = escape_f(v)
|
||||
elseif k == "Title" then mpd_now.title = escape_f(v)
|
||||
elseif k == "Album" then mpd_now.album = escape_f(v)
|
||||
elseif k == "Date" then mpd_now.date = escape_f(v)
|
||||
elseif k == "Time" then mpd_now.time = v
|
||||
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
|
||||
|
@ -90,7 +103,7 @@ local function worker(args)
|
|||
|
||||
if mpd_now.state == "play"
|
||||
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
|
||||
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.received = string.gsub(string.format('%.1f', net_now.received), ',', '.')
|
||||
|
||||
widget = net.widget
|
||||
settings()
|
||||
|
||||
net.last_t = total_t
|
||||
net.last_r = total_r
|
||||
end
|
||||
|
||||
widget = net.widget
|
||||
settings()
|
||||
end
|
||||
|
||||
helpers.newtimer(iface, timeout, update)
|
||||
|
|
|
@ -6,14 +6,15 @@
|
|||
|
||||
--]]
|
||||
|
||||
local read_pipe = require("lain.helpers").read_pipe
|
||||
local newtimer = require("lain.helpers").newtimer
|
||||
local wibox = require("wibox")
|
||||
local read_pipe = require("lain.helpers").read_pipe
|
||||
local newtimer = require("lain.helpers").newtimer
|
||||
local wibox = require("wibox")
|
||||
|
||||
local string = { match = string.match,
|
||||
format = string.format }
|
||||
local string = { gmatch = string.gmatch,
|
||||
match = string.match,
|
||||
format = string.format }
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local setmetatable = setmetatable
|
||||
|
||||
-- PulseAudio volume
|
||||
-- lain.widgets.pulseaudio
|
||||
|
@ -25,7 +26,7 @@ local function worker(args)
|
|||
local settings = args.settings or function() end
|
||||
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('')
|
||||
|
||||
function pulseaudio.update()
|
||||
|
@ -33,9 +34,19 @@ local function worker(args)
|
|||
local s = read_pipe(pulseaudio.cmd)
|
||||
|
||||
volume_now = {}
|
||||
volume_now.left = tonumber(string.match(s, ":.-(%d+)%%"))
|
||||
volume_now.right = tonumber(string.match(s, ":.-(%d+)%%"))
|
||||
volume_now.muted = string.match(s, "muted: (%S+)")
|
||||
volume_now.index = string.match(s, "index: (%S+)") or "N/A"
|
||||
volume_now.sink = string.match(s, "device.string = \"(%S+)\"") or "N/A"
|
||||
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
|
||||
settings()
|
||||
|
|
|
@ -27,6 +27,7 @@ local setmetatable = setmetatable
|
|||
-- lain.widgets.pulsebar
|
||||
local pulsebar = {
|
||||
sink = 0,
|
||||
step = "1%",
|
||||
|
||||
colors = {
|
||||
background = beautiful.bg_normal,
|
||||
|
@ -105,6 +106,7 @@ local function worker(args)
|
|||
pulsebar.colors = args.colors or pulsebar.colors
|
||||
pulsebar.notifications = args.notifications or pulsebar.notifications
|
||||
pulsebar.sink = args.sink or 0
|
||||
pulsebar.step = args.step or pulsebar.step
|
||||
pulsebar.followmouse = args.followmouse or false
|
||||
|
||||
pulsebar.bar = awful.widget.progressbar()
|
||||
|
@ -148,10 +150,26 @@ local function worker(args)
|
|||
end
|
||||
end
|
||||
|
||||
pulsebar.bar:buttons (awful.util.table.join (
|
||||
awful.button ({}, 1, function()
|
||||
pulsebar.bar:buttons(awful.util.table.join (
|
||||
awful.button({}, 1, function()
|
||||
awful.util.spawn(pulsebar.mixer)
|
||||
end)
|
||||
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)
|
||||
))
|
||||
|
||||
timer_id = string.format("pulsebar-%s", pulsebar.sink)
|
||||
|
|
|
@ -108,7 +108,7 @@ local function worker(args)
|
|||
local pos, err
|
||||
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 = ''
|
||||
for i = 1, weather_now["cnt"] do
|
||||
weather.notification_text = weather.notification_text ..
|
||||
|
@ -128,7 +128,7 @@ local function worker(args)
|
|||
local pos, err, icon
|
||||
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
|
||||
local now = os.time()
|
||||
local sunrise = tonumber(weather_now["sys"]["sunrise"])
|
||||
|
|
2
wiki
2
wiki
|
@ -1 +1 @@
|
|||
Subproject commit 25dd1a2ec44da832d06ded29f393d716e4b54783
|
||||
Subproject commit d0df450d05655c5d8f724c42dc6b5d18b3676a60
|
Loading…
Reference in New Issue