From 32a5f32dc47cf930a72e14962caf8f624fbb9d4c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 02:38:48 -0700 Subject: [PATCH 001/572] Initial commit --- LICENSE | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 4 + 2 files changed, 343 insertions(+) create mode 100644 LICENSE create mode 100644 README.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8c97c99 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + Next generation Vain + Copyright (C) 2013 Luke Bonham + + 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2f3d7af --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +lain +==== + +Next generation Vain From 3387b4caef938fc40d30dc0adb22386f9f3342ab Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:05:00 -0700 Subject: [PATCH 002/572] Initial Commit --- Home.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Home.md diff --git a/Home.md b/Home.md new file mode 100644 index 0000000..a520d81 --- /dev/null +++ b/Home.md @@ -0,0 +1 @@ +Welcome to the lain wiki! \ No newline at end of file From 046b0279b0f3eb827bcc2b2e395e6ea69c019733 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 7 Sep 2013 12:06:42 +0200 Subject: [PATCH 003/572] first commit --- LICENSE | 339 ++++++++++++++ README.md | 419 ++++++++++++++++++ helpers.lua | 90 ++++ icons/cal/white/1.png | Bin 0 -> 888 bytes icons/cal/white/10.png | Bin 0 -> 3476 bytes icons/cal/white/11.png | Bin 0 -> 2109 bytes icons/cal/white/12.png | Bin 0 -> 2349 bytes icons/cal/white/13.png | Bin 0 -> 2442 bytes icons/cal/white/14.png | Bin 0 -> 1378 bytes icons/cal/white/15.png | Bin 0 -> 1711 bytes icons/cal/white/16.png | Bin 0 -> 2056 bytes icons/cal/white/17.png | Bin 0 -> 1435 bytes icons/cal/white/18.png | Bin 0 -> 2207 bytes icons/cal/white/19.png | Bin 0 -> 2062 bytes icons/cal/white/2.png | Bin 0 -> 1553 bytes icons/cal/white/20.png | Bin 0 -> 2754 bytes icons/cal/white/21.png | Bin 0 -> 2092 bytes icons/cal/white/22.png | Bin 0 -> 2060 bytes icons/cal/white/23.png | Bin 0 -> 2495 bytes icons/cal/white/24.png | Bin 0 -> 2280 bytes icons/cal/white/25.png | Bin 0 -> 2325 bytes icons/cal/white/26.png | Bin 0 -> 2645 bytes icons/cal/white/27.png | Bin 0 -> 2044 bytes icons/cal/white/28.png | Bin 0 -> 2744 bytes icons/cal/white/29.png | Bin 0 -> 2597 bytes icons/cal/white/3.png | Bin 0 -> 1808 bytes icons/cal/white/30.png | Bin 0 -> 2912 bytes icons/cal/white/31.png | Bin 0 -> 2232 bytes icons/cal/white/4.png | Bin 0 -> 1140 bytes icons/cal/white/5.png | Bin 0 -> 1437 bytes icons/cal/white/6.png | Bin 0 -> 1776 bytes icons/cal/white/7.png | Bin 0 -> 1147 bytes icons/cal/white/8.png | Bin 0 -> 1930 bytes icons/cal/white/9.png | Bin 0 -> 1786 bytes icons/layout/default/browse.png | Bin 0 -> 190 bytes icons/layout/default/browsew.png | Bin 0 -> 190 bytes icons/layout/default/cascade.png | Bin 0 -> 233 bytes icons/layout/default/cascadebrowse.png | Bin 0 -> 235 bytes icons/layout/default/cascadebrowsew.png | Bin 0 -> 235 bytes icons/layout/default/cascadew.png | Bin 0 -> 233 bytes icons/layout/default/centerwork.png | Bin 0 -> 258 bytes icons/layout/default/centerworkw.png | Bin 0 -> 277 bytes icons/layout/default/gimp.png | Bin 0 -> 289 bytes icons/layout/default/gimpw.png | Bin 0 -> 289 bytes icons/layout/default/termfair.png | Bin 0 -> 191 bytes icons/layout/default/termfairw.png | Bin 0 -> 191 bytes icons/layout/zenburn/browse.png | Bin 0 -> 269 bytes icons/layout/zenburn/cascade.png | Bin 0 -> 299 bytes icons/layout/zenburn/cascadebrowse.png | Bin 0 -> 290 bytes icons/layout/zenburn/centerwork.png | Bin 0 -> 252 bytes icons/layout/zenburn/gimp.png | Bin 0 -> 3424 bytes icons/layout/zenburn/termfair.png | Bin 0 -> 289 bytes icons/mail.png | Bin 0 -> 634 bytes icons/no_net.png | Bin 0 -> 1697 bytes init.lua | 20 + layout/cascade.lua | 65 +++ layout/cascadetile.lua | 159 +++++++ layout/centerwork.lua | 122 +++++ layout/init.lua | 20 + layout/termfair.lua | 160 +++++++ layout/uselessfair.lua | 122 +++++ layout/uselesspiral.lua | 112 +++++ layout/uselesstile.lua | 232 ++++++++++ scripts/checkmail | 104 +++++ scripts/dfs | 385 ++++++++++++++++ scripts/mpdcover | 64 +++ util/init.lua | 174 ++++++++ util/markup.lua | 102 +++++ widgets/alsa.lua | 103 +++++ widgets/alsabar.lua | 164 +++++++ widgets/bat.lua | 147 ++++++ widgets/borderbox.lua | 61 +++ widgets/calendar.lua | 124 ++++++ widgets/cpu.lua | 80 ++++ widgets/fs.lua | 134 ++++++ widgets/imap.lua | 166 +++++++ widgets/init.lua | 24 + widgets/maildir.lua | 129 ++++++ widgets/mem.lua | 87 ++++ widgets/mpd.lua | 138 ++++++ widgets/net.lua | 153 +++++++ widgets/sysload.lua | 70 +++ widgets/temp.lua | 52 +++ widgets/yawn/README.rst | 133 ++++++ widgets/yawn/icons/BlowingSnow.png | Bin 0 -> 11454 bytes widgets/yawn/icons/Cloudy.png | Bin 0 -> 7469 bytes widgets/yawn/icons/DayClear.png | Bin 0 -> 6147 bytes widgets/yawn/icons/DayMostlyCloudy.png | Bin 0 -> 8016 bytes widgets/yawn/icons/DayPartlyCloudy.png | Bin 0 -> 7478 bytes widgets/yawn/icons/Foggy.png | Bin 0 -> 7325 bytes widgets/yawn/icons/FreezingDrizzle.png | Bin 0 -> 13166 bytes widgets/yawn/icons/FreezingRain.png | Bin 0 -> 13979 bytes widgets/yawn/icons/Hail.png | Bin 0 -> 7325 bytes widgets/yawn/icons/HeavySnow.png | Bin 0 -> 12733 bytes widgets/yawn/icons/LightSnowShowers.png | Bin 0 -> 8779 bytes widgets/yawn/icons/MixedRainAndHail.png | Bin 0 -> 9060 bytes widgets/yawn/icons/MixedRainAndSleet.png | Bin 0 -> 10978 bytes widgets/yawn/icons/MixedRainAndSnow.png | Bin 0 -> 10808 bytes widgets/yawn/icons/NightClear.png | Bin 0 -> 5198 bytes widgets/yawn/icons/NightMostlyCloudy.png | Bin 0 -> 7058 bytes widgets/yawn/icons/NightPartlyCloudy.png | Bin 0 -> 6583 bytes widgets/yawn/icons/README.md | 6 + widgets/yawn/icons/Rain.png | Bin 0 -> 8052 bytes widgets/yawn/icons/RainThunder.png | Bin 0 -> 9879 bytes widgets/yawn/icons/Showers.png | Bin 0 -> 9694 bytes widgets/yawn/icons/SnowShowers.png | Bin 0 -> 9961 bytes widgets/yawn/icons/Sunny.png | Bin 0 -> 14018 bytes widgets/yawn/icons/Wind.png | Bin 0 -> 8726 bytes widgets/yawn/icons/na.png | Bin 0 -> 11160 bytes widgets/yawn/init.lua | 227 ++++++++++ widgets/yawn/localizations/it_IT | 57 +++ .../yawn/localizations/localization_template | 57 +++ 112 files changed, 4801 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 helpers.lua create mode 100644 icons/cal/white/1.png create mode 100644 icons/cal/white/10.png create mode 100644 icons/cal/white/11.png create mode 100644 icons/cal/white/12.png create mode 100644 icons/cal/white/13.png create mode 100644 icons/cal/white/14.png create mode 100644 icons/cal/white/15.png create mode 100644 icons/cal/white/16.png create mode 100644 icons/cal/white/17.png create mode 100644 icons/cal/white/18.png create mode 100644 icons/cal/white/19.png create mode 100644 icons/cal/white/2.png create mode 100644 icons/cal/white/20.png create mode 100644 icons/cal/white/21.png create mode 100644 icons/cal/white/22.png create mode 100644 icons/cal/white/23.png create mode 100644 icons/cal/white/24.png create mode 100644 icons/cal/white/25.png create mode 100644 icons/cal/white/26.png create mode 100644 icons/cal/white/27.png create mode 100644 icons/cal/white/28.png create mode 100644 icons/cal/white/29.png create mode 100644 icons/cal/white/3.png create mode 100644 icons/cal/white/30.png create mode 100644 icons/cal/white/31.png create mode 100644 icons/cal/white/4.png create mode 100644 icons/cal/white/5.png create mode 100644 icons/cal/white/6.png create mode 100644 icons/cal/white/7.png create mode 100644 icons/cal/white/8.png create mode 100644 icons/cal/white/9.png create mode 100644 icons/layout/default/browse.png create mode 100644 icons/layout/default/browsew.png create mode 100644 icons/layout/default/cascade.png create mode 100644 icons/layout/default/cascadebrowse.png create mode 100644 icons/layout/default/cascadebrowsew.png create mode 100644 icons/layout/default/cascadew.png create mode 100644 icons/layout/default/centerwork.png create mode 100644 icons/layout/default/centerworkw.png create mode 100644 icons/layout/default/gimp.png create mode 100644 icons/layout/default/gimpw.png create mode 100644 icons/layout/default/termfair.png create mode 100644 icons/layout/default/termfairw.png create mode 100644 icons/layout/zenburn/browse.png create mode 100644 icons/layout/zenburn/cascade.png create mode 100644 icons/layout/zenburn/cascadebrowse.png create mode 100644 icons/layout/zenburn/centerwork.png create mode 100644 icons/layout/zenburn/gimp.png create mode 100644 icons/layout/zenburn/termfair.png create mode 100644 icons/mail.png create mode 100755 icons/no_net.png create mode 100644 init.lua create mode 100644 layout/cascade.lua create mode 100644 layout/cascadetile.lua create mode 100644 layout/centerwork.lua create mode 100644 layout/init.lua create mode 100644 layout/termfair.lua create mode 100644 layout/uselessfair.lua create mode 100644 layout/uselesspiral.lua create mode 100644 layout/uselesstile.lua create mode 100755 scripts/checkmail create mode 100755 scripts/dfs create mode 100755 scripts/mpdcover create mode 100644 util/init.lua create mode 100644 util/markup.lua create mode 100644 widgets/alsa.lua create mode 100644 widgets/alsabar.lua create mode 100644 widgets/bat.lua create mode 100644 widgets/borderbox.lua create mode 100644 widgets/calendar.lua create mode 100644 widgets/cpu.lua create mode 100644 widgets/fs.lua create mode 100644 widgets/imap.lua create mode 100644 widgets/init.lua create mode 100644 widgets/maildir.lua create mode 100644 widgets/mem.lua create mode 100644 widgets/mpd.lua create mode 100644 widgets/net.lua create mode 100644 widgets/sysload.lua create mode 100644 widgets/temp.lua create mode 100644 widgets/yawn/README.rst create mode 100755 widgets/yawn/icons/BlowingSnow.png create mode 100755 widgets/yawn/icons/Cloudy.png create mode 100755 widgets/yawn/icons/DayClear.png create mode 100755 widgets/yawn/icons/DayMostlyCloudy.png create mode 100755 widgets/yawn/icons/DayPartlyCloudy.png create mode 100755 widgets/yawn/icons/Foggy.png create mode 100755 widgets/yawn/icons/FreezingDrizzle.png create mode 100755 widgets/yawn/icons/FreezingRain.png create mode 100755 widgets/yawn/icons/Hail.png create mode 100755 widgets/yawn/icons/HeavySnow.png create mode 100755 widgets/yawn/icons/LightSnowShowers.png create mode 100755 widgets/yawn/icons/MixedRainAndHail.png create mode 100755 widgets/yawn/icons/MixedRainAndSleet.png create mode 100755 widgets/yawn/icons/MixedRainAndSnow.png create mode 100755 widgets/yawn/icons/NightClear.png create mode 100755 widgets/yawn/icons/NightMostlyCloudy.png create mode 100755 widgets/yawn/icons/NightPartlyCloudy.png create mode 100644 widgets/yawn/icons/README.md create mode 100755 widgets/yawn/icons/Rain.png create mode 100755 widgets/yawn/icons/RainThunder.png create mode 100755 widgets/yawn/icons/Showers.png create mode 100755 widgets/yawn/icons/SnowShowers.png create mode 100755 widgets/yawn/icons/Sunny.png create mode 100755 widgets/yawn/icons/Wind.png create mode 100755 widgets/yawn/icons/na.png create mode 100644 widgets/yawn/init.lua create mode 100644 widgets/yawn/localizations/it_IT create mode 100644 widgets/yawn/localizations/localization_template diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + + , 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8aa9449 --- /dev/null +++ b/README.md @@ -0,0 +1,419 @@ +VAin agaIN +========== + +Author: Luke Bonham + +Source: https://github.com/copycat-killer/vain + +Version: 1.9.9 + +Release version: 2.0 + +**Please note**: until release version, this documentation will be not updated. + +Foreword +-------- + +Based on a port of [awesome-vain](https://github.com/vain/awesome-vain), this +costantly evolving module provides new layouts, a set of widgets and +utility functions in order to improve Awesome usability and configurability. + +This work is licensed under [GNU GPLv2 License](http://www.gnu.org/licenses/gpl-2.0.html). +Installation +============ + +Simply clone this repository into your Awesome directory. + +Widgets +======= + +systemload +---------- + +Show the current system load in a textbox. Read it directly from +`/proc/loadavg`. + + mysysload = vain.widgets.systemload() + +A click on the widget will call `htop` in your `terminal`. + +The function takes a table as an optional argument. That table may +contain: + +* `.refresh_timeout`: Default to 10 seconds. +* `.show_all`: Show all three values (`true`) or only the first one (`false`). Default to `false`. +* `.color`: Default to beautiful.bg_normal or "#FFFFFF". + +cpu +-------- + +Shows the average CPU usage percent for a given amount of time. + + mycpuusage = vain.widgets.cpu() + +A click on the widget will call `htop` in your `terminal`. + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`refresh_timeout` | Refresh timeout seconds | int | 10 +`header` | Text to show before value | string | " Vol " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to show after value | string | "%" + +**Note**: `footer` color is `color`. + +memusage +-------- + +Show used memory and total memory in MiB. + + mymem = vain.widgets.mem() + + +The function takes a table as an optional argument. That table may +contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`refresh_timeout` | Refresh timeout seconds | int | 10 +`show_swap` | Show amount of used swap space? | boolean | false +`show_total` | Show amout of total memory? | boolean | false +`header` | Text to show before value | string | " Vol " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to show after value | string | "MB" + +**Note**: `footer` color is `color`. + +mailcheck +--------- +Checks maildirs and shows the result in a textbox. +Maildirs are structured as follows: + + ~/Mail + . + |-- arch + | |-- cur + | |-- new + | `-- tmp + |-- gmail + | |-- cur + | |-- new + | `-- tmp + . + . + . + +therefore `mailcheck` checks whether there are files in the `new` +directories. To do so, it calls `find`. If there's new mail, the textbox +will say something like "mail: bugs(3), system(1)", otherwise it says +"no mail". + + mymailcheck = vain.widgets.mailcheck("/path/to/my/maildir") + +The function takes a table as an optional argument. That table may +contain: + +* `.mailprogram`: Your favourite mail program. Clicking on the widget will + spawn it. Default is `mutt`. +* `.refresh_timeout`: Default to 60 seconds. +* `.mailpath`: Path to your maildir, default is `~/Mail`. +* `.ignore_boxes`: Another table which lists boxes (just the last part, + like `lists`) to ignore. Default to an empty table. +* `.initial_update`: Check for mail when starting Awesome (`true`) or + wait for the first refresh timeout (`false`)? Default to `false`. +* `.header_text`: Text to show along with output, default is "Mail". +* `.header_text_color`: Default to "#9E9E9E". +* `.color_newmail`: Default to "#D4D4D4". +* `.color_nomail`: Default to "#9E9E9E". +* `.shadow`: Hides widget when there are no mails. Default is `false`. + +imapcheck +--------- + +Check new mails over imap protocol. + +Dependencies: + +* Python3 + +Since [luasec](https://github.com/brunoos/luasec/) is still not officially +supported in lua 5.2, writing a pure lua solution would have meant too many +hacks and dependencies, resulting in a very big and not efficient-proven submodule. + +That's why I chose Python. + +Python offers [imaplib](http://docs.python.org/2/library/imaplib.html), a simple yet powerful IMAP4 client library which provides encrypted communication over SSL sockets. + +Basically, `imapcheck` calls ``vain/scripts/checkmail`` and parse its output in a widget. New mails are also notified through Naughty, with a popup like this: + + +---------------------------------------------------+ + | +---+ | + | |\ /| donald@disney.org has 3 new messages | + | +---+ | + | Latest From: Mickey Mouse | + | Subject: Re: Vacation Day | + | | + | Not after what you did yesterday. | + | Daisy told me everything [...] | + | | + +---------------------------------------------------+ + +Text will be cut if the mail is too long. + + myimapcheck = vain.widgets.mailcheck(args) + +The function takes a table as argument. Required table parameters are: + +* `.server`: You email server. Example: `imap.gmail.com`. +* `.mail`: Your email. +* `.password`: Your email password. + +while the optional are: + +* `.port`: Imap port. Default is `993`. +* `.refresh_timeout`: Default to 60 seconds. +* `.notify_timeout`: Notification timeout. Default to 8 seconds. +* `.notify_position`: Notification position. Default is "top_left". Check + [Naughty position parameter](http://awesome.naquadah.org/doc/api/modules/naughty.html) for a list of other possible values. +* `.mailprogram`: Your favourite mail program. Clicking on the widget will + spawn it. Default is `mutt`. +* `.mail_encoding`: If you wish to set an encoding. Default is `nil`. +* `.initial_update`: Check for mail when starting Awesome (`true`) or + wait for the first refresh timeout (`false`)? Default to `false`. +* `.header_text`: Text to show along with output, default is "Mail". +* `.header_text_color`: Default to "#9E9E9E". +* `.color_newmail`: Default to "#D4D4D4". +* `.color_nomail`: Default to "#9E9E9E". +* `.shadow`: Hides widget when there are no mails. Default is `false`. +* `.maxlen`: Maximum mail length. If mail is longer, it will be cut. Default is + `100`. +* `.is_plain`: Define whether `.password` field is a plain password (`true`) or a function that retrieves it (`false`). Default to `false`. + +Let's focus better on `.is_plain` parameter. + +You can just easily set your password like this: + + args.is_plain = false + args.password = "mypassword" + +and you'll have the same security provided by `~/.netrc`. (In this case, it's +better to set your `rc.lua` permissions to 700 or 600) + +**Or**, you can use a keyring, like gnome's: + + args.password = "gnome-keyring-query get password" + +(`gnome-keyring-query` is not in gnome-keyring pkg, you have to download it +separately) + +or the very light [python keyring](https://pypi.python.org/pypi/keyring). + +When `.is_plain` is `false`, it *executes* `.password` before using it, so you can also use whatever password fetching solution you want. + +You can also define your icon for the naughty notification. Just set `vain_mail_notify` into your ``theme.lua``. + + + +mpd +--- + +Provides a `table` with 2 elements: + +* `table["widget"]` is a textbox displaying current song in play. + +* `table["force"]` is a function to *force* the widget to update, exactly + like `vicious.force()`. + +Also, a notification is shown when a new song is playing. + +Dependencies: + +* libnotify +* imagemagick + + + mpdwidget = vain.widgets.mpd() + ... + right_layout:add(mpdwidget["widget"]) + +The function takes a table as an optional argument. That table may +contain: + +* `.password`: Mpd password. Default is unset. +* `.host`: Mpd host. Default is "127.0.0.1" (localhost). +* `.port`: Mpd port. Default is "6600". +* `.music_dir`: Your music directory. Default is "~/Music". If you have to + change this, be sure to write the absolute path. +* `.refresh_timeout`: Widget refresh timeout. Default is `1`. +* `.notify_timeout`: Notification timeout. Default is `5`. +* `.color_artist`: Artist name color. Default is `#9E9E9E`. +* `.color_song`: Song name color. Default is `#EBEBFF`. +* `.musicplr`: Your favourite music player. Clicking on the widget will spawn + it. Default is `ncmpcpp`. +* `.shadow`: Hides widget when no song is playing. Default is `false`. + +You can use `table["force"]` to make your mpd keybindings immediate. +Example usage: + + globalkeys = awful.util.table.join( + ... + -- Music control + awful.key({ altkey, "Control" }, "Up", function () + awful.util.spawn_with_shell( "mpc toggle || ncmpcpp toggle || ncmpc toggle || pms toggle", false ) + mpdwidget["force"]() + end), + awful.key({ altkey, "Control" }, "Down", function () + awful.util.spawn_with_shell( "mpc stop || ncmpcpp stop || ncmpc stop || pms stop", false ) + mpdwidget["force"]() + end ), + awful.key({ altkey, "Control" }, "Left", function () + awful.util.spawn_with_shell( "mpc prev || ncmpcpp prev || ncmpc prev || pms prev", false ) + mpdwidget["force"]() + end ), + awful.key({ altkey, "Control" }, "Right", function () + awful.util.spawn_with_shell( "mpc next || ncmpcpp next || ncmpc next || pms next", false ) + mpdwidget["force"]() + end ), + +net +--- + +Monitors network interfaces and shows current traffic in a textbox. If +the interface is not present or if there's not enough data yet, you'll +see `wlan0: -` or similar. Otherwise, the current traffic is shown in +kilobytes per second as `eth0: ↑(00,010.2), ↓(01,037.8)` or similar. + + neteth0 = vain.widgets.net() + +The function takes a table as an optional argument. That table may +contain: + +* `.iface`: Default to `eth0`. +* `.refresh_timeout`: Default to 2 seconds. +* `.color`: Default to beautiful.bg_normal or "#FFFFFF". + +gitodo +------ + +This is an integration of [gitodo](https://github.com/vain/gitodo) into +Awesome. + + todolist = vain.widgets.gitodo() + +The function takes a table as an optional argument. That table may +contain: + +* `.refresh_timeout`: Default to 120 seconds. +* `.initial_update`: Check for todo items when starting Awesome (`true`) + or wait for the first refresh timeout (`false`)? Default to `true`. + +`beautiful.gitodo_normal` is used as the color for non-outdated items, +`beautiful.gitodo_warning` for those items close to their deadline and +`beautiful.gitodo_outdated` is the color of outdated items. + + + +Utility functions +================= + +I'll only explain the more complex functions. See the source code for +the others. + +menu\_clients\_current\_tags +---------------------------- + +Similar to `awful.menu.clients()`, but this menu only shows the clients +of currently visible tags. Use it like this: + + globalkeys = awful.util.table.join( + ... + awful.key({ "Mod1" }, "Tab", function() + awful.menu.menu_keys.down = { "Down", "Alt_L", "Tab", "j" } + awful.menu.menu_keys.up = { "Up", "k" } + vain.util.menu_clients_current_tags({ width = 350 }, { keygrabber = true }) + end), + ... + ) + +magnify\_client +--------------- + +Set a client to floating and resize it in the same way the "magnifier" +layout does it. Place it on the "current" screen (derived from the mouse +position). This allows you to magnify any client you wish, regardless of +the currently used layout. Use it with a client keybinding like this: + + clientkeys = awful.util.table.join( + ... + awful.key({ modkey, "Control" }, "m", vain.util.magnify_client), + ... + ) + +If you want to "de-magnify" it, just reset the clients floating state to +`false` (hit `Mod4`+`CTRL`+`Space`, for example). + +niceborder\_{focus, unfocus} +---------------------------- + +By default, your `rc.lua` contains something like this: + + client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end) + client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end) + +You can change it to this: + + client.connect_signal("focus", vain.util.niceborder_focus(c)) + client.connect_signal("unfocus", vain.util.niceborder_unfocus(c)) + +Now, when a client is focused or unfocused, Awesome will look up its +nice value in `/proc//stat`. If it's less than 0, the client is +classified as "high priority"; if it's greater than 0, the client is +classified as "low priority". If it's equal to 0, nothing special +happens. + +This requires to define additional colors in your `theme.lua`. For example: + + theme.border_focus_highprio = "#FF0000" + theme.border_normal_highprio = "#A03333" + + theme.border_focus_lowprio = "#3333FF" + theme.border_normal_lowprio = "#333366" + +tag\_view\_nonempty +------------------------------ + +This function lets you jump to the next/previous non-empty tag. +It takes two arguments: + +* `direction`: `1` for next non-empty tag, `-1` for previous. +* `sc`: Screen in which the taglist is. Default is `mouse.screen` or `1`. This + argument is optional. + +Usage example: + + globalkeys = awful.util.table.join( + ... + -- Non-empty tag browsing + awful.key({ altkey }, "Left", function () vain.util.tag_view_nonempty(-1) + end), + awful.key({ altkey }, "Right", function () vain.util.tag_view_nonempty(1) end), + ... + +prompt\_rename\_tag +------------------- + +This function enables you to dynamically rename the current tag you have +focused. +Usage example: + + globalkeys = awful.util.table.join( + .. + -- Dynamic tag renaming + awful.key({ modkey, "Shift" }, "r", function () vain.util.prompt_rename_tag(mypromptbox) end), + ... + +Credits goes to [minism](https://bbs.archlinux.org/viewtopic.php?pid=1315135#p1315135). diff --git a/helpers.lua b/helpers.lua new file mode 100644 index 0000000..7677768 --- /dev/null +++ b/helpers.lua @@ -0,0 +1,90 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + * (c) 2010, Adrian C. + +--]] + +local awful = require("awful") +local debug = require("debug") +local pairs = pairs +local rawget = rawget + +-- Lain helper functions for internal use +-- lain.helpers +local helpers = {} + +helpers.lain_dir = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]] +helpers.icons_dir = helpers.lain_dir .. 'icons/' +helpers.scripts_dir = helpers.lain_dir .. 'scripts/' + +-- {{{ Modules loader + +function helpers.wrequire(table, key) + local module = rawget(table, key) + return module or require(table._NAME .. '.' .. key) +end + +-- }}} + +-- {{{ +-- If lain.terminal is a string, e.g. "xterm", then "xterm -e " .. cmd is +-- run. But if lain.terminal is a function, then terminal(cmd) is run. + +function helpers.run_in_terminal(cmd) + if type(terminal) == "function" + then + terminal(cmd) + elseif type(terminal) == "string" + then + awful.util.spawn(terminal .. ' -e ' .. cmd) + end +end + +-- }}} + +-- {{{ Format units to one decimal point + +function helpers.uformat(array, key, value, unit) + for u, v in pairs(unit) do + array["{"..key.."_"..u.."}"] = string.format("%.1f", value/v) + end + return array +end + +-- }}} + +-- {{{ Read the first line of a file or return nil. + +function helpers.first_line(f) + local fp = io.open(f) + if not fp + then + return nil + end + + local content = fp:read("*l") + fp:close() + return content +end + +-- }}} + +-- {{{ A map utility + +helpers.map_table = {} + +function helpers.set_map(element, value) + helpers.map_table[element] = value +end + +function helpers.get_map(element) + return helpers.map_table[element] +end + +-- }}} + +return helpers diff --git a/icons/cal/white/1.png b/icons/cal/white/1.png new file mode 100644 index 0000000000000000000000000000000000000000..90b696ca0820164118bea3af0df0f41b0b2ba4bb GIT binary patch literal 888 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 literal 0 HcmV?d00001 diff --git a/icons/cal/white/11.png b/icons/cal/white/11.png new file mode 100644 index 0000000000000000000000000000000000000000..cf43296120793006ccdeb2b08da06fba5bc629a2 GIT binary patch literal 2109 zcmZuz3pCUH8~<&LxlK$iE7yOGXrWwl8!=NGQmfn=ja)*CMdf8mWb{UQLyA{4ml(;V z*qE0HMH%(lTvoZZWTj@_n0NI*=l}ly=lnnCJkRGj&-0w~J>T!UyO>%( zRI1>YU*JrywnUuk(aj9A7c#C-D_o2k;_n%{6F0f%eVp16tlyhDAR~)0gAHKQ^%5JB zqrc1nM%@-J2OCihz|a}?hgp%1<4C4B(5m)RL}uzEPt=*@B&pBC<@qazW%jKd4O7Fm&+TxYiEFlBL{x&oeTR!e8+G=#Q*W?ezy59{UshHo{v=H!Gyg1XR>p#ehrM3{!93&r7l6W>G#5i8mdrFu zkgmonLHCfrBNnvgW~*Oyonpo^&s86quLRE2&g16J2aWu!&CZ^*iWv_t^04$%0+ukZ z7#KW>)0SXb;d!?Kr*v0yM@}d(zg$zx46fd7e-^jYs~Bw251*B z1;VUtV$Z%PLJBjR)IgSjb)l@I64`u6?TJfjzS`?sb23zwOC4!4xGW8jKDf%pI>niPq^rB zfD7VJbYxt-h_drN5NnBS%VsIL#Atu~qmnm_)Tc*OHPTa*6CpTT?W|zUn!q-7HHdr_ zp%f#UT2`Yi_~DL(Tj9f+*qvyl!NdpA#2(A&YS)y~R7;CDP zwY5J?9z@Vq`!W&zmU^!~xJzcJR|}RA&F;kTrCT{m^Yiod_(u$k1%k}b68r|BP^hS} zhWj5JA}X#vJ>esD_*<_GxW@MpE#_TdOU%Ss_AwRKuh?xq)(<(OhYeW!zf5|suWfcA z5Ei5k!`T*c8C_&}T?hzPA318Qf|jlvmnHLQ z&9p3fK?Rc4S=TuI3E=6owvvT%kgR;L5%omTk@LBQg<9MxeXs~k85{Gh0#)~o4mnkH zbW91Ke?i2>#TlTR%<*|)L&fJE2a_C6+rji!q-v&RWx<3k81jvUg@|3p8R1WAZ$HZV z>uhtZp*Yk(`fKQ5lri`wnn2iHm^~+(Mx)VO0Yg!jVMz`SSy)gYh!-y%*)ubMWLe;m zhK3GXrnLotnpI zM}BiA)**z#MSmUpL|#9k<*cTb*2Bd$+cU!N$0=K?)YjM6v$L~D>~9%*6~``3Ivl+q zrYqDZGAZ|!O{d56^73$AUT+$a2wmN|*R}pr_GnO;a_&<8wJnIP<#xG}&9=6-2CRCC zePSjVeODATc6x2C(8#+%mP-BOLttl6PI0l$QE}c%6J_7NJ5DK+R{x4cs05{+I$Ae8 zI)S&@N(*zAv9?M0bZ3T7B9Z7dA;#dH2ITd<6PeQK!SyK{$*=2(OBWQW_sp!UW;tS4 zAZwPluI#8+^rC^(3p=;SndwhfIPkocNeN-f2}(kfXz#Z0#iE4@AfB8MC;aFO)3%>a z#63Kg-P!5xio;`~KjY{j`(~OrCcSr_+QQ!GB#F(4O?-fEC8GpNjE*Rq4@>FIZDoQ<7q*{#PT zEoOfR(1=lV(!2Kf0 B!w3KX literal 0 HcmV?d00001 diff --git a/icons/cal/white/12.png b/icons/cal/white/12.png new file mode 100644 index 0000000000000000000000000000000000000000..42cf092c707630612ecda89455794e1cecd2579f GIT binary patch literal 2349 zcmZ9Oc{J4h7stOdgPAa)!6>Fs%CU}=HL{GQu~bxQq_Om5Uxq|k8cVh;Wf{wiog!06 zh9~4(luEV~m1PFm!kALortwVA?~mW}JfCy!=Y7xpoO{nb_ngn?^+`TqZ-o@zB@6%n z@|ZQwfv@D>h7jWK9ma0md=YZDvBL3{zt+uLuJdJEkoCC`01!d_HV9Bali>&9myg+5 zz{e1h!e}8sM2b29ARZsXnVt&&v{V@3CufD}IvT#vcCx$YfVThQ;|YY$zYYY zqnV46sieYb@mus;l>Ve# zqE{$sH`1n}wINP5cy~kT=^NOeEm1t)EdXI;vlmf{wLaeUznG!Xa z(g;_$y-v+k3-HGQih!wrd=elaLGF)zWXNdK`fNm3nH|<+sOuN@b5E!H`@Zt@^r=Xhv#`qoh&GwCY|Jmv2y}Brb1<&g zOzqyD(5lEh^$jz^hFOy1AgLLiw3>xX@yZ7#)yvo1Hy|7~`NgV-6i11L;GA@ zblCO=KI)D3%O0(nSJYNdBGX!;^IIKZVI|RXO_ux%tc~&A<+V0k{tgAk6*;1HT|g}7 zwq>$BW0&h|QeH3(2|9wBZH&f&NSN36Sju)+#GHRTLJ>_K{_zEF8DmtGSSXk#V@35$!O@BJLwziJo}Br@$w%X9Lrp-S&~CBYWj5qh zoh&gRNFHqTjLCJUJQa(IX2R$~0r16xlcWqM-j!WzWGBaL(ZL4BM}eTK1m9lB>Q$w= z<60uFGU24BTbeBUNk1s>Le>QF>V@(j7_cy5{!fOt0BarM2r^Y4WtsY0l2_kKBo&i&Ua=(j^l#ORTG!hH0Uoi;z-8ILxhg+SolkM188Is+{h;O%rW zd;NeraP24|&}1QE;2Q6AWgDSdlZdjNO#dcWiEMt9UjUG;js&(KxB_SM8|cS@u1WfW zuHWcOin{Y;>Nm1mb0z7A;odIiG;Qd4!8iQ-Fc}+Cf3EzL%D~td65n>dY>T*8jY}L} zawc>kJ3Tv-PpP zy}f$nE*|2STD@ODGI1(7Wi>UbPY^kHi0;mKu0Jb)jwsPNm~TrPaEUWal!saiFD)&R zD7-+~c&;W}@f@)ej>Y-fSy@?~9~cvE9h4tMk*8*X6fyBki<{EVPj0BQoD)iylizFZ zfZ(2u<)uw;y|4Y1QTDy50(d)r`Ca9f0joTrwEf(|jT)y~X~;f%0PiBSh!y<>XVnvI zuIo^xAbAF{5<9PJu^sAigi39|yKw?~p#^%^dU6Eum|InTdJT=M?b2$`&IY;*XeGB@d$a^*Cr@Y*Dl4A zo1EucGbC+Nf0my6Rd+(;(&1^HdvprFq0<2V{_0~te}%||r#@&YVL=I#D5|f8aj{rL z*6LLHFjYfk&4?|1=yZNj(a)&u5+-{EO5XK=eUQO{3KGk_S+%?-c;?N{YRH#Y;}dQP z2?>!lXQZaYSOJr+2E~ywt2wm=%*DLILMg~Q+53kN*wYX`+!1ndg4as%YAP|Lb7f`a zO;69daU25t9^+VD(oxkEVNdn$*py?pL}!^o?dseg zMj7gT!0`H+O)30C%wYFHb$!{qzFFU$;*U{lgrq8-==luh22bVvT4yJJ5W>;*5xQ}4 zaj9u(>x?z94MdyaLJ(nDiMh6^L}ke@IwJ?598y_2Ms?HP$B^CYHex;+eUyEr>8@R> z7*@$Ktg zdno}WrcTQmqo%hAaI>QQYZUrOj5C%vBXxKSjAC*o(I(=p_dSZAjfJ$6TiWYh6y9}e zRt=uLH`bA{VtCuf=+U8ES;CsuJbnV$*x2~cdR2S=a=~Q-J5SF8`L+qR`#ZSYBMl7= zlEQ*BGc(H4H~Eeb9DWjCnq9_!6o!T@b*O(ZpF}0U44nROrP2G|Z`N97-Rd{3whr=h zJ~>@3H7SsSQvMs~f1}i_W+2$+S;7691Bd?&@KW9wIGyevm`V3}8$d!1K8-yD`7hl2 b<+x&FhIMceqNd*OU(YcMd)xyv*Vw-R5;Zc~ literal 0 HcmV?d00001 diff --git a/icons/cal/white/13.png b/icons/cal/white/13.png new file mode 100644 index 0000000000000000000000000000000000000000..37db670cb71fecb2f2932981b09dae765adee205 GIT binary patch literal 2442 zcmZ8jdo+}L8-3r`%osGTky}EE3h7Kr3ga@aDI}Lnj5y@lsD=^7%uyspLiniA#S99$ zWFkx5ZFW}Xu9SiKyD_1v?(#{^o`Vs0FywrSJ546SStrb|(D6JCH!OXo zKIl#+EA0bDlUe4T{JFQ4>|H|-d@c?{(mGZ z;1@Jb8boUX=Kr7kr|F0fp@l5GnOLc##OZv8lpRdgXFohcX0?j^n{R>P0!^Qm*Qsw_ zzkc_5LtaY#^bZODEc$!q28;$c&ZjS(r>H7S)5R(=GYY|Ha;+_*u zAS(SQ@1;a#g2uF2Xyi|AxWIeIo5Ptg)M zJennkeQM%kM2hAcHR8_22v`oRC=l@$y@U2A@U8%b+tv&gz2Q}j_al;o5}!Iqf6<7< zRA{xhAe*mvM$Th-6pWRioMiaCE5=0KpG?~Kpcz`*x+nv8%4{B!V4F9m0d-*WD(g(D zxJD+TC4}oEGAEj7p=kEdQ@8T58(hsnliWp8o73x{@3g^2@j~t?M?;1vOJ|AKr`6PT z9&#=5k=y{;2NM^*_0v0XW~8b-^l=KbQ;kC&UU$bQH><5R>SN*#OfL>7ruw|u4foe~ zN~dTWxFJ)Io_LOIa_mn?FcumA>#3$m8(+Wq>O3>x=^R1q&?l~@oPnd)$hBC=47f3V+?1I$Hm|-%9fkE zX)U;1(x6=L86J6AP`nI0--vy=0HqWu!PrRu9*)GGOHkhcqCbOsv?}b%3;P9o~C+u+9ev`ym)53}d1=37qdvWm+ zaGDV26rcio^FO%z*4V+4XSL&%6jxW(Z+Cah@TqVd>v^)l<-=vbJ#kW}5*$v{Tda8* zT!;=ecLY`epB23}2~6|acgY~0OrpEtZD8*J$mNX2ZrQ|!t#!!+STIrIUUgR(VjC`p z7hW*tP^QEQ;;*0hU3DSbBaU*u`2X=LlA}u6AN+O|%aPbE>r9?F`4R3Nx>CF8lUKO^HbT>iMzRWRQdm+e-8F1+FeSC|$U61J>Btb-fR>x=&UPCB>day=$d z%s{8sw*{4^W^#oproP7`yKSboOl5WA=l=Mkf}-IUYfq;)YW#E3p3g!( zhwO6A=N0NDEiFeiY5rocH_T*dM2ze5OSa--Vq%8u*z&azHRTgNvwctGz&lI`Fr4R0 z2gkR*Hh5%~-+2RgbqFEXYTdK@U1#lx(SZXR5V~bpz z12`$NU)kPGp*CVNxO@Fp{VfhQ5RziwMR+@`{yeY^s+b%iE$$|U++F_F zd7LQ?u3b`4EUQu@Zc+3$uvxT+A8^{y&0M3KH%^n>86)Qa=c#b&)G5Y6s@5o~Nojdc0m6tplQqSY z23s{~16YCNMx;V?wStG~kt2K5)a}(`zBorN3{87hX&y3VP4JFd4oqZBPY221df4S1 zpFgw2xH(Fa(W4VsEcRZrIYRoYXy8w`Fb`0><_^_$M9vSKUQJ+SUu6nyjCr!)&^r5G z`Zu!T9_b(~H74e$P)V&My4UgpCv#H)JV;B5;sp?iw6QT?xtrDK9U@Ct(S>x(OKv-3 z&V~=|C0_Q2u2%_8l2wSIp^rDF!dOl#QBa6x>~F?!j0W$nb=y9VgK08`CC3cL-?Suk zoNbVBwtV)4lkcQryaS|K+&({IxV1FDcBw_*Y`{xrs{+F#nk<0_#ypL#4gNClFd|c* zE>)-*cdVmB#Pak5q+!9P<;>`wFE9)j@{rERj1vt&_?Pv^+t$jdK0TTgur_Ycyv>A= zAb#A4E4^eG*|% zXjj#GBmG{bnq52jn79PIt2Xg{&1;|P!3K#~d2N21vG$V9wVIb!yTKg`S_R5vGt!)e zH&(=!O?LygfX&HE>-r?AU~u}D5mqw}a*{D~V0FI@2L$JhknK)hFT+8BTvX&PPhb<{ zSPnoO;R9sF79>~^pEzLg-o2h{`R8i1 z>x<1!79;bgV6Q zmrMVneK|27ecwNi73j_wHJER|eKcWU;*wTyqhK$r$>;6u3EHWBBr5hdJJ(-xm|y2U za<``7Q7BZUu0%(b&Tadenws>^fFmTBhE}J6%(5)E9OLn6vRI!4(%Bc=$BbghZQoIFvP3TxA= z!WA8t7zyVZh2}=9MJbPt9B;`KzxzP@<<6_NcWd9j{U3eyLg}vj`JY3t?%lpBzg6s` z#PP;n-dQ=@1da*rJd-~^=+12q22KT)h6xN#OdWD52a@kxc~sqE85jT7Q0ubg+5Dr) zYqXBfVrpR#5OVNfP-Mixn9|kAlY303B{#h)a6fm3{@N$klh-h8mO@jna)&*mqjiI4 zW{&*ZbL-t0d>NgXIAGR88H>avPP}fc?5RCqd0?%i^S%uN`(EGrxNAMrG?g}A#@}ai z!kGTdH$A|7pjq)iFpjGw=Y6m0clnyvlk?bk!` z@kfsA{Jr&nUM%Yp@w()_AF{hd4H@cj`<#g*tF0Fzx$jv95Mg;|EI6G8z{X|pzg%O zJNrc=<_mnXEYRE#p?u(FrTB_#-2bgM+;OU~SblUrONE``8_!RBk1yJ-+|X+9&@hhE zCz9iM(Y)D)5B{`#0|xY=yX>kC$(;N24y4}SdqB1`ardsNmz8`OU3Wa&&rxA$_{P@w z_m+R(7qDoURX4hFzO8?L|2NYw6^Fv=|920>0+pYA)A5d3WdD!u#_7U``AiIBJsReG z5=!8F>(3OuYv=NKrZe&H_Y3b(H_TZ+Q&#s^`TO9Hf1Ms&J+h&{A^g;bzotwFxDOl! zs%H2;J2I3>WdHYkhIigP)pyS9)A#24Rkh>CbH?97htddmJOp2g<5w11;hu4Q>+>xbEFA1ptIGp2Q0 zF(oL@`E&k%Xx8f|TKoK%T9JK%S{59MNr~i*d1aUvw(6AUw7(2a!KhB{DEc72Qp9db TyViOQP*LgW>gTe~DWM4fJyKGN literal 0 HcmV?d00001 diff --git a/icons/cal/white/15.png b/icons/cal/white/15.png new file mode 100644 index 0000000000000000000000000000000000000000..64418a6f659edbd1e1976f646525cb8b96491828 GIT binary patch literal 1711 zcmZ{leKgyL8pnUXyphCf)XUngLX*xgQPHZ(h)RZfZK*PD8Xb{oRf-TZ@)IvbbwRag ztxUCAMbm4lZ8VZ=Xf@GUxs;Nql^)DnTG6pux^wOy_uRYZobU7bp68tB`Sbe}1_yfU zW42-d0MPgKp&ix|`XF7Dws*NlKhXkp+|Qe)rMBLAiTPTfIX)4|0Dv|5AP~4zZJ{0N zr1%EVb;fnKV61G1oX zyI?E59D6%kC)~y3 zst-`=m7i|m(7du;Mx5wWbOo0Ne*G6DZjum(vIX3(dkWc+`LOm!r#cZ$o<9r4Pxk}GVLx>B?x#*FTo}3^1=2}n_O;a;j z`r(%&L5iL^@D#2oPk+s+HN6oA<#7#UO;Kjxj(qG?Zf9$MyAz!Y#hAQr**BROXMVe^90t%jqvh*7vg-f0T0dwB?0NHeCh@1$}IQ^ z3O(wo`mDBFz*HD*)EzwmK2XdXzJ-T|8CFg#a!Dd|c%mogUUuJR&5&MGvEfTrAZf|K zQ6XS*F}Thb?hrh}7(cLGDqvQeneD5`|Z{HJxSD);Q zX%Gv67N8&CgZv&oA1PTJlQ;Rn>T8nLf#1`D&wbavygZjK?ONWXrzOJo!pG$Exkb=P z-C$cJ6FfBY@6&0@*@b6BY8Jwxa;yc&O3@5Y9ruPgGm#t{S~z?@S>uYsd$>xeJz&O* z%xj284Zu&$1&Rd;12%XYJ%aFWQ72Gl7J_`B-yIDsN(Jj9uNM?J{Ftd!b`Qr>j+6XW z>SlEXe^3nvLf^Re!~a2z+i1sHAdAl>7vG9cA*r+D3R${-5W%t4WWn8xz2L_o&q-(x zqhmZix(*7B&!ufI`e8B15Bin351mqehi}NSnHYsMFCONxKhNp?%GLJT(0HP6e8&&7 zfY&Djp5#a!f9tKgqZDiJy^o+zMj7{CetuTkXG`GOFdDyrIg4~HVYkD0YvHPI&_Ay= zowd7o!O<7yoaMkV8~Ji_(u7FeJ3<6k6r~s;mO$NmBgG=T0r3bmWk*@4)bcYNUTI$e zxOR^>z%EcUi#9`~bUSdidd&rJyE(7Zp1=w#2Obkb)xpA{G|eq2sL^KAdoa4wpE#V!zf; zibsm@Y>i__4f|tB9ny24OGI@B)k#>vm91O!e>?rsIOy4xz&G1uF?Dh1H_Cn^uA$}5 zFD*r62c@Qa@$L7ml`lyV5A3qd5DhvV4mfVr>fpxcp^EvS<@GHjR&c+W3nH0)w-=SO0y%%-!(6ox% zBZ-t`XkFA#ZB3NNmK9g2v3cBF_xqgl`Mlrfea`2+|9qVb3G&m?#%coq zpcCNlb3m=&_tiqEZ@U}qrCJa%fqp(}RnMX~pQRQg-JhHe04Tlh3jr=w7^y?e;{p49 zH6>d5+GbV-YG^=Mkp~k+2GP5k8QRZ+G@kiTo@l ztEm{kc=!W&NIqQG+rPIVIj!`{x;2V#6TCRfiAyD^?F}{8caii=&A}qT3#x_uKPKkt z;l?!KUKDL2H1*44@O{tz#Zx7AAoA^hJvo=sh@@A|(@>oZBh zE976aj%kSfKwNPe;RP1>L zv}rMJi$;~FN<1-4j3^RepXA~`ay#-eJGh%qHrduDaXM?~<5p~Yf1V-d| zvQpjcy+v4!Z|yb;lZm{>Y;?pL#{H2cya)?t($LG~99`8Y$OXkZdo`QMH0krwHt zS;DYZ#gDVnE86eE=_wBlBGx7YJa`6l2V_*xRNm@Lr~-9P7z!kX2&OjfkicLiN7^qq zWt&Z@0xRY>;`o{a8ZCE!mx`ezm|XTTb^*wQSqYQ*&g@mOe8_P;OiGl(rROl>$v)!v zmIbI4TTdvnTG3xVkOZJUMDyarMI+eD1cef6MaXA$T#F@#twu>XZ^i^>wo7^AkRiEd zh3ZE2r)~#L_)+{gb7W*6CjvvcBW+#5hYo3!yTm6BNvuIJsmz?IC}J7C(x)8u4r8(mc}z9A;mP zZ;aJ`ZCDhH69ouI{i)j*y$tLi8sYaObx22vkhIT$0oZ1vvrH6K#F^&M9Pre`RTg}l zOOE7*lnn;i@{Lq!G0dCIOU0P0o1iicx72tSy&j5j@6C>J95RG(JN%7x{6gsYw0IVz zjaw%7`kn=ETd8@;IOvi-Ywl6M?1C31d4yLpN3|>U7vJL{ch*x2$|s4Y@+YL7M~Z<9 zKYw_Mb2@GX&i}RM+7S?z?&HaIx=~}s3(*N-=+s%^CGVg!L5bo=Tyh{(-wsJ#z)t>9 zHBj(Ai{mpK3ey+IA`>|S{GGm)lbEYnn}Yq*$qvfTlAMf~gc-RyvF~2wxt@WPW)^=+ z!1Ug|2y`l8lp75qOG*OyMUha#9aF-b>Gn>Y-4(#znUkBnFchnmmh88w0g{8n*>lBgFvU~U_1O_svnxU zmD!Ov#?OVw3JUW~!UVTd5X=yg6MDXIPx;`ZF6B<*M=wh=m9_MXW9)Xw-j67Od(ttY zL)qYt7ee}HjhzkXrk@|2$o9Q|>6p@@1Xv1CSW#`>rW{@|U##pcf!_+sjXpmzH~5cZ zeQRMTp{&!g?GZey3LXrgVuD-xAAnzlvYyc({3*qjf0^-Z^(be_x9}z#B}{HB|ABJGt9I6>+gcF$v3jHZ`Ha$3=XJQI zT|q`UP?i27Lhnqb!iL+W)QW;FKND{K68bM4@qO65Yxp6pz-mV)@qKT0I9PJJdxnry zjH3vV q8hn+N*nLCfwWe?2{|PZ8^f%NChmEDEO0%->Ko9T@@~QQr=KdQ}8=t)Z literal 0 HcmV?d00001 diff --git a/icons/cal/white/17.png b/icons/cal/white/17.png new file mode 100644 index 0000000000000000000000000000000000000000..033b5ff1b827df2f072642522c44e4612ae74553 GIT binary patch literal 1435 zcmZ`(dr*=I5dS_vKsYQgE7J~BNT(=Gd?e)yAu;oHSL34;d(oNC4n0i^Q0p|y%rX>F zvxnK4ikF)CNV#dcN`u%^on0;OeZ4MkM4 zUjP#|ie81WF^|}kY!3iNc76=+y=gDh<@@iL?X%43s+&H-G4j?Ay7y4fB)g|MS(o2e z(i7cN29@`|ZD&`|eD}z$uq*m;ZC+t3$aF?9L1K z>hPED8FJZ&?75`jx$z8n#CRfSUKT~g(MV}sV2S55YplE#mrGhq&1-uw#sZA3NPhvE?*#50H0urr921TPk_0sKm`H?Px0Xzn;Igoe(S zu2DqNRO1t;;U$XIUk))Y&H+~r^==7v{iz^9E4dH6Fhc*g{{JMGrYJuCC`QDU&=*XMZ!`BbZpaIwECPxpVU`f?3+oV{rc2pKtDhAwEd@ zkdPzJC*LsI*N5cQw{M(3ATnK5gX>1W0|{Vmpn- z>PrDJm$CzM0kBO8&my*^&sxxl4IVd=TSWn@w%IYGOrYBQqb9IEcw=VY=A@OW)TF51 z(sHQ<)49O`l(in5X!k?%);qi`+b?{b7j^H5ich(bd{&enIDP3HY(#TJ2^mNyI0 zqa|)F;+Y>~8M>Uz>o+VSK0UVLCitF3Rjj1*kLZRlEwtjc+a8niCPY!rVK9xyk`Kp)0(SSQrLr>To6?#nmk5~ULyadPM0Z)F z76Mb#7jrcQ@SuO%CJB{u8ltHP8j{CVBkt_d_4S5RK}yi|kAzBB6+4l$!@wSnC^HLj zE$POv1ieaq5<`{2xgP*4y7stGMP$X0NnQtZ)y&&^AL>hMu%-~A+RRk!iD#0$PN>G? zI7C0e-(1_IT_f5hLglcAAH%UA8xF>9f4E6i3@j-5l!fXv@D#km2AmN?-qhILg7n*Z z+X(K4OTZMzI4OcLilOcxf!*bhN}7$Y>Vipbb@B+687g)R2SxUBe@^^CewqO*5?4uo z!KVai50w@pST;+1W!p0&LglMhxH3YBwpOIR3QPs+Pe|eTs>QdHPWHx%MU8~o=t(j# z=v^Dy;@)irA-TKY{GE(`8LxP``NC68L7~*pnv|?e#HUC^BU_DwA zTrU)zwg+cK&_?5cxy!)ESJ*Pk5N!fJNLzasShPM4<$bOlwk^gLjeag7u5Tx7-?kW= zQ}?Ewyfj&hGKLF?t5v- zBBe1v>WqJ4f{Q+0n5wORz8c^ryvfyzM>2;pNiT+Wr^cYzs7yNStHNPcU4A!{nytkS n?i;*???|k%Xu^IeG$B|B3_=D%{Uec8%Npy)3}n>PqqF`6n@M)6 literal 0 HcmV?d00001 diff --git a/icons/cal/white/18.png b/icons/cal/white/18.png new file mode 100644 index 0000000000000000000000000000000000000000..817c4267d2d8d6fe36ae370c388aeae0f79c86d2 GIT binary patch literal 2207 zcmaKudoa+i0&kz$) z8q?nBT{bQePs)BV;q=xcAR{Sz)$ZzbcikvUhQ{s$!lCesbn@eCf8r&bo`-MNzT=A+ z@E&a5AIA)~=0?6W4gCDkw0oGdHTRVJp}J{&eW_{uL_$qd$7w0#>`C$`qjJvi9B%rt zfep;8_w-~dU;xfRP5uQ;zZTN(WNP1RF!tQ=Q+!VYTrYxj+s~-Q?S7Yhy?&oIs;$#x?@z9yq$Emvw@dsxFs!HBTSm z)z?R=%7X+OH%wwQ!89Yb6+v=Zva=hizaC27$sb55QASi7H$)z=0+4>SX-rXpb1?q+ z9kcy9uU9C}p{A-1Min6m5OfbcxegZS$z(56cy}3NM#==YZ_dVdi+hTMH!82Bg;4{6 zqB{GtPcu*>%?UzLk~p$EbvE{KsCR6t#metY<+uvbfp+a?yH^e%8$7qOdVTn+{<7?O z<=)Jk-)%;JU^Czv?2D(~gU_{D)y>kD-Z8u48dIRe9I1IAyrwjbvCsb1rp36<=8;h@ zE01L;GuFh!BtR5(y*5=4iRP+{8H^m|WAX1EPcWV2e-@2rLWBRDo9@y$=t7^GchJ~*CqJRR04lo>&b2HI~YOT1*1SYkEx|BkN(_dv2!XldL6@7aR{c5 z_v$di45}Ubw(W96q1(cmOG|(u*)^qH$5nuh8KxFYP9NwfP=WM4mmgM{@&d({#|2uI zxn`W;#Ei5VRHCkG<~;+;D%#ydp)gOY5%GyrRNPfJfm*=fu9~MaGde*Jkgno0c=7$B zaU-12%q&}9lAtdAEa^IbYQ|s>?7#^CuL$a+-f#oK1x|2Np1u(-Z&EG*hNGDOjAcot zb6~!^ppGCNpQJvG(z|4*W)9P1Jpa7c@_rM`melsU;c#DjW>;5zDAtE`F$^I0#P*)zCS3y)neslbcjq2RV$o38aZn*0YL64=QP z1g5|>b&Y^Md>T%14l3&-I5tooceTp$Y#F3#sG1GeD&w;mF5J*l>U;=K(%I>y6Hh{} zcqJ`KiI4l@tjIVI73lE2@M8m-_2)AZk6gC(K1B`e0BYXqjON~}gOu5?U%{qx+1>bd z)k9C@fQ+N@ZLi^{xm*i@hGCiyn2!CZ=&y9gcT|B_XsI^i*g3&D8Vxzon?j(BKheP# z)x6CpEIo<;np_|~W+E-fMvf>P%9ScJynmuA`J0WwLK`qtx5dU%mqHltZ{zje?fjB= z_?&3O_Ky7FH;=*x(tXqqLN@lPE-schn?^zu0v!BXLr{G`2>z{OMDUCVvjGd~6h6I2 z26;Y8{L5MYRyiU#U$1FA{SMWaK=p53*lro^?_=Uqm&?RIN&p?d`U7y<*4~ z?)qM1LYD--k6 z8|CmtRXixxeE6sPoo`E!`JHX{jbq;ti}3l8zh+-5Od=9JM%8R=-#_X78oSXTA20Ld zZsq156g}ycG}ShtsebyI+#6DxhF}omWlqFL1J(}FRfl#Zg7quql$B8=QT1H_Bj!dl z*Aq<+^H-~M+u?Q1rKeR~a12>XL#}-n(R5gMo6IA=jR3;{&At+}^1Uwocl0dYPO>R; znnS(b-JgfwGM$QViLkKmTAn*Vj=t{0dQb*;%?YWOLNg2>D7faJ2qL66RY3{alpjbu z{o4pHE;$b)*_oSIKi^77U4@kllt+Btstb@@qh?R3f2=!m=y*KV)qC~x@y&ylTbZ5N z;y0qe4P-g3M2ciA`Ga18*U1Qz8NVr&YF5-uT|Q|^pM(BSnEfZ)8V@#giszqF<$SL` qj2>@?%)VkJ+obpd&A@=wH literal 0 HcmV?d00001 diff --git a/icons/cal/white/19.png b/icons/cal/white/19.png new file mode 100644 index 0000000000000000000000000000000000000000..0e6dafcc9ff661f86836c6746265b9d2bb34f20e GIT binary patch literal 2062 zcmZ8ic{tPy7yivKVt&**?M*buBZ6nL*mnO$)}BTavb+ zBs;&jrH5fGr7Xj*WXUpwn3&<4o^N@+`<>@`&wI{!&U4=L-+RTCLX_R2vIPJDSx1un zQ86=r0)-UkR;$1cF(HG0N&r*a#E938G(=CNLIIVd9e_~lIRCx%K&J-OIuGU@6Y z!y9GqgCZ6rE??2k#gp!3E(RU#expstWFFt;fzjVddRq0gq#b9!JwW!0g_2WNcE^3H z=*;29sm3|}0E_o^b~7h(urwjQi?fu!M3@XYzI?f@MhS1(?sd!u<%_9mXwsQdkTX{} z1V^E_Yca0_K`7;Kc&`L>i>X8a#+UUj7(s>h99#$|dU{=H)RpWXj2!W4I@Cr%Dw zTgLlD5Bd=vWWx_1f+Jzu^k5exrrWXuD>*W+>1C1w#@h$)bZuKtkMkBT*SV=0;szSjV(QqHNk)hjU zjF&K{vqp(x~Pto?9Wma$9ZrCNmCfOE0Fj=m*fhDI=oJuKIzi z$@!hL4pp$y<|XbbeqJ&@7L&+ifu9NKRI0y(g-qnsPJw%m-i0O@t(!;mgbNvvA;5-N zxu({M3c*#TgOX5a8}PV(6m~)^D-(x?jOg9L4LE_bbIK+f8o8Qc%}Qs^@teZ-AQtdB z2^mAlr@{3Ic>#vHiLIzDYh8c!6-?sO`Q0eU=-T;=gUSBzdA8e9u<=4IOwAlvty#Zu zSQ;{7FW^@J-*lu~;o6cH?y1nm2q&=V84D`{G{%A;9C)s3CawhgV@>5B?=&;&UeK=!KqUvbW}$PIS-{52TYgSN_*u*&nfz0bTdc%qZ@CYkIgVat2o z!o!(3Ge@Zlg}CHQ&}s#HSS1i>{3?_ z$JVdwI&XuH75hoj-7$hHtgSWiuaSZQbzWbqQFTZO%SN*(cO`EBN86gdU<;}JVLN0Z zE^=lFy+?pXj@h8B8bFyN@CeWcXFXVjyoO4^!j8_-ne3!cv+SgQ*t!tBc(F*Q?2JdOHyI!q--w~9E)c2K<*g7S&*agMY0j9X-*--N zpr3j}nn|$EsUrcHidLTa^`dXq0ij&VmbGw@NUF@pS;^&!JpC{KsR(k0dC`(hw|;EX zf%_X+)vVtufwB8^sUyMTaG50}M%5`YpwR7>Oo+?*+kjFwT#8x#&LUr-I0zjDr+bg- z*GZNYxxg8Z!bes}%xQA6U5Vq}gx|8O(0WBOJ7F7pUs*wk&;!%AMbq$> zP0VT_zV7SMjur;`T6g)v8&0IWWF<9D_4DlW*hL-q1;5_y-DApM8M|Rfoff+By2Tmo za8^Gz*-l+cUFWo3ocb@LoPHo080ibaZtdYYJ&Jtc_T||SQZ+gA_4$+-$I7ez+5;elT9uSE#9R8($5yer(~PAZrQny0@fR+VB1|wc${WyTb0^`+!w!3ngvW2YmA#61Ed2V zw9(Mv)Tb}gx>xYNC0BAQ^)IyU*5HRirX}ONN|Jk>9QM1w2GRum(~GTF=G_ibH@UwB zYHx}{Cf#C;B6!FO`K=;u^H50|_7d6hnvW#=?U50^#n@qle(979-2;eXd+ z{>^Ou>pCVy6lCf|LdN6Rhk1@2!I3kBvMvAXN+iHYQ7C-{t2M8Aa);JWTX%Gz*t2Z| GQvL}B_QKWx literal 0 HcmV?d00001 diff --git a/icons/cal/white/2.png b/icons/cal/white/2.png new file mode 100644 index 0000000000000000000000000000000000000000..b93789a59ad776ad87b50024d765abfe4b9258ee GIT binary patch literal 1553 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 RROQfZ0+wcW*k`6V@;{z-^c4UA literal 0 HcmV?d00001 diff --git a/icons/cal/white/21.png b/icons/cal/white/21.png new file mode 100644 index 0000000000000000000000000000000000000000..79a74f3d2ba82322a3ae7fb7be95ac6805f77747 GIT binary patch literal 2092 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 b$FI6mP9E&~mrMu9*8yMe0I%Ae^z?rND^aSB literal 0 HcmV?d00001 diff --git a/icons/cal/white/22.png b/icons/cal/white/22.png new file mode 100644 index 0000000000000000000000000000000000000000..e8845ce2e8950e7a773d7fd9dad893f3f490882c GIT binary patch literal 2060 zcmZ9Nc~BDQ8^^f(_G zdhPKbsFb!GYEaev(&b2-N}xx*@g6EwomqEYx=P^WJqP0f0Clb900OR;=%`HCIWJ!v zY(PzWrJ3#KKu1%RQ|#rjJCGuoxJkXVdcVHNHJ*RF@EDW&8F$nOjmz7#5KtbFH=LO# zU>P1+#l%H+8sKtqM{q{f@Po#IYZ$p2S&O5LN9mB&42>?VkwId+V}$p^>1k2>qq;GE zU$Naxd&!fTxeUg@9A?g0G2<-W5#MaGDXsn~yr_S~q>g7+;H$Q|t)bj_GArin2DZmJ<_Fv-fzzYb&$X_gvLjhN( zihDx~TESNads2Z3Uc|<<`oDpxF~4TR-vO_8?XPYp*hpR`%>KDz-`ZcAjq11FEF2E0 znM%@ODP99U^!#W%{f*DzSn3*jmKDV7V9zuCJ8wBq+F_6;{A-9@iRLk9N&GAn(O*D8U^RhSL^vOg(AZ;Q$6{0`DT*4=q10Eb6J$2}d#^Me^GHJW=QUz$^I5iyj z2%PV)J5CWMx>H+)Cq6+hsqweB_dG-N>03e@A?(VksmbVuNP1pHNcsjY`oLOL_Jia0 zT;0cQ0?1@c0||8KP1wp2J~0ZzUGw-)4qQ(IHSlimsMdR10R&&TmI*!$uG|y_m-P+0 zEqgmi;?sJD~Zz;_pk>w*uc9e#gR()|cz;ed@~B_k+pWp3tR4bgnu@WV=*jE>J8 zW`=LvQVlwhPP@tLzD3Fplbpy7)@vzXObI~@l4qkjS!&z1WuWnCAel@av6=Q!U@ISC z{A?jawG?sFS^37#<1>&puCZ+XVpfEy7^XK5whZl}=?dcH3U)^AQW%nAc`wP-C-%wo@ux6FnP*L5 z!E_2zGdk-hjR&_(wS;m2E+^m1M2cQAxA0n<*2rv+B-YbkdY?TIX&rUa75fTuXd&kO zaqm?%y+1{ei)ulwd0`d$(2@eu^@i0&(K@4^Ntg?YV`T%EEe);RZ(c#Fws*;u8D}>? zh=H*a-b9Jx@cZhp_#tnl+QV>UMYf+y@YlaP_CgbZ3$>zHiwE74Zt5g>_mlHE{TKT0 zKCiqrIJP6ken%75-I_9q z-B8jM*0V;QO#jWY$&MBw@m^80V5L*8v{Ev_^+Q`HaB;vjpgx_H(q%JgsI^N(&RZ17pSRTc^Ay-TEvEuzOb`SKQ_tN%XhxK76cknU_Q3tsCm3gp$6c4 zg1BA;ec)-%Ug}$fYINzwSx#{pN^|_S^XIU+$;nCcuOu8*y3Wux^&r40qNsg}3(!EM zMl@&ZmSE1jNKn>9ou-04=&tK1&N#wvFHFx_5BsfegL3ci2auZZ#cyPZojL9~j~$?N z7T;-T=nHZTspS{k2ncn+Zu}9i_U;*8*Yx{pp^c?)$cb1em&3PME_0H*lP(+~@G_+E zQ~kFCEF=$->|*;k6_u5h1^wJR&Y67>h_GbH~J>=)I zvd6+NiqW@sqU%)e>h#iY=0bv>Fg@!WzBC0-KHurDH;*>)?37B|rv7RkGgl2c{Eyvs z)j!&3mBfwTEyyO{r&~l@UgbE(kvgtBjLV*MkEBcAvWQAM8|=t9R)d11nB&e42z&)! zOocfp$jpTFkC7!wH!DIZ{L0VB4GA~JBq~_iuTQQx1zhyenqRaL2s2^%*K*fSSfCnT zmvwza&|OzjO3z)iN<+wi^EVxT0EXhEYi811sFHZjY!Hv8+6K*%`g}GZ7=73<+DoZL z^5>Zd8@fOq^l-SkvQ_)_da$K2hEw4ujf6vlCq9WyW2y$e6@!j>3k@_< znEgRjTTG%;2*G-3hVRc1bBtrfwd$83OI_qnJ9OfXI^h_jhxIAR-LV<)1*9PQWZfIk z1^bwhlYDN!?96xHrLT)!X3jE7I?Wc%u#HsdJ|5c966&lb%b5+@DxG&Di^F))+l}i^ zz<6#ouNgX4!+NPNGj*67jBY4rn`)BtC?zn@Yv|^Y?=6W)5aT~2VH!|!d)91%dHw&n y_Ajp98g&b%RDe5#>t%O;(D@^i@hjCls7izCrN**Y`(B4-sC(i3JUDJ7`u_m7L#wC& literal 0 HcmV?d00001 diff --git a/icons/cal/white/23.png b/icons/cal/white/23.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d4dfb6dc75657f4b5b9cd07704bafc0b779340 GIT binary patch literal 2495 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 literal 0 HcmV?d00001 diff --git a/icons/cal/white/24.png b/icons/cal/white/24.png new file mode 100644 index 0000000000000000000000000000000000000000..1a3b38ad29f89a08702f67ddb9cc2d37126673f4 GIT binary patch literal 2280 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 skY#85i2>&$&h_-vzcflVR{#J2 literal 0 HcmV?d00001 diff --git a/icons/cal/white/26.png b/icons/cal/white/26.png new file mode 100644 index 0000000000000000000000000000000000000000..f26731bbf41bb4fcebae8d075310abc25128c299 GIT binary patch literal 2645 zcmZuzdpOgJ8~<)Lvl&7*avye(+%M&RGPjdN$CpI4#3*;ATvoQjVeXf1GTPLsvD}^{ z$?e;9bV!}fP=;lygJ`78{pbAkyPV(qJfHXTJn!>)-{<}7eLuN=zMgWJ9T)%rh(wjg~ljpLO^y5*?#CnyXGJPVI%~B;c+eq$(=PfTRB747kg<-^w0R+$RN1glvEpuzb_m}W58+Vp>OeRhhw=lBb zJAQwc&Pvzn9_Xt||8%``a4dSgE4_YvrJh%-N37^Km2xiqRHj(gYx2bK_m%oq~pk4I&0Uwt>d4$HW*(;Y39`x)ytau0NH5B9H#nj{c-sJ z77MsHsu|HA_YtiuhH~zk=^UB(vysxA?3&;5k7h+(`4W6@c*EUOKE?NDh7JQW@U0d8 z&&b2<>PjsSaE2b|s;9Ft?m$06SYRDCXK?SM?DKkNz+C`1i=e8i!m-jTu*i?6E(d(m zX_6g=*8zcyp5Il%hi#!YsQr9!@#Y-t4BUQo{M*I~hZG(FqFq4;DG_~!Mt2>N=^c@B zS|3n>V!%<1Bf4)}sZ&JM;!(&3;?VNxXBEqe>ndcX3aR>l-K8I_H)SCA_Qagn;3F6QEY`b=nYp*LYqec#W?>f zh8>tXsloJ&FabR{n>3MhG|V}l`LI(hC8K8kKo~B;T<1te_ZYjpwHt4)`)4G= z6jz%2A#Uwn2tb-dF0kU2%RZTcM*yFK@_TZxT6%P+t#9lHwK-^2Qvx%3kGvmd5P3V= zWMcLUsz7e>vst~qh%*NNt*0CQCfRhNVydf!@mM~7Eof&wVP^|ca*q7a2|2d$HSx`m zf13eo9&GUi4>aR+_E^%VDrBh}$v05c!2F)D_`lMGdJpz6x}f&8FV3zga5OVy@}aVX zsjbwAD{b`wUdyO4wdd!vsG^M;`Dj`5XX+QQ3HXGg*Js*SSWA-QQ{m)BZUdrAkI>y} z%HAz4{oC6>QYG8%siQV>Y-ar9ugC({fSDR{%@<_(@tujZwe>SjagQPb0`ZcyJes2? zP`qqsZ<^et^7aPT?i!GE+DQC;J3>59b8Nrm*L5Fq1grdGgj@E{b?}G&Z^-P>MS$PyrZDY*r$n73$R4YgK z;Y&YiM5txSYJ9_X@PZ#0iPdagBPF`ydqZQKvQh~P90GG_cMMEAujhPQfr1Vpnx+7_ z6el)DNB5%2_Z@nwK+e?m#Jg2)Yz{yMgu9(J>baj4OJ74~@Go|*-~cxbRx^EsbZq`~ zC6OGSb&FpO-;EV)OEG^Iz;b?i)a}k;fSaZ#?uRCGI_8;#@AbNlIt1okrMwj3=J>#U%H&i2<}e+*Zz6>v+C%N_hBqt z=@a@C)9t7*D^HsMcqe5ybzLrW(Q0KAtaVycR71(P%?fesd@fPZ2^;J#IHh4Y3m8ikp(4lYf5v5WiIs~5 zpQ6%!S%|j~`HUm zU&$G%xrho~bUbWP>mheTZ7gy!Q0CtPE@Uw@{P}I9W2pk5&W}Ih9_~v|YtxXZ&AsB5 zL~fpZE9(lT!v~ZyZpEf2u`F>p`=JgE);iGo$ZEQl9GiHIY@ubxT;3_PQ9S9-Z{9QC zZ>TJzKs~QlC=%^ZvfW4>lSKa9RaweYiwWe{ZXfe3$(N<)tdD!HofSVvTu zPeGh=O})EZ@sWn$QJ{B6sJH5-YQml3LsvQhQ?|WCV@{U)f_{>);B)xe$ddH+hbldA zkxWSIRsDSL<$^F}*EmJTnVhE8!&8d36SyiZE7-m3GJ)@j=PUM6XWSw7L2B@AG`mUW zC_*~*fMaYC>|9}s5S+Pm~x*joTo=6Lo{ zcFq+*5zyBS@@!zWZ}Z!|M?X?~!--*&Byi;Y<4z~~+yl^oBO1hhMxI@5IAPbM8THdh zJL*-;{UUh2mwF#HS0a-m=}t}S_F!8CeYpBqQqM=K{(!B!EUvS~)Fl3=CHgNvaua7r tF=cZo&3biQ?!~a%nR5U1EH~{XW(uV%>sKyYFZ}Hez1@9D4SUJI{0p5+sm}la literal 0 HcmV?d00001 diff --git a/icons/cal/white/27.png b/icons/cal/white/27.png new file mode 100644 index 0000000000000000000000000000000000000000..e4dde7700dd2c86fed2c94ec070f3fb751ced45b GIT binary patch literal 2044 zcmZ`)X*8P&7k-lv5+$TMK^I$5>E^Sx&1Wmo=u9oGr7bF2(#<;6rmA?24%I}7enps4 zOWT=Dl~j>d!#fOBLOz`;LC91sMM6t$*(UunKjwVjJ?FX4J@?#u&;9e9C)>~GkT%)~ z4FG_)H_7v;iovhYM5=O|OGLMdkf*;rdIYnueGI5^Q%S;-*G&#%D@x#W|2O-7`$9*Zs>z*4i zBIS+&?eZM8Jm4T)6J@d;oc2I+`wy@qxAkDwuCp3XvOapwQlXG)A?u7Y{Dzt?){O+1 z!v0UOq@NKZ>p6PSk-tss!NvLQj+z+=sfLk{Q~$A}J_+miy|`y%U{1gPW%-QG{X^j2 zAN*ZRYaox|=}k^xM!E;kt&|3mX-sbUOg^f8H?>wN9#tX?V>mt$qMVT=a_6uVaeP^u2l4;Wqn~RCw+0LMLDaM(c?V$-0%a zHQuMoe^&BG&s^WolIpf5wdI?uD9*Nh4dn6M4t)`pe5a{wN+L}(;a6UWpHh6k`#`!R z_2;HB?P#@L4a>l#K#eIz)2J}_-5qC`YCnlp)8FXIx9W?yt}=LJ1GvCN-ndyQwJczcT`%OD&tno~V{Zu~lkAArYhA%gvoI%T;A zo_kj;Nwtmt*FqCS7_cW3OU4@6T?Nz?_ooi@iqO8;aa@v1P`i<+U3NuBfFE6>EEht} z?XhI{=KJ=pCbW+zVTZ3(N&T)?Ehy}=0kV0F+y-Gf3u5`O+vpe>W+9op!$gQ%lq3CL zS1R9tRl!U_FaBC*z>eR>=_$=eNTneoDTaQ}!fkc-*`%A!7(!>!50f6S7=dApH=Ol~ zBzbBT%6zbj)-xA|s?91y{BeXHDltZSDuc-91Jzl-0_BVFVKXn~Dm2~F%Ns2K%+Dhq zN_{^}?|tFd;B4$;4)gk)4cZfWqLX_nl$osV&|ug@WR<{x{jv`9#eKIJAw z_yD=;>{!M zQuD<23ZmNi6>YjAi#IoqCHoQ;nePdyqi5{|I-(UbVp`|H{t5QX3kG?dZ#lfSxivXy zJno7Al4}Gdmjph>o&_5J(|P&{vzitls{`9+KhOF4fHJ?VzpEknr+2c2waInXbZ2J`o!#7-KX4_jHO zSE*di8_IUkXB_|H$nHvFx2S}&d<}jXXCx0kRQ!N$1vX*ww(1dTJRN7jji<%pdA}vXf(G_4}UkX~9w`{$53VVN1Mz3wN2)^=pz{IiL`h*0jkq8)ajY!1BBNif?)m-q_a~e0$ zX*LynsSX0-;C)v11l;a)HRx;n(8sOQi3+r;vnaq0uUuRd6NM^T=wq(0h!r~f+XxB&cy*X zA|fYdgf22?NCJSE1I~WGd*tA^`;-z757ky1{skFRxOSt$Te)|zlL?u$8T}n-3UzI# zYI6&gICnqPttB({V_8qL=cDmQM=;LGJt;tEnOq0VN}eUM&(&0DY6I=g23ES&DOQt~ zqm=h2C`)8sEuYV_iXEo#qGS2d8-3@BKG{1ycVkJ#R5GzT1(lcf;q~UL2MTLKCcz|- zr4i67JXQl_t2y2AKuuy=J`TR+YZbYzWE!3RWA2?_);s?>{$DK!1*(AI3)~gwoc}lP zKa#V@D%@ANiJ{@v<&TX2_}Z2RKlLwk&!k2yf&QcGpH$r&st=C#4DKE+EVaB{?7swx z5&7SPqrrwJ+Y?x35D1k2r!MOhNT=qe1H8(~2TtAh?(Kb7n;)R-D7#2S$h` zKpjD^sj7SC(zsz-B~UN1Vc4+l?AvXkmu<$Dm#u_8E1jC#(I$_fNJI)nO0Si()8|t7 zp+@w%9zD~O4nHAy5MIa;+<1+s}FK zD8otEHV||ZlpYfKn-99`$|yr1bROg@a8v`lkI8qT%SSYon?%=6N><%Yr(tQAtWu}D z(dv3H0A#q(RS!*21@PsL$mPfkdh2qXbX61kAw!aB3VgP9M*1fv@MSp}j$Y6cQtmI>A%C6I9N^*X}{ zS6UHcUf+A#OXKM?jiS+eoLSY4*nP{VaYvt>-dLWgS4xfD?zHiT2rwvm8e2}=;=;c;1-I^21! z?!l+4;N%{)mXE)k%;R`ztMQ1u%_zk)pLXpH8#?ydNM^-2QO4}uUE*=*R4@L}w|3NFxbLp zqFp8V$)W)@EoJ;yex&}V3#8y29&UZ3Bar~xndwz$TY19HWYK$)YtTyyA^Jkm66azLpxsI1U zt~DI6lRTufbu=JwWKtNtOOsoc`hH7u*Eu^XtaG7#%=A}t%NL_t^F6m}UUb%Js^EbD zL-lf-E!XzxnIKLc{AaXeNjG;UW56E6WZhTS$uQw ziqESC8hxC3BNoDpJ74sb2aJDfGSK|1juTfwLt5h}I(-kDgZ$Ggs&2KZgo{{0EO%-S z@5RY8AFyXR;g?WL%7kpT?(KsQYH6dJ$Huzb#`=SuH!qIeR90BW5w5ebx1HH3(Nuk{ z1Rdaxwsop@04_`WzHl~t;|27jpD;piwl_~U^lWl^*=BJSgO;^4*mZjz`3DmpgAg-->hzTEj(}Y~N8Gc@RwL|Q(Y+uK z{yOtvjl!sjlrq?V1rD3Z@XkGJ3}CVjMknR+y<8?h^;SV@(Bw5UqLpa9%o^pc2S%(W z-$(E|JnZT=r5M3>_bUA;kswKxTn>}tB+*8Yi2x5?n6ll<{Udv?WWzl-fmmrgYMu_m ziIdyfEpR+UV1_t6?czsD9~NhPFjKkZJN;pL`>UuCJTUGSKY;AYIzooxEWVnq@73M4 z=D{&xm|rAdPolV8bkdYT3_Mn&$t8>aumj)W$LJ~|w&J^w z<797Hg!45Q>x0$>dZi0omW}<=wQKCmINL?dnJ!YUSLTx=_U7y=qI(&PEN6Mmqy?k&kT-K4x9!Yata9+nSJbjx8;*a%+LjiBc<1&SHa|Em|t-(xy;< zzKe0VRobObb5k`kYdJEEzN33fjl9B%Ri44B-{1*}A}>v)hOjA@h54{W-64srerDKW z&nqb@#_!)js7hm*6Nj1?HdH2xd;Wy037^#~Sn;u&jMcF-Rlym#zU()s7Twb4NNE?% z6I?cLvaFq2(|skrmn(?K1c#_ws9X=K`yw z#UFp+)GBlQQ)Vf=HXQbK1j0o{O}?$*KVF^)H>Qh%rS_}Yc8iEzeds%LQ2VKD!Z z%8pt5gd|hGbN`5iLp*bc4b2BmIm?P z&pd6QR*&+%4^MP%#H6VB^==UC?^yVq{c$}Jsc^(lB<_^h&!JJ=VYkb^z+2Hk{qsH@ zW^X+~)&ei|{|uCaY(|e!u=-KExW5f3&H-;< Ie1H)54|_xGTmS$7 literal 0 HcmV?d00001 diff --git a/icons/cal/white/29.png b/icons/cal/white/29.png new file mode 100644 index 0000000000000000000000000000000000000000..e9a74f8be9e55a8e7db753e3689354dea3f9028f GIT binary patch literal 2597 zcmaJ@XHb)g7X1~aC)iDYEwqE(oC50`{ z3P>|2A5>qdJ5pgim=PwlYcHCE7e)!yspwCb@~+=xL||*kO}Xy7)+0!FAxO#MXWA)7 z!-z~#PZ&c3>zvIMQhcjLtd2uhtF8P3q?X)KZOvV9&etrr0{lkop{Yyi<&T8diH{V3 zCpzow#34tVb1#+?2vNjBu)))*4`lsJ0KH%#Kt%~7U`B=!=yVuu{!4>ctp2u3^{gY7 z0&c(3V_%g78#rUtVir|w?XgcluO~jaJm4OH5?^qC7Pkp=E?XqH2SZlx|1lNRFPT*g ziWmJh>B$IoDzOl$w043IX9B&wA3Msm)}x$O^43``>f2w-FlVuNnTSCWAlvonCyPX^ zIdndqvxr$ByVeEDxFOgkm3fz&D*G1HX{);BRn!&kICQdJoIsWV@YxCwB;n~XR@f@fiy{xZk<1rH2XncWmXb?e%rl2D>~*C6DMGOz(E@ul;0 z%Jjgwt7!NA(RVu7U621@ZxGuufR5tdMM~X^aAifwsd+8dtSKxc%qSUYtvL#eq?1D!0)E$z{faGV~PG|(AieicSFsn4IdoNq?c zr6)Pmr;;x()r-?Ku}kNU@Gyy!^3O4Tzdmyc6na=ni}t;hOpTqee13H`HBJ5P#Uogl z_TF;xIIl4}n|QW;E=U+hBp;l-TfWA@FVUZS%?BQoy1_c4yfarNXj7dF#M}Y2ABCKX zdtL;O0frLsn)t#aU-sM$sh zldE~>@9!#XsS*C7utwv9dQr2V`I@K&8hsFIkJ_CjH=vO{t`&X4EN=`mi%oJF6`~7A z)hE2kgZ=4u>H8WVXU2!-*3jhhYZW&jo7yk*WadROH-+rbwaCTS?HNTbhP>E}lRa}t zFCnFAPjO?|J>T6vsmuzMDXA`t*!Z#_#~ZG5+6`qvkK;lh8amBouZ02HzR2*$(fgaA zDx|geC?)xY1;OYMZlWa>)2Qt|)Y})}IyU7_;HF`cqixV=8<}5Q0y`4RL45z2Meh-6 z^2^)QQKa$sGv5g@?bog6c26>tXAD=>Zyr4Z@dRA;$Lh`Tkma9-LwIolE8WamdY61P zn7WjYqOO@Tb{z$ZN*1?BJ*Z;IwORv>y3@ZqDA*sN7^)v;FLyTKy^&9^+ZGtDyEx^V zWX)VlTpqszZbL5Gk6b^PBKd!QlpM;d%{cI)DSVjiBX=Z43X{p;;vub;@_iYap!A~v z^gtLC>`7rBl>$;xs|R5ug+Z#fqZaPhjbW|+1uW)^h)1%l^3!5pUOE0s(f{RrPb!$oF}D{JH9C*Y?DjYE~AYiU#-)ld9NeJRP8xN zPje`$FvRGUGNiSDpI6reTj;pYC;v4-?7GOqT0#}=LY1v(tvPSaR*KSqim|U{PwFdaRXEXt`+>2?F_ue=1pDELk_@+oJEWfyBbYLsmS;#; z1lzo0{!2oF5sj0g@P_fER4 zIIFGl;A^_~uBC+RYf1U4m7%$js<6iU7*2X~4{~7&JK7WG3#~tyVOYXi572TtS>0#{5fYF5&O;MFA z8(a+HNN`Ox71xvyPSJ1CT32NV`-%-zBkqj367P#6J{e}}CfX)^4IbL%n3<($<9!tE z6X(>8Q$xSoWWv%s`4Y}?T`AFS&zDSzb5TkdDe@QPY|QXx+TZJK)HTt0O|;qouD|?c zGmJx#V?xBgHbXEgJ6p(j{M|lh#;H~og#Knpb7)Ziz=IfGIC1Za)4k)3?`ZAQJI(Pt zZY>DUT)7=I6DHV_QGR^Z-PNOI2$d zUD@iSZ^_K&VjCvHn;9lDHQVdM2zRq%&RGNUngSkj^FL`x$0|+5-gKc;S8s0^Hm3_F zL`FsL1zWhROv@tDj`kzAgIEFT#wiN;L3&(w6VbU@=(oqt?_e3ZIQPm#xz2gW{|PPq zzyJ1@fOl6*i@E&EC8;;AArV?Ts{aZpi%Cb2Z;p#W-&C8_{z-dQ7&~-@DK_bEgwVu3 literal 0 HcmV?d00001 diff --git a/icons/cal/white/3.png b/icons/cal/white/3.png new file mode 100644 index 0000000000000000000000000000000000000000..11242710cb04449563e2e6c56440d9f19c8afbe1 GIT binary patch literal 1808 zcmZ{lc~p~U7RJAPNm!Dh^n(!Dkr0ZsfK(9#0a+4~7-cD2uz(qYGRzPNWea;!EL$OB zaG@YYM`{WP1Vs~}C20wWMGTuDdqyh=A_hT?D9~^^bNbiZbDsD2ocEslzW+V9B+#Fv zgEB?|0H8x56TVQBvm-4H_1W$D_kJ}rVyGm7n(BJz+nKM1Hj5mQ0sv_J9l?O=ONQ!8 z%~Z-UqUMYiM*DNk$%{q3>cLtH!8?RK`J(n;#ipUgg>@9S8rid~O+v`1xa6W?E1PsP zIVwNlsMDT*vxx*KpY01Fq0{VcyZ3jW*F8KL9s#9J&@p<}M$lCllA$$AEdM2=Y#iTP z7N0+=tzUf~->|aSGP3Czc;9g*GSr{&XbZh-qr~)U}Z>0td#cuOcar+ zIlD$6L>`|0HhPz1hf}bGzrh*c{qNr?wAKhArp@Hip83)-X7!trQ z!gm3|RMQxDR?cK1xWvbTxmPDlKa7(95pr|2d86znG69==jmJnpV_-LHEb zKLg|-+}%;-bA7f_9Aypv(9SE)Bp+0oE48Kqei&PF>qOIV@d4;T*DaLk&@b}CW~#dS zRdaZ1q5RXp!u?zUms(vM`y}|#I?RMS$H^j$+Do+vG8DxEp1;Hja=5VWL--*2Ju~5` z&P#{Oh`nL;rn>c?m)r$BK9yQ7?i&T$zjNUv9a$D(RV_Uy@AQG~`KCf6)wWhr1H7M` zDUFcE(tSD-E}=|Omw?C%v*V+o-1^)cgTe0-71f23W=(U=d6I0YFepQ(s>*NX38xkJ z*i2zWiG$0*pjUN^WvDc&hm{oP)i9I?nj`0fr)O&RG+?2EFNx*eiiLI^C&IZNz5@bl zINCgB@8z0k-zIM?R%tv^c+;=dZ)KZX z#XU9V<=5BM*n53nF8NHEr1+rMsS9i$3CE|QE5f@iG$K)v#N=SX-_H2S3Qgsbu^ydl z1Z&zkdeZFRZsy&fY4kq|w?>(CSmTJQlKXbbv2XL^DicUDe>{99%Yel;dB6m!9y-2G zfMuQTk!nM$K|TG8C6}=`xiPl}U7=N?#?#k?z;844*mfeS2YS#g5ez%h(Fd+O1alVf z_LZqOkk6w0HKHq>M!?vEs(7dqK;s95z{AJ(is#O`V|ax%C2pP;6y>UK2+dL4ig6}n zt8C!?ekZdWH>K#4=P`Q9pX%>HZL?sA@7Lb+0q5xB@avNsy8Jir7DUUn52a6Xxh8vF zVZ`XZqZbZ9s~K9=9ta7b$`ojXIEUk52hM?WuRIkDn z%Y=ItfzGSHhx34UN0cT)2jb})E}31ah`zcSTRp#wTR;Q}pk#c3kIzA}@i@<*ndLVdr-bX$kQsRnc&1$tC(_EoSwsG;UN+i+W8}^)2 zV9R$qc7<&5wg`JJ-d;EemgT7|F5;v-M=mb+%R^#j_E0Z_Gv-(jb2jcg4Fhf8Z^oq< zD1ItEA7}Q!U^;9*HvKrk&MM`G{%)KzNj8CzzseR3SV+JsBWRo?(@lj<_#;U&pVEj< zBPqivb}P}+gu4yo^NO!p#n?s>##{=9Urgm)J~3R5Im54^w6WF*bP>O33&Gx><{~G` zM5(rS=5&^)_}49)5m~NGvaxU5Zwo5S;v0W>pSIM(R?lrq>qAAJKj;a}l8p|F-cB%v z^{IAVMOIQF16eBIv`#k;y%DfO+@+rs4tJhGrX%xahHmA~45}v3fj(9L=~_4}K5yvp zjRYEfLIZa4`_CjD>?9l8#OJiuio!K?2B3tm5Pv0i7m93Z7td>IJhWIDl5s$c{;P$R buA?MyJa+1G>;y)k-dzBN=uc?zp@01chCUUL literal 0 HcmV?d00001 diff --git a/icons/cal/white/30.png b/icons/cal/white/30.png new file mode 100644 index 0000000000000000000000000000000000000000..8147d78f042bc2918a7cb6b8ff0f482c91a8f363 GIT binary patch literal 2912 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 literal 0 HcmV?d00001 diff --git a/icons/cal/white/4.png b/icons/cal/white/4.png new file mode 100644 index 0000000000000000000000000000000000000000..16713bcd6729a74a11856b7199365bffe6fd3689 GIT binary patch literal 1140 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE5z6j+Ogmui>jeZt3s22<3V}Oe`f1qEoSGKbmzqE z{L(BazNlNSNaNa>>~&z5Mu=-`BYw2q*t`BH9vxl?dUP!oxL)tlp_l&E3OXrFvh;O)R0uqVi-;>d$Es{_Z z`DOQkrOS4l0j&kS@N8n^&$yGu~soHscl->xnb62j;RW&S$pQJYX=Xp7(=S z;te~kI1%G5Tm>9E_AK}d^oSGtd43ItpZESN6qG04*lFAx)-X@~zt)4Thc@&pJ=*;7 zKal@fY{Rw%fAjwo#~#pPeewQYy?sG^;*EbDKW@o4*orF{UuVo0X_JjURlx*K z?hm`Eb)e+?zugV(T!-g%cD(l~Jr8vK>4w9tiS9~|He|}Vv08A%L|^#F@?nLhTm!?* zO7;&Ci8t1D{J1CbJ*MGI%;7^y{mT?`^pxxj_8wlrpwB4Hee3_8o-Ck??*7haE)#3B zl@zp}b!(~NtAbDZiHVuzolDdk*3Ps%+wGWl=FESq`4^bxyBs;rwZTY+Ay1=cCsRe% zsoPr9{nia+e))Y6KoO$&24hv2ZRsk@au#4rz=SRI^ zjB3v$z`y6IizPRGC)t-6wGQ;0tz>EZSFVNNf%ztL{&fIx- pos^ny+AkH}c4$TeWw(`W_Kam!@6_TZ*%yHd4^LM=mvv4FO#nI&@%8`! literal 0 HcmV?d00001 diff --git a/icons/cal/white/5.png b/icons/cal/white/5.png new file mode 100644 index 0000000000000000000000000000000000000000..466aa7122c025b1983de187ae9d2e565380fbd6e GIT binary patch literal 1437 zcmZvcdo+}37{I@|G0ilr(ilv|Sc>Gb8n@iaOlFdy!B!L_qS?q;+I9EQ$$pK?I77LO zTP|JXQllgr-$7C#iAXUcjdD#Zxzw&5o%(C{J?D9U&v~Bbyyt!2KYr)kSWX0-1`YrK z0+T^w%L%RpRzbeE+W9?}L*cly6HQL}T6SzqkYgQ>aU>i7@Eg|x0py8D@}gn{(}k`$ zj8(;<(PIqsv?F3q9txY%aue#qHQn^)mX))V7qR)W+3C*i5v#>` zdtT0q+=hg4(UU@nRZw?>+JP!=#9b6~cVf&R%N>)@;KcRWt}ip;!~sn_2a$>~A;O0N zcgGdos!86~XZs>oe`9t}Z0V9DmsQLUYRh~6--rG$IZ*yCbkwZIsm)z2=GheTuJg9# z9aj;ea015=yaBW$N%*fxpz0XVxR3bA0)^=BlKZ#vJY^T{gvk*qr9 zLEJP1jVU4ee<=3UfRDkI@Dt%}XRnipNgepytv6oM9n6}tT7Se(!9e;stR{F?I9m%W zTtyfKDAXS6wZ^--A{h6eDq&$gAUlKj3^wQ%wVMgIhyj@iDrXS&_6EJz2JbebAmtrZ z`cs#?H$69J-l0cZ>dNWO80ZGh!Vb}7v>xi2ds-MhyIaPRa`~HDh#VXFrGyoz`EIpH znut^~Y{G@sTOb9%@9yirL_FGPh3m=K)f+MH7pk7QTSx>1D1n}pwI9>C%i`lsf3HfW zl2e-=N9lg*C~JJtetI9Li6S}=y#>!~X3ROP)QAD~lsWS`c7DFAV)ZRxS*%YreCd~t z>1ZZe5`sg+=U)(uHKuO^3*(IZmo8$Uzj&C-LCI^K!QqYmavIA2ATSMcMPE3Mnt4?{ zb8~jTe;W(8K^%zp~l0E)TgCa}j z&N)L9QNn+%M9k_hFTDl3U_NBY#B@}t@haN NvP?RQR=t;#^e^g-c-Q~{ literal 0 HcmV?d00001 diff --git a/icons/cal/white/6.png b/icons/cal/white/6.png new file mode 100644 index 0000000000000000000000000000000000000000..a1c9798bd0c4cf8f03ebdb6524f723c6f8e415ec GIT binary patch literal 1776 zcmZXVdpy(oAIHC&ZFV`T4RcG;A(sf9Vs(TvF@EMGmo}G&BBWw+X(uh;Rli))F)NpB zq)?qAYG}vOz8)N)a$VNRj58di!>oOOPW`sep~Jl^lu`|*CiKcDws@8>7)7pkuw z))Wf>fF8w<9IRFFtD#X^-{G<6kycQ91ANI^)t)(TQMOhv3_n^L0O0h$8Vo4s8*7ug z>6Abp-66CA7G)H=Cr_fi$fA(9g)j#uDkAD4cdg73r){Z^sKtD-v>UkI>T@!f5E8<( zpxXu7+Wqxk|K3FAenkDLd?6WqiGZKovC%%%UsLtW`YcDf!T|5M^x;HxXj?%}8zqWb zK@%kOs4pl>`Hwpumv2h=B5vy&IM9GA`|Zk&VW-^OTIg5N+yetjK-9B(+P$ImFMGP+ zyMb6(0n(WWrCSu|mPNikvQpzYRd@znntrAvC7c`*)s+nYxBk8H|AQvOVvl3vdni9; zW%a&=n+9whGs8zgR5{QEH^#*{fVch^BpK`WJ95{GjLm$jAIUd?yl0XR7=pZq+1#yU^{j4hk@i?L_G7+B|Pr$>!iQML)v zLgbaPZJsxK58U(5K`y$E9CKruTX~TSfMi&_u=m9_IJt8bGy&C_zR1K$QSF|H-9PX{ z2s_usCAb|#W&)v`7Pbq8>C9Sogd| zv|PHSUA#iroJUKBt!f17@t^fU8`}|}F6tAJsk<9f2X}>ufvsMJHAwqBo(O;*6hf|FhhxZN~f~ui`TSKUtammI%bB}^%a=PC&k;xOTRnDdWGuJH@)DiN?tGnYu45_uNE(;uk%())6 zw6lt^7o8QfSdFFG8jrQ&@{3foN1T9t6*lG5DZsltWPyu+@lS2s1zrWK^RGEh)8jJ8 zk+HCH$sd^grnkUY3r!4puz1$a!ApPOcE^^ywhq&J{Q*iO%A_hC%8LSn2y8*>l&2E+3ta0Of26y8-lmfXeS8a_;kU zh2g=4NZXQ2&peeWTN%q0*T(0g$!0;WjE(Ltg z;9g4G<;n9Oc5+h{b(eAo(-n!Z{4sfFy3_LuDM<;F&bVJ3%m^|y@TUADPh#O;H06bp zF2U=HnrgwjVs(y)h|{c|)jYYIb}bwzR$=yt`T%e2z+;zv#CO_l`cn?@^kruqET+!S z9E%dP98sZRRujPR#MNPDKKVeDj)5csv%kmQLTQlKM+0Bdia6u9k5)eQ?HuXs8I=>O zm|?*SmF^2b__Lzd)_JOu2=L_sOw2u`2wo=$PVQcFdHaleRhX+z3LWg?+_vjYl*PY^ zEbm_wuUEO@q{c)YJJGL$=J<0-!udiZ(Q2{F$kwD5?>jMrfd}l1F#n8Jz$Nq}NHg@H5k8!=b)04LDO%Q(YmDOWXqnO2Cn>W=f|BiC&7{^6 zykzsaWw^o8PlmDGnMj@fN+;dbbSP-y2PU5o+}eDIJE>b@XqAm`Z-A%0#|Pk~RyPsH z6N{7^f@JHg9q%8;TBv+SHps>&47&;CBHvrcexDO^u)8M6Kku`0Q0NvBT*H5q-dcN5i5iCT!8N zV@my=?{V=*=kw9=noNJq&pW^+ETfsOS0Ir!e?zK@Y+o^7cqAiZ^ZZRMzZ<{hwWxgs vEX6a)|4H51Y{S}2k_jXlU_DZJJvyVdcqC)`f*WwsN|d5V@~`7SL7+6 literal 0 HcmV?d00001 diff --git a/icons/cal/white/7.png b/icons/cal/white/7.png new file mode 100644 index 0000000000000000000000000000000000000000..e97195177c15ae97839e9c4925e9cb7d4a314acc GIT binary patch literal 1147 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)9b2D$@3URf&(u zuGjXR$ui%XxXssXDwv+~_Ecq;p`Pqw>&uF>W;iUm(IITn;36({r(=OqlY)wpN*A+Z zL4)v-j)_~!%6D!!=;~Ac%FgTF-tWJ+y`OtMbosvj_f{>+pUM(?x#t(NU}3K8y{(Fhqs{%)&c! z3tV(2Z;89an!Ky?{;hvZjBUyNOMV}Vx%73LeF~RE+iK$*$FeQh8CV$3F($nH+$zd_ zeBneBt$M9 zmvw8Xzr5eZ@Nad_|3-$?CI7qTnX0SU&i(ACd?4fH{rul7Oi#}1PSSfHSsZlf-ktJ2 zs((+uoWHGBhVj$$FwfUj*Uos{3O#gg`;z#6l_~oYeyg*bn15U7lD+oJ&LF7^VRQZ! z3tj%d>TNPdfZH$q*OA8hneLvx8J_j}d^i4a0nI4$oUV4ocj~o{ZI`~-&k6X|_x3!{ z;qN?r{(lpieKBm>Khe&Y_4mIm2kZA-QN8C%+mB;U~~S$Z|s~(`ezlw{z~j>tslOw(H2Qw=%!# zPyAh*xLbAYrJMV$6Z|gKdCqrr*?dDh`$zqOH>?}}PF(U@_?)bi=V>){_5Yt=-t)a| zz%-@j?Yh^yA{qNTof#a!@PVC!>y?s~$2k~~q3t{7HQgP)TUPnZ>UfdC9E_Adt{l2w XE%ralcMpmK0OY102?9kWD1`}+CwaNT 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 literal 0 HcmV?d00001 diff --git a/icons/layout/default/browse.png b/icons/layout/default/browse.png new file mode 100644 index 0000000000000000000000000000000000000000..c063ca09de3e77e8a605ab39bef9b9c21c5bacda GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt&q zurz(=c_77D666=m;PC858ivL>4nJa0`PlBg3pY5H=O z_B)KS0!qA}lg;YFU978nDC;#AQ<(bjL&g1Z*p|Q5W=z-pm6rLz^{?Ox({Zts_ XZ!gY%>+x_hP(6dEtDnm{r-UW|pPn$+ literal 0 HcmV?d00001 diff --git a/icons/layout/default/browsew.png b/icons/layout/default/browsew.png new file mode 100644 index 0000000000000000000000000000000000000000..9b0b2b3141a857c618202685f759ee37925e4dd1 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt)< z|NmclbN*eBbV-n3FoVOh8)+a;lDE4HLkFv@2av;A;1OBOz`!jG!i)^F=12eq*-Jcq zUD@w2%J6B5nRIWs3=~rFba4#PIG_B3pOt4u4?B;;hla-50;30dM^bpA%=tr)KlW2$ YkiWe+`>n^r$w2iCp00i_>zopr0ADUNL;wH) literal 0 HcmV?d00001 diff --git a/icons/layout/default/cascade.png b/icons/layout/default/cascade.png new file mode 100644 index 0000000000000000000000000000000000000000..292a057f017e2f26c7f1b99bdf57bb193d75158c GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt&q zurz(=c_77D666=m;PC858ivL>4nJa0`PlBg3pY5H=O z_B)KS0;Xo}(^MjXLjImEjv*T7lYj8D^33RA=Seu=7tdyY;T8K0$r=aIf@A;L=JXt& z(Nn)evNpxof$#9a1dW7*gkuL+uxlMUn2?u{@Zj)4hE+e?=Q@7&I5^jX;l}YzZ#%xR RwE&G~@O1TaS?83{1OWU|M#KOB literal 0 HcmV?d00001 diff --git a/icons/layout/default/cascadebrowse.png b/icons/layout/default/cascadebrowse.png new file mode 100644 index 0000000000000000000000000000000000000000..2f12ada6300e54c16b5b2337824c7651c5909f29 GIT binary patch literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt&q zurz(=c_77D666=m;PC858ivL>4nJa0`PlBg3pY5H=O z_B)KS0+tH$-|w*ig#tZY978nDC;#AQ<(bjL&cnmg!!B{7-HQ3e^m+>khtL`Ww*UNd zcL;o<%ysnGr~VFR;mOE+W47iR0`gG?(p*bmDA31(fMLUkdA!1EW(5-n7^ QfQB=8y85}Sb4q9e0OJlkmH+?% literal 0 HcmV?d00001 diff --git a/icons/layout/default/cascadebrowsew.png b/icons/layout/default/cascadebrowsew.png new file mode 100644 index 0000000000000000000000000000000000000000..c46b48be2b4132ca68f77250765f4dc7bc6bb4be GIT binary patch literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt)< z|NmclbN*eBbV-n3FoVOh8)+a;lDE4HLkFv@2av;A;1OBOz`!jG!i)^F=12eq*-Jcq zUD@w2$_iMrD1WiK3KRi(g;OXk;vd$@?2>?IfKnnl> literal 0 HcmV?d00001 diff --git a/icons/layout/default/cascadew.png b/icons/layout/default/cascadew.png new file mode 100644 index 0000000000000000000000000000000000000000..da64bd6ceb1e6c8ed74213d2ee38d33129591cf3 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt)< z|NmclbN*eBbV-n3FoVOh8)+a;lDE4HLkFv@2av;A;1OBOz`!jG!i)^F=12eq*-Jcq zUD@w2$_ki?D_lxH0u=K1ba4#PIG_B3pOt4u4?9o70l#=Q`wOqwZ%EcSh!!0C&o-y$ z_>7+V9g?*v#twXk4<=|NBqSU=xPo2l(7}YfgoFo&4>GL!**@3tv&X@?9t<~*Z+hGD SjjaV}G=rzBpUXO@geCxv&PvPx literal 0 HcmV?d00001 diff --git a/icons/layout/default/centerwork.png b/icons/layout/default/centerwork.png new file mode 100644 index 0000000000000000000000000000000000000000..826b331b48679d671048f232a9c2c254ba5e7af4 GIT binary patch literal 258 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPa8#@oTPIBk>g+QTxPZ!6Kid%1Q7;+sj;9$KFQS@K? z_TDK@UK*nJ?;EMSaGu_yc*&~J@_Bdl&&6`nUfb{Tcc^aIS!w%d@vh?QRnd$=QFfzC-3Gj=N=B$=}aeY5X*3;F`Wt~$( F698vdNn8K` literal 0 HcmV?d00001 diff --git a/icons/layout/default/centerworkw.png b/icons/layout/default/centerworkw.png new file mode 100644 index 0000000000000000000000000000000000000000..fcfa7e317d0c3a093c18568bf16418fc9010260c GIT binary patch literal 277 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPa8#@mVYhKk)kdcc#T^vIyZoR!}$kkxL!+IfX&;O~f zqgtHSgiYMD-_qrga-@%@(#qi9?bo8XMXyG!zozrMp)>B+EZyHMOW1EHCkx50FFw2K z%on3o8<~K{VFHh-591%M=a(xNetVxQqERnj)+{V_S-m!@jRF%}28J29*~C-V}>VGHmHaRt&q zurz(=c_77D666=m;PC858ivL>4nJa0`PlBg3pY5H=O z_B)KS0xB$bW`vyt3blK>IEHAPUwUaHFS8;K>xKSx1t&Soxn{>o^ae^i^x_hE{wGzb zmBV${jw(_4TIpBK`5^^Q>|A8|*SZ9}ZHZ`5+_vE625}W7#)%dUy)PUTZhhULXwuK| zyl1VR;#0Ln)8;qS9B>lfu--3&Z_h>czQ!rC;epnI)-%o-ZNC0nrgi>hu78nFe|f~M X@LS8-mC1Vu=p+VDS3j3^P6@jRF%}28J29*~C-V}>VGHmHaRt)< z|NmclbN*eBbV-n3FoVOh8)+a;lDE4HLkFv@2av;A;1OBOz`!jG!i)^F=12eq*-Jcq zUD@w2%J6Bb{E2xO3>0ejba4#PIKTALMqXw`9@Y!}>k3YCm~+jJmFNwWc<99?^88P# zQY(k+t{qjP^0m^hn)5>np4hp_@~?FXc-s=uptxA$Qs5#&yzG1yz2H&2G?0t<>WWxik1+8bCGunLpw@mB&%Uu5=pZ@ZQ YTj95svn!ML5YR~sp00i_>zopr055%EXaE2J literal 0 HcmV?d00001 diff --git a/icons/layout/default/termfair.png b/icons/layout/default/termfair.png new file mode 100644 index 0000000000000000000000000000000000000000..06226c1683ac0a42a762f2b280df9bf500cac969 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt&q zurz(=c_77D666=m;PC858ivL>4nJa0`PlBg3pY5H=O z_B)KS0*X3QqPWU{LaLrFjv*T7lYj8D^33RA=c(awIAHfeqUFvXhGi87Ms1587w(p1 ZIC*~q>w_b_TY(xFJYD@<);T3K0RX%`F@OL7 literal 0 HcmV?d00001 diff --git a/icons/layout/default/termfairw.png b/icons/layout/default/termfairw.png new file mode 100644 index 0000000000000000000000000000000000000000..0a8b5763125fd7391a1f555d2b9d7b59c59bd724 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt)< z|NmclbN*eBbV-n3FoVOh8)+a;lDE4HLkFv@2av;A;1OBOz`!jG!i)^F=12eq*-Jcq zUD@w2$_gm*Ia+y70t%^mx;TbtoKOD2&&o5Shn=T}$Kin83yGFHe;Afk7#OuJdR(|$ alHuh24Xh82@NNZaVDNPHb6Mw<&;$T)jx?_T literal 0 HcmV?d00001 diff --git a/icons/layout/zenburn/browse.png b/icons/layout/zenburn/browse.png new file mode 100644 index 0000000000000000000000000000000000000000..f0bd177143266961916a20d295faeccc73c58ba0 GIT binary patch literal 269 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPgg4PHABl-j7F`rvZg}JzX3_DsH{K zxskU)LBJuQL70(Y)*K0-AbW|YuPgg)78yZao?r7mcL9Y~d%8G=RNQ)d zeIqZEArEVSd=g{X2ac61^A*b$x0xwdv`aTeKX}n(q4|Eg-kKLLy~C7J-sz;*Muh(V zQ&gW8t)!&4*&JvLDlmv&w^%&v>vWKF84j!oPe{1ue)vq;b!1h?{<5z6WtH*#?dh7! tU~!Arq7pNXUo_ZkYl^H6!ghG_{w8DQe!d+hy-ZagAx~F7mvv4FO#o0nR|xQL70(Y)*K0-AbW|YuPgg)P8m))^}89hia?=7o-U3d6}R5r z+{oLYAix@6(07P~??gk-0liz2Nwuv{?!C|9*mvhUm$#tj++B8OEZ^D3ZQ8n8ulx<; z^S$XZH`Reg-~zf!2++1 m)d%MPWAnwW1R~>6^@{D4qCjzzV;#`Z3=E#GelF{r5}E+bvOHS= literal 0 HcmV?d00001 diff --git a/icons/layout/zenburn/gimp.png b/icons/layout/zenburn/gimp.png new file mode 100644 index 0000000000000000000000000000000000000000..ded8e62a73f952493e2df9e0d5ac2f7606bcb101 GIT binary patch literal 3424 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 literal 0 HcmV?d00001 diff --git a/icons/layout/zenburn/termfair.png b/icons/layout/zenburn/termfair.png new file mode 100644 index 0000000000000000000000000000000000000000..b7d5880c64fb32af4906b58bae4a347e8f8db4f5 GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPgg4P6-|>dAIUKKoN$8o-U3d6}R5r z+{oK(AmVz_y=#N3R{wzpo)a7)ITKBmY`t{M!{h&*zGo+`m;x;(dYOOa|GjVSf4*(o zeD2<}dNg6J?&}k0>)r?cz##tJ$0(e&LiMLgWjL!v4HHBZg;cq_;^Fnj_OqX} lK9{L#eXoxqiONw}=@MTkCz`vrwL%Ugvd$@?2>`wVQ}6%) literal 0 HcmV?d00001 diff --git a/icons/mail.png b/icons/mail.png new file mode 100644 index 0000000000000000000000000000000000000000..60ba6e03c83096ece4c7b3e819fbf465a57c33db GIT binary patch literal 634 zcmV-=0)_pFP)!1A1KpjVT02waR7`@oYE0(=2nKc;~afuVKL0ail@gISmBxIO#2q53F6m7`dDF;Rp*ya4}MWke=f zuW~_2-y;%@Q3SFI`|SB%zq+&sRbElm4_B*vj?AbEU(1Ico^0`nZn`Wf(i8t0mEJd4Nj{FKM?PI)*vkFy!S0S(8o U)3CzePyhe`07*qoM6N<$g2BTP;Q#;t literal 0 HcmV?d00001 diff --git a/icons/no_net.png b/icons/no_net.png new file mode 100755 index 0000000000000000000000000000000000000000..1a3e8a8ab82472adbce12200207d3af55956e9c7 GIT binary patch literal 1697 zcmV;S244AzP)I6pyXtIei2`XwJ#s?$ zoT7gy!6?RnO3*2ZQRk|2s3`IfH$emh0}5jZ0pkPu+UEM$?LGd{O(%5S9QbJIN$x-W zo!j2?`Tfp0-{0?+5QnBQr)q9DfjP1R5hSxYNJKt4-h%g3R!wk^7`v}uM^yzgC&wKC zcDaoJFyzExist9E7BfO2Mc`t!?)12L0d!jeKmtGlz{PF<>o&;DaF3f*3RUH(j(R;? z4(x7@I{Psk%$yZ}Lg=^EYfS!C&$SK2H+|Fl6n6lEZ`WN303vVbOfX0MT{0R1>fx5n zaV>?-&09Z-Dr)j=i5idqkN}X_4)@@K@;lXo-@WKt`J6}V3MgXuuu66Nj^wlbycM${($gk&eRE)2*RI{WL{@g8 z=f=6`51?aN&A@$^KXIXhU!b=Bu#SkBgF(qXW89u#>)?cqTJ2t241&`lVhaVD?eG!X^*aaD|uKWe}e%Y7Fn`0013t;g0A5d$D1 z0tbV7-(yd@(i-bh+7{l|$)}x~$jHcTyXNYW;O4D+31ARWIA-FYqv25dl4@J%XluFe zl~)ae0^qN!w~*23k;Yhuu*+?Ts($QfpW_ADmWB}(4z;n%vd1^~*ZBOuj%rX&J zRmnSRuG7+bFolS|^v=Hdir{D4nu);SsYWk%;y|6_u&!*%giuTC&x0?5L`ZL}*8p_% zHSV+)^?uetTSv``Vg7Zs8_o{?FAxHOBv(OUTl>-nuM50Wzdh_r6!FQ3SZ&_5Z^*Gj zA|{GpO3kCElo{n$a5#95%$vZ0pyAKp`y|g$6jgui^sJcb0;ctAcPi7Tl`?Zw2tDZ@ zCHPR%!n?D&cJGY z15#_(?a)t~TE@)81BbxS>sh(&mK@{5)voX-3}{R-DTGqrSiem_rL=s&6;{!ADRZiF zQyzchOhhT{%(o4QWPj)L|Adht*?X?Ss{&}d^k-~FdDxS|T8VC3+iqv0qtjR&#{*ykVO zv=;qjTDv;8ZQ&B6u6e%K3Sa<=9_G(CujuEXq6X*l24axLoxZf*GcOg4x+LIuzXh5m z4>Sdc2<-FcI7g5BF?G%Jd4CRoMR$q#-l5C?NVoi=6Bcm$mq`etH?lh7^9P<_u+Ktn3b~kKkp}O)a&V zw|u-(Dze`lMJzD@NY+t{V@e8JzHVA3a&w>NbK4$62+~cyyg2o>SB`ipXBQfmE`Cin zvE=p$5SRgyiwi4BN&4JZyTKGQ0J^?C1k0YLheb}#s$LKnvP_cQc3JA1wFd!!&$!I( zixvmd8tXU6CFAG!K;Z7+CA)1_`lb&W)$hMQmUPEF5(w{{dMb#BboI)hvsV(BS&4K3 z05rZ3yWw!ZF1E|eEL-+ASBvbd7g*B(Nh00k%S+hf_5QZ<*{tvxmjGnx2mqvi=%|%T z#@)r5MqnnXaO@oOryCmp0HKf$ng$s{bV3L?3yRofEsm@K3W@+#1!ZNr0YHqkIk9(t zdcXGw0eSrRP5_`3qZ2wA&VnM2cE$in{4p-s?Jl)xC!F~I^?#}X*rN}9(mNrFPue}cEBGnLI^;J rP8|P-m+muzxW_ed^1qT+M*#c|BkP&jBU;IV00000NkvXXu0mjfn#wI2 literal 0 HcmV?d00001 diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..3abf9f6 --- /dev/null +++ b/init.lua @@ -0,0 +1,20 @@ + +--[[ + + Lain + Layouts, widgets and utilities for Awesome WM + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local lain = +{ + layout = require("lain.layout"), + util = require("lain.util"), + widgets = require("lain.widgets") +} + +return lain diff --git a/layout/cascade.lua b/layout/cascade.lua new file mode 100644 index 0000000..cabacef --- /dev/null +++ b/layout/cascade.lua @@ -0,0 +1,65 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local tag = require("awful.tag") + +local cascade = +{ + name = "cascade", + nmaster = 0, + offset_x = 32, + offset_y = 8 +} + +function cascade.arrange(p) + + -- Cascade windows. + + -- Screen. + local wa = p.workarea + local cls = p.clients + + -- Opening a new window will usually force all existing windows to + -- get resized. This wastes a lot of CPU time. So let's set a lower + -- bound to "how_many": This wastes a little screen space but you'll + -- get a much better user experience. + local t = tag.selected(p.screen) + local num_c + if cascade.nmaster > 0 + then + num_c = cascade.nmaster + else + num_c = tag.getnmaster(t) + end + + local how_many = #cls + if how_many < num_c + then + how_many = num_c + end + + local current_offset_x = cascade.offset_x * (how_many - 1) + local current_offset_y = cascade.offset_y * (how_many - 1) + + -- Iterate. + for i = 1,#cls,1 + do + local c = cls[i] + local g = {} + + g.x = wa.x + (how_many - i) * cascade.offset_x + g.y = wa.y + (i - 1) * cascade.offset_y + g.width = wa.width - current_offset_x + g.height = wa.height - current_offset_y + + c:geometry(g) + end +end + +return cascade diff --git a/layout/cascadetile.lua b/layout/cascadetile.lua new file mode 100644 index 0000000..a94bbed --- /dev/null +++ b/layout/cascadetile.lua @@ -0,0 +1,159 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local tag = require("awful.tag") +local beautiful = require("beautiful") +local tonumber = tonumber + +local cascadetile = +{ + name = "cascadetile", + nmaster = 0, + ncol = 0, + mwfact = 0, + offset_x = 5, + offset_y = 32, + extra_padding = 0 +} + +function cascadetile.arrange(p) + + -- Layout with one fixed column meant for a master window. Its + -- width is calculated according to mwfact. Other clients are + -- cascaded or "tabbed" in a slave column on the right. + + -- It's a bit hard to demonstrate the behaviour with ASCII-images... + -- + -- (1) (2) (3) (4) + -- +-----+---+ +-----+---+ +-----+---+ +-----+---+ + -- | | | | | | | | | | | 4 | + -- | | | | | 2 | | | 3 | | | | + -- | 1 | | -> | 1 | | -> | 1 | | -> | 1 +---+ + -- | | | | +---+ | +---+ | | 3 | + -- | | | | | | | | 2 | | |---| + -- | | | | | | | |---| | | 2 | + -- | | | | | | | | | | |---| + -- +-----+---+ +-----+---+ +-----+---+ +-----+---+ + + -- A useless gap (like the dwm patch) can be defined with + -- beautiful.useless_gap_width. + local useless_gap = tonumber(beautiful.useless_gap_width) + if useless_gap == nil + then + useless_gap = 0 + end + + -- Screen. + local wa = p.workarea + local cls = p.clients + + -- Width of main column? + local t = tag.selected(p.screen) + local mwfact + if cascadetile.mwfact > 0 + then + mwfact = cascadetile.mwfact + else + mwfact = tag.getmwfact(t) + end + + -- Make slave windows overlap main window? Do this if ncol is 1. + local overlap_main + if cascadetile.ncol > 0 + then + overlap_main = cascadetile.ncol + else + overlap_main = tag.getncol(t) + end + + -- Minimum space for slave windows? See cascade.lua. + local num_c + if cascadetile.nmaster > 0 + then + num_c = cascadetile.nmaster + else + num_c = tag.getnmaster(t) + end + + local how_many = #cls - 1 + if how_many < num_c + then + how_many = num_c + end + local current_offset_x = cascadetile.offset_x * (how_many - 1) + local current_offset_y = cascadetile.offset_y * (how_many - 1) + + if #cls > 0 + then + -- Main column, fixed width and height. + local c = cls[#cls] + local g = {} + local mainwid = wa.width * mwfact + local slavewid = wa.width - mainwid + + if overlap_main == 1 + then + g.width = wa.width + + -- The size of the main window may be reduced a little bit. + -- This allows you to see if there are any windows below the + -- main window. + -- This only makes sense, though, if the main window is + -- overlapping everything else. + g.width = g.width - cascadetile.extra_padding + else + g.width = mainwid + end + + g.height = wa.height + g.x = wa.x + g.y = wa.y + if useless_gap > 0 + then + -- Reduce width once and move window to the right. Reduce + -- height twice, however. + g.width = g.width - useless_gap + g.height = g.height - 2 * useless_gap + g.x = g.x + useless_gap + g.y = g.y + useless_gap + + -- When there's no window to the right, add an additional + -- gap. + if overlap_main == 1 + then + g.width = g.width - useless_gap + end + end + c:geometry(g) + + -- Remaining clients stacked in slave column, new ones on top. + if #cls > 1 + then + for i = (#cls - 1),1,-1 + do + c = cls[i] + g = {} + g.width = slavewid - current_offset_x + g.height = wa.height - current_offset_y + g.x = wa.x + mainwid + (how_many - i) * cascadetile.offset_x + g.y = wa.y + (i - 1) * cascadetile.offset_y + if useless_gap > 0 + then + g.width = g.width - 2 * useless_gap + g.height = g.height - 2 * useless_gap + g.x = g.x + useless_gap + g.y = g.y + useless_gap + end + c:geometry(g) + end + end + end +end + +return cascadetile diff --git a/layout/centerwork.lua b/layout/centerwork.lua new file mode 100644 index 0000000..2035c65 --- /dev/null +++ b/layout/centerwork.lua @@ -0,0 +1,122 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local awful = require("awful") +local beautiful = require("beautiful") +local tonumber = tonumber +local math = { floor = math.floor } + +local centerwork = +{ + name = "centerwork", + top_left = 0, + top_right = 1, + bottom_left = 2, + bottom_right = 3 +} + +function centerwork.arrange(p) + -- A useless gap (like the dwm patch) can be defined with + -- beautiful.useless_gap_width . + local useless_gap = tonumber(beautiful.useless_gap_width) + if useless_gap == nil + then + useless_gap = 0 + end + + -- Screen. + local wa = p.workarea + local cls = p.clients + + -- Width of main column? + local t = awful.tag.selected(p.screen) + local mwfact = awful.tag.getmwfact(t) + + if #cls > 0 + then + -- Main column, fixed width and height. + local c = cls[#cls] + local g = {} + local mainwid = math.floor(wa.width * mwfact) + local slavewid = wa.width - mainwid + local slaveLwid = math.floor(slavewid / 2) + local slaveRwid = slavewid - slaveLwid + local slaveThei = math.floor(wa.height / 2) + local slaveBhei = wa.height - slaveThei + + g.height = wa.height - 2 * useless_gap + g.width = mainwid + g.x = wa.x + slaveLwid + g.y = wa.y + useless_gap + + c:geometry(g) + + -- Auxiliary windows. + if #cls > 1 + then + local at = 0 + for i = (#cls - 1),1,-1 + do + -- It's all fixed. If there are more than 5 clients, + -- those additional clients will float. This is + -- intentional. + if at == 4 + then + break + end + + c = cls[i] + g = {} + + if at == centerwork.top_left + then + -- top left + g.x = wa.x + useless_gap + g.y = wa.y + useless_gap + g.width = slaveLwid - 2 * useless_gap + g.height = slaveThei - useless_gap + elseif at == centerwork.top_right + then + -- top right + g.x = wa.x + slaveLwid + mainwid + useless_gap + g.y = wa.y + useless_gap + g.width = slaveRwid - 2 * useless_gap + g.height = slaveThei - useless_gap + elseif at == centerwork.bottom_left + then + -- bottom left + g.x = wa.x + useless_gap + g.y = wa.y + slaveThei + useless_gap + g.width = slaveLwid - 2 * useless_gap + g.height = slaveBhei - 2 * useless_gap + elseif at == centerwork.bottom_right + then + -- bottom right + g.x = wa.x + slaveLwid + mainwid + useless_gap + g.y = wa.y + slaveThei + useless_gap + g.width = slaveRwid - 2 * useless_gap + g.height = slaveBhei - 2 * useless_gap + end + + c:geometry(g) + + at = at + 1 + end + + -- Set remaining clients to floating. + for i = (#cls - 1 - 4),1,-1 + do + c = cls[i] + awful.client.floating.set(c, true) + end + end + end +end + +return centerwork diff --git a/layout/init.lua b/layout/init.lua new file mode 100644 index 0000000..d79679a --- /dev/null +++ b/layout/init.lua @@ -0,0 +1,20 @@ + +--[[ + + Lain + Layouts, widgets and utilities for Awesome WM + + Layouts section + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local wrequire = require("lain.helpers").wrequire +local setmetatable = setmetatable + +local layout = { _NAME = "lain.layout" } + +return setmetatable(layout, { __index = wrequire }) diff --git a/layout/termfair.lua b/layout/termfair.lua new file mode 100644 index 0000000..62eef9a --- /dev/null +++ b/layout/termfair.lua @@ -0,0 +1,160 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local tag = require("awful.tag") +local beautiful = require("beautiful") +local math = { ceil = math.ceil, + floor = math.floor, + max = math.max } +local tonumber = tonumber + +local termfair = +{ + name = "termfair", + + -- You can set the number of columns and rows, + -- -- otherwise they are read from awful.tag + nmaster = 0, -- columns + ncol = 0 -- rows +} + +function termfair.arrange(p) + -- Layout with fixed number of vertical columns (read from nmaster). + -- New windows align from left to right. When a row is full, a now + -- one above it is created. Like this: + + -- (1) (2) (3) + -- +---+---+---+ +---+---+---+ +---+---+---+ + -- | | | | | | | | | | | | + -- | 1 | | | -> | 2 | 1 | | -> | 3 | 2 | 1 | -> + -- | | | | | | | | | | | | + -- +---+---+---+ +---+---+---+ +---+---+---+ + + -- (4) (5) (6) + -- +---+---+---+ +---+---+---+ +---+---+---+ + -- | 4 | | | | 5 | 4 | | | 6 | 5 | 4 | + -- +---+---+---+ -> +---+---+---+ -> +---+---+---+ + -- | 3 | 2 | 1 | | 3 | 2 | 1 | | 3 | 2 | 1 | + -- +---+---+---+ +---+---+---+ +---+---+---+ + + -- A useless gap (like the dwm patch) can be defined with + -- beautiful.useless_gap_width. + local useless_gap = tonumber(beautiful.useless_gap_width) + if useless_gap == nil + then + useless_gap = 0 + end + + -- Screen. + local wa = p.workarea + local cls = p.clients + + -- How many vertical columns? + local t = tag.selected(p.screen) + local num_x + if termfair.nmaster ~= 0 + then + num_x = termfair.nmaster + else + num_x = tag.getnmaster(t) + end + + -- Do at least "desired_y" rows. + local desired_y + if termfair.ncol ~= 0 + then + desired_y = termfair.ncol + else + desired_y = tag.getncol(t) + end + + if #cls > 0 + then + local num_y = math.max(math.ceil(#cls / num_x), desired_y) + local cur_num_x = num_x + local at_x = 0 + local at_y = 0 + local remaining_clients = #cls + local width = math.floor(wa.width / num_x) + local height = math.floor(wa.height / num_y) + + -- We start the first row. Left-align by limiting the number of + -- available slots. + if remaining_clients < num_x + then + cur_num_x = remaining_clients + end + + -- Iterate in reversed order. + for i = #cls,1,-1 + do + -- Get x and y position. + local c = cls[i] + local this_x = cur_num_x - at_x - 1 + local this_y = num_y - at_y - 1 + + -- Calc geometry. + local g = {} + if this_x == (num_x - 1) + then + g.width = wa.width - (num_x - 1) * width + else + g.width = width + end + if this_y == (num_y - 1) + then + g.height = wa.height - (num_y - 1) * height + else + g.height = height + end + g.x = wa.x + this_x * width + g.y = wa.y + this_y * height + if useless_gap > 0 + then + -- Top and left clients are shrinked by two steps and + -- get moved away from the border. Other clients just + -- get shrinked in one direction. + if this_x == 0 + then + g.width = g.width - 2 * useless_gap + g.x = g.x + useless_gap + else + g.width = g.width - useless_gap + end + + if this_y == 0 + then + g.height = g.height - 2 * useless_gap + g.y = g.y + useless_gap + else + g.height = g.height - useless_gap + end + end + c:geometry(g) + remaining_clients = remaining_clients - 1 + + -- Next grid position. + at_x = at_x + 1 + if at_x == num_x + then + -- Row full, create a new one above it. + at_x = 0 + at_y = at_y + 1 + + -- We start a new row. Left-align. + if remaining_clients < num_x + then + cur_num_x = remaining_clients + end + end + end + end +end + +return termfair diff --git a/layout/uselessfair.lua b/layout/uselessfair.lua new file mode 100644 index 0000000..92e8d45 --- /dev/null +++ b/layout/uselessfair.lua @@ -0,0 +1,122 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2012, Josh Komoroske + * (c) 2010-2012, Peter Hofmann + +--]] + +local beautiful = require("beautiful") +local ipairs = ipairs +local math = { ceil = math.ceil, sqrt = math.sqrt } +local tonumber = tonumber + +local uselessfair = {} + +local function fair(p, orientation) + -- A useless gap (like the dwm patch) can be defined with + -- beautiful.useless_gap_width. + local useless_gap = tonumber(beautiful.useless_gap_width) + if useless_gap == nil + then + useless_gap = 0 + end + + local wa = p.workarea + local cls = p.clients + + if #cls > 0 then + local cells = math.ceil(math.sqrt(#cls)) + local strips = math.ceil(#cls / cells) + + local cell = 0 + local strip = 0 + for k, c in ipairs(cls) do + local g = {} + -- Save actual grid index for use in the useless_gap + -- routine. + local this_x = 0 + local this_y = 0 + if ( orientation == "east" and #cls > 2 ) + or ( orientation == "south" and #cls <= 2 ) then + if #cls < (strips * cells) and strip == strips - 1 then + g.width = wa.width / (cells - ((strips * cells) - #cls)) + else + g.width = wa.width / cells + end + g.height = wa.height / strips + + this_x = cell + this_y = strip + + g.x = wa.x + cell * g.width + g.y = wa.y + strip * g.height + + else + if #cls < (strips * cells) and strip == strips - 1 then + g.height = wa.height / (cells - ((strips * cells) - #cls)) + else + g.height = wa.height / cells + end + g.width = wa.width / strips + + this_x = strip + this_y = cell + + g.x = wa.x + strip * g.width + g.y = wa.y + cell * g.height + end + + -- Useless gap. + if useless_gap > 0 + then + -- Top and left clients are shrinked by two steps and + -- get moved away from the border. Other clients just + -- get shrinked in one direction. + if this_x == 0 + then + g.width = g.width - 2 * useless_gap + g.x = g.x + useless_gap + else + g.width = g.width - useless_gap + end + + if this_y == 0 + then + g.height = g.height - 2 * useless_gap + g.y = g.y + useless_gap + else + g.height = g.height - useless_gap + end + end + -- End of useless gap. + + c:geometry(g) + + cell = cell + 1 + if cell == cells then + cell = 0 + strip = strip + 1 + end + end + end +end + +--- Horizontal fair layout. +-- @param screen The screen to arrange. +uselessfair.horizontal = {} +uselessfair.horizontal.name = "uselessfairh" +function uselessfair.horizontal.arrange(p) + return fair(p, "east") +end + +-- Vertical fair layout. +-- @param screen The screen to arrange. +uselessfair.name = "uselessfair" +function uselessfair.arrange(p) + return fair(p, "south") +end + +return uselessfair diff --git a/layout/uselesspiral.lua b/layout/uselesspiral.lua new file mode 100644 index 0000000..695728c --- /dev/null +++ b/layout/uselesspiral.lua @@ -0,0 +1,112 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2009 Uli Schlachter + * (c) 2008 Julien Danjolu + +--]] + +local beautiful = require("beautiful") +local ipairs = ipairs +local tonumber = tonumber + +local uselesspiral = {} + +local function spiral(p, spiral) + -- A useless gap (like the dwm patch) can be defined with + -- beautiful.useless_gap_width. + local useless_gap = tonumber(beautiful.useless_gap_width) + if useless_gap == nil + then + useless_gap = 0 + end + + local wa = p.workarea + local cls = p.clients + local n = #cls + + local static_wa = wa + + for k, c in ipairs(cls) do + if k < n then + if k % 2 == 0 then + wa.height = wa.height / 2 + else + wa.width = wa.width / 2 + end + end + + if k % 4 == 0 and spiral then + wa.x = wa.x - wa.width + elseif k % 2 == 0 or + (k % 4 == 3 and k < n and spiral) then + wa.x = wa.x + wa.width + end + + if k % 4 == 1 and k ~= 1 and spiral then + wa.y = wa.y - wa.height + elseif k % 2 == 1 and k ~= 1 or + (k % 4 == 0 and k < n and spiral) then + wa.y = wa.y + wa.height + end + + local wa2 = {} + wa2.x = wa.x + wa2.y = wa.y + wa2.height = wa.height + wa2.width = wa.width + + -- Useless gap. + if useless_gap > 0 + then + -- Top and left clients are shrinked by two steps and + -- get moved away from the border. Other clients just + -- get shrinked in one direction. + + top = false + left = false + + if wa2.y == static_wa.y then + top = true + end + + if wa2.x == static_wa.x then + left = true + end + + if top then + wa2.height = wa2.height - 2 * useless_gap + wa2.y = wa2.y + useless_gap + else + wa2.height = wa2.height - useless_gap + end + + if left then + wa2.width = wa2.width - 2 * useless_gap + wa2.x = wa2.x + useless_gap + else + wa2.width = wa2.width - useless_gap + end + end + -- End of useless gap. + + c:geometry(wa2) + end +end + +--- Dwindle layout +uselesspiral.dwindle = {} +uselesspiral.dwindle.name = "uselessdwindle" +function uselesspiral.dwindle.arrange(p) + return spiral(p, false) +end + +--- Spiral layout +uselesspiral.name = "uselesspiral" +function uselesspiral.arrange(p) + return spiral(p, true) +end + +return uselesspiral diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua new file mode 100644 index 0000000..b82c97e --- /dev/null +++ b/layout/uselesstile.lua @@ -0,0 +1,232 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2009 Donald Ephraim Curtis + * (c) 2008 Julien Danjolu + +--]] + +local tag = require("awful.tag") +local beautiful = require("beautiful") +local ipairs = ipairs +local math = { floor = math.floor, + max = math.max, + min = math.min } +local tonumber = tonumber + +local uselesstile = {} + +local function tile_group(cls, wa, orientation, fact, group) + -- A useless gap (like the dwm patch) can be defined with + -- beautiful.useless_gap_width . + local useless_gap = tonumber(beautiful.useless_gap_width) + if useless_gap == nil + then + useless_gap = 0 + end + + -- get our orientation right + local height = "height" + local width = "width" + local x = "x" + local y = "y" + if orientation == "top" or orientation == "bottom" then + height = "width" + width = "height" + x = "y" + y = "x" + end + + -- make this more generic (not just width) + available = wa[width] - (group.coord - wa[x]) + + -- find our total values + local total_fact = 0 + local min_fact = 1 + local size = group.size + for c = group.first,group.last do + -- determine the width/height based on the size_hint + local i = c - group.first +1 + local size_hints = cls[c].size_hints + local size_hint = size_hints["min_"..width] or size_hints["base_"..width] or 0 + size_hint = size_hint + cls[c].border_width*2 + size = math.max(size_hint, size) + + -- calculate the height + if not fact[i] then + fact[i] = min_fact + else + min_fact = math.min(fact[i],min_fact) + end + total_fact = total_fact + fact[i] + end + size = math.min(size, available) + + local coord = wa[y] + local geom = {} + local used_size = 0 + local unused = wa[height] + local stat_coord = wa[x] + --stat_coord = size + for c = group.first,group.last do + local i = c - group.first +1 + geom[width] = size + geom[height] = math.floor(unused * fact[i] / total_fact) + geom[x] = group.coord + geom[y] = coord + + coord = coord + geom[height] + unused = unused - geom[height] + total_fact = total_fact - fact[i] + used_size = math.max(used_size, geom[width]) + + -- Useless gap + if useless_gap > 0 + then + -- Top and left clients are shrinked by two steps and + -- get moved away from the border. Other clients just + -- get shrinked in one direction. + + top = false + left = false + + if geom[y] == wa[y] then + top = true + end + + if geom[x] == 0 or geom[x] == wa[x] then + left = true + end + + if top then + geom[height] = geom[height] - 2 * useless_gap + geom[y] = geom[y] + useless_gap + else + geom[height] = geom[height] - useless_gap + end + + if left then + geom[width] = geom[width] - 2 * useless_gap + geom[x] = geom[x] + useless_gap + else + geom[width] = geom[width] - useless_gap + end + end + -- End of useless gap. + + geom = cls[c]:geometry(geom) + end + + return used_size +end + +local function tile(param, orientation) + local t = tag.selected(param.screen) + orientation = orientation or "right" + + -- this handles are different orientations + local height = "height" + local width = "width" + local x = "x" + local y = "y" + if orientation == "top" or orientation == "bottom" then + height = "width" + width = "height" + x = "y" + y = "x" + end + + local cls = param.clients + local nmaster = math.min(tag.getnmaster(t), #cls) + local nother = math.max(#cls - nmaster,0) + + local mwfact = tag.getmwfact(t) + local wa = param.workarea + local ncol = tag.getncol(t) + + local data = tag.getdata(t).windowfact + + if not data then + data = {} + tag.getdata(t).windowfact = data + end + + local coord = wa[x] + local place_master = true + if orientation == "left" or orientation == "top" then + -- if we are on the left or top we need to render the other windows first + place_master = false + end + + -- this was easier than writing functions because there is a lot of data we need + for d = 1,2 do + if place_master and nmaster > 0 then + local size = wa[width] + if nother > 0 then + size = math.min(wa[width] * mwfact, wa[width] - (coord - wa[x])) + end + if not data[0] then + data[0] = {} + end + coord = coord + tile_group(cls, wa, orientation, data[0], {first=1, last=nmaster, coord = coord, size = size}) + end + + if not place_master and nother > 0 then + local last = nmaster + + -- we have to modify the work area size to consider left and top views + local wasize = wa[width] + if nmaster > 0 and (orientation == "left" or orientation == "top") then + wasize = wa[width] - wa[width]*mwfact + end + for i = 1,ncol do + -- Try to get equal width among remaining columns + local size = math.min( (wasize - (coord - wa[x])) / (ncol - i + 1) ) + local first = last + 1 + last = last + math.floor((#cls - last)/(ncol - i + 1)) + -- tile the column and update our current x coordinate + if not data[i] then + data[i] = {} + end + coord = coord + tile_group(cls, wa, orientation, data[i], { first = first, last = last, coord = coord, size = size }) + end + end + place_master = not place_master + end + +end + +uselesstile.right = {} +uselesstile.right.name = "uselesstile" +uselesstile.right.arrange = tile + +--- The main tile algo, on left. +-- @param screen The screen number to tile. +uselesstile.left = {} +uselesstile.left.name = "uselesstileleft" +function uselesstile.left.arrange(p) + return tile(p, "left") +end + +--- The main tile algo, on bottom. +-- @param screen The screen number to tile. +uselesstile.bottom = {} +uselesstile.bottom.name = "uselesstilebottom" +function uselesstile.bottom.arrange(p) + return tile(p, "bottom") +end + +--- The main tile algo, on top. +-- @param screen The screen number to tile. +uselesstile.top = {} +uselesstile.top.name = "uselesstiletop" +function uselesstile.top.arrange(p) + return tile(p, "top") +end + +uselesstile.arrange = uselesstile.right.arrange +uselesstile.name = uselesstile.right.name + +return uselesstile diff --git a/scripts/checkmail b/scripts/checkmail new file mode 100755 index 0000000..67c5206 --- /dev/null +++ b/scripts/checkmail @@ -0,0 +1,104 @@ +#!/usr/bin/python + +# Simple email checker +# +# Wrote by copycat-killer on a rainy day of august 2013 +# to be used in Lain. +# +# https://github.com/copycat-killer/lain + +import sys, getopt, locale, imaplib + +def main(argv): + usage = "usage: checkmail -s -u -p [--port ] [--encoding ] [--cut]" + server = "" + user = "" + password = "" + port = 993 + cut = False + encoding = locale.getdefaultlocale()[1] + output = "" + + try: + opts, args = getopt.getopt(argv, "hs:u:p:", ["port=", "encoding=", "cut"]) + except getopt.GetoptError: + print(usage) + sys.exit(2) + + if len(argv) == 0: + print(usage) + sys.exit() + + for opt, arg in opts: + if opt == "-h": + print(usage) + sys.exit() + elif opt == "-s": + server = arg + elif opt == "-u": + user = arg + elif opt == "-p": + password = arg + elif opt == "--port": + port = int(arg) + elif opt == "--cut": + cut = True + elif opt == "--encoding": + encoding = arg + + try: + mail = imaplib.IMAP4_SSL(server, port) + mail.login(user, password) + except imaplib.IMAP4.error: + print("CheckMailError: invalid credentials") + sys.exit(2) + + status, counts = mail.status("Inbox","(MESSAGES UNSEEN)") + + unread = int(counts[0].split()[4][:-1]) + + if status == "OK" and unread: + mail.select("Inbox", readonly = 1) + ret, messages = mail.uid("search", None, "(UNSEEN)") + + if ret == "OK": + latest_email_uid = messages[0].split()[-1] + + ret_header, new_mail_header = mail.uid("fetch", latest_email_uid, + "(BODY.PEEK[HEADER.FIELDS (SUBJECT FROM)])") + ret_text, new_mail_text = mail.uid("fetch", latest_email_uid, "(BODY[TEXT])") + + if ret_header == "OK" and ret_text == "OK": + try: # not all the servers like this, that's why we try + mail.store(latest_email_uid, "-FLAGS", "\\Seen") + except imaplib.IMAP4.error: + # this simply means the server refused to + # toggle Seen flag from mail + print("[+Seen]\n") + + nm_header = new_mail_header[0][1].decode(encoding, "replace").strip() + nm_text = new_mail_text[0][1].decode(encoding, "replace").strip() + + if unread == 1: + print(user, "has 1 new message\n") + else: + print(user, "has", unread, "new messages\n") + nm_header.replace("From:", "Latest from:", 1) + + print(nm_header, "\n") + + if cut: + if len(nm_text) <= 100: + print(nm_text) + else: + print(nm_text[0:100]) + print("[...]") + else: + print(nm_text) + else: + print("No new messages") + + mail.logout() + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/scripts/dfs b/scripts/dfs new file mode 100755 index 0000000..1730b6e --- /dev/null +++ b/scripts/dfs @@ -0,0 +1,385 @@ +#!/bin/bash +# +# Adapted from Eridan's "fs" (cleanup, enhancements and switch to bash/Linux) +# JM, 10/12/2004 +# +# Integrated into Lain in september 2013 +# https://github.com/copycat-killer/lain + +# ------------------------------------------------------------------------- +# Decoding options +# ------------------------------------------------------------------------- +USAGE="Usage: $0 [-h(elp)] | [-n(arrow mode)] | [-w(eb output)]" + +NARROW_MODE=0 +WEB_OUTPUT=0 + +while [ $# -gt 0 ]; do +case "$1" in +"-h" ) +echo $USAGE +exit +;; +"-d" ) +DEBUG=1 +;; +"-n" ) +NARROW_MODE=1 +;; +"-w" ) +WEB_OUTPUT=1 +;; +* ) +echo $USAGE +exit +;; +esac +shift +done + +# ------------------------------------------------------------------------- +# Preparations +# ------------------------------------------------------------------------- +SYSTEM=`uname -s` +PATTERN="/" + +case "$SYSTEM" in +"Linux" ) +DF_COMMAND="/usr/bin/env df -k" +SORT_COMMAND="/usr/bin/env sort -k6" +AWK_COMMAND="/usr/bin/env awk" +;; +* ) +DF_COMMAND="/bin/df -k" +SORT_COMMAND="/usr/bin/sort -k6" +AWK_COMMAND="/usr/bin/env gawk" +;; +esac + +# ------------------------------------------------------------------------- +# Grabbing "df" result +# ------------------------------------------------------------------------- +DF_RESULT=`$DF_COMMAND` +if [ ! -z $DEBUG ]; then +echo "--> DF_RESULT:" +echo "$DF_RESULT" +echo "" +fi + +# ------------------------------------------------------------------------- +# Preprocessing "df" result, to join split logical lines +# ------------------------------------------------------------------------- +PREPROCESSING_RESULT=` \ + echo "$DF_RESULT" | $AWK_COMMAND -v PATTERN=$PATTERN \ + ' + NF == 1 { + printf ("%s", $0) + } + +NF == 5 { + printf ("%s\n", $0) +} + +NF > 6 { +} + +NF == 6 { + printf ("%s\n", $0) +}' +` +if [ ! -z $DEBUG ]; then +echo "--> PREPROCESSING_RESULT:" +echo "$PREPROCESSING_RESULT" +echo "" +fi + +SORTED_FILE_SYSTEMS_INFO=`echo "$PREPROCESSING_RESULT" | $SORT_COMMAND` + +if [ ! -z $DEBUG ]; then +echo "--> SORTED_FILE_SYSTEMS_INFO:" +echo "$SORTED_FILE_SYSTEMS_INFO" +echo "" +fi + +# ------------------------------------------------------------------------- +# Computing mount point max length +# ------------------------------------------------------------------------- +MOUNT_POINT_MAX_LENGTH=` \ + echo $SORTED_FILE_SYSTEMS_INFO | $AWK_COMMAND -v PATTERN=$PATTERN \ + ' + BEGIN { + mount_point_length_max = 15; + } + +END { + printf ("%d", mount_point_length_max); +} + +$0 ~ PATTERN { +# printf ("$6 = %s\n", $6); + + mount_point = $6; +# printf ("mount_point = %s\n", mount_point); + + mount_point_length = length (mount_point); +# printf ("mount_point_length = %d\n", mount_point_length); + + if (mount_point_length > mount_point_length_max) + mount_point_length_max = mount_point_length; +}' +` +if [ ! -z $DEBUG ]; then +echo "MOUNT_POINT_MAX_LENGTH: $MOUNT_POINT_MAX_LENGTH" +fi + +# ------------------------------------------------------------------------- +# Computing mount point data max size +# ------------------------------------------------------------------------- +MOUNT_POINT_MAX_SIZE=` \ + echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v PATTERN=$PATTERN \ + ' + BEGIN { + mount_point_size_max = 0; + } + +END { + printf ("%d", mount_point_size_max); +} + +$0 ~ PATTERN { +# df -k shows k_bytes! +# printf ("$2 = %s\n", $2); + + mount_point_size = $2 * 1024; +# printf ("mount_point_size = %d\n", mount_point_size); + + if (mount_point_size > mount_point_size_max) + mount_point_size_max = mount_point_size; +}' +` +if [ ! -z $DEBUG ]; then +echo "MOUNT_POINT_MAX_SIZE: $MOUNT_POINT_MAX_SIZE" +fi + +# ------------------------------------------------------------------------- +# Let's go! +# ------------------------------------------------------------------------- +echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v DEBUG=$DEBUG -v PATTERN=$PATTERN -v NARROW_MODE=$NARROW_MODE -v LEFT_COLUMN=$MOUNT_POINT_MAX_LENGTH -v MAX_SIZE=$MOUNT_POINT_MAX_SIZE -v SCALE=$SCALE -v WEB_OUTPUT=$WEB_OUTPUT \ + ' +# {printf ("$0 = %s\n", $0);} +# {printf ("$1 = %s\n", $1);} +# {printf ("PATTERN = %s\n", PATTERN);} +# {printf ("LEFT_COLUMN = %s\n", LEFT_COLUMN);} + + BEGIN { + k_bytes = 1024.0; + m_bytes = 1024.0 * k_bytes; + g_bytes = 1024.0 * m_bytes; + t_bytes = 1024.0 * g_bytes; + + if (WEB_OUTPUT) + { + all_stars = "**************************************************"; + current_date = strftime ("%d-%m-%Y @ %H:%M:%S", localtime (systime ())); + free_threshold = 10; # % + + printf ("\n"); + + printf ( \ + "\n" \ + "

%s -- STATUS OF ALCOR FILE SYSTEMS


\n", + current_date ) + + printf ("\n"); + + printf ( \ + "\n" \ + "\n" \ + "\n" \ + "\n" \ + "\n" \ + "\n" \ + "\n" ); + } + else + { + narrow_margin = " "; +# printf ("%-*s", LEFT_COLUMN + 2, "Mount point"); + if (NARROW_MODE) + printf ("\n%s", narrow_margin); + else + printf ("%-*s", LEFT_COLUMN + 2, ""); + print " Used Free Total "; + if (! NARROW_MODE) + print ""; + } + } + +END { + if (WEB_OUTPUT) + { + printf ("
Mount point%% Usato (*)" \ + " - %% Free (*)%% UsatoSpazio liberoSpazio totale
\n"); + + printf ("\n"); + } + else + { + if (NARROW_MODE) + printf ("%s", narrow_margin); + else + printf ("%-*s", LEFT_COLUMN + 2, ""); + print "|----|----|----|----|----|----|----|----|----|----|" + if (NARROW_MODE) + printf ("\n%s", narrow_margin); + else + printf ("%-*s", LEFT_COLUMN + 2, ""); + print "0 10 20 30 40 50 60 70 80 90 100"; + print ""; + } +} + +$0 ~ PATTERN { + + if (index ($0, "members") == 0 && index ($0, "Download") == 0 && index ($0, "admin") == 0) + { +# df -k shows k_bytes! + + total_size = $2 * k_bytes; + free_size = $4 * k_bytes; + percentage_occupied = substr($5, 0, 3); + mount_point = $6; + + percentage_free = int (100 - percentage_occupied); + +# reduction_factor: 2 + stars_number = int (percentage_occupied / 2); + + if (WEB_OUTPUT) + { + posGroup = index (mount_point, "scratch"); + if (posGroup == 0) + posGroup = index (mount_point, "u1"); + if (posGroup == 0) + posGroup = index (mount_point, "u2"); + if (posGroup == 0) + posGroup = index (mount_point, "u4"); + if (posGroup == 0) + posGroup = index (mount_point, "u5"); + + printf ("\n"); + + if (posGroup > 0 || percentage_free < free_threshold) + { + if (percentage_free < free_threshold) + { + class = "titlered"; + if (posGroup == 0) + posGroup = 1; # to display the whole mount_point in this color anyway + } + else if ((index (mount_point, "scratch") != 0) || (index (mount_point, "u1") != 0) || (index (mount_point, "u2") != 0)) + { + class = "titleorange"; + posGroup = 1; # to display the whole mount_point in this color + } + else if ((index (mount_point, "u4") != 0) || (index (mount_point, "u5") != 0)) + { + class = "titlebrown"; + posGroup = 1; # to display the whole mount_point in this color + } + + printf ( \ + "%s%s\n", + substr (mount_point, 1, posGroup - 1), + class, + substr (mount_point, posGroup) ); + } + else + { + printf ("%s\n", mount_point); + } + + printf ( \ + "%s%s\n", + substr (all_stars, 1, stars_number), substr (all_stars, stars_number + 1, 49) ); + + if (percentage_free < free_threshold) + { + color_beginning = ""; + color_end = "" + } + else + { + color_beginning = ""; + color_end = "" + } + + if (total_size > 1 * t_bytes) + printf ( \ + "%s%3d%%%s%5.1f Tb%5.1f Tb\n", \ + color_beginning, percentage_occupied, color_end, free_size / t_bytes, total_size / t_bytes \ + ); + else if (total_size > 1 * g_bytes) + printf ( \ + "%s%3d%%%s%5.1f Gb%5.1f Gb\n", \ + color_beginning, percentage_occupied, color_end, free_size / g_bytes, total_size / g_bytes \ + ); + else if (total_size > 1 * m_byptes) + printf ( \ + "%s%3d%%%s%5.1f Mb%5.1f Mb\n", \ + color_beginning, percentage_occupied, color_end, free_size / m_bytes, total_size / m_bytes \ + ); + else + printf ( \ + "%s%3d%%%s%5.1f Kb%5.1f Kb\n", \ + color_beginning, percentage_occupied, color_end, free_size / k_bytes, total_size / k_bytes \ + ); + + printf ("\n"); + } + + else + { +# printf ("percentage_occupied = %d\n", percentage_occupied); +# printf ("percentage_free = %d\n", percentage_free); + + printf ("%-*s", LEFT_COLUMN + 2, mount_point); + if (NARROW_MODE) + printf ("\n%s", narrow_margin); + +# printf ("stars_number = %d\n", stars_number); + + printf ("|"); + for (i = 1; i <= stars_number; i++) + { + printf ("%s", "*"); + } + for (i = stars_number + 1; i <= 49; i++) + { + printf ("%s", "-"); + } + + + if (total_size > 1 * t_bytes) + printf ( \ + "| %3d%% %5.1f %5.1f Tb\n", \ + percentage_occupied, free_size / t_bytes, total_size / t_bytes \ + ); + else if (total_size > 1 * g_bytes) + printf ( \ + "| %3d%% %5.1f %5.1f Gb\n", \ + percentage_occupied, free_size / g_bytes, total_size / g_bytes \ + ); + else if (total_size > 1 * m_byptes) + printf ( \ + "| %3d%% %5.1f %5.1f Mb\n", \ + percentage_occupied, free_size / m_bytes, total_size / m_bytes \ + ); + else + printf ( \ + "| %3d%% %5.1f %5.1f Kb\n", \ + percentage_occupied, free_size / k_bytes, total_size / k_bytes \ + ); + } + } # if +}' diff --git a/scripts/mpdcover b/scripts/mpdcover new file mode 100755 index 0000000..38b43e9 --- /dev/null +++ b/scripts/mpdcover @@ -0,0 +1,64 @@ +#!/bin/bash +# +# A simple cover fetcher script for current playing song on mpd. +# +# Author : Wolfgang Mueller +# +# Adapted for Lain internal use. +# https://github.com/copycat-killer/lain +# +# You can use, edit and redistribute this script in any way you like. +# +# Dependencies: imagemagick. +# +# Usage: mpdcover + +# Configuration------------------------------------------------------- + +# Music directory +MUSIC_DIR=$1 + +# Song file +file=$2 + +# The default cover to use (optional) +DEFAULT_ART=$3 + +# Regex expression used for image search +IMG_REG="(front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif)$" + +# Path of temporary resized cover +TEMP_PATH="/tmp/mpdcover.png" + +# Resize cover +COVER_RESIZE="100x100" + +# Thumbnail background (transparent) +COVER_BACKGROUND="none" + +#-------------------------------------------------------------------- + +# check if anything is playing at all +[[ -z $file ]] && exit 1 + +# Art directory +art="$MUSIC_DIR/${file%/*}" + +# find every file that matches IMG_REG set the first matching file to be the +# cover. +cover="$(find "$art/" -maxdepth 1 -type f | egrep -i -m1 "$IMG_REG")" + +# when no cover is found, use DEFAULT_ART as cover +cover="${cover:=$DEFAULT_ART}" + +# check if art is available +if [[ -n $cover ]]; then + if [[ -n $COVER_RESIZE ]]; then + convert "$cover" -thumbnail $COVER_RESIZE -gravity center -background "$COVER_BACKGROUND" -extent $COVER_RESIZE "$TEMP_PATH" + cover="$TEMP_PATH" + fi +else + rm $TEMP_PATH +fi + +exit 0 diff --git a/util/init.lua b/util/init.lua new file mode 100644 index 0000000..a44d52c --- /dev/null +++ b/util/init.lua @@ -0,0 +1,174 @@ + +--[[ + + Lain + Layouts, widgets and utilities for Awesome WM + + Utilities section + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local awful = require("awful") +local beautiful = require("beautiful") +local math = { sqrt = math.sqrt } +local mouse = mouse +local pairs = pairs +local string = string +local client = client +local screen = screen +local tonumber = tonumber + +local wrequire = require("lain.helpers").wrequire +local setmetatable = setmetatable + +-- Lain utilities submodule +-- lain.util +local util = { _NAME = "lain.util" } + +-- Like awful.menu.clients, but only show clients of currently selected +-- tags. +function util.menu_clients_current_tags(menu, args) + -- List of currently selected tags. + local cls_tags = awful.tag.selectedlist(mouse.screen) + + -- Final list of menu items. + local cls_t = {} + + if cls_tags == nil + then + return nil + end + + -- For each selected tag get all clients of that tag and add them to + -- the menu. A click on a menu item will raise that client. + for i = 1,#cls_tags + do + local t = cls_tags[i] + local cls = t:clients() + + for k, c in pairs(cls) + do + cls_t[#cls_t + 1] = { awful.util.escape(c.name) or "", + function () + c.minimized = false + client.focus = c + c:raise() + end, + c.icon } + end + end + + -- No clients? Then quit. + if #cls_t <= 0 + then + return nil + end + + -- menu may contain some predefined values, otherwise start with a + -- fresh menu. + if not menu + then + menu = {} + end + + -- Set the list of items and show the menu. + menu.items = cls_t + local m = awful.menu.new(menu) + m:show(args) + return m +end + +-- Magnify a client: Set it to "float" and resize it. +function util.magnify_client(c) + awful.client.floating.set(c, true) + + local mg = screen[mouse.screen].geometry + local tag = awful.tag.selected(mouse.screen) + local mwfact = awful.tag.getmwfact(tag) + local g = {} + g.width = math.sqrt(mwfact) * mg.width + g.height = math.sqrt(mwfact) * mg.height + g.x = mg.x + (mg.width - g.width) / 2 + g.y = mg.y + (mg.height - g.height) / 2 + c:geometry(g) +end + +-- Read the nice value of pid from /proc. +local function get_nice_value(pid) + local n = first_line('/proc/' .. pid .. '/stat') + if n == nil + then + -- This should not happen. But I don't want to crash, either. + return 0 + end + + -- Remove pid and tcomm. This is necessary because tcomm may contain + -- nasty stuff such as whitespace or additional parentheses... + n = string.gsub(n, '.*%) ', '') + + -- Field number 17 now is the nice value. + fields = split(n, ' ') + return tonumber(fields[17]) +end + +-- To be used as a signal handler for "focus" +-- This requires beautiful.border_focus{,_highprio,_lowprio}. +function util.niceborder_focus(c) + local n = get_nice_value(c.pid) + if n == 0 + then + c.border_color = beautiful.border_focus + elseif n < 0 + then + c.border_color = beautiful.border_focus_highprio + else + c.border_color = beautiful.border_focus_lowprio + end +end + +-- To be used as a signal handler for "unfocus" +-- This requires beautiful.border_normal{,_highprio,_lowprio}. +function util.niceborder_unfocus(c) + local n = get_nice_value(c.pid) + if n == 0 + then + c.border_color = beautiful.border_normal + elseif n < 0 + then + c.border_color = beautiful.border_normal_highprio + else + c.border_color = beautiful.border_normal_lowprio + end +end + +-- Non-empty tag browsing +-- direction in {-1, 1} <-> {previous, next} non-empty tag +function util.tag_view_nonempty(direction, sc) + local s = sc or mouse.screen or 1 + local scr = screen[s] + + for i = 1, #tags[s] do + awful.tag.viewidx(direction,s) + if #awful.client.visible(s) > 0 then + return + end + end +end + +-- Dynamically rename the current tag you have focused. +function util.prompt_rename_tag(mypromptbox) + local tag = awful.tag.selected(mouse.screen) + awful.prompt.run({prompt="Rename tag: "}, mypromptbox[mouse.screen].widget, + function(text) + if text:len() > 0 then + tag.name = text + tag:emit_signal("property::name") + end + end) +end + +return setmetatable(util, { __index = wrequire }) diff --git a/util/markup.lua b/util/markup.lua new file mode 100644 index 0000000..e7baec0 --- /dev/null +++ b/util/markup.lua @@ -0,0 +1,102 @@ + +--[[ + + Licensed under MIT License + * (c) 2013, Luke Bonham + * (c) 2009, Uli Schlachter + * (c) 2009, Majic + +--]] + +local beautiful = require("beautiful") +local tostring = tostring +local setmetatable = setmetatable + +-- Lain markup util submodule +-- lain.util.markup +local markup = {} + +local fg = {} +local bg = {} + +--[[ clean this as soon as you document it + + +-- markup + | + |`-- bold() Set bold. + |`-- italic() Set italicized text. + |`-- strike() Set strikethrough text. + |`-- underline() Set underlined text. + |`-- monospace() Set monospaced text. + |`-- big() Set bigger text. + |`-- small() Set smaller text. + |`-- font() Set the font of the text. + | + |`--+ bg + | | + | |`-- color() Set background color. + | |`-- focus() Set focus background color. + | |`-- normal() Set normal background color. + | `-- urgent() Set urgent background color. + | + |`--+ fg + | | + | |`-- color() Set foreground color. + | |`-- focus() Set focus foreground color. + | |`-- normal() Set normal foreground color. + | `-- urgent() Set urgent foreground color. + | + |`-- focus() Set both foreground and background focus colors. + |`-- normal() Set both foreground and background normal colors. + `-- urgent() Set both foreground and background urgent colors. + +]] + +-- Convenience tags. +function markup.bold(text) return '' .. tostring(text) .. '' end +function markup.italic(text) return '' .. tostring(text) .. '' end +function markup.strike(text) return '' .. tostring(text) .. '' end +function markup.underline(text) return '' .. tostring(text) .. '' end +function markup.monospace(text) return '' .. tostring(text) .. '' end +function markup.big(text) return '' .. tostring(text) .. '' end +function markup.small(text) return '' .. tostring(text) .. '' end + +-- Set the font. +function markup.font(font, text) + return '' .. tostring(text) ..'' +end + +-- Set the foreground. +function fg.color(color, text) + return '' .. tostring(text) .. '' +end + +-- Set the background. +function bg.color(color, text) + return '' .. tostring(text) .. '' +end + +-- Context: focus +function fg.focus(text) return fg.color(beautiful.fg_focus, text) end +function bg.focus(text) return bg.color(beautiful.bg_focus, text) end +function markup.focus(text) return bg.focus(fg.focus(text)) end + +-- Context: normal +function fg.normal(text) return fg.color(beautiful.fg_normal, text) end +function bg.normal(text) return bg.color(beautiful.bg_normal, text) end +function markup.normal(text) return bg.normal(fg.normal(text)) end + +-- Context: urgent +function fg.urgent(text) return fg.color(beautiful.fg_urgent, text) end +function bg.urgent(text) return bg.color(beautiful.bg_urgent, text) end +function markup.urgent(text) return bg.urgent(fg.urgent(text)) end + +markup.fg = fg +markup.bg = bg + +-- link markup.{fg,bg}(...) calls to markup.{fg,bg}.color(...) +setmetatable(markup.fg, { __call = function(_, ...) return markup.fg.color(...) end }) +setmetatable(markup.bg, { __call = function(_, ...) return markup.bg.color(...) end }) + +-- link markup(...) calls to markup.fg.color(...) +return setmetatable(markup, { __call = function(_, ...) return markup.fg.color(...) end }) diff --git a/widgets/alsa.lua b/widgets/alsa.lua new file mode 100644 index 0000000..7c26908 --- /dev/null +++ b/widgets/alsa.lua @@ -0,0 +1,103 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + * (c) 2010, Adrian C. + +--]] + +local markup = require("lain.util.markup") +local run_in_terminal = require("lain.helpers").run_in_terminal + +local awful = require("awful") +local beautiful = require("beautiful") +local wibox = require("wibox") + +local io = io +local string = { format = string.format, + match = string.match } + +local setmetatable = setmetatable + +-- ALSA volume infos +-- nain.widgets.alsa +local alsa = { + volume = 0, + mute = false, +} + +function worker(args) + local args = args or {} + local channel = args.channel or "Master" + local step = args.step or "1%" + local header = args.header or " Vol " + local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" + local color = args.color or beautiful.fg_focus or "#FFFFFF" + + local myvolume = wibox.widget.textbox() + local myvolumeupdate = function() + local f = io.popen('amixer get ' .. channel) + local mixer = f:read("*all") + f:close() + + local volume, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") + + if volume == nil + then + alsa.volume = 0 + else + alsa.volume = volume + end + + if mute == nil or mute == 'on' + then + alsa.mute = true + mute = '' + else + alsa.mute = false + mute = 'M' + end + + local ret = markup(color, string.format("%d%s", volume, mute)) + myvolume:set_markup(markup(header_color, header) .. ret .. " ") + end + + local myvolumetimer = timer({ timeout = 5 }) + myvolumetimer:connect_signal("timeout", myvolumeupdate) + myvolumetimer:start() + myvolumetimer:emit_signal("timeout") + + myvolume:buttons(awful.util.table.join( + awful.button({}, 1, + function() + run_in_terminal('alsamixer') + end), + awful.button({}, 3, + function() + awful.util.spawn('amixer sset ' .. channel ' toggle') + end), + + awful.button({}, 4, + function() + awful.util.spawn('amixer sset ' .. channel .. ' ' .. step '+') + myvolumeupdate() + end), + + awful.button({}, 5, + function() + awful.util.spawn('amixer sset ' .. channel .. ' ' .. step '-') + myvolumeupdate() + end) + )) + + alsa.widget = myvolume + alsa.channel = channel + alsa.step = step + alsa.notify = myvolumeupdate + + return setmetatable(alsa, { __index = alsa.widget }) +end + +return setmetatable(alsa, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua new file mode 100644 index 0000000..0421f5c --- /dev/null +++ b/widgets/alsabar.lua @@ -0,0 +1,164 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2013, Rman +--]] + +local awful = require("awful") +local beautiful = require("beautiful") +local naughty = require("naughty") + +local io = io +local math = { modf = math.modf } +local string = { match = string.match, + rep = string.rep } +local tonumber = tonumber + +local setmetatable = setmetatable + +-- ALSA volume bar +-- lain.widgets.alsabar +local alsabar = +{ + channel = "Master", + step = "5%", + + colors = + { + background = beautiful.bg_normal, + mute = "#EB8F8F", + unmute = "#A4CE8A" + }, + + mixer = terminal .. " -e alsamixer", + + notifications = + { + font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), + font_size = "11", + bar_size = 18 -- Awesome default + }, + + _current_level = 0, + _muted = false +} + +function alsabar:notify() + local preset = + { + title = "", text = "", + timeout = 3, + font = alsabar.notifications.font .. " " .. alsabar.notifications.font_size, + fg = beautiful.fg_focus + } + + if alsabar._muted then + preset.title = alsabar.channel .. " - Muted" + else + preset.title = alsabar.channel .. " - " .. alsabar._current_level * 100 .. "%" + end + + local int = math.modf(alsabar._current_level * alsabar.notifications.bar_size) + preset.text = "[" .. string.rep("|", int) + .. string.rep(" ", alsabar.notifications.bar_size - int) .. "]" + + if alsabar._notify ~= nil then + alsabar._notify = naughty.notify ({ replaces_id = alsabar._notify.id, + preset = preset }) + else + alsabar._notify = naughty.notify ({ preset = preset }) + end +end + +function worker(args) + local args = args or {} + local width = args.width or 63 + local height = args.heigth or 1 + local ticks = args.ticks or true + local ticks_size = args.ticks_size or 7 + local vertical = args.vertical or false + alsabar.channel = args.channel or alsabar.channel + alsabar.step = args.step or alsabar.step + alsabar.colors = args.colors or alsabar.colors + alsabar.notifications = args.notifications or alsabar.notifications + + alsabar.bar = awful.widget.progressbar() + alsabar.bar:set_background_color(alsabar.colors.background) + alsabar.bar:set_color(alsabar.colors.unmute) + alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } }) + alsabar.bar:set_width(width) + alsabar.bar:set_height(height) + alsabar.bar:set_ticks(ticks) + alsabar.bar:set_ticks_size(ticks_size) + + if vertical then + alsabar.bar:set_vertical(true) + end + + local myvolumebarupdate = function() + -- Get mixer control contents + local f = io.popen("amixer get " .. alsabar.channel) + local mixer = f:read("*all") + f:close() + + -- Capture mixer control state: [5%] ... ... [on] + local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") + -- Handle mixers without data + if volu == nil then + volu = 0 + mute = "off" + end + + alsabar._current_level = tonumber(volu) / 100 + alsabar.bar:set_value(alsabar._current_level) + + if mute == "" and volu == "0" or mute == "off" + then + alsabar._muted = true + alsabar.tooltip:set_text (" [Muted] ") + alsabar.bar:set_color(alsabar.colors.mute) + else + alsabar._muted = false + alsabar.tooltip:set_text(" " .. alsabar.channel .. ": " .. volu .. "% ") + alsabar.bar:set_color(alsabar.colors.unmute) + end + end + + local myvolumebartimer = timer({ timeout = 5 }) + myvolumebartimer:connect_signal("timeout", myvolumebarupdate) + myvolumebartimer:start() + myvolumebartimer:emit_signal("timeout") + + alsabar.bar:buttons (awful.util.table.join ( + awful.button ({}, 1, function() + awful.util.spawn(alsabar.mixer) + end), + awful.button ({}, 3, function() + awful.util.spawn("amixer sset " .. alsabar.channel .. " toggle") + myvolumebarupdate() + end), + awful.button ({}, 4, function() + awful.util.spawn("amixer sset " .. alsabar.channel .. " " + .. alsabar.step .. "+") + myvolumebarupdate() + end), + awful.button ({}, 5, function() + awful.util.spawn("amixer sset " .. alsabar.channel .. " " + .. alsabar.step .. "-") + myvolumebarupdate() + end) + )) + + return { widget = alsabar.bar, + channel = alsabar.channel, + step = alsabar.step, + notify = function() + myvolumebarupdate() + alsabar.notify() + end + } +end + +return setmetatable(alsabar, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/bat.lua b/widgets/bat.lua new file mode 100644 index 0000000..0461607 --- /dev/null +++ b/widgets/bat.lua @@ -0,0 +1,147 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local markup = require("lain.util.markup") +local first_line = require("lain.helpers").first_line + +local beautiful = require("beautiful") +local naughty = require("naughty") +local wibox = require("wibox") + +local math = { floor = math.floor } +local string = { format = string.format } + +local setmetatable = setmetatable + +-- Battery infos +-- lain.widgets.bat +local bat = { + status = "not present", + perc = "N/A", + time = "N/A", +} + +function worker(args) + local args = args or {} + local battery = args.battery or "BAT0" + local show_all = args.show_all or false + local refresh_timeout = args.refresh_timeout or 30 + local header = args.header or " Bat " + local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" + local color = args.color or beautiful.fg_focus or "#FFFFFF" + local shadow = args.shadow or false + + local mybattery = wibox.widget.textbox() + + local mybatteryupdate = function() + local present = first_line("/sys/class/power_supply/" + .. battery + .. "/present") + + if present == "1" + then + local rate = first_line("/sys/class/power_supply/" + .. battery .. + "/power_now") + local ratev = first_line("/sys/class/power_supply/" + .. battery .. + "/voltage_now") + local rem = first_line("/sys/class/power_supply/" + .. battery .. + "/energy_now") + local tot = first_line("/sys/class/power_supply/" + .. battery .. + "/energy_full") + bat.status = first_line("/sys/class/power_supply/" + .. battery .. + "/status") + + local time_rat = 0 + if bat.status == "Charging" + then + status = "(+)" + time_rat = (tot - rem) / rate + elseif bat.status == "Discharging" + then + status = "(-)" + time_rat = rem / rate + else + status = "(.)" + end + + local hrs = math.floor(time_rat) + local min = (time_rat - hrs) * 60 + bat.time = string.format("%02d:%02d", hrs, min) + + local amount = (rem / tot) * 100 + + if shadow + then + bat.perc = string.format("%d", amount) + else + bat.perc = string.format("%d%%", amount) + end + + local watt = string.format("%.2fW", (rate * ratev) / 1e12) + + if show_all + then + text = watt .. " " .. bat.perc .. " " .. bat.time .. " " .. bat.status + else + text = bat.perc + end + + -- notifications for low and critical states + if amount <= 5 + then + naughty.notify{ + text = "shutdown imminent", + title = "battery nearly exhausted", + position = "top_right", + timeout = 15, + fg="#000000", + bg="#ffffff", + ontop = true + } + elseif amount <= 15 + then + old_id = naughty.notify{ + text = "plug the cable", + title = "battery low", + position = "top_right", + timeout = 5, + fg="#202020", + bg="#cdcdcd", + ontop = true + } + end + else + text = "none" + end + + if shadow + then + mybattery:set_text('') + else + mybattery:set_markup(markup(header_color, header) + .. markup(color, text) .. " ") + end + end + + local mybatterytimer = timer({ timeout = refresh_timeout }) + mybatterytimer:connect_signal("timeout", mybatteryupdate) + mybatterytimer:start() + mybatterytimer:emit_signal("timeout") + + bat.widget = mybattery + + return setmetatable(bat, { __index = bat.widget }) +end + +return setmetatable(bat, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/borderbox.lua b/widgets/borderbox.lua new file mode 100644 index 0000000..150c1c3 --- /dev/null +++ b/widgets/borderbox.lua @@ -0,0 +1,61 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local wibox = require("awful.wibox") +local setmetatable = setmetatable + +-- Creates a thin wibox at a position relative to another wibox +-- lain.widgets.borderbox +local borderbox = {} + +local function worker(relbox, s, args) + local where = args.position or 'above' + local color = args.color or '#FFFFFF' + local size = args.size or 1 + local box = nil + local wiboxarg = { + position = nil, + bg = color + } + + if where == 'above' + then + wiboxarg.width = relbox.width + wiboxarg.height = size + box = wibox(wiboxarg) + box.x = relbox.x + box.y = relbox.y - size + elseif where == 'below' + then + wiboxarg.width = relbox.width + wiboxarg.height = size + box = wibox(wiboxarg) + box.x = relbox.x + box.y = relbox.y + relbox.height + elseif where == 'left' + then + wiboxarg.width = size + wiboxarg.height = relbox.height + box = wibox(wiboxarg) + box.x = relbox.x - size + box.y = relbox.y + elseif where == 'right' + then + wiboxarg.width = size + wiboxarg.height = relbox.height + box = wibox(wiboxarg) + box.x = relbox.x + relbox.width + box.y = relbox.y + end + + box.screen = s + return box +end + +return setmetatable(borderbox, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/calendar.lua b/widgets/calendar.lua new file mode 100644 index 0000000..4b6d469 --- /dev/null +++ b/widgets/calendar.lua @@ -0,0 +1,124 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + +--]] + +local icons_dir = require("lain.helpers").icons_dir + +local awful = require("awful") +local beautiful = require("beautiful") +local naughty = require("naughty") + +local io = io +local os = { date = os.date } +local tonumber = tonumber + +local setmetatable = setmetatable + +-- Calendar notification +-- lain.widgets.calendar +local calendar = {} +local notification = nil + +local function create(background, foreground) + calendar.offset = 0 + calendar.icons_dir = icons_dir .. "cal/white/" -- default + calendar.notify_icon = nil + calendar.font_size = 12 + calendar.bg = background or beautiful.bg_normal or "#FFFFFF" + calendar.fg = foreground or beautiful.fg_normal or "#FFFFFF" +end + +function calendar:hide() + if notification ~= nil then + naughty.destroy(notification) + notification = nil + end +end + +function calendar:show(t_out, inc_offset) + calendar:hide() + + local offs = inc_offset or 0 + local tims = t_out or 0 + local f, c_text + local today = tonumber(os.date('%d')) + local init_t = '/usr/bin/cal | sed -r -e "s/(^| )( ' + -- let's take font only, font size is set in calendar table + local font = beautiful.font:sub(beautiful.font:find(""), + beautiful.font:find(" ")) + + if offs == 0 + then -- current month showing, today highlighted + if today >= 10 + then + init_t = '/usr/bin/cal | sed -r -e "s/(^| )(' + end + + calendar.offset = 0 + calendar.notify_icon = calendar.icons_dir .. today .. ".png" + + -- bg and fg inverted to highlight today + f = io.popen( init_t .. today .. + ')($| )/\\1\\2<\\/span><\\/b>\\3/"' ) + + else -- no current month showing, no day to highlight + local month = tonumber(os.date('%m')) + local year = tonumber(os.date('%Y')) + + calendar.offset = calendar.offset + offs + month = month + calendar.offset + + if month > 12 then + month = month % 12 + year = year + 1 + if month <= 0 then + month = 12 + end + elseif month < 1 then + month = month + 12 + year = year - 1 + if month <= 0 then + month = 1 + end + end + + calendar.notify_icon = nil + + f = io.popen('/usr/bin/cal ' .. month .. ' ' .. year) + end + + + c_text = "" + .. f:read() .. "\n\n" + .. f:read() .. "\n" + .. f:read("*all"):gsub("\n*$", "") + .. "" + f:close() + + notification = naughty.notify({ text = c_text, + icon = calendar.notify_icon, + fg = calendar.fg, + bg = calendar.bg, + timeout = tims }) +end + +function calendar:attach(widget, background, foreground) + create(background, foreground) + widget:connect_signal("mouse::enter", function () calendar:show() end) + widget:connect_signal("mouse::leave", function () calendar:hide() end) + widget:buttons(awful.util.table.join( awful.button({ }, 1, function () + calendar:show(0, -1) end), + awful.button({ }, 3, function () + calendar:show(0, 1) end) )) +end + +return setmetatable(calendar, { __call = function(_, ...) return create(...) end }) diff --git a/widgets/cpu.lua b/widgets/cpu.lua new file mode 100644 index 0000000..cf0b76c --- /dev/null +++ b/widgets/cpu.lua @@ -0,0 +1,80 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local markup = require("lain.util.markup") +local first_line = require("lain.helpers").first_line + +local beautiful = require("beautiful") +local wibox = require("wibox") + +local math = { ceil = math.ceil } +local string = { format = string.format, + gmatch = string.gmatch } + +local setmetatable = setmetatable + +-- CPU usage +-- lain.widgets.cpu +local cpu = { + last_total = 0, + last_active = 0 +} + +function worker(args) + local args = args or {} + local refresh_timeout = args.refresh_timeout or 5 + local header = args.header or " Cpu " + local header_color = args.header or beautiful.fg_normal or "#FFFFFF" + local color = args.color or beautiful.fg_focus or "#FFFFFF" + local footer = args.footer or "%" + + local w = wibox.widget.textbox() + + local cpuusageupdate = function() + -- Read the amount of time the CPUs have spent performing + -- different kinds of work. Read the first line of /proc/stat + -- which is the sum of all CPUs. + local times = first_line("/proc/stat") + local at = 1 + local idle = 0 + local total = 0 + for field in string.gmatch(times, "[%s]+([^%s]+)") + do + -- 3 = idle, 4 = ioWait. Essentially, the CPUs have done + -- nothing during these times. + if at == 3 or at == 4 + then + idle = idle + field + end + total = total + field + at = at + 1 + end + local active = total - idle + + -- Read current data and calculate relative values. + local dactive = active - cpu.last_active + local dtotal = total - cpu.last_total + local dta = math.ceil((dactive / dtotal) * 100) + + w:set_markup(markup(header_color, header) .. markup(color, dta .. footer) .. " ") + + -- Save current data for the next run. + cpu.last_active = active + cpu.last_total = total + end + + local cpuusagetimer = timer({ timeout = refresh_timeout }) + cpuusagetimer:connect_signal("timeout", cpuusageupdate) + cpuusagetimer:start() + cpuusagetimer:emit_signal("timeout") + + return w +end + +return setmetatable(cpu, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/fs.lua b/widgets/fs.lua new file mode 100644 index 0000000..9611617 --- /dev/null +++ b/widgets/fs.lua @@ -0,0 +1,134 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010, Adrian C. + * (c) 2009, Lucas de Vries + +--]] + +local markup = require("lain.util.markup") +local helpers = require("lain.helpers") + +local beautiful = require("beautiful") +local wibox = require("wibox") +local naughty = require("naughty") + +local io = io +local string = { match = string.match } +local tonumber = tonumber + +local setmetatable = setmetatable + +-- File system disk space usage +-- lain.widgets.fs +local fs = {} +local notification = nil + +function fs:hide() + if notification ~= nil then + naughty.destroy(notification) + notification = nil + end +end + +function fs:show(t_out) + fs:hide() + + local f = io.popen(helpers.scripts_dir .. "dfs") + ws = f:read("*all"):gsub("\n*$", "") + f:close() + + notification = naughty.notify({ + text = ws, + timeout = t_out, + fg = beautiful.fg_focus, + }) +end + +-- Variable definitions +local unit = { ["mb"] = 1024, ["gb"] = 1024^2 } + +local function worker(args) + local args = args or {} + local partition = args.partition or "/" + local refresh_timeout = args.refresh_timeout or 600 + local header = args.header or " Hdd " + local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" + local color = args.color or beautiful.fg_focus or "#FFFFFF" + local footer = args.header or "" + local shadow = args.shadow or false + + local myfs = wibox.widget.textbox() + + helpers.set_map("fs", false) + + local fsupdate = function() + local fs_info = {} -- Get data from df + local f = io.popen("LC_ALL=C df -kP") + + local function set_text() + local info = fs_info['{' .. partition .. ' used_p}'] + myfs:set_markup(markup(header_color, header) + .. markup(color, info .. footer) .. " ") + end + + for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount) + local s = string.match(line, "^.-[%s]([%d]+)") + local u,a,p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%") + local m = string.match(line, "%%[%s]([%p%w]+)") + + if u and m then -- Handle 1st line and broken regexp + helpers.uformat(fs_info, m .. " used", u, unit) + fs_info["{" .. m .. " used_p}"] = tonumber(p) + end + end + + f:close() + + if shadow + then + myfs:set_text('') + else + set_text() + end + + local part = fs_info['{' .. partition .. ' used_p}'] + + if part >= 90 then + if part >= 99 and not helpers.get_map("fs") then + naughty.notify({ title = "warning", + text = partition .. " ran out!\n" + .. "make some room", + timeout = 8, + position = "top_right", + fg = beautiful.fg_urgent, + bg = beautiful.bg_urgent }) + helpers.set_map("fs", true) + end + if shadow then set_text() end + end + end + + local fstimer = timer({ timeout = refresh_timeout }) + fstimer:connect_signal("timeout", fsupdate) + fstimer:start() + fstimer:emit_signal("timeout") + + myfs:connect_signal('mouse::enter', function () fs:show(0) end) + myfs:connect_signal('mouse::leave', function () fs:hide() end) + + local fs_out = + { + widget = myfs, + show = function(t_out) + fsupdate() + fs:show(t_out) + end + } + + return setmetatable(fs_out, { __index = fs_out.widget }) +end + +return setmetatable(fs, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/imap.lua b/widgets/imap.lua new file mode 100644 index 0000000..94652b6 --- /dev/null +++ b/widgets/imap.lua @@ -0,0 +1,166 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + +--]] + +local markup = require("lain.util.markup") +local helpers = require("lain.helpers") + +local awful = require("awful") +local beautiful = require("beautiful") +local naughty = require("naughty") +local wibox = require("wibox") + +local io = io +local tonumber = tonumber +local string = string + +local setmetatable = setmetatable + +-- Mail imap check +-- lain.widgets.imap +local imap = {} + +function worker(args) + local args = args or {} + + local server = args.server + local mail = args.mail + local password = args.password + + local port = args.port or "993" + local refresh_timeout = args.refresh_timeout or 60 + local header = args.header or " Mail " + local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" + local color_newmail = args.color_newmail or beautiful.fg_focus or "#FFFFFF" + local color_nomail = args.color_nomail or beautiful.fg_normal or "#FFFFFF" + local mail_encoding = args.mail_encoding or nil + local maxlen = args.maxlen or 200 + local app = args.app or "mutt" + local is_plain = args.is_plain or false + local shadow = args.shadow or false + + helpers.set_map(mail, true) + helpers.set_map(mail .. " count", "0") + + local checkmail = helpers.scripts_dir .. "checkmail" + + if not is_plain + then + local f = io.popen(password) + password = f:read("*all"):gsub("\n", ""):gsub("\r", "") + f:close() + end + + local myimapcheck = wibox.widget.textbox() + + local myimapcheckupdate = function() + function set_nomail() + if shadow + then + myimapcheck:set_text('') + else + myimapcheck:set_markup(markup(color_nomail, " no mail ")) + end + end + + conn = io.popen("ip link show") + check_conn = conn:read("*all") + conn:close() + + if not check_conn:find("state UP") then + set_nomail() + return + end + + to_execute = checkmail .. ' -s ' .. server .. + ' -u ' .. mail .. ' -p ' .. password + .. ' --port ' .. port + + if mail_encoding ~= nil + then + to_execute = to_execute .. ' --encoding ' + .. mail_encoding + end + + f = io.popen(to_execute) + ws = f:read("*all") + f:close() + + if ws:find("No new messages") ~= nil + then + helpers.set_map(mail, true) + set_nomail() + elseif ws:find("CheckMailError: invalid credentials") ~= nil + then + helpers.set_map(mail, true) + myimapcheck.set_markup(markup(header_color, header) .. + markup(color_newmail, "invalid credentials ")) + else + mailcount = ws:match("%d") or "?" + + if helpers.get_map(mail .. " count") ~= mailcount and mailcount ~= "?" + then + helpers.set_map(mail, true) + helpers.set_map(mail .. " count", mailcount) + end + + myimapcheck:set_markup(markup(header_color, header) .. + markup(color_newmail, mailcount) .. " ") + + if helpers.get_map(mail) + then + if mailcount == "?" + -- May happens sometimes using keyrings or other password fetchers. + -- Since this should be automatically fixed in short times, we threat + -- this exception delaying the update to the next timeout. + then + set_nomail() + return + elseif tonumber(mailcount) >= 1 + then + notify_title = ws:match(mail .. " has %d new message.?") + ws = ws:gsub(notify_title, "", 1):gsub("\n", "", 2) + + ws = ws:gsub("--Content.%S+.-\n", "") + ws = ws:gsub("--%d+.-\n", "") + + if string.len(ws) > maxlen + then + ws = ws:sub(1, maxlen) .. "[...]" + end + + notify_title = notify_title:gsub("\n", "") + end + + naughty.notify({ title = notify_title, + fg = color_newmail, + text = ws, + icon = beautiful.lain_mail_notify or + helpers.icons_dir .. "mail.png", + timeout = 8, + position = "top_left" }) + + helpers.set_map(mail, false) + end + end + end + + local myimapchecktimer = timer({ timeout = refresh_timeout }) + myimapchecktimer:connect_signal("timeout", myimapcheckupdate) + myimapchecktimer:start() + myimapcheck:buttons(awful.util.table.join( + awful.button({}, 0, + + function() + helpers.run_in_terminal(app) + end) + )) + + return myimapcheck +end + +return setmetatable(imap, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/init.lua b/widgets/init.lua new file mode 100644 index 0000000..78cac9b --- /dev/null +++ b/widgets/init.lua @@ -0,0 +1,24 @@ + +--[[ + + Lain + Layouts, widgets and utilities for Awesome WM + + Widgets section + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local wrequire = require("lain.helpers").wrequire +local setmetatable = setmetatable + +local widgets = +{ + _NAME = "lain.widgets", + terminal = "xterm" -- X default +} + +return setmetatable(widgets, { __index = wrequire }) diff --git a/widgets/maildir.lua b/widgets/maildir.lua new file mode 100644 index 0000000..b5437bd --- /dev/null +++ b/widgets/maildir.lua @@ -0,0 +1,129 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local markup = require("lain.util.markup") +local run_in_terminal = require("lain.helpers").run_in_terminal + +local awful = require("awful") +local beautiful = require("beautiful") +local wibox = require("wibox") + +local io = io +local os = { getenv = os.getenv } +local pairs = pairs +local string = { len = string.len, + match = string.match } +local table = { sort = table.sort } + +local setmetatable = setmetatable + +-- Maildir check +-- lain.widgets.maildir +local maildir = {} + +function worker(args) + local args = args or {} + local mailpath = args.mailpath or os.getenv("HOME") .. "/Mail" + local ignore_boxes = args.ignore_boxes or {} + local refresh_timeout = args.refresh_timeout or 60 + local header = args.header or " Mail " + local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" + local color_newmail = args.color_newmail or beautiful.fg_focus or "#FFFFFF" + local color_nomail = args.color_nomail or beautiful.fg_normal or "#FFFFFF" + local app = args.app or "mutt" + local shadow = args.shadow or false + + local mymailcheck = wibox.widget.textbox() + local mymailcheckupdate = function() + -- Find pathes to mailboxes. + local p = io.popen("find " .. mailpath .. + " -mindepth 1 -maxdepth 1 -type d" .. + " -not -name .git") + local boxes = {} + local line = "" + repeat + line = p:read("*l") + if line ~= nil + then + -- Find all files in the "new" subdirectory. For each + -- file, print a single character (no newline). Don't + -- match files that begin with a dot. + -- Afterwards the length of this string is the number of + -- new mails in that box. + local np = io.popen("find " .. line .. + "/new -mindepth 1 -type f " .. + "-not -name '.*' -printf a") + local mailstring = np:read("*all") + + -- Strip off leading mailpath. + local box = string.match(line, mailpath .. "/*([^/]+)") + local nummails = string.len(mailstring) + if nummails > 0 + then + boxes[box] = nummails + end + end + until line == nil + + table.sort(boxes) + + local newmail = "" + local count = 0 + for box, number in pairs(boxes) + do + count = count + 1 + -- Add this box only if it's not to be ignored. + if not util.element_in_table(box, ignore_boxes) + then + if newmail == "" + then + newmail = box .. "(" .. number .. ")" + else + newmail = newmail .. ", " .. + box .. "(" .. number .. ")" + end + end + end + + if count == 1 then + -- it will be only executed once + for box, number in pairs(boxes) + do -- it's useless to show only INBOX(x) + if box == "INBOX" then newmail = number end + end + end + + if newmail == "" + then + if shadow + then + mymailcheck:set_text('') + else + myimapcheck:set_markup(markup(color_nomail, " no mail ")) + end + else + myimapcheck:set_markup(markup(header_color, header) .. + markup(color_newmail, newmail) .. " ") + end + end + + local mymailchecktimer = timer({ timeout = refresh_timeout }) + mymailchecktimer:connect_signal("timeout", mymailcheckupdate) + mymailchecktimer:start() + mymailcheck:buttons(awful.util.table.join( + awful.button({}, 0, + function() + run_in_terminal(app) + end) + )) + + return mymailcheck +end + +return setmetatable(maildir, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/mem.lua b/widgets/mem.lua new file mode 100644 index 0000000..09be00f --- /dev/null +++ b/widgets/mem.lua @@ -0,0 +1,87 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + * (c) 2010, Adrian C. + * (c) 2009, Lucas de Vries + +--]] + +local markup = require("lain.util.markup") +local run_in_terminal = require("lain.helpers").run_in_terminal + +local beautiful = require("beautiful") +local wibox = require("wibox") + +local io = { lines = io.lines } +local math = { floor = math.floor } +local string = { format = string.format, + gmatch = string.gmatch, + len = string.len } + +local setmetatable = setmetatable + +-- Memory usage (ignoring caches) +-- lain.widgets.mem +local mem = {} + +function worker(args) + local args = args or {} + local refresh_timeout = args.refresh_timeout or 10 + local show_swap = args.show_swap or false + local show_total = args.show_total or false + local header = args.header or " Mem " + local header_color = args.header or beautiful.fg_normal or "#FFFFFF" + local color = args.color or beautiful.fg_focus or "#FFFFFF" + local footer = args.footer or "MB" + + local widg = wibox.widget.textbox() + + local upd = function() + local mem = {} + for line in io.lines("/proc/meminfo") + do + for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+") + do + if k == "MemTotal" then mem.total = math.floor(v / 1024) + elseif k == "MemFree" then mem.free = math.floor(v / 1024) + elseif k == "Buffers" then mem.buf = math.floor(v / 1024) + elseif k == "Cached" then mem.cache = math.floor(v / 1024) + elseif k == "SwapTotal" then mem.swap = math.floor(v / 1024) + elseif k == "SwapFree" then mem.swapf = math.floor(v / 1024) + end + end + end + + used = mem.total - (mem.free + mem.buf + mem.cache) + swapused = mem.swap - mem.swapf + + if show_total + then + local fmt = "%" .. string.len(mem.total) .. ".0f/%.0f" + widg:set_markup(markup(header_color, header) .. + markup(color, string.format(fmt, used, mem.total) .. footer .. " ")) + else + widg:set_markup(markup(header_color, header) .. + markup(color, used .. footer .. " ")) + end + + if show_swap + then + widg:set_markup(widg._layout.text .. ' (' + .. string.format('%.0f '.. footer, swapused) + .. ') ') + end + end + + local tmr = timer({ timeout = refresh_timeout }) + tmr:connect_signal("timeout", upd) + tmr:start() + tmr:emit_signal("timeout") + + return widg +end + +return setmetatable(mem, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/mpd.lua b/widgets/mpd.lua new file mode 100644 index 0000000..dcb7101 --- /dev/null +++ b/widgets/mpd.lua @@ -0,0 +1,138 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010, Adrian C. + +--]] + +local markup = require("lain.util.markup") +local helpers = require("lain.helpers") + +local awful = require("awful") +local beautiful = require("beautiful") +local naughty = require("naughty") +local wibox = require("wibox") + +local io = io +local os = { execute = os.execute, + getenv = os.getenv } +local string = { gmatch = string.gmatch } + +local setmetatable = setmetatable + +-- MPD infos +-- lain.widgets.mpd +local mpd = { id = nil } + +function worker(args) + local args = args or {} + local password = args.password or "" + local host = args.host or "127.0.0.1" + local port = args.port or "6600" + local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" + local refresh_timeout = args.refresh_timeout or 1 + local notify_timeout = args.notify_timeout or 5 + local color_artist = args.color_artist or beautiful.fg_normal or "#FFFFFF" + local color_song = args.color_song or beautiful.fg_focus or "#FFFFFF" + local spr = args.spr or "" + local musicplr = args.musicplr or "ncmpcpp" + local shadow = args.shadow or false + + local mpdcover = helpers.scripts_dir .. "mpdcover" + local mpdh = "telnet://"..host..":"..port + local echo = "echo 'password "..password.."\nstatus\ncurrentsong\nclose'" + + local mympd = wibox.widget.textbox() + + helpers.set_map("current mpd track", nil) + + local mympdupdate = function() + local function set_nompd() + if shadow + then + mympd:set_text('') + else + mympd:set_markup(markup(color_artist, " mpd "), markup(color_song , "off ")) + end + end + + local mpd_state = { + ["{state}"] = "N/A", + ["{file}"] = "N/A", + ["{Artist}"] = "N/A", + ["{Title}"] = "N/A", + ["{Album}"] = "N/A", + ["{Date}"] = "N/A" + } + + -- Get data from MPD server + local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh) + + for line in f:lines() do + for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do + if k == "state" then mpd_state["{"..k.."}"] = v + elseif k == "file" then mpd_state["{"..k.."}"] = v + elseif k == "Artist" then mpd_state["{"..k.."}"] = awful.util.escape(v) + elseif k == "Title" then mpd_state["{"..k.."}"] = awful.util.escape(v) + elseif k == "Album" then mpd_state["{"..k.."}"] = awful.util.escape(v) + elseif k == "Date" then mpd_state["{"..k.."}"] = awful.util.escape(v) + end + end + end + + f:close() + + if mpd_state["{state}"] == "play" + then + if mpd_state["{Title}"] ~= helpers.get_map("current mpd track") + then + helpers.set_map("current mpd track", mpd_state["{Title}"]) + os.execute(mpdcover .. " '" .. music_dir .. "' '" + .. mpd_state["{file}"] .. "'") + mpd.id = naughty.notify({ + title = "Now playing", + text = mpd_state["{Artist}"] .. " (" .. + mpd_state["{Album}"] .. ") - " .. + mpd_state["{Date}"] .. "\n" .. + mpd_state["{Title}"], + icon = "/tmp/mpdcover.png", + fg = beautiful.fg_focus or "#FFFFFF", + bg = beautiful.bg_normal or "#000000" , + timeout = notify_timeout, + replaces_id = mpd.id + }).id + end + mympd:set_markup(markup(color_artist, " " .. mpd_state["{Artist}"]) + .. spr .. + markup(color_song, " " .. mpd_state["{Title}"] .. " ")) + elseif mpd_state["{state}"] == "pause" + then + mympd:set_markup(markup(color_artist, " mpd") + .. spr .. + markup(color_song, " paused ")) + else + helpers.set_map("current mpd track", nil) + set_nompd() + end + end + + local mympdtimer = timer({ timeout = refresh_timeout }) + mympdtimer:connect_signal("timeout", mympdupdate) + mympdtimer:start() + mympdtimer:emit_signal("timeout") + + mympd:buttons(awful.util.table.join( + awful.button({}, 0, + function() + helpers.run_in_terminal(musicplr) + end) + )) + + local mpd_out = { widget = mympd, notify = mympdupdate } + + return setmetatable(mpd_out, { __index = mpd_out.widget }) +end + +return setmetatable(mpd, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/net.lua b/widgets/net.lua new file mode 100644 index 0000000..f361146 --- /dev/null +++ b/widgets/net.lua @@ -0,0 +1,153 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local markup = require("lain.util.markup") +local helpers = require("lain.helpers") + +local awful = require("awful") +local beautiful = require("beautiful") +local wibox = require("wibox") + +local io = io +local tostring = tostring +local string = { format = string.format } + +local setmetatable = setmetatable + +-- Network infos +-- lain.widgets.net +local net = { + send = "0", + recv = "0", + last_t = {}, + last_r = {} +} + +local unit = { + ["b"] = 1, + ["kb"] = 1024, + ["mb"] = 1024^2, + ["gb"] = 1024^3 +} + +function net.get_device() + f = io.popen("ip link show | cut -d' ' -f2,9") + ws = f:read("*all") + f:close() + ws = ws:match("%w+: UP") + if ws ~= nil then + return ws:gsub(": UP", "") + else + return "" + end +end + +function worker(args) + local args = args or {} + local iface = args.iface or net.get_device() + local delta = args.refresh_timeout or 2 + local unit = args.unit or unit["kb"] + local spr = args.spr or " " + local header = args.header or iface + local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" + local color_up = args.color_up or beautiful.fg_focus or header_color + local color_down = args.color_down or beautiful.fg_focus or header_color + local app = args.app or "sudo wifi-menu" + + helpers.set_map(iface, true) + helpers.set_map("carrier", 0) + + local mynet = wibox.widget.textbox() + + local mynetupdate = function() + if iface == "" then + iface = net.get_device() + header = iface + end + + local carrier = helpers.first_line('/sys/class/net/' .. iface .. + '/carrier') or "" + local state = helpers.first_line('/sys/class/net/' .. iface .. + '/operstate') + local now_t = helpers.first_line('/sys/class/net/' .. iface .. + '/statistics/tx_bytes') + local now_r = helpers.first_line('/sys/class/net/' .. iface .. + '/statistics/rx_bytes') + local text = '' .. header .. ' ' + + if carrier ~= "1" + then + if helpers.get_map(iface) + then + n_title = iface + if n_title == "" then + n_title = "network" + header = "Net" + end + naughty.notify({ title = n_title, text = "no carrier", + timeout = 7, + position = "top_left", + icon = beautiful.lain_no_net_notify or + helpers.icons_dir .. "no_net.png", + fg = beautiful.fg_focus or "#FFFFFF" }) + + mynet:set_markup(markup(header_color, header) .. markup(color_up, " Off")) + helpers.set_map(iface, false) + end + return + else + helpers.set_map(iface, true) + end + + if state == 'down' or not now_t or not now_r + then + mynet:set_markup(' ' .. text .. '-' .. ' ') + return + end + + if net.last_t[iface] and net.last_t[iface] + then + net.send = tostring((now_t - net.last_t[iface]) / delta / unit) + net.recv = tostring((now_r - net.last_r[iface]) / delta / unit) + + text = text + .. '' + .. string.format('%.1f', net.send) + .. '' + .. spr + .. '' + .. string.format('%.1f', net.recv) + .. '' + + mynet:set_markup(' ' .. text .. ' ') + else + mynet:set_markup(' ' .. text .. '-' .. ' ') + end + + net.last_t[iface] = now_t + net.last_r[iface] = now_r + end + + local mynettimer = timer({ timeout = delta }) + mynettimer:connect_signal("timeout", mynetupdate) + mynettimer:start() + mynettimer:emit_signal("timeout") + + mynet:buttons(awful.util.table.join( + awful.button({}, 0, function() + helpers.run_in_terminal(app) + mynetupdate() + end))) + + net.widget = mynet + + return setmetatable(net, { __index = net.widget }) +end + +return setmetatable(net, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/sysload.lua b/widgets/sysload.lua new file mode 100644 index 0000000..8583ccb --- /dev/null +++ b/widgets/sysload.lua @@ -0,0 +1,70 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local markup = require("lain.util.markup") +local helpers = require("lain.helpers") + +local awful = require("awful") +local beautiful = require("beautiful") +local wibox = require("wibox") + +local io = io +local string = { format = string.format, + match = string.match } + +local setmetatable = setmetatable + +-- System load +-- lain.widgets.sysload +local sysload = {} + +function worker(args) + local args = args or {} + local refresh_timeout = args.refresh_timeout or 5 + local show_all = args.show_all or false + local header = args.header or " Load " + local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" + local color = args.color or beautiful.fg_focus or header_color + local app = args.app or "top" + + local mysysload = wibox.widget.textbox() + + local mysysloadupdate = function() + local f = io.open("/proc/loadavg") + local ret = f:read("*all") + f:close() + + if show_all + then + local a, b, c = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") + mysysload:set_text(string.format("%s %s %s", a, b, c)) + else + local a = string.match(ret, "([^%s]+) ") + mysysload:set_text(string.format("%s", a)) + end + mysysload:set_markup(markup(header_color, header) .. + markup(color, mysysload._layout.text .. " ")) + end + + local mysysloadtimer = timer({ timeout = refresh_timeout }) + mysysloadtimer:connect_signal("timeout", mysysloadupdate) + mysysloadtimer:start() + mysysloadtimer:emit_signal("timeout") + + mysysload:buttons(awful.util.table.join( + awful.button({}, 0, + function() + helpers.run_in_terminal(app) + end) + )) + + return mysysload +end + +return setmetatable(sysload, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/temp.lua b/widgets/temp.lua new file mode 100644 index 0000000..301bc1c --- /dev/null +++ b/widgets/temp.lua @@ -0,0 +1,52 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + +--]] + +local markup = require("lain.util.markup") + +local beautiful = require("beautiful") +local wibox = require("wibox") + +local io = io +local tonumber = tonumber + +local setmetatable = setmetatable + +-- coretemp +-- lain.widgets.temp +local temp = {} + +function worker(args) + local args = args or {} + local refresh_timeout = args.refresh_timeout or 5 + local header = args.header or " Temp " + local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" + local color = args.color or beautiful.fg_focus or header_color + local footer = args.footer or "C " + + local mytemp = wibox.widget.textbox() + + local mytempupdate = function() + local f = io.open("/sys/class/thermal/thermal_zone0/temp") + local ret = f:read("*all") + f:close() + + ret = tonumber(ret) / 1000 + + mytemp:set_markup(markup(header_color, header) .. + markup(color, ret .. footer)) + end + + local mytemptimer = timer({ timeout = refresh_timeout }) + mytemptimer:connect_signal("timeout", mytempupdate) + mytemptimer:start() + mytemptimer:emit_signal("timeout") + + return mytemp +end + +return setmetatable(temp, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/yawn/README.rst b/widgets/yawn/README.rst new file mode 100644 index 0000000..d067db3 --- /dev/null +++ b/widgets/yawn/README.rst @@ -0,0 +1,133 @@ +========================================= +Yahoo's Awesome (WM) Weather Notification +========================================= + +---------------- +Lain integration +---------------- + +:Author: Luke Bonham +:License: WTFPLv2_ +:Version: 2.0-git + +Description +----------- + +Yawn is a module for Awesome WM providing brief and compact +weather notification via Naughty and Yahoo! Weather API. + +Originally a port of perceptive_, it became a completely new module after various improvements and style changes. + +----- +Usage +----- + +You can ``register`` Yawn to get a set of widgets, or ``attach`` it to +an existent widget. + +register +^^^^^^^^ + +Call: :: + + lain.widgets.yawn(id, args) + +Arguments: + +``id`` + An integer that defines the WOEID code of your city. + To obtain it you can google 'yahoo weather %CITYNAME%' and follow the first link. + It will look like:: + + http://weather.yahoo.com/united-states/california/san-diego-2487889/ + + and the last number in that link will be the ID you need. +``args`` + An optional table which can contain the following settings: + ``u`` + Units. Type: string. Possible values: "c" (Celsius), "f" (Fahrenheit). Default: "c". + + ``toshow`` + What to show. Type: string. Possible values: "units", "forecast", "both". + Default: "forecast". + + ``units_color`` + Color of units text. Type: string. Possible values: hexadecimal color + codes. + + ``forecast_color`` + Color of forecast text. Type: string. Possible values: hexadecimal color + codes. + + ``notification_color`` + Color of notification text. Type: string. Possible values: hexadecimal color + codes. + + ``spr`` + A separator. Type: string. You can define it when ``toshow`` is set to "both". + + ``footer`` + A footer. Type: string. You can define it when ``toshow`` is set to + "both". + +The function creates an imagebox icon and a textbox widget. Add them to you wibox like this: :: + + right_layout:add(lain.widgets.yawn.icon) + right_layout:add(lain.widgets.yawn.widget) + +Hovering over ``yawn.icon`` will display the notification. + +attach +^^^^^^ + +Call: :: + + lain.widgets.yawn.attach(widget, id, args) + +Arguments: + +``widget`` + The widget which you want to attach yawn to. +``id`` + same as in ``register`` +``args`` + same as in ``register`` + +Hovering over ``widget`` will display the notification. + +-------------- +Popup shortcut +-------------- + +You can also create a keybinding for the weather popup like this: :: + + globalkeys = awful.util.table.join( + ... + awful.key( { "Mod1" }, "w", function () lain.widgets.yawn.show(5) end ) + ... + +where ``show`` argument is an integer defining timeout seconds. + +------------ +Localization +------------ + +Default language is English, but Yawn can be localized. +Move to ``localizations`` subdirectory and fill ``localization_template``. + +Once you're done, rename it like your locale id. In my case: :: + + $ lua + Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio + > print(os.getenv("LANG"):match("(%S*$*)[.]")) + it_IT + > + +hence I named my file "it_IT" (Italian localization). + +**NOTE:** If you create a localization, feel free to send me! I will add it. + +.. _WTFPLv2: http://www.wtfpl.net +.. _perceptive: https://github.com/ioga/perceptive +.. _Tamsyn: http://www.fial.com/~scott/tamsyn-font/ +.. _Rainbow: https://github.com/copycat-killer/awesome-copycats> diff --git a/widgets/yawn/icons/BlowingSnow.png b/widgets/yawn/icons/BlowingSnow.png new file mode 100755 index 0000000000000000000000000000000000000000..6223f8f7d2c1be89dbb216537dbfe0e97e4edd28 GIT binary patch literal 11454 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 literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/Cloudy.png b/widgets/yawn/icons/Cloudy.png new file mode 100755 index 0000000000000000000000000000000000000000..bac1e7ebb84426f6bf1704f4c8a3c70486713cd1 GIT binary patch literal 7469 zcmai(byQSgx5m#5-QArkDGgFXg9u1>3Bv#aLkwL*i-?4RbSNPxAxPH%A|Ne|q)14E zw8VG3_x^R)UF*(TXU@dC-V^WM&-2^+#6Q;6AR%NV1OR|UOHGd?|8oWo-r(deesJ)J?%?eIu146+#R2Z&1NRYr5-8~5An0Q+EGBec zcoCa%4FH&Wv{aRh0&;e(T~O4M^^3-nKD?rF1)21zq)|%5+-TKSB5o)!r0f>^rUQVX%>;+b|$07!_AGR%Oh%T;9pkT@6ray;@$wPq{0w6W*caL zbSw6OX8^(S$^j*&dxZxb*Zsc-sJ2-{n0a`3j1a@xnwoaj)^vKnWcJGPFyRmV04;kq zd0jwOd7qC18)uIPi$Pu)U{dZ)GW2`tgNf;%lNpYBL(H;i0+nVDu(Z^ugAh$&!;&BY z@$An$IMC?jdv0trHKT|tIcjeES~HGNB#s_$7_ zO(eat(kba%_LhXN*>l!;%BK;`p z_+qtF7LJ%u=>KZh*{wBNEChp{&zrpOD2))7vr0afDGFmU{%a+|*@F&MCki4hvjl*Z zJxpHP=yY?6E)^#B;P8gU_%A29$@S*h{Jwq*fHT*z3YEmCeofEo$gc@C?ab9$DK`Vk z)_kr-To+bdZKGM}Ab?ol(XUbSS|@o?x0!1D&d$!UC!c0C1Zer`V^coY)lHU7Zf#v& zUT$S&WtATt9hHavJ+kZKD5J89Rq^=o1eP!Qo)xatVg zLNmqQjkcP)8$Cbfv73Uzfkay<%>9Iq3WdzZv4u%LIsDo4l!sEwZu$d~Nnn6c*t+?6 z;iGx&jcJ8RgR(3{TGSI~63Pw5Z~8E{ADv@ZPZ*SkBd-H3y$1Nw2$4AT(Ia(13_u@v zarZsO-l}b@ai-)GZSCQ2_Vx8?tdHd98$5oT?Em-FU2sK;8?vfmno8E4ehWEs`#DV~ z&Ko>Own7cTuV6F1exEi%0mB83+<(-=2lM2Ed344N=q4BJ`y6YM?-`c7=pPvwY4X{4 zNm{1ZKtn0FSH&L4Ic6`Qu%lKr&{-jus!M?$y*vzKqfscmgl|t*vB@Hab0(?PL@LW0 zYm*-qM;MkoVhFvty2vRn=hLN1jx>5-`}|j)dZNX=j-c|e?-#E4NdJ$e_{-HK%dqX< ziVzu~kBW*)XGW6cE=Lf8FmWYSR{UvIWjU`0d*_i-LDOK3OqJr(?KZ0=YY{I$HJBw6q8&7c4MN zbj!;bY`bSov_$}*=Han-M?^$K&rhYT<;D8?`W68dZ>y!D;W+Vbx6%X$HrlySPw^Tx z@%o;jQ*2C({F4D>XU)gL%F4>3j~@m6e}6AlOixRbh^W(`JX2Z@!+$IMw&fX&8;upg zI`MGbq7~kV2PnK#Pb6IG2*35nD&bks_cAT0u0F6eEY-cnJ+HJUJ*Kk_ISdF2y0i)p zzja1bRgC{;Jo@veBYeA};dG(JzY6C;&f|GnUmcqgH)2)XDT9-f#TaEAVwPY$+Vv|K;%agVik)YsSV z7w)+7R`>Muy!bs{`cx?Z+iu`*-!4@s9$(sX<%HUIczL*<>`ho?yOe_Az(Ie1zc~X9 zP1=@`dl2O0&_g^+-Tl+*R0Y>m8tpYgt!JCHe^ndgt82Qlv3891lUV4$_lh@E=YAqN)t@qml> z`tL6He>5OlDirezp`6ZYA1!Y4Z?87&85kH`4i68@ z6ciNXzh_;FK7aoFbT~tVi|D)_-R1%Kv#iE{QvSmM%pNskS@PjYol19FzG&avbiN%N z9K49aBg@-dU8P#7DP4u!rzfrem+#MntFIX9*WG1o_8y{W!aWU`7CSuxqmmwgN}AXJ zS3=T%Z=NGt3V9>P$LHE=CUEMzyBc_)H2yiG?qT0y_$+}3)eA077R(qa zEaY0Wi4E4#!X?mS8i096Mqu`@F>DWjG8V|FQzXXvkA5ar9h z!41O@kV%@S0Mme^eCX|Yui|1tLPGFY{(xy1@2e9-zBK#r%kg~9w1;rj+nZ~ZsHmv! ztLtknRnC+NXK~jdH3xA22z+KP*MLhQAo0#0K<`Z<$aP#!HcT4ljbW5M!y?1Z6!@fI~4fK>EXuBnY zUew0tn6!vK3iRti`@@}{-rl&K#kSzmN4!M4-xq>byy+9wbzEG2FJAoFK)SoQtjHx4 z4I(NFxU0Q6$w@k_Tl_-FnVGLN^%gVeUPipVtMBZ*`D`OESm^h+H2#aUv^0y&%~kiN z_FY|i0+0B0JT=qTrVwzu%7xVTtny_>s~Jc*k6bAz|h z^}7g`d@hZbAD=ycp7q_Q;isDE=){E4=}zrPyS}yc0{(6%uh5aEw|J&BbopyOGeAuk z)3p!g&g_#BBWWg^ORzpQW6{Wi$Vf8vtD{E7SlCM7hx@7?2L11!esw zxPtt2!Zrf(sLjWL4i4`~tG^IrmHcjOlwJbEzvK1m*NtG77s(xus&u<#`L(Fk?RG9L z*_&!W2o|u}NI)OtsPcEl^{`@H>>$h|MdoWXM(vC%Ft{?e$p>4Zq3GCFo~Nou{1St#=t}k`QWR$o7l% zzS&wt$IkZlHtqQQj#BCPf}WOECMh5Yj1poyB#T{*GSx*h-=43M?P?3R9gBD059OWz zF*j$?05XNnz#HL__VC*dAI z2Gl%ziA<_ALK0LY)F7Z(@iI&5N@k77X{Xb~8wdGg6@m}awcV`hGS zK6a8Nxq^rJMG1$w&L1dnak~41j+9B#O-avqUjO~%*0;08V5E+h*C)dBudJn8_kaT1 z(38n8F5@Lb#3Urf&s8~N+P1e)4}3vMDBJJ2y(xWlN6#cOF+N)*j+Df##c%gXuI{vn zrDbqSYisM#(b_eHT2v23|S2kPv_4Df3NK^SabxfWz;}52pKA9UXZ0iNc0+ zWK?VdR$`h~R#tMKJJkq0<>TX<>u~H(T>#f^Uf@ZHJ{}Mj)?OhOW>b0ljDjnYPQWZV z{q^hPXyroB-!<%D6xh#wb{UzNp8imn3s_lUD5+qz8kz(#=?`lKwAVH^Y&G@t*o0{l zWF_psPfCMzPNjVC=@o8B9hqHN-v`sGJUNhQ$wEUzb1ecWv1nLXD{~Y=gK8cYH=CH4 zlt{AOQJ=;%e_${6vHS+IjAaswtVwEaZm30>(etkEZoG(u=4W6$UISzkk)WQGdo=QeQ9Gz0w_*u)ok^D((HNZv|Axf$ckc zb9GPMy}Y~x&8RS`>cbT1U&I^=jagZYLwgG?;kufd&d*-FVAj$%LN;p6B0H`nYpbiP zaq(TlL1$E#p*BhZo#K1;aGhc3fDh}*P!ox3rmo6Fe84rUsSlq+n@2t55Mm9EKerw;- z;tH;v1WaUr(TByNn+yI+*Ltz`&2X6q;2}YNQz2uOJFnF(U1i9^oR#5MaAfWy~1z>4Q~31;&m64AZfMQec#9U-r$wzajr0Hx3A4mbB; za=+usu*sA;J#lP0k9K;i;p4}iWaldKxIo4~(A?`w;X?TO%M%h2k+of){!m1tJM7m7 zGe7CcpBTBixw(l->DYXjoH8{wwr=uXdpHJCypU_1#Y@b4LHqtuo7MoYZ$2aPXN6)X z<&~8RH*-&`LgywXCZJP>qlYmy=BX=)1nhIhz;v|&&{K}VYt_*KMUKO;VvIV8j`z5C|+?=%h$&Mb*CSeSp9ot@3Dt*If5=-?L0 z!;hQ;1oBjLYw!flUbs~VSiBo^9vm8~n5jjK#9KCau#l0ExQj3*>VSpm;5POr-dFv0 z;*50_6&2;6HZg&Y-*a)Wxuwif#5a=R)#5Y$Ck z4DxWZi;8>y?sgxP;^nZp%A3bM8&x7R?Q2<}DH;5X#33@lKbdu{yZl;i{9($f8AV`x zVbX;M9NOMqPH$)=u`U>5gDpfb^LL2x@gG0R5_jR%8PByKsQdKkaJ?&r=*{%hl(+Wa ziUKaP0FXf+E5eYdezis)@Ibo%d|Q)ZqRVJ82KG*g}uTFd#D1qU%a2&bZ9-ga>Li6Yf8TCfmGF$`SQ2=NVL@Oy-NG?3^l6 z%OOs`whg;jO9$m-Eh8f%;FH;)AlC@1e9-YYTiE#uA9-vLX2g+JFJD34erM*B-YE(- zY&@$R5fR}9ZfSvmfoU_Qjqmzx98_>dnEqfzV4G}X&zTE67dL=yQ2(TmeD0Y;9rF%? z*1t>rw(jZl@S{hMLawJOEdPS8eok`Q(JJKp^Gm!w7!>*cie;l1<*^Nf;O~>mbQzy@ z0as^dXB>No_uod079*M-iff4tc%CQPHQHu>PA74BnuLG+uS}w$qie{-x_2Ig!wHZJ z+qTQe3kvS~`rACK5u0i8-+yCnZr*|R-J}(6T-INC6&upp&Nhh6E<~rdNec9la_lK9 zOG1V%3bR*?Ynq!aK)TlF>ZANfNJ?q~s_8{;QBjdhThmpDzY8uOy!um_q-2DTbWajXHz(fa7HPx+vO5b8^gKzs;a6lYR!KuyeKItnFH%%mUz&q z@rj7Gm#RP}pjOkL7x$_#v9vWX@b&}8BS5QSEbRW-8y8;B8}mRH0OD+k-S_DeLlMXf zmpZwjUbgTnB&ehVJ0>$&cA}Z6y1KfJksO&?uywPGGrDq8d!ozD&x9$Iip3|U(NC_? ziS8;Y>VICOO0?)Laqr%}>y4r8h7u_onbnsCcb^}goFr;JdNfEc<6X3Oez#~ zG<%iWFsuR;(#xwlz|+*^Ff7b8DXsfKCm!1%2>}7aswZ3?&&bTo?8qTW-bvbT$Be=( z*hOF2vwFvWYj=g2f|(oZERI__`E;zZ^E*xJ`Okzua8dK52Z5KAkx@}>B&4M6srmWg zc+pFWc06%HvLXi(&IG5CqkWJ9hc?ELr^e=rii&XCyy6M00uae*k+U^CBRj0>3;Wy- zEWinNGvRwb&&S&MGT8#8Y{do)8F_i_qs26#00(6}^xfOH9yzl9d%Ve5u*zxRCFW&1 zc@2@k*8wp2CO}PE^KOzW!7Kk!DiUz891nOhf4md9`baEaHh5%!{XFHNCDxAU? z6(A$!XJklo+`X$g%W_sY=4=F(>Mg|vWtxSL!G=tx6=zCcvBA9tUUZU~Kzf2ICr?Vs7!ylO-i=Lww{r>v*sZRvu7o%;wsy#`>F<;qQ1%`{0)YJy zGzVW9`Mt|W@*9bmc`rT(sL_Or|Q^Taz>&$X%2NR+MgeI*(dBaSw9tTrV8mPfZ;4_|Qb zuTZ{R`TGR0!zHF)KAW;c4uM^qz~&Fyi}ZpcdG_>ih~=zD zyw*NGe@?)zQ9g(zNHP#WBp^-sJrY2J@0WF@@R41j3k^@sWe9tA1bYKJfQKiRG6vwe z_=**pYpS{zKEBIc>omkzX2fS05*msJE~{O@ zOg_}vU61NR@e|u(V4OI*%pOlAc*rjF47M6|Ry0JkHC)jpNS|Ac zpiRlz%!nl%&ke%PbXEjmNl8cYRXJfM7h>>)3q@#KvhE>GE#av(FNZOUE# zMp)8WIx$l*KY9^PDW~p)Y#0*o_M&KODn9$NwF5M4u$kfyjb9F4m(yD@wM(|VQQ?uZo@-a#*f;{zPM!EkjK)RxQMae3eyV* z7%Cv9&1BmASfcRV!Ch#8J&C_I;mO;$|MOAT|NAWLhOJ9s>vC=s*#JI21hmw2RV$V4 GBL4%n%mMoV literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/DayClear.png b/widgets/yawn/icons/DayClear.png new file mode 100755 index 0000000000000000000000000000000000000000..d9e2745cee4f88db9a855ed58d9bc3f2c34ddb12 GIT binary patch literal 6147 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 literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/DayMostlyCloudy.png b/widgets/yawn/icons/DayMostlyCloudy.png new file mode 100755 index 0000000000000000000000000000000000000000..22b929c612e7d04a2408bc71625114908f255769 GIT binary patch literal 8016 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 literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/DayPartlyCloudy.png b/widgets/yawn/icons/DayPartlyCloudy.png new file mode 100755 index 0000000000000000000000000000000000000000..8fd0a5b04d686db4e7dea16981db46d5d1f94de2 GIT binary patch literal 7478 zcmZX3XH*kSp!NnsAP`zWK#*QV>4YjBq<2I>Akw50dJPzQQ)w?Ep-XQfQbjt_6saQ8 zK}0%Iq_?|%-~D&zoXwsjv$Hd^&pc%|PG47zjD&#%001%#brnPKjQe*G!@$pOIqNUr z3F@t+VN47bEU{fI_#N({ZsrZvpZs?~lz1}(z#nh~PVO$= zw$>i@0vIoc%$@rTU?u8*l@xt_95G&ij=h(wle@8_y`jBb&pcZ&__x;oZ^PHi)*f*5 z@$rxr6mZq3S|1KVj)# z_vUrneK2A_U-UV$yCCfZ-Tl65m{`^t_)QjkuudG9sN_z$D-i!FmIB+w5SO;=J~{Hh#BoXvYl!P)jB8UZGaG?%i zbsXfSA_2k!fqa6qO#*J*j)2lH(sOnIL`++VlXyl6cl~**Og#QGbc30KwDigb{#Vs8 ztfN~qGISIgKq;rHKHs%@4a>xZDdqA2dY#Jz9Psx%aXuKm!1c+sS{)o?XTj=;0|2lY zqax<|R&pq`QYpm8J-Zsh%O)V?yKs}9(jXPL=+6v}e zlHU}dNO-tDM>=D1NrFxcg)(S0_}<3;x&SbQEGx0XbNo2tmU+Jp z53|4lL$wqsWT-&TkW@Qnp-r}Pk0}Tvz69+|l?X|Zi^EZOC}Wtb*J(Ul_%zlWQy@68 zyLVlbJw5lZK$1)fLTl~VYfC0jQBiTa{9%QklEj@6hdfSJC&ZXc-k-Iyd*SgZB3E09{=83H39&>G|f8KsrT2f2JE`?6DY+w z&6tMkq+ZS+QSkPmXqHYxNFWmcv^N#H`L>}}?T**4Z(9Zh52Cb+#zw_-`ktLE#XN>6 zKmbiZpKaCgC-%694&73&&&wUB@+Nj`YfHsrg4HpV4Km3cUQMC6m34&TAIS^>+K!lS z-Z$^4?ASXphgm8a12~)UVjXWlVNeM1si#NQ$k1>f=0hq8ZH`sY{LG>DvLy+RKO^ZD z>JUQQKi{go)!!;h6_$u#))+~r6e4({tu`SyKVQ(r^WBT{&bvZwJw5bik|b+-bqx(O z&#fOdlQbl%ygqOS9z|lHl$`l~lh^OTjOv1GCJFahk+ttgNA|1|=A_g8twFwbJSO;FaA_DA zjP6g>I#kne9?%O|wVc?Sn0)6M;m02JzeH35PeRVO8&lEPy`F{G9-GrrgMz0A78w8A zr`@LiEM$ zo;^(em4aL!@q+1seZPYkLr*K0X}+}(J>zBWM^l)8bu><(9Grjt09HPxD4g+`7r_|M?mgeR?e?CTQW;H#Kz`l)0HO9 zx;wf^DZPdm*B+rJ^1Q~5EhSH4Q4rGNbfEFul1>Ya#a={SX#y`Eh*CArcW3X8zPCX^ zHta}9;MfKzQoF_d#eE#&5a%-Oi#Ka@n-S-cl?`b_V~{H9MPrm7EJ7PAE4LsX9Es}o zQC)661{hP)%RRzfvSU+Z6Lp)YPPQ~Ebn3mmV1fAQ)oUvdLg_ISEOOB15F$sL5Ta6Q zIO=Yy_CPB^E=s}3h+1Pe%cG*Sl-CK1ZD}bgBILp)7&*)|xOt1aP1hN4rss~#KgJtA?ac$LG)@?gn|o@OQxt!tx$eA)X?_kjg7p{IR4eESLMyk z%`!|(On#{YoG@S|mWrd-Neu7lTyM@XTk)4n2w_`YUEPjd9m>`MS75rEc&1{Jp;>o# zcSc=Z9hIl2r>ztIsfeiPb!|~m55gjWZAXH*$)F!ikjE_i&5Yx6Mete1yU@$CY87^a zQrzkG@e}%9Lko+ndiyW0zKpmD*C{j((ARSS3Qsf^ji@`uAu8SVShl7LY=@d9=ODQiekN1^kns$2dg_I}k<9j-U z6%~%BB|)|i-jRV#PEYs$>|Bozw>;_8HK~}$%FVsLxjPw}1#Kl@!vl??{?0BgRbY{a zJq9{;rL%W-CMq83;Ec&V$k@5K0OBm#U3DO5`p=8W;adaav$I(F9|XjHW6t%*5J>}_ zllw$S_=pGvF?{xnpylt`9-*Ezx}mmqyk}B=WMqDR9x{s`enla38p*HhLqoZ13PEQn zV(aI}Kaqo@l=jS{X657KgPg1~y^r&S<;T&BvD370;dnmE4=m{2z}cPsU9YjWw(cg9 zhOl#Rq>3@pi|WTMxYcvN%^aDvroc_+W+9Q+||jl#5ZS@M6nB?#EI14 z*1^+&kLW_yBg&0vcxm}|cT$p-k`)1~E(vt27y@*BhsOn;*R&KdbTpZjjDC8wr}3JVGjFBiUm5c5e% z1#VoN9xM;#%0DZsub)8Jx#3bF07ryAbkP?^)e>5$&H|S-zD(iLLedFXocsdm^}Ujk zQVQX~oHC+f!nw4fLgw^v68)^fVL0b5@B|9_*_gD{mPmjg7#_lgOV|+P zGnTfxN2^AhoF7J<&|`=ZW2k08M1PKtkN@ev5OOT;;Xt<}ngHd%p{W!>_tj$c@Zn+H zockX{Lw=Dw555@1#>RFF(cLlM8oa4)za5h`+chHxphXo}Wc(_x_E)~BmFQ%?D%IzG z0OKp55Cv!AEsM0z+Jd^nhiXoojwZVQ&>=jXHY@T`8t z;~5Il?FA)U*nowAZ!0pHUweQ3{vB#3l2O+wFx!?h_|)6Q-Q8VLSvlgC#l(GdAgM0& zS$eFe8P_H_jNVipJzBz#xbq-Taldtf0?CNW(+QL#g0>-X!`cJZJ8dE7d|Q4WWq(A? zK1$_~ETj>XsMHQ7yz(Ik6rG!$b#-@ht0E;OW!&kzWHEQFpEj?U*m(QO6<{`|kPiH-aSC@Tj$J3Hi59Z&oH_)R#|;+K1Up8tWsxCy9q zy1Se^r+isS_Ff%&(f8$rehwt2y#PpO?afz?;rl(5eSYwS&I_&Q^1X6E@iQgAmf;i( z(e^rgF91j{n*U@|<2w1)auaO7mr!J!;)XHb!`XM%-5Wz$QbuGK74b^~);vKn%(zLq zMRjD6;T>?y3y&FIJPl)&Vg%H+wX@`GKE+OtjTwGBS2KTz05}wd;JA-b>+9nsYQI)j z+gWbjL`hPNNW>zM$ftT)l6##4sXP@OC>V~0o&X4m0e*IMbwz!7#XnP_&pQSk811-m zlaWzo6_j5lH!+6c`DWh=vJ<*=ANJQ!j}%rxL5!EC=4XZ))7v@*#<8qY40%Zdb_K=S z86xrm0y~-DB%mTz$QjNwv-hE2NbLj1eVu*AKI=!k30qn#6>fB{cjA6<-w0_ zKP_M1!=>=>aJ|iq4f8x1W=czE+HFcCN)bZ^bokP%lfcy;T^T-5Q=^yy5iuPZ8Hp3v zxJN@DU1L^dQZV7XT{p9Bf-klg)A`b4Q$qv2ogjfiJ-pgWe0GrsDj?AsZ3~sfKIoM-iwqC1F3%T8DJcG==Gz3dUiD>4U|ykH0`{iksClmJ zMKUTos_bcW#@SyyC)Vvc+gEz=aef_CnvuLRXm z3uFydTL`2Jn7!xZ7Zvq3Q&EW&3}O0xFf9LUGgVLSPK-c)L0r}4n$?Yy+YlTp62RS; z9n7ZH53^k^R*oUxHsMPfRkHiR^21g9phzqI>NtWz?&Livi^Nu@v$t7w<3m=`9x;FE z?>8;e=e_UO_t@NApxUbSjBJr4JDaHEd#H~?3a;Vu9(E5VJ;Cl%I|iGJ3g0R2oHA1e zy{!Q+jUtzVt?lw*wv2yhz~=X=rylY{4@lFEAz6PeM%7p@7Z$FL8f(GX3$-46Ej-*5 z+}2~`1aX&1)VpF`fe$AxdTb(oS~ECZF=)Yjx>Z*N7(usCn$sB_9qoc?*?Z7g^|+BC z?Ea^&C|$2Eq5i`y8FL@$Y&HprW4(Xu`^}QsRXh`7L8ynnTz>VRlHje?QN~!=B$}S^ zVHa;UMRj#`EM?R)l!Syo=xAMt9v#M~6FTLSV&Qa0t)u>Rt_y9KweR1*U#QLZcv}0R z281kDS-HDW{_^kmqx$;#)sEm2y=qmWLowFKLP#v9x~}f4yEO5V(d(CsNxi+j6(2r) zAOsb6i~LE`;vFFGm)D1113bC6r96Lr5(7Qj1Mbu)5Rj=oHtRx}U)@kB)Fe5J+=Zo) zQ7Y9(qLSNwJF|iJL`4rYLDt%tu6N=HNIZo&sWYz3gclT!;@CMkIqm+;x2ka=HJGi9hko6n3 z%$V;EFK+-pD7#du1~%wFItKsQ{di}+4hGJIli!&bJ|-Q;0mJ?yx|7P-oS?G+vjQj# zClL6qtmI{W4ifmv>G`|`%zK|eI=qGi1ty#o7Z+*Rd_nw+P*fFQ)zr|4qnE=5l&W(gL6GI&4XY^- zl2d9rCr=vIJ<)`+9g}+W!nwJ)?tt7?*WAp2d#6YP^cNYH*>p#f4eNmYH`6l~CU3Pu z8yOq_jRDi)HDIw+8~7g$E$!P$N3q1y^LsR)Lp+%e{^RzxyxdtO$0b+PVQ56k`}ckP z>(`P-Wyah902=8(Yimsp(P(tD%jDa3=lW^#wRtz1ZJM7$ta6ND3n9>F{s=Z^U+HX} ziizp4FS@$ipxM40%n)t7NBd>lbGcWRT(&xG5VV={GtIu6J9s>vd+}&6JCwBEyvm}+ zrl%SVgmoIoIF*zd+dgh)`Ou5|z{s6Dcakx!hu^24KYyOJwzjs1jN?Rn$O5U;fQpJL z@&4W?YQ4zl=5-Lpv{{vs0qiR|E|DnO{Nd?}Oo;dE5H@ z@_6AIB`<&dtkT4Vr-@|YLrf<~lDRo4DIylsg_~+>`7ccgP8Rs_WzPmma%>wA>o<#K~zrmub&?&2(W(_(gm?iP=ZL z?O|#p^7n{X6#+mTEj6tbOLxySDFj^Z_tzRqe`YIP@Oov{{(0^!kBxA)B31+p$<$VIOEW zDe4*<3*KU9AyIyx=bRz!cz^)@V{lR7g@~&P8J@o0TsGwI z{Y&JHHsnrZyQ4(NmUJpI#tedWnoAz?^K6f8KE zBO5GN;uI9SAoz_UZ+u;|0pz!`*48;-w!^S3mIu}`A-#4WloSbOc?WjM=cc<1g70f< zslgo`HD)QVUn>zr6z@0J3qrlHa~5uRbRM18LW&pLjSHbf z7G#U!g^2XV#T@BZ){$2b^9ZT-wEzD5#w_WvXzzjY+YM{&b=qN)55u|**H7?Us0?KIB0kc@$m~88Q!4QoVurSXeG0ud9^})Ue{D^9doLr^z{PDI2CX! zz%q2@b6SuG88_Plnx*|C|2TT90Ag-c(YW5h{2XD!E;9BZV{`MMVOQ}5(xWlK)@*Q5 z{*Lg!g0KgPn%{wy)AOI*MG|ZBsU;a76aR*EGsYHxB@+GTORKQ*3pqy$AD(}$3m<%eed+>sAq1m6N>m7&9tjH2;3P8 zzmIcvjWhfJ@RCxDt&Y;R-n<^%<2eI;OVsJw)$?qYFPIgLC*rU$}jHjZpd`4g@l&>bo2h`WljRKTMz z^TcmT{={76sz8lpni%B{-k_ZTV4j>)gK-fb_JI)P+tW=dl1nSK(+fbkS-54q>XQIEgGRkD3x@TJwkyiA`J{&th zA}Eu*!`dWG4ujo;=o2p%L2*|cJ~aQ{gRO19?oj+I{D0n!^|3-=l29T72ax65ng9R* literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/Foggy.png b/widgets/yawn/icons/Foggy.png new file mode 100755 index 0000000000000000000000000000000000000000..009039f8dd2433627a9499003f6c86bfad4b0c80 GIT binary patch literal 7325 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
  • S236D+`KjrhMq5Ij+iT7#d>q&))}ssJ4g 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 SkrO>h^&xJMv@VQGJePR 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%0A%@Z-MgdAQ8>#OcqF{V6qfz^dJoC^ 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 Q|Gz*qRdrO}DA`2)AC2#6RsaA1 literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/LightSnowShowers.png b/widgets/yawn/icons/LightSnowShowers.png new file mode 100755 index 0000000000000000000000000000000000000000..d797ee948695d7ce46053fe7b54433b610b3097c GIT binary patch literal 8779 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 literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/MixedRainAndHail.png b/widgets/yawn/icons/MixedRainAndHail.png new file mode 100755 index 0000000000000000000000000000000000000000..758b01e48eaa6ad27d8b0d692e285a92e90a4ee1 GIT binary patch literal 9060 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 F{s-1-Kk5Jg literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/MixedRainAndSleet.png b/widgets/yawn/icons/MixedRainAndSleet.png new file mode 100755 index 0000000000000000000000000000000000000000..7f0d252565ba1e256fc4fb281eab2ba2fbd1be12 GIT binary patch literal 10978 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 IvXbTf?`dGNzKt4V`T=vcm9#$5vHe4?5 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 b@c`k>S|VAx$A*JPDIsNfb-5}T^U(hTcXN<$ literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/NightClear.png b/widgets/yawn/icons/NightClear.png new file mode 100755 index 0000000000000000000000000000000000000000..84ea1408ba782bc48e03bbbd79f862412d3cb48d GIT binary patch literal 5198 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 C7rvhW literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/NightMostlyCloudy.png b/widgets/yawn/icons/NightMostlyCloudy.png new file mode 100755 index 0000000000000000000000000000000000000000..d8b3673492f457ab354bf4276b2a2e49cc4c6dee GIT binary patch literal 7058 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 Yv4~UN31ejeKT-jzikb?Qa+V?g10eTDiU0rr literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/NightPartlyCloudy.png b/widgets/yawn/icons/NightPartlyCloudy.png new file mode 100755 index 0000000000000000000000000000000000000000..9e4404d7511aa84a563fbc2e4933ee032a1ce88e GIT binary patch literal 6583 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 literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/README.md b/widgets/yawn/icons/README.md new file mode 100644 index 0000000..e4dc111 --- /dev/null +++ b/widgets/yawn/icons/README.md @@ -0,0 +1,6 @@ +Yawn icons +========== + +These are [Plain Weather Icons](http://merlinthered.deviantart.com/art/plain-weather-icons-157162192), created by [MerlinTheRed](http://merlinthered.deviantart.com/). + + diff --git a/widgets/yawn/icons/Rain.png b/widgets/yawn/icons/Rain.png new file mode 100755 index 0000000000000000000000000000000000000000..d00552a5fd8d96d08d0e5915d51a7963d40cc7ae GIT binary patch literal 8052 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 bIC(mO&E@D(xc>(pLj#JkDl%WBOhW$$bRr|s literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/RainThunder.png b/widgets/yawn/icons/RainThunder.png new file mode 100755 index 0000000000000000000000000000000000000000..d30e120582fe1084bbfc6f33f67dfa4ef4e66539 GIT binary patch literal 9879 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 literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/Showers.png b/widgets/yawn/icons/Showers.png new file mode 100755 index 0000000000000000000000000000000000000000..3cc6665dc0e98c2be584079add634d9744b459a5 GIT binary patch literal 9694 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 O6i`>zR;p4k5B(n_WNM25 literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/SnowShowers.png b/widgets/yawn/icons/SnowShowers.png new file mode 100755 index 0000000000000000000000000000000000000000..30534a20d052bbc9c6353dd9eb950f3ea5956954 GIT binary patch literal 9961 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 literal 0 HcmV?d00001 diff --git a/widgets/yawn/icons/na.png b/widgets/yawn/icons/na.png new file mode 100755 index 0000000000000000000000000000000000000000..62a5350d878dccc626e9e7be17e728aab0737b87 GIT binary patch literal 11160 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 uAxI$vvXU%&SeT6Z$sT;G_Uh)zHFuz)Q)>Is(", "") + weather_data = weather_data:match("Current Conditions:.-Full") + weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ") + weather_data = weather_data:gsub("Forecast:.-\n", "") + weather_data = weather_data:gsub("\nFull", "") + weather_data = weather_data:gsub("[\n]$", "") + weather_data = weather_data:gsub(" [-] " , ": ") + weather_data = weather_data:gsub("[.]", ",") + weather_data = weather_data:gsub("High: ", "") + weather_data = weather_data:gsub(" Low: ", " - ") + + -- Getting info for text widget + local now = weather_data:sub(weather_data:find("Now:")+5, + weather_data:find("\n")-1) + local forecast = now:sub(1, now:find(",")-1) + local units = now:sub(now:find(",")+2, -2) + + -- Day/Night icon change + local hour = tonumber(os.date("%H")) + sky = icon_path + + if forecast == "Clear" or + forecast == "Fair" or + forecast == "Partly Cloudy" or + forecast == "Mostly Cloudy" + then + if hour >= 6 and hour <= 18 + then + sky = sky .. "Day" + else + sky = sky .. "Night" + end + end + + sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png" + + -- In case there's no defined icon for current forecast + f = io.popen(sky) + if f == nil then + sky = icon_path .. "na.png" + else + io.close(f) + end + + -- Localization + local f = io.open(localizations_path .. language, "r") + if language:find("en_") == nil and f ~= nil + then + io.close(f) + for line in io.lines(localizations_path .. language) + do + word = string.sub(line, 1, line:find("|")-1) + translation = string.sub(line, line:find("|")+1) + weather_data = string.gsub(weather_data, word, translation) + end + end + + -- Finally setting infos + forecast = weather_data:match(": %S+"):gsub(": ", ""):gsub(",", "") + yawn.forecast = markup(yawn.forecast_color, markup.font(beautiful.font, forecast)) + yawn.units = markup(yawn.units_color, markup.font(beautiful.font, units)) + yawn.icon:set_image(sky) + + if toshow == "forecast" then + return yawn.forecast + elseif toshow == "units" then + return yawn.units + else -- "both" + return yawn.forecast .. spr + .. yawn.units .. footer + end +end + +function yawn.hide() + if notification ~= nil then + naughty.destroy(notification) + notification = nil + end +end + +function yawn.show(t_out) + if yawn.widget._layout.text == "?" + then + if update_timer ~= nil + then + update_timer:emit_signal("timeout") + else + fetch_weather(settings) + end + end + + yawn.hide() + + notification = naughty.notify({ + text = weather_data, + icon = sky, + timeout = t_out, + fg = yawn.notification_color + }) +end + +function yawn.register(id, args) + local args = args or {} + + settings = { args.toshow, args.spr, args.footer } + + yawn.units_color = args.units_color or + beautiful.fg_normal or "#FFFFFF" + yawn.forecast_color = args.forecast_color or + yawn.units_color + yawn.notification_color = args.notification_color or + beautiful.fg_focus or "#FFFFFF" + + if args.u == "f" then units_set = '?u=f&w=' end + + city_id = id + + update_timer = timer({ timeout = 600 }) -- 10 mins + update_timer:connect_signal("timeout", function() + yawn.widget:set_markup(fetch_weather(settings)) + end) + update_timer:start() + update_timer:emit_signal("timeout") + + yawn.icon:connect_signal("mouse::enter", function() + yawn.show(0) + end) + yawn.icon:connect_signal("mouse::leave", function() + yawn.hide() + end) +end + +function yawn.attach(widget, id, args) + yawn.register(id, args) + + widget:connect_signal("mouse::enter", function() + yawn.show(0) + end) + + widget:connect_signal("mouse::leave", function() + yawn.hide() + end) +end + +-- }}} + +return setmetatable(yawn, { __call = function(_, ...) return yawn.register(...) end }) diff --git a/widgets/yawn/localizations/it_IT b/widgets/yawn/localizations/it_IT new file mode 100644 index 0000000..0b74b60 --- /dev/null +++ b/widgets/yawn/localizations/it_IT @@ -0,0 +1,57 @@ +Now:|Ora: +Sun:|Dom: +Mon:|Lun: +Tue:|Mar: +Wed:|Mer: +Thu:|Gio: +Fri:|Ven: +Sat:|Sab: +Mostly Sunny|Abbastanza Soleggiato +Sunny|Soleggiato +Sun|Soleggiato +Rain/Thunder|Temporali +Isolated Thunderstorms|Temporali Isolati +Scattered Thunderstorms|Temporali Sparsi +Thundershowers|Rovesci Temporaleschi +Thunderstorms|Temporali +Thunder|Temporale +AM|In Mattinata +PM|Nel Pomeriggio +Early|In Mattinata +Late|In Serata +Few|Sporadiche +Severe|Forti +Clear|Sereno +Fair|Sereno +Partly|Parzialmente +Mostly|Molto +Cloudy|Nuvoloso +Clouds|Nuvoloso +Scattered Showers|Temporali Sparsi +Light Snow Showers|Nevicate Leggere +Snow Showers|Nevicate +aeavy Snow|Forti Nevicate +Scattered Snow Showers|Nevicate Sparse +Mixed Rain And Snow|Pioggia E Neve +Mixed Rain And Sleet|Pioggia E Nevischio +Mixed Snow And Sleet|Neve E Nevischio +Mixed Rain And Hail|Pioggia E Grandine +Snow Flurries|Folate Di Neve +Blowing Snow|Neve Battente +Blowing Rain|Pioggia Battente +Heavy Rain|Forti Piogge +Freezing Rain|Pioggia Congelantesi +Showers|Piogge +Light Rain|Pioggia Leggera +Heavy|Forti +Rain|Piovoso +Windy|Ventoso +Wind|Ventoso +Snow|Neve +Sleet|Nevischio +Drizzle|Pioggerella +Freezing Drizzle|Pioggerella Congelantesi +Hail|Grandine +Foggy|Nebbia +Haze|Nebbia +Light|Leggere diff --git a/widgets/yawn/localizations/localization_template b/widgets/yawn/localizations/localization_template new file mode 100644 index 0000000..98d527d --- /dev/null +++ b/widgets/yawn/localizations/localization_template @@ -0,0 +1,57 @@ +Now:| +Sun:| +Mon:| +Tue:| +Wed:| +Thu:| +Fri:| +Sat:| +Mostly Sunny| +Sunny| +Sun| +Rain/Thunder| +Isolated Thunderstorms| +Scattered Thunderstorms| +Thundershowers| +Thunderstorms| +Thunder| +AM| +PM| +Early| +Late| +Few| +Severe| +Clear| +Fair| +Partly| +Mostly| +Cloudy| +Clouds| +Scattered Showers| +Light Snow Showers| +Snow Showers| +Heavy Snow| +Scattered Snow Showers| +Mixed Rain And Snow| +Mixed Rain And Sleet| +Mixed Snow And Sleet| +Mixed Rain And Hail| +Snow Flurries| +Blowing Snow| +Blowing Rain| +Heavy Rain| +Freezing Rain| +Showers| +Light Rain| +Heavy| +Rain| +Windy| +Wind| +Snow| +Sleet| +Drizzle| +Freezing Drizzle| +Hail| +Foggy| +Haze| +Light| From 7ec0f4f1534e576130b5283c753d30b1531bf92d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:10:58 -0700 Subject: [PATCH 004/572] Created To start (markdown) --- To-start.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 To-start.md diff --git a/To-start.md b/To-start.md new file mode 100644 index 0000000..9135be2 --- /dev/null +++ b/To-start.md @@ -0,0 +1,26 @@ +All you have to do is to include the module: + + local lain = require("lain") + +Some widgets require a terminal, lain default is `xterm`, but can be changed: + + lain.widgets.terminal = "urxvtc" + +or + + lain.widgets.terminal = terminal + +providing you have something like this: + + terminal = "urxvtc" + +in your `rc.lua`. + +`terminal` may also be a lua function that accepts one parameter. +Something like this: + + function footerm(cmd) + -- elaborate cmd + end + + lain.widgets.terminal = footerm \ No newline at end of file From f026d1011a3b28c1f649b32afe85920175355b38 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:11:44 -0700 Subject: [PATCH 005/572] Created mem (markdown) --- mem.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 mem.md diff --git a/mem.md b/mem.md new file mode 100644 index 0000000..58ccf72 --- /dev/null +++ b/mem.md @@ -0,0 +1,19 @@ +Show used memory and total memory in MiB. + + mymem = lain.widgets.mem() + + +The function takes a table as an optional argument. That table may +contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`refresh_timeout` | Refresh timeout seconds | int | 10 +`show_swap` | Show amount of used swap space? | boolean | false +`show_total` | Show amout of total memory? | boolean | false +`header` | Text to show before value | string | " Vol " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to show after value | string | "MB" + +**Note**: `footer` color is `color`. \ No newline at end of file From 095e7e28bfef98509b296ed3e0f0b34c69cf058c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:12:36 -0700 Subject: [PATCH 006/572] Created maildir (markdown) --- maildir.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 maildir.md diff --git a/maildir.md b/maildir.md new file mode 100644 index 0000000..df5f6fe --- /dev/null +++ b/maildir.md @@ -0,0 +1,37 @@ +Checks your maildirs. + +Maildirs are structured as follows: + + ~/Mail + . + |-- arch + | |-- cur + | |-- new + | `-- tmp + |-- gmail + | |-- cur + | |-- new + | `-- tmp + . + . + . + +therefore the widget checks whether there are files in the `new` directories. +If there's new mail, the textbox will say something like "mail: bugs(3), system(1)", otherwise it says +"no mail". + + mymaildir= lain.widgets.maildir("/path/to/my/maildir") + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`mailpath` | Path to your maildir | string | "~/Mail" +`ignore_boxes` | A list of boxes to ignore | table | empty table +`refresh_timeout` | Refresh timeout seconds | int | 60 +`header` | Text to show before value | string | " Mail " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color_newmail` | New mail value color | string | `beautiful.fg_focus` or "#FFFFFF" +`color_nomail` | No mail value color | string | `beautiful.fg_normal` or "#FFFFFF" +`app` | Mail program to spawn on click | string | "mutt"| boolean | false +`shadow` | Hide widget when there are no mails | boolean | false \ No newline at end of file From cce1bce3306b774f3a8a35128f76c93f26960c29 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:16:55 -0700 Subject: [PATCH 007/572] Created Layouts (markdown) --- Layouts.md | 271 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 Layouts.md diff --git a/Layouts.md b/Layouts.md new file mode 100644 index 0000000..b5aacc5 --- /dev/null +++ b/Layouts.md @@ -0,0 +1,271 @@ +Currently, there are **7** layouts. + + lain/layout + . + |-- cascade + |-- cascadetile + |-- centerwork + |-- termfair + |-- uselessfair + |-- uselesspiral + `-- uselesstile + +Just add your favourites to ``layouts`` table: + + layouts = + { + ... + lain.layout.termfair, + lain.layout.uselesstile, + ... + } + +Or set them on specific tags like this: + + awful.layout.set(lain.layout.uselessfair, tags[1][7]) + +How do layouts work? +========================= + +cascade +------- + +Cascade all windows of a tag. + +You can control the offsets by setting those two variables: + + lain.layout.cascade.cascade_offset_x = 64 + lain.layout.cascade.cascade_offset_y = 16 + +The following reserves space for 5 windows: + + lain.layout.cascade.nmaster = 5 + +That is, no window will get resized upon the creation of a new window, +unless there's more than 5 windows. + +cascadetile +----------- + +Similar to `awful.layout.suit.tile` layout, however, clients in the slave +column are cascaded instead of tiled. + +Left column size can be set, otherwise is controlled by `mwfact` of the +tag. Additional windows will be opened in another column on the right. +New windows are placed above old windows. + +Whether the slave column is placed on top of the master window or not is +controlled by the value of `ncol`. A value of 1 means "overlapping slave column" +and anything else means "don't overlap windows". + +Usage example: + + lain.layout.cascadetile.cascade_offset_x = 2 + lain.layout.cascadetile.cascade_offset_y = 32 + lain.layout.cascadetile.extra_padding = 5 + lain.layout.cascadetile.nmaster = 5 + lain.layout.ncol = 1 + +`extra_padding` reduces the size of the master window if "overlapping +slave column" is activated. This allows you to see if there are any +windows in your slave column. + +Setting `cascade_offset_x` to a very small value or even 0 is reccommended to avoid wasting space. + +centerwork +---------- + +You start with one window, centered horizontally: + + +--------------------------+ + | +----------+ | + | | | | + | | | | + | | | | + | | MAIN | | + | | | | + | | | | + | | | | + | | | | + | +----------+ | + +--------------------------+ + +This is your main working window. You do most of the work right here. +Sometimes, you may want to open up additional windows. They're put in +the following four slots: + + +--------------------------+ + | +---+ +----------+ +---+ | + | | | | | | | | + | | 0 | | | | 1 | | + | | | | | | | | + | +---+ | MAIN | +---+ | + | +---+ | | +---+ | + | | | | | | | | + | | 2 | | | | 3 | | + | | | | | | | | + | +---+ +----------+ +---+ | + +--------------------------+ + +Yes, the number "four" is fixed. In total, you can only have five open +windows with this layout. Additional windows are not managed and set to +floating mode. **This is intentional**. + +You can set the order of the four auxiliary windows. This is the default +configuration: + + lain.layout.centerwork.top_left = 0 + lain.layout.centerwork.top_right = 1 + lain.layout.centerwork.bottom_left = 2 + lain.layout.centerwork.bottom_right = 3 + +This means: The bottom left slot will be occupied by the third window +(not counting the main window). Suppose you want your windows to appear +in this order: + + +--------------------------+ + | +---+ +----------+ +---+ | + | | | | | | | | + | | 3 | | | | 0 | | + | | | | | | | | + | +---+ | MAIN | +---+ | + | +---+ | | +---+ | + | | | | | | | | + | | 2 | | | | 1 | | + | | | | | | | | + | +---+ +----------+ +---+ | + +--------------------------+ + +This would require you to use these settings: + + lain.layout.centerwork.top_left = 3 + lain.layout.centerwork.top_right = 0 + lain.layout.centerwork.bottom_left = 2 + lain.layout.centerwork.bottom_right = 1 + +*Please note:* If you use Awesome's default configuration, navigation in +this layout may be very confusing. How do you get from the main window +to satellite ones depends on the order in which the windows are opened. +Thus, use of `awful.client.focus.bydirection()` is suggested. +Here's an example: + + globalkeys = awful.util.table.join( + ... + awful.key({ modkey }, "j", + function() + awful.client.focus.bydirection("down") + if client.focus then client.focus:raise() end + end), + awful.key({ modkey }, "k", + function() + awful.client.focus.bydirection("up") + if client.focus then client.focus:raise() end + end), + awful.key({ modkey }, "h", + function() + awful.client.focus.bydirection("left") + if client.focus then client.focus:raise() end + end), + awful.key({ modkey }, "l", + function() + awful.client.focus.bydirection("right") + if client.focus then client.focus:raise() end + end), + ... + ) + +termfair +-------- + +I do a lot of work on terminals. The common tiling algorithms usually +maximize windows, so you'll end up with a terminal that has about 200 +columns or more. That's way too much. Have you ever read a manpage in a +terminal of this size? + +This layout restricts the size of each window. Each window will have the +same width but is variable in height. Furthermore, windows are +left-aligned. The basic workflow is as follows (the number above the +screen is the number of open windows, the number in a cell is the fixed +number of a client): + + (1) (2) (3) + +---+---+---+ +---+---+---+ +---+---+---+ + | | | | | | | | | | | | + | 1 | | | -> | 2 | 1 | | -> | 3 | 2 | 1 | -> + | | | | | | | | | | | | + +---+---+---+ +---+---+---+ +---+---+---+ + + (4) (5) (6) + +---+---+---+ +---+---+---+ +---+---+---+ + | 4 | | | | 5 | 4 | | | 6 | 5 | 4 | + +---+---+---+ -> +---+---+---+ -> +---+---+---+ + | 3 | 2 | 1 | | 3 | 2 | 1 | | 3 | 2 | 1 | + +---+---+---+ +---+---+---+ +---+---+---+ + +The first client will be located in the left column. When opening +another window, this new window will be placed in the left column while +moving the first window into the middle column. Once a row is full, +another row above it will be created. + +Default number of columns and rows are respectively taken from `nmaster` +and `ncol` values in `awful.tag`, but you can set your own. + +For example, this sets `termfair` to 3 columns and at least 1 row: + + lain.layout.termfair.nmaster = 3 + lain.layout.termfair.ncol = 1 + +uselessfair, uselesspiral & uselesstile +--------------------------------------- +These are duplicates of the stock `fair`, `spiral` and `tile` layouts. +However, "useless gaps" (see below) have been added. + +Useless gaps +============ + +Useless gaps are gaps between windows. They are "useless" because they +serve no special purpose despite increasing overview. I find it easier +to recognize window boundaries if windows are set apart a little bit. + +The `uselessfair` layout, for example, looks like this: + + +================+ + # # + # +---+ +---+ # + # | 1 | | | # + # +---+ | | # + # | 3 | # + # +---+ | | # + # | 2 | | | # + # +---+ +---+ # + # # + +================+ + +All of lain layouts provide useless gaps. To set the width of the gaps, +you have to add an item called `useless_gap_width` in your `theme.lua`. +If it doesn't exist, the width will default to 0. +Example: + + ... + theme.useless_gap_width = "5" + ... + +What about layout icons? +======================== + +They are located in ``lain/icons/layout``. + +To use them, add lines to your ``theme.lua`` like this: + + ... + theme.lain_icons = os.getenv("HOME") .. "/.config/awesome/lain/icons/layout/default/" + theme.layout_termfair = theme.lain_icons .. "termfairw.png" + theme.layout_cascade = theme.lain_icons .. "cascadew.png" + theme.layout_cascadetile = theme.lain_icons .. "cascadetilew.png" + theme.layout_centerwork = theme.lain_icons .. "centerworkw.png" + ... + +Credits goes to [Nicolas Estibals](https://github.com/nestibal) for creating +layout icons for default theme. + +You can use them as a template for your custom versions. \ No newline at end of file From b7cdfbeaacdf9d767a963576b05ef9386e50045a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:20:25 -0700 Subject: [PATCH 008/572] Updated Layouts (markdown) --- Layouts.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Layouts.md b/Layouts.md index b5aacc5..7f50efe 100644 --- a/Layouts.md +++ b/Layouts.md @@ -63,8 +63,8 @@ Usage example: lain.layout.cascadetile.cascade_offset_x = 2 lain.layout.cascadetile.cascade_offset_y = 32 lain.layout.cascadetile.extra_padding = 5 - lain.layout.cascadetile.nmaster = 5 - lain.layout.ncol = 1 + lain.layout.cascadetile.nmaster = 5 + lain.layout.ncol = 1 `extra_padding` reduces the size of the master window if "overlapping slave column" is activated. This allows you to see if there are any @@ -150,7 +150,7 @@ Thus, use of `awful.client.focus.bydirection()` is suggested. Here's an example: globalkeys = awful.util.table.join( - ... + ... awful.key({ modkey }, "j", function() awful.client.focus.bydirection("down") @@ -218,6 +218,7 @@ For example, this sets `termfair` to 3 columns and at least 1 row: uselessfair, uselesspiral & uselesstile --------------------------------------- These are duplicates of the stock `fair`, `spiral` and `tile` layouts. + However, "useless gaps" (see below) have been added. Useless gaps @@ -246,9 +247,7 @@ you have to add an item called `useless_gap_width` in your `theme.lua`. If it doesn't exist, the width will default to 0. Example: - ... theme.useless_gap_width = "5" - ... What about layout icons? ======================== @@ -257,13 +256,11 @@ They are located in ``lain/icons/layout``. To use them, add lines to your ``theme.lua`` like this: - ... theme.lain_icons = os.getenv("HOME") .. "/.config/awesome/lain/icons/layout/default/" theme.layout_termfair = theme.lain_icons .. "termfairw.png" theme.layout_cascade = theme.lain_icons .. "cascadew.png" theme.layout_cascadetile = theme.lain_icons .. "cascadetilew.png" theme.layout_centerwork = theme.lain_icons .. "centerworkw.png" - ... Credits goes to [Nicolas Estibals](https://github.com/nestibal) for creating layout icons for default theme. From 6c93e00e676792632a81435a96e7ddbaebae859a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:24:05 -0700 Subject: [PATCH 009/572] Created imap (markdown) --- imap.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 imap.md diff --git a/imap.md b/imap.md new file mode 100644 index 0000000..f12a1e7 --- /dev/null +++ b/imap.md @@ -0,0 +1,64 @@ +Check new mails over IMAP protocol. + +Dependencies: + +- Python3 + +New mails are notified through a notification like this: + + +---------------------------------------------------+ + | +---+ | + | |\ /| donald@disney.org has 3 new messages | + | +---+ | + | Latest From: Mickey Mouse | + | Subject: Re: pay raise | + | | + | Not after what you did yesterday. | + | Daisy told me everything [...] | + | | + +---------------------------------------------------+ + +Text will be cut if the mail is too long. + + myimapcheck = lain.widgets.imap(args) + +The function takes a table as argument. Required table parameters are: + +Variable | Type +--- | --- +`server` | string +`mail` | string +`password` | string + +while the optional are: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`port` | IMAP port | int | 993 +`refresh_timeout` | Refresh timeout seconds | int | 60 +`header` | Text to show before value | string | " Mail " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color_newmail` | New mail value color | string | `beautiful.fg_focus` or "#FFFFFF" +`color_nomail` | No mail value color | string | `beautiful.fg_normal` or "#FFFFFF" +`mail_encoding` | Mail character encoding | string | autodetected +`maxlen` | Maximum chars to display in notification | int | 200 +`app` | Mail program to spawn on click | string | "mutt" +`shadow` | Hide widget when there are no mails | boolean | false +`is_plain` | Define whether `password` is a plain password (true) or a function that retrieves it (false) | boolean | false + +Let's focus better on `is_plain`. + +You can just set your password like this: + + args.is_plain = false + args.password = "mypassword" + +and you'll have the same security provided by `~/.netrc` + +**Or** you can use a keyring, like [python keyring](https://pypi.python.org/pypi/keyring): + + args.password = "keyring get password" + +When `is_plain == false`, it *executes* `password` before using it, so you can also use whatever password fetching solution you want. + +You can also define your custom icon for the naughty notification. Just set `lain_mail_notify` into `theme.lua`. \ No newline at end of file From 4a72f6f3942a0838ff8a13fffcd4c3a08736e753 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:25:06 -0700 Subject: [PATCH 010/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index f12a1e7..3c049dd 100644 --- a/imap.md +++ b/imap.md @@ -53,7 +53,7 @@ You can just set your password like this: args.is_plain = false args.password = "mypassword" -and you'll have the same security provided by `~/.netrc` +and you'll have the same security provided by `~/.netrc`. **Or** you can use a keyring, like [python keyring](https://pypi.python.org/pypi/keyring): From 11d7af8cf33203a30f49a447a466079b022a8f43 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:26:19 -0700 Subject: [PATCH 011/572] Updated imap (markdown) --- imap.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imap.md b/imap.md index 3c049dd..5f8ce30 100644 --- a/imap.md +++ b/imap.md @@ -61,4 +61,6 @@ and you'll have the same security provided by `~/.netrc`. When `is_plain == false`, it *executes* `password` before using it, so you can also use whatever password fetching solution you want. -You can also define your custom icon for the naughty notification. Just set `lain_mail_notify` into `theme.lua`. \ No newline at end of file +You can also define your custom icon for the naughty notification. Just set `lain_mail_notify` into `theme.lua`: + + theme.lain_mail_notify = "/path/to/my/icon" \ No newline at end of file From c1d7ccacb1671088bfa9089b76916e1a9792bed6 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:27:10 -0700 Subject: [PATCH 012/572] Created fs (markdown) --- fs.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 fs.md diff --git a/fs.md b/fs.md new file mode 100644 index 0000000..98016fb --- /dev/null +++ b/fs.md @@ -0,0 +1,32 @@ +Shows disk space usage for a set partition. + +Displays a notification when the partition is full or has low space. + + mypartition = lain.widgets.fs() + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`partition` | Partition to monitor | string | "/" +`refresh_timeout` | Refresh timeout seconds | int | 600 +`header` | Text to show before value | string | " Hdd " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to show after value | string | "%" +`shadow` | Hide the widget if `partition` < 90 | boolean | false + +**Note**: `footer` color is `color`. + +`lain.widgets.fs` outputs the following table: + +Variable | Type +--- | --- +`widget` | `wibox.widget.textbox` +`show` | function + +You can display a notification of current disk space usage with the following key binding: + + awful.key({ altkey }, "h", function () mypartition.show(7) end), + +where ``altkey = "Mod1"`` and ``show`` argument is an optional integer, meaning timeout seconds. \ No newline at end of file From d866043cd7ef8b9861573fba00f9e95b186f261d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:28:21 -0700 Subject: [PATCH 013/572] Created cpu (markdown) --- cpu.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 cpu.md diff --git a/cpu.md b/cpu.md new file mode 100644 index 0000000..bdcc128 --- /dev/null +++ b/cpu.md @@ -0,0 +1,15 @@ +Shows the average CPU usage percent for a given amount of time. + + mycpuusage = lain.widgets.cpu() + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`refresh_timeout` | Refresh timeout seconds | int | 10 +`header` | Text to show before value | string | " Vol " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to add after value | string | "%" + +**Note**: `footer` color is `color`. \ No newline at end of file From 022552ba3389c8b617c216e0fa2ded8571353555 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:28:39 -0700 Subject: [PATCH 014/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index bdcc128..ce59a15 100644 --- a/cpu.md +++ b/cpu.md @@ -7,7 +7,7 @@ The function takes a table as optional argument, which can contain: Variable | Meaning | Type | Default --- | --- | --- | --- `refresh_timeout` | Refresh timeout seconds | int | 10 -`header` | Text to show before value | string | " Vol " +`header` | Text to show before value | string | " Cpu " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `footer` | Text to add after value | string | "%" From 82d4aa066309b80e870a3b0b8e346b888cae4004 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:30:54 -0700 Subject: [PATCH 015/572] Created calendar (markdown) --- calendar.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 calendar.md diff --git a/calendar.md b/calendar.md new file mode 100644 index 0000000..06e1b48 --- /dev/null +++ b/calendar.md @@ -0,0 +1,35 @@ +Attaches a calendar to a ``widget``. Example: + + lain.widgets.calendar:attach(mytextclock) + +- Left click: switch to previous month. +- Right click: switch to next month. + +Optionally you can call the function with background and foreground colors arguments, both or just one: + + lain.widgets.calendar:attach(mytextclock, "#FFFFFF", "#000000") + -- or + lain.widgets.calendar:attach(mytextclock, "#FFFFFF") + -- or + lain.widgets.calendar:attach(mytextclock, nil, "#000000") + +Notification will show an icon displaying current day, and formatted output +from ``cal`` with current day highlighted. + +Calendar icons are placed in [lain/icons/cal](https://github.com/copycat-killer/lain/tree/master/icons/cal), default set being ``white``. + +You can add your own set, and tell lain to use it like this: + + lain.widgets.calendar.icons_dir = lain.widgets.icons_dir .. "cal/myicons" + +also, you can set notification font size: + + lain.widgets.calendar.font_size = 14 + +default is 12. + +Finally, you can call the notification with a key binding like this: + + awful.key({ altkey }, "c", function () lain.widgets.calendar:show(7) end), + +where ``altkey = "Mod1"`` and ``show`` argument is an optional integer, meaning timeout seconds. \ No newline at end of file From bde0a1a4175c0f2fb4ee6e318949f0884c1636ef Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:33:28 -0700 Subject: [PATCH 016/572] Created borderbox (markdown) --- borderbox.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 borderbox.md diff --git a/borderbox.md b/borderbox.md new file mode 100644 index 0000000..cdeece2 --- /dev/null +++ b/borderbox.md @@ -0,0 +1,47 @@ +Creates a thin wibox at a position relative to another wibox. + +This allows to create "borders" for your wiboxes. + + lain.widget.borderbox(relbox, s, args) + +`relbox` and `s` (an integer being screen number) are required arguments, `args` is an optional table +which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`position` | Position of the additional box | string | "above" +`color` | Color of the additional box | string | `#FFFFFF` +`size` | Size in pixels of the additional box | int | 1 + +Possible values for `.position`: `above`, `below`, `left` and `right`. + +### Example usage + +Think of this as a wibox: + + [======================] + +If `args.position = "above"`, then you'll get an additional wibox below +the existing one: + + ________________________ + [======================] + +It'll match position and size of the existing wibox. + +If your main wiboxes are stored in a table called `mywibox` (one wibox +for each screen) and are located at the bottom of your screen, then this +adds a borderbox on top of them: + + -- Layout section + for s = 1, screen.count() do + ... + + -- Most likely, you'll want to do this as well: + awful.screen.padding(screen[s], { bottom = 1 }) + + -- Create the box and place it above the existing box. + lain.widgets.borderbox(mywibox[s], s, { position = "above" } ) + + ... + end \ No newline at end of file From 0fb405d2a53257a83661b1cb1bbc8f23ff9b7c41 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:34:00 -0700 Subject: [PATCH 017/572] Created bat (markdown) --- bat.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 bat.md diff --git a/bat.md b/bat.md new file mode 100644 index 0000000..9e2d8c5 --- /dev/null +++ b/bat.md @@ -0,0 +1,18 @@ +Shows the remaining time and percentage capacity of your laptop battery, as well as +the current wattage. + +Displays a notification when battery is low or critical. + + mybattery = lain.widgets.bat() + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`battery` | Identifier of the battery | string | "BAT0" +`show_all` | Show all values (true), or only remaining capacity (false) | boolean | false +`refresh_timeout` | Refresh timeout seconds | int | 30 +`header` | Text to show before value | string | " Vol " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`shadow` | Hide the widget when battery is not present | boolean | false \ No newline at end of file From c4b8e98d191882af19038ff776d5b697745256da Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:37:03 -0700 Subject: [PATCH 018/572] Created alsabar (markdown) --- alsabar.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 alsabar.md diff --git a/alsabar.md b/alsabar.md new file mode 100644 index 0000000..a4d1768 --- /dev/null +++ b/alsabar.md @@ -0,0 +1,81 @@ +Shows and controls alsa volume with a progressbar. + +Dependencies: + +- alsa-utils + +Plus tooltips, notifications, and color changes at mute/unmute switch. + + myvolumebar = lain.widgets.alsabar() + +* Left click: Launch `alsamixer` in your `terminal`. +* Right click: Mute/unmute. +* Scroll wheel: Increase/decrase volume. + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`width` | Bar width | int | 63 +`height` | Bar height | int | 1 +`ticks` | Set bar ticks on | boolean | true +`ticks_size` | Ticks size | int | 7 +`vertical` | Set the bar vertical | boolean | false +`channel` | Mixer channel | string | "Master" +`step` | Step at which volume is increased/decreased | string | "5%" +`colors` | Bar colors | table | see **colors** +`notifications` | Notifications settings | table | see **notifications** + +### colors + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`background` | Bar backgrund color | string | `beautiful.bg_normal` +`mute` | Bar mute color | string | "#EB8F8F" +`unmute` | Bar unmute color | string | "#A4CE8A" + +### notifications + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`font` | Notifications font | string | The one defined in `beautiful.font` +`font_size` | Notifications font size | string | "11" +`bar_size` | Wibox height | int | 18 + +It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height, +**if** you have set it different than default (18). + +`lain.widgets.alsabar` outputs the following table: + +Variable | Type +--- | --- +`widget` | `awful.widget.progressbar` +`channel` | string +`step` | string +`notify` | function + +Finally, you can control the widget with the following key bindings: + + -- Volume control + awful.key({ altkey }, "Up", + function () + awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "+") + volume.notify() + end), + awful.key({ altkey }, "Down", + function () + awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "-") + volume.notify() + end), + awful.key({ altkey }, "m", + function () + awful.util.spawn("amixer set Master playback toggle") + volume.notify() + end), + awful.key({ altkey, "Control" }, "m", + function () + awful.util.spawn("amixer set Master playback 100%", false ) + volume.notify() + end), + +where `altkey = "Mod1"`. \ No newline at end of file From 8b82ccb058471a0684d3c0608a8d18b8a11975a9 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:37:23 -0700 Subject: [PATCH 019/572] Updated alsabar (markdown) --- alsabar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsabar.md b/alsabar.md index a4d1768..76e1205 100644 --- a/alsabar.md +++ b/alsabar.md @@ -2,7 +2,7 @@ Shows and controls alsa volume with a progressbar. Dependencies: -- alsa-utils +- alsa-utils (of course) Plus tooltips, notifications, and color changes at mute/unmute switch. From 31e3ed277d41e5fc6cbeca33b4285f4ece6da46d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:38:35 -0700 Subject: [PATCH 020/572] Updated alsabar (markdown) --- alsabar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsabar.md b/alsabar.md index 76e1205..53c49b4 100644 --- a/alsabar.md +++ b/alsabar.md @@ -54,7 +54,7 @@ Variable | Type `step` | string `notify` | function -Finally, you can control the widget with the following key bindings: +Finally, you can control the widget with key bindings like these: -- Volume control awful.key({ altkey }, "Up", From 201e219a1849e5d74604550c4d88bfdbc4535899 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:39:52 -0700 Subject: [PATCH 021/572] Created alsa (markdown) --- alsa.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 alsa.md diff --git a/alsa.md b/alsa.md new file mode 100644 index 0000000..5a3497b --- /dev/null +++ b/alsa.md @@ -0,0 +1,52 @@ +Shows and controls alsa volume with a textbox. + + myvolume = lain.widgets.alsa() + +* Left click: Launch `alsamixer` in your `terminal`. +* Right click: Mute/unmute. +* Scroll wheel: Increase/decrase volume. + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`channel` | Mixer channel | string | "Master" +`step` | Step at which volume is increased/decreased | string | "1%" +`header` | Text to show before value | string | " Vol " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" + +and outputs the following table: + +Variable | Type +--- | --- +`widget` | `awful.widget.textbox` +`channel` | string +`step` | string +`notify` | function + +Finally, you can control the widget with key bindings like these: + + -- Volume control + awful.key({ altkey }, "Up", + function () + awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "+") + volume.notify() + end), + awful.key({ altkey }, "Down", + function () + awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "-") + volume.notify() + end), + awful.key({ altkey }, "m", + function () + awful.util.spawn("amixer set Master playback toggle") + volume.notify() + end), + awful.key({ altkey, "Control" }, "m", + function () + awful.util.spawn("amixer set Master playback 100%", false ) + volume.notify() + end), + +where `altkey = "Mod1"`. \ No newline at end of file From e25277ef15b7bcbdcbd2033e6f1488f042111610 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:40:38 -0700 Subject: [PATCH 022/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index 98016fb..0659682 100644 --- a/fs.md +++ b/fs.md @@ -25,7 +25,7 @@ Variable | Type `widget` | `wibox.widget.textbox` `show` | function -You can display a notification of current disk space usage with the following key binding: +You can display a notification of current disk space usage with a key binding like this: awful.key({ altkey }, "h", function () mypartition.show(7) end), From d6a60f6c89ea5421b21723f12b07888cda3f5530 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 03:41:20 -0700 Subject: [PATCH 023/572] Created Widgets (markdown) --- Widgets.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Widgets.md diff --git a/Widgets.md b/Widgets.md new file mode 100644 index 0000000..cbf3fb9 --- /dev/null +++ b/Widgets.md @@ -0,0 +1,9 @@ +### Foreword + +Every widget is output by a `function`. + +Unless otherwise expressly noted, `function` returns a `wibox.widget.textbox`. + +We say this because, for some widget, `function` return a table to be used for notification and update purposes. + +### Index \ No newline at end of file From e483d3810e703986b52b0b26b643466cede56e65 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:10:14 -0700 Subject: [PATCH 024/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index 5f8ce30..085cb8d 100644 --- a/imap.md +++ b/imap.md @@ -2,7 +2,7 @@ Check new mails over IMAP protocol. Dependencies: -- Python3 +- python3 New mails are notified through a notification like this: From d5e38892f0d7df3a2d34760101c322fbf7f795f9 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:18:36 -0700 Subject: [PATCH 025/572] Updated alsa (markdown) --- alsa.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/alsa.md b/alsa.md index 5a3497b..3b485c2 100644 --- a/alsa.md +++ b/alsa.md @@ -18,12 +18,12 @@ Variable | Meaning | Type | Default and outputs the following table: -Variable | Type ---- | --- -`widget` | `awful.widget.textbox` -`channel` | string -`step` | string -`notify` | function +Variable | Meaning | Type +--- | --- | --- +`widget` | The widget | `wibox.widget.textbox` +`channel` | Alsa channel | string +`step` | Increase/decrease step | string +`notify` | The notification | function Finally, you can control the widget with key bindings like these: From 04217d3bf616375fad343fec425d54fa71d4a9d9 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:19:48 -0700 Subject: [PATCH 026/572] Updated alsabar (markdown) --- alsabar.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/alsabar.md b/alsabar.md index 53c49b4..8275101 100644 --- a/alsabar.md +++ b/alsabar.md @@ -47,12 +47,12 @@ It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height, `lain.widgets.alsabar` outputs the following table: -Variable | Type ---- | --- -`widget` | `awful.widget.progressbar` -`channel` | string -`step` | string -`notify` | function +Variable | Meaning | Type +--- | --- | --- +`widget` | The widget | `awful.widget.progressbar` +`channel` | Alsa channel | string +`step` | Increase/decrease step | string +`notify` | The notification | function Finally, you can control the widget with key bindings like these: From 6e227023200a7a03139d10265ba182bd2b7aa023 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:21:12 -0700 Subject: [PATCH 027/572] Updated fs (markdown) --- fs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs.md b/fs.md index 0659682..951f73b 100644 --- a/fs.md +++ b/fs.md @@ -20,10 +20,10 @@ Variable | Meaning | Type | Default `lain.widgets.fs` outputs the following table: -Variable | Type ---- | --- -`widget` | `wibox.widget.textbox` -`show` | function +Variable | Meaning | Type +--- | --- | --- +`widget` | The widget | `wibox.widget.textbox` +`show` | The notification | function You can display a notification of current disk space usage with a key binding like this: From 14162d53c96c4fbf6205ed5c30edc2e4890e77c7 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:21:34 -0700 Subject: [PATCH 028/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index 951f73b..3b43d8c 100644 --- a/fs.md +++ b/fs.md @@ -25,7 +25,7 @@ Variable | Meaning | Type `widget` | The widget | `wibox.widget.textbox` `show` | The notification | function -You can display a notification of current disk space usage with a key binding like this: +You can display the notification with a key binding like this: awful.key({ altkey }, "h", function () mypartition.show(7) end), From 10e87f1bd87291cb1a82c9e2d19929d4f6cdf779 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:22:29 -0700 Subject: [PATCH 029/572] Updated calendar (markdown) --- calendar.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/calendar.md b/calendar.md index 06e1b48..9330df7 100644 --- a/calendar.md +++ b/calendar.md @@ -1,6 +1,6 @@ -Attaches a calendar to a ``widget``. Example: +Attaches a calendar to a ``widget``. - lain.widgets.calendar:attach(mytextclock) + lain.widgets.calendar:attach(mywidget) - Left click: switch to previous month. - Right click: switch to next month. From 978e912a0a08bbf19aec66e19b4fe8dfe4b0c524 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:22:53 -0700 Subject: [PATCH 030/572] Updated calendar (markdown) --- calendar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calendar.md b/calendar.md index 9330df7..bfceac9 100644 --- a/calendar.md +++ b/calendar.md @@ -1,4 +1,4 @@ -Attaches a calendar to a ``widget``. +Attaches a calendar to a widget. lain.widgets.calendar:attach(mywidget) From d56d42ecd829b65a31e74dddf8b2c6a600dd357a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:25:10 -0700 Subject: [PATCH 031/572] Updated alsa (markdown) --- alsa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsa.md b/alsa.md index 3b485c2..7500bf8 100644 --- a/alsa.md +++ b/alsa.md @@ -23,7 +23,7 @@ Variable | Meaning | Type `widget` | The widget | `wibox.widget.textbox` `channel` | Alsa channel | string `step` | Increase/decrease step | string -`notify` | The notification | function +`notify` | Update `widget` | function Finally, you can control the widget with key bindings like these: From 4fd9ef1d072166be3951f87451713d17a815c28c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:30:54 -0700 Subject: [PATCH 032/572] Created mpd (markdown) --- mpd.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 mpd.md diff --git a/mpd.md b/mpd.md new file mode 100644 index 0000000..17acab8 --- /dev/null +++ b/mpd.md @@ -0,0 +1,67 @@ +Shows mpd status in a textbox. + + mympd = lain.widgets.mpd() + +Now playing songs are notified like this: + + +--------------------------------------------------------+ + | +-------+ | + | |/^\_/^\| Now playing | + | |\ O O /| Cannibal Corpse (Hammer Smashed Face) - 1993 | + | | '.o.' | Hammer Smashed Face (Radio Disney Version) | + | +-------+ | + +--------------------------------------------------------+ + +Dependencies + +- imagemagick + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`password` | Mpd password | string | "" +`host` | Mpd server | string | "127.0.0.1" +`port` | Mpd port | string | "6600" +`music_dir` | Music directory | string | "~/Music" +`refresh_timeout` | Refresh timeout seconds | int | 1 +`color_artist` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" +`color_song` | Song value color | string | `beautiful.fg_focus` or "#FFFFFF" +`spr` | Separator text between artist and song values | string | " " +`app` | Music program to spawn on click | string | "ncmpcpp" +`shadow` | Hide widget when there are no songs playing | boolean | false + +**Note**: `spr` can be a markup text. + +`lain.widgets.mpd` outputs the following table: + +Variable | Meaning | Type +--- | --- | --- +`widget` | The textbox | `wibox.widget.textbox` +`notify` | The notification | function + +Finally, you can control the widget with key bindings like these: + + -- MPD control + awful.key({ altkey, "Control" }, "Up", + function () + awful.util.spawn_with_shell( "mpc toggle || ncmpcpp toggle || ncmpc toggle || pms toggle", false ) + mympd.notify() + end), + awful.key({ altkey, "Control" }, "Down", + function () + awful.util.spawn_with_shell( "mpc stop || ncmpcpp stop || ncmpc stop || pms stop", false ) + mympd.notify() + end), + awful.key({ altkey, "Control" }, "Left", + function () + awful.util.spawn_with_shell( "mpc prev || ncmpcpp prev || ncmpc prev || pms prev", false ) + mympd.notify() + end), + awful.key({ altkey, "Control" }, "Right", + function () + awful.util.spawn_with_shell( "mpc next || ncmpcpp next || ncmpc next || pms next", false ) + mympd.notify() + end), + +where `altkey = "Mod1"`. \ No newline at end of file From 3a79e2bd99a112bfb08483cf2d55dd7604f1e3da Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:34:31 -0700 Subject: [PATCH 033/572] Updated alsabar (markdown) --- alsabar.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/alsabar.md b/alsabar.md index 8275101..52fa417 100644 --- a/alsabar.md +++ b/alsabar.md @@ -56,26 +56,26 @@ Variable | Meaning | Type Finally, you can control the widget with key bindings like these: - -- Volume control - awful.key({ altkey }, "Up", - function () - awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "+") - volume.notify() - end), - awful.key({ altkey }, "Down", - function () - awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "-") - volume.notify() - end), - awful.key({ altkey }, "m", - function () - awful.util.spawn("amixer set Master playback toggle") - volume.notify() - end), - awful.key({ altkey, "Control" }, "m", - function () - awful.util.spawn("amixer set Master playback 100%", false ) - volume.notify() - end), + -- Volume control + awful.key({ altkey }, "Up", + function () + awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "+") + volume.notify() + end), + awful.key({ altkey }, "Down", + function () + awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "-") + volume.notify() + end), + awful.key({ altkey }, "m", + function () + awful.util.spawn("amixer set Master playback toggle") + volume.notify() + end), + awful.key({ altkey, "Control" }, "m", + function () + awful.util.spawn("amixer set Master playback 100%", false ) + volume.notify() + end), where `altkey = "Mod1"`. \ No newline at end of file From 7d464df335205fa6ab1178051f23f58a3d3880a4 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:34:48 -0700 Subject: [PATCH 034/572] Updated alsabar (markdown) --- alsabar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsabar.md b/alsabar.md index 52fa417..c9e3b49 100644 --- a/alsabar.md +++ b/alsabar.md @@ -76,6 +76,6 @@ Finally, you can control the widget with key bindings like these: function () awful.util.spawn("amixer set Master playback 100%", false ) volume.notify() - end), + end), where `altkey = "Mod1"`. \ No newline at end of file From 862213c785736c8e3c5d038683257030ca00b673 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:35:37 -0700 Subject: [PATCH 035/572] Updated alsa (markdown) --- alsa.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/alsa.md b/alsa.md index 7500bf8..fb9b28f 100644 --- a/alsa.md +++ b/alsa.md @@ -27,26 +27,26 @@ Variable | Meaning | Type Finally, you can control the widget with key bindings like these: - -- Volume control - awful.key({ altkey }, "Up", - function () - awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "+") - volume.notify() - end), - awful.key({ altkey }, "Down", - function () - awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "-") - volume.notify() - end), - awful.key({ altkey }, "m", - function () - awful.util.spawn("amixer set Master playback toggle") - volume.notify() - end), - awful.key({ altkey, "Control" }, "m", - function () - awful.util.spawn("amixer set Master playback 100%", false ) - volume.notify() - end), + -- Volume control + awful.key({ altkey }, "Up", + function () + awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "+") + volume.notify() + end), + awful.key({ altkey }, "Down", + function () + awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "-") + volume.notify() + end), + awful.key({ altkey }, "m", + function () + awful.util.spawn("amixer set Master playback toggle") + volume.notify() + end), + awful.key({ altkey, "Control" }, "m", + function () + awful.util.spawn("amixer set Master playback 100%", false ) + volume.notify() + end), where `altkey = "Mod1"`. \ No newline at end of file From 8fc9c620eeb9b410a2bcb36c65b15d73b5e5c9e1 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:37:51 -0700 Subject: [PATCH 036/572] Updated mpd (markdown) --- mpd.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mpd.md b/mpd.md index 17acab8..d86b2c6 100644 --- a/mpd.md +++ b/mpd.md @@ -1,4 +1,4 @@ -Shows mpd status in a textbox. +Shows MPD status in a textbox. mympd = lain.widgets.mpd() @@ -20,9 +20,9 @@ The function takes a table as optional argument, which can contain: Variable | Meaning | Type | Default --- | --- | --- | --- -`password` | Mpd password | string | "" -`host` | Mpd server | string | "127.0.0.1" -`port` | Mpd port | string | "6600" +`password` | MPD password | string | "" +`host` | MPD server | string | "127.0.0.1" +`port` | MPD port | string | "6600" `music_dir` | Music directory | string | "~/Music" `refresh_timeout` | Refresh timeout seconds | int | 1 `color_artist` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" From 186e3351969927785355bc4c982483ccac9b4f03 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:55:46 -0700 Subject: [PATCH 037/572] Created net (markdown) --- net.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 net.md diff --git a/net.md b/net.md new file mode 100644 index 0000000..58b27e3 --- /dev/null +++ b/net.md @@ -0,0 +1,30 @@ +Monitors network interfaces and shows current traffic in a textbox. + + mynet = lain.widgets.net() + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`iface` | Network device | string | autodetected +`refresh_timeout` | Refresh timeout seconds | int | 2 +`units` | Units | int | 1024 (kilobytes) +`spr` | Separator text between download and upload values | string | " " +`header` | Text to show before value | string | `iface` +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color_up` | Upload value color | string | `beautiful.fg_focus` or "#FFFFFF" +`color_down` | Download value color | string | `beautiful.fg_focus` or "#FFFFFF" +`app` | Net program to spawn on click | string | "sudo wifi-menu" + +**Note**: `spr` can be a markup text. + +Possible value for `units` are stored in table `lain.widgets.net.units`, which contains: + + { + ["b"] = 1, + ["kb"] = 1024, + ["mb"] = 1024^2, + ["gb"] = 1024^3 + } + + From 2201da1aff925d0f0506defe93cae094ec1e8406 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:56:53 -0700 Subject: [PATCH 038/572] Updated net (markdown) --- net.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/net.md b/net.md index 58b27e3..868fb68 100644 --- a/net.md +++ b/net.md @@ -20,11 +20,7 @@ Variable | Meaning | Type | Default Possible value for `units` are stored in table `lain.widgets.net.units`, which contains: - { - ["b"] = 1, - ["kb"] = 1024, - ["mb"] = 1024^2, - ["gb"] = 1024^3 - } - - + ["b"] = 1, + ["kb"] = 1024, + ["mb"] = 1024^2, + ["gb"] = 1024^3 \ No newline at end of file From e4c6b75c4937970478bdee0b6eac04e9ed7be1f4 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:57:14 -0700 Subject: [PATCH 039/572] Updated net (markdown) --- net.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net.md b/net.md index 868fb68..c3a635c 100644 --- a/net.md +++ b/net.md @@ -20,7 +20,7 @@ Variable | Meaning | Type | Default Possible value for `units` are stored in table `lain.widgets.net.units`, which contains: - ["b"] = 1, - ["kb"] = 1024, + ["b"] = 1, + ["kb"] = 1024, ["mb"] = 1024^2, ["gb"] = 1024^3 \ No newline at end of file From a4b6e75ba37146a84c8cfbd8eeb435061677f0d9 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 04:57:32 -0700 Subject: [PATCH 040/572] Updated net (markdown) --- net.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net.md b/net.md index c3a635c..59390dc 100644 --- a/net.md +++ b/net.md @@ -22,5 +22,5 @@ Possible value for `units` are stored in table `lain.widgets.net.units`, which c ["b"] = 1, ["kb"] = 1024, - ["mb"] = 1024^2, - ["gb"] = 1024^3 \ No newline at end of file + ["mb"] = 1024^2, + ["gb"] = 1024^3 \ No newline at end of file From 296e0172a4a15f52c4b39fa3c1a8c9706c374057 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:03:04 -0700 Subject: [PATCH 041/572] Created sysload (markdown) --- sysload.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 sysload.md diff --git a/sysload.md b/sysload.md new file mode 100644 index 0000000..5b925b1 --- /dev/null +++ b/sysload.md @@ -0,0 +1,14 @@ +Show the current system load in a textbox. + + mysysload = lain.widgets.systemload() + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`show_all` | Show all the three values (true), or only the first one (false) | boolean | false +`refresh_timeout` | Refresh timeout seconds | int | 5 +`header` | Text to show before value | string | " Load " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`app` | Proc program to spawn on click | string | "top" \ No newline at end of file From ce4a3cd07665a8ad0d8f86d676e65a78da491b65 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:03:21 -0700 Subject: [PATCH 042/572] Updated sysload (markdown) --- sysload.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysload.md b/sysload.md index 5b925b1..0e57a8f 100644 --- a/sysload.md +++ b/sysload.md @@ -1,6 +1,6 @@ Show the current system load in a textbox. - mysysload = lain.widgets.systemload() + mysysload = lain.widgets.sysload() The function takes a table as optional argument, which can contain: From a33ec3d1dad5b724d2b86821e7517ae684286564 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:07:01 -0700 Subject: [PATCH 043/572] Created temp (markdown) --- temp.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 temp.md diff --git a/temp.md b/temp.md new file mode 100644 index 0000000..60d03e2 --- /dev/null +++ b/temp.md @@ -0,0 +1,13 @@ +Show the current core temperature in a textbox. Reads from `/sys/class/thermal`, so value is expressed in Celsius. + + mytemp = lain.widgets.temp() + +The function takes a table as optional argument, which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`refresh_timeout` | Refresh timeout seconds | int | 5 +`header` | Text to show before value | string | " Temp " +`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to show after value | string | "C " \ No newline at end of file From 5217a727ddb9a5d3c1afb1aacddb6d29adbd3b99 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:07:17 -0700 Subject: [PATCH 044/572] Updated temp (markdown) --- temp.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/temp.md b/temp.md index 60d03e2..11a8aa1 100644 --- a/temp.md +++ b/temp.md @@ -1,4 +1,6 @@ -Show the current core temperature in a textbox. Reads from `/sys/class/thermal`, so value is expressed in Celsius. +Show the current core temperature in a textbox. + +Reads from `/sys/class/thermal`, so value is expressed in Celsius. mytemp = lain.widgets.temp() From c4b5b25067dd79700982bde92ac9c176e846b68a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:08:42 -0700 Subject: [PATCH 045/572] Updated mem (markdown) --- mem.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mem.md b/mem.md index 58ccf72..1efdb3a 100644 --- a/mem.md +++ b/mem.md @@ -1,4 +1,4 @@ -Show used memory and total memory in MiB. +Shows memory status (in MiB) in a textbox. mymem = lain.widgets.mem() @@ -11,7 +11,7 @@ Variable | Meaning | Type | Default `refresh_timeout` | Refresh timeout seconds | int | 10 `show_swap` | Show amount of used swap space? | boolean | false `show_total` | Show amout of total memory? | boolean | false -`header` | Text to show before value | string | " Vol " +`header` | Text to show before value | string | " Mem " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `footer` | Text to show after value | string | "MB" From 85b4fcb759b050c4f6763272875d6603e174db65 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:09:48 -0700 Subject: [PATCH 046/572] Updated maildir (markdown) --- maildir.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maildir.md b/maildir.md index df5f6fe..28de551 100644 --- a/maildir.md +++ b/maildir.md @@ -17,10 +17,10 @@ Maildirs are structured as follows: . therefore the widget checks whether there are files in the `new` directories. -If there's new mail, the textbox will say something like "mail: bugs(3), system(1)", otherwise it says +If there's new mails, the textbox will say something like "mail: bugs(3), system(1)", otherwise it says "no mail". - mymaildir= lain.widgets.maildir("/path/to/my/maildir") + mymaildir = lain.widgets.maildir("/path/to/my/maildir") The function takes a table as optional argument, which can contain: From e058524601d80006095656ffdf806c1bd3d415c9 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:10:43 -0700 Subject: [PATCH 047/572] Updated maildir (markdown) --- maildir.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maildir.md b/maildir.md index 28de551..c35b2f9 100644 --- a/maildir.md +++ b/maildir.md @@ -1,4 +1,4 @@ -Checks your maildirs. +Shows maildirs status in a textbox. Maildirs are structured as follows: From 4b6422456be44bc26ac1f1335e125f96245dbb81 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:11:28 -0700 Subject: [PATCH 048/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index 085cb8d..a11759a 100644 --- a/imap.md +++ b/imap.md @@ -1,4 +1,4 @@ -Check new mails over IMAP protocol. +Show mail status in a textbox over IMAP protocol. Dependencies: From bcafb3f44da056e8453893e2517c86c37d42b554 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:11:42 -0700 Subject: [PATCH 049/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index a11759a..2a70a4c 100644 --- a/imap.md +++ b/imap.md @@ -1,4 +1,4 @@ -Show mail status in a textbox over IMAP protocol. +Shows mail status in a textbox over IMAP protocol. Dependencies: From d153d6dbe50f48419d0a2dca266ac9f60a95a480 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:12:13 -0700 Subject: [PATCH 050/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index ce59a15..01af669 100644 --- a/cpu.md +++ b/cpu.md @@ -1,4 +1,4 @@ -Shows the average CPU usage percent for a given amount of time. +Shows in a textbox the average CPU usage percent for a given amount of time. mycpuusage = lain.widgets.cpu() From f19d67a8fea9681befe6ca3658213b1abe5e60c8 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:12:52 -0700 Subject: [PATCH 051/572] Updated calendar (markdown) --- calendar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calendar.md b/calendar.md index bfceac9..182c805 100644 --- a/calendar.md +++ b/calendar.md @@ -1,4 +1,4 @@ -Attaches a calendar to a widget. +Attaches a calendar notification to a widget. lain.widgets.calendar:attach(mywidget) From 1c3ec6c8c71836e3770c2df3e2354b4479b0e747 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:13:26 -0700 Subject: [PATCH 052/572] Updated bat (markdown) --- bat.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bat.md b/bat.md index 9e2d8c5..3ff9e65 100644 --- a/bat.md +++ b/bat.md @@ -1,4 +1,4 @@ -Shows the remaining time and percentage capacity of your laptop battery, as well as +Shows in a textbox the remaining time and percentage capacity of your laptop battery, as well as the current wattage. Displays a notification when battery is low or critical. @@ -12,7 +12,7 @@ Variable | Meaning | Type | Default `battery` | Identifier of the battery | string | "BAT0" `show_all` | Show all values (true), or only remaining capacity (false) | boolean | false `refresh_timeout` | Refresh timeout seconds | int | 30 -`header` | Text to show before value | string | " Vol " +`header` | Text to show before value | string | " Bat " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `shadow` | Hide the widget when battery is not present | boolean | false \ No newline at end of file From e022767b56ddeb392761b619c2ac01d3a6594efe Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:14:53 -0700 Subject: [PATCH 053/572] Updated alsa (markdown) --- alsa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsa.md b/alsa.md index fb9b28f..f978bce 100644 --- a/alsa.md +++ b/alsa.md @@ -1,4 +1,4 @@ -Shows and controls alsa volume with a textbox. +Shows and controls alsa volume. myvolume = lain.widgets.alsa() From 6535da261c1309e360df5323ef2c06a80b005d56 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:15:53 -0700 Subject: [PATCH 054/572] Updated alsa (markdown) --- alsa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsa.md b/alsa.md index f978bce..fb9b28f 100644 --- a/alsa.md +++ b/alsa.md @@ -1,4 +1,4 @@ -Shows and controls alsa volume. +Shows and controls alsa volume with a textbox. myvolume = lain.widgets.alsa() From ea982fc1b0ce01530a8c7fa368131d6ea8bf1f9e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:18:02 -0700 Subject: [PATCH 055/572] Updated Home (markdown) --- Home.md | 1 - Index.md | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) delete mode 100644 Home.md create mode 100644 Index.md diff --git a/Home.md b/Home.md deleted file mode 100644 index a520d81..0000000 --- a/Home.md +++ /dev/null @@ -1 +0,0 @@ -Welcome to the lain wiki! \ No newline at end of file diff --git a/Index.md b/Index.md new file mode 100644 index 0000000..e14945d --- /dev/null +++ b/Index.md @@ -0,0 +1,3 @@ +- [Layouts](https://github.com/copycat-killer/lain/wiki/Layouts) +- [Widgets](https://github.com/copycat-killer/lain/wiki/Widgets) +- Utilities \ No newline at end of file From ac9d15f7a39843d0136c0ec970573dfbf79edf3b Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:19:32 -0700 Subject: [PATCH 056/572] Updated Index (markdown) --- Index.md => Home.md | 2 ++ 1 file changed, 2 insertions(+) rename Index.md => Home.md (85%) diff --git a/Index.md b/Home.md similarity index 85% rename from Index.md rename to Home.md index e14945d..434dfdc 100644 --- a/Index.md +++ b/Home.md @@ -1,3 +1,5 @@ +### Index + - [Layouts](https://github.com/copycat-killer/lain/wiki/Layouts) - [Widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - Utilities \ No newline at end of file From d6071f5dbc2b8534c7c1c9af11645570b5f5bfae Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:20:29 -0700 Subject: [PATCH 057/572] Updated Home (markdown) --- Home.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Home.md b/Home.md index 434dfdc..f8b1142 100644 --- a/Home.md +++ b/Home.md @@ -1,5 +1,10 @@ +### Installation + +Simply clone this repository into your Awesome directory. + ### Index +- [To start](https://github.com/copycat-killer/lain/wiki/To-start) - [Layouts](https://github.com/copycat-killer/lain/wiki/Layouts) - [Widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - Utilities \ No newline at end of file From 1d74c3ddec81e125cc6539cfc242e641db72ebdf Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:27:01 -0700 Subject: [PATCH 058/572] Updated Widgets (markdown) --- Widgets.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Widgets.md b/Widgets.md index cbf3fb9..7c1349e 100644 --- a/Widgets.md +++ b/Widgets.md @@ -1,4 +1,5 @@ -### Foreword +[<- home](https://github.com/copycat-killer/lain/wiki) + Every widget is output by a `function`. @@ -6,4 +7,19 @@ Unless otherwise expressly noted, `function` returns a `wibox.widget.textbox`. We say this because, for some widget, `function` return a table to be used for notification and update purposes. -### Index \ No newline at end of file +------- + +- [alsa](https://github.com/copycat-killer/lain/wiki/alsa) +- [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) +- [bat](https://github.com/copycat-killer/lain/wiki/bat) +- [borderbox](https://github.com/copycat-killer/lain/wiki/borderbox) +- [calendar](https://github.com/copycat-killer/lain/wiki/caldendar) +- [cpu](https://github.com/copycat-killer/lain/wiki/cpu) +- [fs](https://github.com/copycat-killer/lain/wiki/fs) +- [imap](https://github.com/copycat-killer/lain/wiki/imap) +- [maildir](https://github.com/copycat-killer/lain/wiki/maildir) +- [mem](https://github.com/copycat-killer/lain/wiki/mem) +- [mpd](https://github.com/copycat-killer/lain/wiki/mpd) +- [net](https://github.com/copycat-killer/lain/wiki/net) +- [sysload](https://github.com/copycat-killer/lain/wiki/sysload) +- [temp](https://github.com/copycat-killer/lain/wiki/temp) \ No newline at end of file From 251c9f74feff7dc1634a0f9e59aa252bffebc178 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:27:20 -0700 Subject: [PATCH 059/572] Updated Widgets (markdown) --- Widgets.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/Widgets.md b/Widgets.md index 7c1349e..f6fde73 100644 --- a/Widgets.md +++ b/Widgets.md @@ -1,14 +1,11 @@ [<- home](https://github.com/copycat-killer/lain/wiki) - Every widget is output by a `function`. Unless otherwise expressly noted, `function` returns a `wibox.widget.textbox`. We say this because, for some widget, `function` return a table to be used for notification and update purposes. -------- - - [alsa](https://github.com/copycat-killer/lain/wiki/alsa) - [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) - [bat](https://github.com/copycat-killer/lain/wiki/bat) From 50e6e90b62a2582a5549b27efe2546ebb015cfe0 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:28:39 -0700 Subject: [PATCH 060/572] Updated To start (markdown) --- To-start.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/To-start.md b/To-start.md index 9135be2..5a3f3db 100644 --- a/To-start.md +++ b/To-start.md @@ -1,3 +1,5 @@ +[<- home](https://github.com/copycat-killer/lain/wiki) + All you have to do is to include the module: local lain = require("lain") From b40fb56ece3ee72d867b6c8dc2ffc1d9dfd98da1 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:28:58 -0700 Subject: [PATCH 061/572] Updated Layouts (markdown) --- Layouts.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Layouts.md b/Layouts.md index 7f50efe..cc5b75d 100644 --- a/Layouts.md +++ b/Layouts.md @@ -1,3 +1,5 @@ +[<- home](https://github.com/copycat-killer/lain/wiki) + Currently, there are **7** layouts. lain/layout From 50ce8518ebdb923fcf529cb9fb345a139751c4ca Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:29:27 -0700 Subject: [PATCH 062/572] Created Utilities (markdown) --- Utilities.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Utilities.md diff --git a/Utilities.md b/Utilities.md new file mode 100644 index 0000000..7bf82a0 --- /dev/null +++ b/Utilities.md @@ -0,0 +1 @@ +[<- home](https://github.com/copycat-killer/lain/wiki) \ No newline at end of file From 7d33cc722e204467baae3921002f55b125bf5b07 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:30:13 -0700 Subject: [PATCH 063/572] Updated Home (markdown) --- Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Home.md b/Home.md index f8b1142..5dfbd14 100644 --- a/Home.md +++ b/Home.md @@ -7,4 +7,4 @@ Simply clone this repository into your Awesome directory. - [To start](https://github.com/copycat-killer/lain/wiki/To-start) - [Layouts](https://github.com/copycat-killer/lain/wiki/Layouts) - [Widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -- Utilities \ No newline at end of file +- [Utilities](https://github.com/copycat-killer/lain/wiki/Utilities) \ No newline at end of file From 35fe9a32d45c54587ba2654fd4f4b8d46f551f7b Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:30:47 -0700 Subject: [PATCH 064/572] Updated To start (markdown) --- To-start.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/To-start.md b/To-start.md index 5a3f3db..309e09b 100644 --- a/To-start.md +++ b/To-start.md @@ -25,4 +25,6 @@ Something like this: -- elaborate cmd end - lain.widgets.terminal = footerm \ No newline at end of file + lain.widgets.terminal = footerm + +[<- home](https://github.com/copycat-killer/lain/wiki) \ No newline at end of file From 4d76f6251673758997cfae5f20c89ed4a9763d8e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:31:05 -0700 Subject: [PATCH 065/572] Updated Utilities (markdown) --- Utilities.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Utilities.md b/Utilities.md index 7bf82a0..c3bbf8b 100644 --- a/Utilities.md +++ b/Utilities.md @@ -1 +1,3 @@ +[<- home](https://github.com/copycat-killer/lain/wiki) + [<- home](https://github.com/copycat-killer/lain/wiki) \ No newline at end of file From 1333924b33e22a16a7c06fee78e8dc9174e59d31 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:31:25 -0700 Subject: [PATCH 066/572] Updated Layouts (markdown) --- Layouts.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Layouts.md b/Layouts.md index cc5b75d..f9dd490 100644 --- a/Layouts.md +++ b/Layouts.md @@ -267,4 +267,6 @@ To use them, add lines to your ``theme.lua`` like this: Credits goes to [Nicolas Estibals](https://github.com/nestibal) for creating layout icons for default theme. -You can use them as a template for your custom versions. \ No newline at end of file +You can use them as a template for your custom versions. + +[<- home](https://github.com/copycat-killer/lain/wiki) \ No newline at end of file From dac05366f71c6d2774a7eae74c54f567e20df7e4 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:31:49 -0700 Subject: [PATCH 067/572] Updated To start (markdown) --- To-start.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/To-start.md b/To-start.md index 309e09b..36f32a0 100644 --- a/To-start.md +++ b/To-start.md @@ -26,5 +26,3 @@ Something like this: end lain.widgets.terminal = footerm - -[<- home](https://github.com/copycat-killer/lain/wiki) \ No newline at end of file From 5c1a24baba7f8bb1192a6e4f762dd2271a81580c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:33:08 -0700 Subject: [PATCH 068/572] Updated temp (markdown) --- temp.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/temp.md b/temp.md index 11a8aa1..92d7d06 100644 --- a/temp.md +++ b/temp.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Show the current core temperature in a textbox. Reads from `/sys/class/thermal`, so value is expressed in Celsius. From 26085f0c1ada5805a857467d82c5978c1a99d083 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:33:23 -0700 Subject: [PATCH 069/572] Updated sysload (markdown) --- sysload.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sysload.md b/sysload.md index 0e57a8f..65b5eec 100644 --- a/sysload.md +++ b/sysload.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Show the current system load in a textbox. mysysload = lain.widgets.sysload() From 02e6f1361ee690954d69e046e8d0fb3fccf694a2 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:33:41 -0700 Subject: [PATCH 070/572] Updated net (markdown) --- net.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net.md b/net.md index 59390dc..b02c239 100644 --- a/net.md +++ b/net.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Monitors network interfaces and shows current traffic in a textbox. mynet = lain.widgets.net() From 0f18138d4d6da391fabec1a0f63a91d35af24bdd Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:33:53 -0700 Subject: [PATCH 071/572] Updated mpd (markdown) --- mpd.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mpd.md b/mpd.md index d86b2c6..27f3faf 100644 --- a/mpd.md +++ b/mpd.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Shows MPD status in a textbox. mympd = lain.widgets.mpd() From e5e479ac7190ccb12c6d67e785c86579f7a0faeb Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:34:12 -0700 Subject: [PATCH 072/572] Updated mem (markdown) --- mem.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mem.md b/mem.md index 1efdb3a..173452d 100644 --- a/mem.md +++ b/mem.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Shows memory status (in MiB) in a textbox. mymem = lain.widgets.mem() From e3e59600a5421339789dbc98e0db33d016c2cd76 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:34:27 -0700 Subject: [PATCH 073/572] Updated imap (markdown) --- imap.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imap.md b/imap.md index 2a70a4c..d7e68b4 100644 --- a/imap.md +++ b/imap.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Shows mail status in a textbox over IMAP protocol. Dependencies: From 885ff3eb65ce2bb8d650c02cad6752d7ea2ce2b5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:34:38 -0700 Subject: [PATCH 074/572] Updated fs (markdown) --- fs.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs.md b/fs.md index 3b43d8c..4946fe7 100644 --- a/fs.md +++ b/fs.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Shows disk space usage for a set partition. Displays a notification when the partition is full or has low space. From 3221d82b6ada0d6c7e2a11d77228c997ed1bbcd2 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:34:51 -0700 Subject: [PATCH 075/572] Updated cpu (markdown) --- cpu.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpu.md b/cpu.md index 01af669..9dcc894 100644 --- a/cpu.md +++ b/cpu.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Shows in a textbox the average CPU usage percent for a given amount of time. mycpuusage = lain.widgets.cpu() From cf8601a25fd04bf384fdd7cb9a7bc21a4d39b3ee Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:35:10 -0700 Subject: [PATCH 076/572] Updated borderbox (markdown) --- borderbox.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/borderbox.md b/borderbox.md index cdeece2..e4d7afb 100644 --- a/borderbox.md +++ b/borderbox.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Creates a thin wibox at a position relative to another wibox. This allows to create "borders" for your wiboxes. From e084da5fa8984448bb4a0e07391dbae10b056afb Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:35:22 -0700 Subject: [PATCH 077/572] Updated bat (markdown) --- bat.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bat.md b/bat.md index 3ff9e65..79c17da 100644 --- a/bat.md +++ b/bat.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Shows in a textbox the remaining time and percentage capacity of your laptop battery, as well as the current wattage. From ec0505310f2886bfe38a61e5f8940b75c0b53c19 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:35:32 -0700 Subject: [PATCH 078/572] Updated alsabar (markdown) --- alsabar.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/alsabar.md b/alsabar.md index c9e3b49..9338ff8 100644 --- a/alsabar.md +++ b/alsabar.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Shows and controls alsa volume with a progressbar. Dependencies: From cf9b62087a65da4cdfb8b2c34b245bff7056e2cc Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:35:43 -0700 Subject: [PATCH 079/572] Updated alsa (markdown) --- alsa.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/alsa.md b/alsa.md index fb9b28f..4cfa8f3 100644 --- a/alsa.md +++ b/alsa.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Shows and controls alsa volume with a textbox. myvolume = lain.widgets.alsa() From df5d4de45bfcca28473faf1d251c7f2534dc4b0f Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 05:36:42 -0700 Subject: [PATCH 080/572] Updated Utilities (markdown) --- Utilities.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/Utilities.md b/Utilities.md index c3bbf8b..45fd0fa 100644 --- a/Utilities.md +++ b/Utilities.md @@ -1,3 +1 @@ [<- home](https://github.com/copycat-killer/lain/wiki) - -[<- home](https://github.com/copycat-killer/lain/wiki) \ No newline at end of file From e00770894268540277d819b0139939d2972d9411 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 06:27:18 -0700 Subject: [PATCH 081/572] Updated Utilities (markdown) --- Utilities.md | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Utilities.md b/Utilities.md index 45fd0fa..d9790da 100644 --- a/Utilities.md +++ b/Utilities.md @@ -1 +1,86 @@ [<- home](https://github.com/copycat-killer/lain/wiki) + +menu\_clients\_current\_tags +---------------------------- + +Similar to `awful.menu.clients()`, but this menu only shows the clients +of currently visible tags. Use it with a key binding like this: + + awful.key({ "Mod1" }, "Tab", function() + awful.menu.menu_keys.down = { "Down", "Alt_L", "Tab", "j" } + awful.menu.menu_keys.up = { "Up", "k" } + lain.util.menu_clients_current_tags({ width = 350 }, { keygrabber = true }) + end), + +magnify\_client +--------------- + +Set a client to floating and resize it in the same way the "magnifier" +layout does it. Place it on the "current" screen (derived from the mouse +position). This allows you to magnify any client you wish, regardless of +the currently used layout. Use it with a client keybinding like this: + + clientkeys = awful.util.table.join( + ... + awful.key({ modkey, "Control" }, "m", lain.util.magnify_client), + ... + ) + +If you want to "de-magnify" it, just reset the clients floating state to +`false` (hit `Mod4`+`CTRL`+`Space`, for example). + +niceborder\_{focus, unfocus} +---------------------------- + +By default, your `rc.lua` contains something like this: + + client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end) + client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end) + +You can change it to this: + + client.connect_signal("focus", lain.util.niceborder_focus(c)) + client.connect_signal("unfocus", lain.util.niceborder_unfocus(c)) + +Now, when a client is focused or unfocused, Awesome will look up its +nice value in `/proc//stat`. If it's less than 0, the client is +classified as "high priority"; if it's greater than 0, the client is +classified as "low priority". If it's equal to 0, nothing special +happens. + +This requires to define additional colors in your `theme.lua`. For example: + + theme.border_focus_highprio = "#FF0000" + theme.border_normal_highprio = "#A03333" + + theme.border_focus_lowprio = "#3333FF" + theme.border_normal_lowprio = "#333366" + +tag\_view\_nonempty +------------------- + +This function lets you jump to the next/previous non-empty tag. +It takes two arguments: + +* `direction`: `1` for next non-empty tag, `-1` for previous. +* `sc`: Screen which the taglist is in. Default is `mouse.screen` or `1`. This + argument is optional. + +You can use it with key bindings like these: + + -- Non-empty tag browsing + awful.key({ altkey }, "Left", function () lain.util.tag_view_nonempty(-1) end), + awful.key({ altkey }, "Right", function () lain.util.tag_view_nonempty(1) end), + +where `altkey = "Mod1"`. + +prompt\_rename\_tag +------------------- + +This function enables you to dynamically rename the current tag you have focused. + +You can use it with a key binding like this: + + awful.key({ modkey, "Shift" }, "r", function () lain.util.prompt_rename_tag(mypromptbox) end) + +Credits goes to [minism](https://bbs.archlinux.org/viewtopic.php?pid=1315135#p1315135). \ No newline at end of file From ee627f468c6f390534c551f7bc6fa1c55e4772f5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 06:35:52 -0700 Subject: [PATCH 082/572] Updated Utilities (markdown) --- Utilities.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Utilities.md b/Utilities.md index d9790da..4fc80e4 100644 --- a/Utilities.md +++ b/Utilities.md @@ -1,5 +1,45 @@ [<- home](https://github.com/copycat-killer/lain/wiki) +markup +------ + +This is a submodule which helps you markupping your text. + +First, call it like this: + + local markup = require("lain.util.markup") + +then you can call its functions: + + +-- markup + | + |`-- bold() Set bold. + |`-- italic() Set italicized text. + |`-- strike() Set strikethrough text. + |`-- underline() Set underlined text. + |`-- monospace() Set monospaced text. + |`-- big() Set bigger text. + |`-- small() Set smaller text. + |`-- font() Set the font of the text. + | + |`--+ bg + | | + | |`-- color() Set background color. + | |`-- focus() Set focus background color. + | |`-- normal() Set normal background color. + | `-- urgent() Set urgent background color. + | + |`--+ fg + | | + | |`-- color() Set foreground color. + | |`-- focus() Set focus foreground color. + | |`-- normal() Set normal foreground color. + | `-- urgent() Set urgent foreground color. + | + |`-- focus() Set both foreground and background focus colors. + |`-- normal() Set both foreground and background normal colors. + `-- urgent() Set both foreground and background urgent colors. + menu\_clients\_current\_tags ---------------------------- From 2b664e5d77ceaa6f0c7d48e18c4940ad7ac043ea Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 06:42:07 -0700 Subject: [PATCH 083/572] Updated Utilities (markdown) --- Utilities.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Utilities.md b/Utilities.md index 4fc80e4..168d95f 100644 --- a/Utilities.md +++ b/Utilities.md @@ -5,7 +5,7 @@ markup This is a submodule which helps you markupping your text. -First, call it like this: +First, require it like this: local markup = require("lain.util.markup") @@ -40,6 +40,11 @@ then you can call its functions: |`-- normal() Set both foreground and background normal colors. `-- urgent() Set both foreground and background urgent colors. +they all take one argument, which is the text to markup, except `fg.color()` and `bg.color()`: + + markup.fg.color(text, color) + markup.bg.color(text, color) + menu\_clients\_current\_tags ---------------------------- From 1c5e9e93b9a3fbd7eeabfa441e9fbb31b3499526 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 06:42:31 -0700 Subject: [PATCH 084/572] Updated Utilities (markdown) --- Utilities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities.md b/Utilities.md index 168d95f..8bb7597 100644 --- a/Utilities.md +++ b/Utilities.md @@ -40,7 +40,7 @@ then you can call its functions: |`-- normal() Set both foreground and background normal colors. `-- urgent() Set both foreground and background urgent colors. -they all take one argument, which is the text to markup, except `fg.color()` and `bg.color()`: +they all take one argument, which is the text to markup, except `fg.color` and `bg.color`: markup.fg.color(text, color) markup.bg.color(text, color) From 88c301fe2d894c8d819233f0c7d6a03590d94676 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 06:43:33 -0700 Subject: [PATCH 085/572] Updated Home (markdown) --- Home.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Home.md b/Home.md index 5dfbd14..b98a1dd 100644 --- a/Home.md +++ b/Home.md @@ -1,3 +1,5 @@ +Welcome to the Lain wiki! + ### Installation Simply clone this repository into your Awesome directory. From fb3da82d1066e9c734f5c0dc4275713e388af31a Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 7 Sep 2013 16:46:56 +0200 Subject: [PATCH 086/572] version 1.0 --- README.md | 419 -------------------------------------------- README.rst | 25 +++ util/markup.lua | 33 ---- widgets/mpd.lua | 13 +- widgets/net.lua | 12 +- widgets/sysload.lua | 2 +- 6 files changed, 38 insertions(+), 466 deletions(-) delete mode 100644 README.md create mode 100644 README.rst diff --git a/README.md b/README.md deleted file mode 100644 index 8aa9449..0000000 --- a/README.md +++ /dev/null @@ -1,419 +0,0 @@ -VAin agaIN -========== - -Author: Luke Bonham - -Source: https://github.com/copycat-killer/vain - -Version: 1.9.9 - -Release version: 2.0 - -**Please note**: until release version, this documentation will be not updated. - -Foreword --------- - -Based on a port of [awesome-vain](https://github.com/vain/awesome-vain), this -costantly evolving module provides new layouts, a set of widgets and -utility functions in order to improve Awesome usability and configurability. - -This work is licensed under [GNU GPLv2 License](http://www.gnu.org/licenses/gpl-2.0.html). -Installation -============ - -Simply clone this repository into your Awesome directory. - -Widgets -======= - -systemload ----------- - -Show the current system load in a textbox. Read it directly from -`/proc/loadavg`. - - mysysload = vain.widgets.systemload() - -A click on the widget will call `htop` in your `terminal`. - -The function takes a table as an optional argument. That table may -contain: - -* `.refresh_timeout`: Default to 10 seconds. -* `.show_all`: Show all three values (`true`) or only the first one (`false`). Default to `false`. -* `.color`: Default to beautiful.bg_normal or "#FFFFFF". - -cpu --------- - -Shows the average CPU usage percent for a given amount of time. - - mycpuusage = vain.widgets.cpu() - -A click on the widget will call `htop` in your `terminal`. - -The function takes a table as optional argument, which can contain: - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`refresh_timeout` | Refresh timeout seconds | int | 10 -`header` | Text to show before value | string | " Vol " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to show after value | string | "%" - -**Note**: `footer` color is `color`. - -memusage --------- - -Show used memory and total memory in MiB. - - mymem = vain.widgets.mem() - - -The function takes a table as an optional argument. That table may -contain: - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`refresh_timeout` | Refresh timeout seconds | int | 10 -`show_swap` | Show amount of used swap space? | boolean | false -`show_total` | Show amout of total memory? | boolean | false -`header` | Text to show before value | string | " Vol " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to show after value | string | "MB" - -**Note**: `footer` color is `color`. - -mailcheck ---------- -Checks maildirs and shows the result in a textbox. -Maildirs are structured as follows: - - ~/Mail - . - |-- arch - | |-- cur - | |-- new - | `-- tmp - |-- gmail - | |-- cur - | |-- new - | `-- tmp - . - . - . - -therefore `mailcheck` checks whether there are files in the `new` -directories. To do so, it calls `find`. If there's new mail, the textbox -will say something like "mail: bugs(3), system(1)", otherwise it says -"no mail". - - mymailcheck = vain.widgets.mailcheck("/path/to/my/maildir") - -The function takes a table as an optional argument. That table may -contain: - -* `.mailprogram`: Your favourite mail program. Clicking on the widget will - spawn it. Default is `mutt`. -* `.refresh_timeout`: Default to 60 seconds. -* `.mailpath`: Path to your maildir, default is `~/Mail`. -* `.ignore_boxes`: Another table which lists boxes (just the last part, - like `lists`) to ignore. Default to an empty table. -* `.initial_update`: Check for mail when starting Awesome (`true`) or - wait for the first refresh timeout (`false`)? Default to `false`. -* `.header_text`: Text to show along with output, default is "Mail". -* `.header_text_color`: Default to "#9E9E9E". -* `.color_newmail`: Default to "#D4D4D4". -* `.color_nomail`: Default to "#9E9E9E". -* `.shadow`: Hides widget when there are no mails. Default is `false`. - -imapcheck ---------- - -Check new mails over imap protocol. - -Dependencies: - -* Python3 - -Since [luasec](https://github.com/brunoos/luasec/) is still not officially -supported in lua 5.2, writing a pure lua solution would have meant too many -hacks and dependencies, resulting in a very big and not efficient-proven submodule. - -That's why I chose Python. - -Python offers [imaplib](http://docs.python.org/2/library/imaplib.html), a simple yet powerful IMAP4 client library which provides encrypted communication over SSL sockets. - -Basically, `imapcheck` calls ``vain/scripts/checkmail`` and parse its output in a widget. New mails are also notified through Naughty, with a popup like this: - - +---------------------------------------------------+ - | +---+ | - | |\ /| donald@disney.org has 3 new messages | - | +---+ | - | Latest From: Mickey Mouse | - | Subject: Re: Vacation Day | - | | - | Not after what you did yesterday. | - | Daisy told me everything [...] | - | | - +---------------------------------------------------+ - -Text will be cut if the mail is too long. - - myimapcheck = vain.widgets.mailcheck(args) - -The function takes a table as argument. Required table parameters are: - -* `.server`: You email server. Example: `imap.gmail.com`. -* `.mail`: Your email. -* `.password`: Your email password. - -while the optional are: - -* `.port`: Imap port. Default is `993`. -* `.refresh_timeout`: Default to 60 seconds. -* `.notify_timeout`: Notification timeout. Default to 8 seconds. -* `.notify_position`: Notification position. Default is "top_left". Check - [Naughty position parameter](http://awesome.naquadah.org/doc/api/modules/naughty.html) for a list of other possible values. -* `.mailprogram`: Your favourite mail program. Clicking on the widget will - spawn it. Default is `mutt`. -* `.mail_encoding`: If you wish to set an encoding. Default is `nil`. -* `.initial_update`: Check for mail when starting Awesome (`true`) or - wait for the first refresh timeout (`false`)? Default to `false`. -* `.header_text`: Text to show along with output, default is "Mail". -* `.header_text_color`: Default to "#9E9E9E". -* `.color_newmail`: Default to "#D4D4D4". -* `.color_nomail`: Default to "#9E9E9E". -* `.shadow`: Hides widget when there are no mails. Default is `false`. -* `.maxlen`: Maximum mail length. If mail is longer, it will be cut. Default is - `100`. -* `.is_plain`: Define whether `.password` field is a plain password (`true`) or a function that retrieves it (`false`). Default to `false`. - -Let's focus better on `.is_plain` parameter. - -You can just easily set your password like this: - - args.is_plain = false - args.password = "mypassword" - -and you'll have the same security provided by `~/.netrc`. (In this case, it's -better to set your `rc.lua` permissions to 700 or 600) - -**Or**, you can use a keyring, like gnome's: - - args.password = "gnome-keyring-query get password" - -(`gnome-keyring-query` is not in gnome-keyring pkg, you have to download it -separately) - -or the very light [python keyring](https://pypi.python.org/pypi/keyring). - -When `.is_plain` is `false`, it *executes* `.password` before using it, so you can also use whatever password fetching solution you want. - -You can also define your icon for the naughty notification. Just set `vain_mail_notify` into your ``theme.lua``. - - - -mpd ---- - -Provides a `table` with 2 elements: - -* `table["widget"]` is a textbox displaying current song in play. - -* `table["force"]` is a function to *force* the widget to update, exactly - like `vicious.force()`. - -Also, a notification is shown when a new song is playing. - -Dependencies: - -* libnotify -* imagemagick - - - mpdwidget = vain.widgets.mpd() - ... - right_layout:add(mpdwidget["widget"]) - -The function takes a table as an optional argument. That table may -contain: - -* `.password`: Mpd password. Default is unset. -* `.host`: Mpd host. Default is "127.0.0.1" (localhost). -* `.port`: Mpd port. Default is "6600". -* `.music_dir`: Your music directory. Default is "~/Music". If you have to - change this, be sure to write the absolute path. -* `.refresh_timeout`: Widget refresh timeout. Default is `1`. -* `.notify_timeout`: Notification timeout. Default is `5`. -* `.color_artist`: Artist name color. Default is `#9E9E9E`. -* `.color_song`: Song name color. Default is `#EBEBFF`. -* `.musicplr`: Your favourite music player. Clicking on the widget will spawn - it. Default is `ncmpcpp`. -* `.shadow`: Hides widget when no song is playing. Default is `false`. - -You can use `table["force"]` to make your mpd keybindings immediate. -Example usage: - - globalkeys = awful.util.table.join( - ... - -- Music control - awful.key({ altkey, "Control" }, "Up", function () - awful.util.spawn_with_shell( "mpc toggle || ncmpcpp toggle || ncmpc toggle || pms toggle", false ) - mpdwidget["force"]() - end), - awful.key({ altkey, "Control" }, "Down", function () - awful.util.spawn_with_shell( "mpc stop || ncmpcpp stop || ncmpc stop || pms stop", false ) - mpdwidget["force"]() - end ), - awful.key({ altkey, "Control" }, "Left", function () - awful.util.spawn_with_shell( "mpc prev || ncmpcpp prev || ncmpc prev || pms prev", false ) - mpdwidget["force"]() - end ), - awful.key({ altkey, "Control" }, "Right", function () - awful.util.spawn_with_shell( "mpc next || ncmpcpp next || ncmpc next || pms next", false ) - mpdwidget["force"]() - end ), - -net ---- - -Monitors network interfaces and shows current traffic in a textbox. If -the interface is not present or if there's not enough data yet, you'll -see `wlan0: -` or similar. Otherwise, the current traffic is shown in -kilobytes per second as `eth0: ↑(00,010.2), ↓(01,037.8)` or similar. - - neteth0 = vain.widgets.net() - -The function takes a table as an optional argument. That table may -contain: - -* `.iface`: Default to `eth0`. -* `.refresh_timeout`: Default to 2 seconds. -* `.color`: Default to beautiful.bg_normal or "#FFFFFF". - -gitodo ------- - -This is an integration of [gitodo](https://github.com/vain/gitodo) into -Awesome. - - todolist = vain.widgets.gitodo() - -The function takes a table as an optional argument. That table may -contain: - -* `.refresh_timeout`: Default to 120 seconds. -* `.initial_update`: Check for todo items when starting Awesome (`true`) - or wait for the first refresh timeout (`false`)? Default to `true`. - -`beautiful.gitodo_normal` is used as the color for non-outdated items, -`beautiful.gitodo_warning` for those items close to their deadline and -`beautiful.gitodo_outdated` is the color of outdated items. - - - -Utility functions -================= - -I'll only explain the more complex functions. See the source code for -the others. - -menu\_clients\_current\_tags ----------------------------- - -Similar to `awful.menu.clients()`, but this menu only shows the clients -of currently visible tags. Use it like this: - - globalkeys = awful.util.table.join( - ... - awful.key({ "Mod1" }, "Tab", function() - awful.menu.menu_keys.down = { "Down", "Alt_L", "Tab", "j" } - awful.menu.menu_keys.up = { "Up", "k" } - vain.util.menu_clients_current_tags({ width = 350 }, { keygrabber = true }) - end), - ... - ) - -magnify\_client ---------------- - -Set a client to floating and resize it in the same way the "magnifier" -layout does it. Place it on the "current" screen (derived from the mouse -position). This allows you to magnify any client you wish, regardless of -the currently used layout. Use it with a client keybinding like this: - - clientkeys = awful.util.table.join( - ... - awful.key({ modkey, "Control" }, "m", vain.util.magnify_client), - ... - ) - -If you want to "de-magnify" it, just reset the clients floating state to -`false` (hit `Mod4`+`CTRL`+`Space`, for example). - -niceborder\_{focus, unfocus} ----------------------------- - -By default, your `rc.lua` contains something like this: - - client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end) - client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end) - -You can change it to this: - - client.connect_signal("focus", vain.util.niceborder_focus(c)) - client.connect_signal("unfocus", vain.util.niceborder_unfocus(c)) - -Now, when a client is focused or unfocused, Awesome will look up its -nice value in `/proc//stat`. If it's less than 0, the client is -classified as "high priority"; if it's greater than 0, the client is -classified as "low priority". If it's equal to 0, nothing special -happens. - -This requires to define additional colors in your `theme.lua`. For example: - - theme.border_focus_highprio = "#FF0000" - theme.border_normal_highprio = "#A03333" - - theme.border_focus_lowprio = "#3333FF" - theme.border_normal_lowprio = "#333366" - -tag\_view\_nonempty ------------------------------- - -This function lets you jump to the next/previous non-empty tag. -It takes two arguments: - -* `direction`: `1` for next non-empty tag, `-1` for previous. -* `sc`: Screen in which the taglist is. Default is `mouse.screen` or `1`. This - argument is optional. - -Usage example: - - globalkeys = awful.util.table.join( - ... - -- Non-empty tag browsing - awful.key({ altkey }, "Left", function () vain.util.tag_view_nonempty(-1) - end), - awful.key({ altkey }, "Right", function () vain.util.tag_view_nonempty(1) end), - ... - -prompt\_rename\_tag -------------------- - -This function enables you to dynamically rename the current tag you have -focused. -Usage example: - - globalkeys = awful.util.table.join( - .. - -- Dynamic tag renaming - awful.key({ modkey, "Shift" }, "r", function () vain.util.prompt_rename_tag(mypromptbox) end), - ... - -Credits goes to [minism](https://bbs.archlinux.org/viewtopic.php?pid=1315135#p1315135). diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..264c9b0 --- /dev/null +++ b/README.rst @@ -0,0 +1,25 @@ +Lain +==== + +--------------------------------------------- +Layouts, widgets and utilities for Awesome WM +--------------------------------------------- + +Author: Luke Bonham +Version: 1.0-git +License: GNU-GPLv2_ +Source: https://github.com/copycat-killer/vain + +Based on a port of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions in order to improve Awesome usability and +configurability. + +Read the wiki_ for all the info. + +Screenshots +----------- + +.. image:: + +.. _GNU-GPLv2: http://www.gnu.org/licenses/gpl-2.0.html +.. _awesome-vain: https://github.com/vain/awesome-vain +.. _wiki: https://github.com/copycat-killer/lain/wiki diff --git a/util/markup.lua b/util/markup.lua index e7baec0..dbb8529 100644 --- a/util/markup.lua +++ b/util/markup.lua @@ -19,39 +19,6 @@ local markup = {} local fg = {} local bg = {} ---[[ clean this as soon as you document it - - +-- markup - | - |`-- bold() Set bold. - |`-- italic() Set italicized text. - |`-- strike() Set strikethrough text. - |`-- underline() Set underlined text. - |`-- monospace() Set monospaced text. - |`-- big() Set bigger text. - |`-- small() Set smaller text. - |`-- font() Set the font of the text. - | - |`--+ bg - | | - | |`-- color() Set background color. - | |`-- focus() Set focus background color. - | |`-- normal() Set normal background color. - | `-- urgent() Set urgent background color. - | - |`--+ fg - | | - | |`-- color() Set foreground color. - | |`-- focus() Set focus foreground color. - | |`-- normal() Set normal foreground color. - | `-- urgent() Set urgent foreground color. - | - |`-- focus() Set both foreground and background focus colors. - |`-- normal() Set both foreground and background normal colors. - `-- urgent() Set both foreground and background urgent colors. - -]] - -- Convenience tags. function markup.bold(text) return '' .. tostring(text) .. '' end function markup.italic(text) return '' .. tostring(text) .. '' end diff --git a/widgets/mpd.lua b/widgets/mpd.lua index dcb7101..0b9a4c9 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -33,11 +33,10 @@ function worker(args) local port = args.port or "6600" local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" local refresh_timeout = args.refresh_timeout or 1 - local notify_timeout = args.notify_timeout or 5 local color_artist = args.color_artist or beautiful.fg_normal or "#FFFFFF" local color_song = args.color_song or beautiful.fg_focus or "#FFFFFF" - local spr = args.spr or "" - local musicplr = args.musicplr or "ncmpcpp" + local spr = args.spr or " " + local app = args.app or "ncmpcpp" local shadow = args.shadow or false local mpdcover = helpers.scripts_dir .. "mpdcover" @@ -100,18 +99,18 @@ function worker(args) icon = "/tmp/mpdcover.png", fg = beautiful.fg_focus or "#FFFFFF", bg = beautiful.bg_normal or "#000000" , - timeout = notify_timeout, + timeout = 6, replaces_id = mpd.id }).id end mympd:set_markup(markup(color_artist, " " .. mpd_state["{Artist}"]) .. spr .. - markup(color_song, " " .. mpd_state["{Title}"] .. " ")) + markup(color_song, mpd_state["{Title}"] .. " ")) elseif mpd_state["{state}"] == "pause" then mympd:set_markup(markup(color_artist, " mpd") .. spr .. - markup(color_song, " paused ")) + markup(color_song, "paused ")) else helpers.set_map("current mpd track", nil) set_nompd() @@ -126,7 +125,7 @@ function worker(args) mympd:buttons(awful.util.table.join( awful.button({}, 0, function() - helpers.run_in_terminal(musicplr) + helpers.run_in_terminal(app) end) )) diff --git a/widgets/net.lua b/widgets/net.lua index f361146..18727f1 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -29,7 +29,7 @@ local net = { last_r = {} } -local unit = { +net.units = { ["b"] = 1, ["kb"] = 1024, ["mb"] = 1024^2, @@ -52,12 +52,12 @@ function worker(args) local args = args or {} local iface = args.iface or net.get_device() local delta = args.refresh_timeout or 2 - local unit = args.unit or unit["kb"] + local units = args.units or net.units["kb"] local spr = args.spr or " " local header = args.header or iface local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color_up = args.color_up or beautiful.fg_focus or header_color - local color_down = args.color_down or beautiful.fg_focus or header_color + local color_up = args.color_up or beautiful.fg_focus or "#FFFFFF" + local color_down = args.color_down or beautiful.fg_focus or "#FFFFFF" local app = args.app or "sudo wifi-menu" helpers.set_map(iface, true) @@ -113,8 +113,8 @@ function worker(args) if net.last_t[iface] and net.last_t[iface] then - net.send = tostring((now_t - net.last_t[iface]) / delta / unit) - net.recv = tostring((now_r - net.last_r[iface]) / delta / unit) + net.send = tostring((now_t - net.last_t[iface]) / delta / units) + net.recv = tostring((now_r - net.last_r[iface]) / delta / units) text = text .. '' diff --git a/widgets/sysload.lua b/widgets/sysload.lua index 8583ccb..eb06828 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -30,7 +30,7 @@ function worker(args) local show_all = args.show_all or false local header = args.header or " Load " local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or header_color + local color = args.color or beautiful.fg_focus or "#FFFFFF" local app = args.app or "top" local mysysload = wibox.widget.textbox() From c4a672c58bcbc804346c3bcd5031dbf68ad5e92f Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 7 Sep 2013 16:47:17 +0200 Subject: [PATCH 087/572] version 1.0 --- widgets/yawn/icons/DayFair.png | 1 + widgets/yawn/icons/Drizzle.png | 1 + widgets/yawn/icons/Haze.png | 1 + widgets/yawn/icons/NightFair.png | 1 + widgets/yawn/icons/Sleet.png | 1 + widgets/yawn/icons/Snow.png | 1 + widgets/yawn/icons/SnowFlurries.png | 1 + 7 files changed, 7 insertions(+) create mode 120000 widgets/yawn/icons/DayFair.png create mode 120000 widgets/yawn/icons/Drizzle.png create mode 120000 widgets/yawn/icons/Haze.png create mode 120000 widgets/yawn/icons/NightFair.png create mode 120000 widgets/yawn/icons/Sleet.png create mode 120000 widgets/yawn/icons/Snow.png create mode 120000 widgets/yawn/icons/SnowFlurries.png diff --git a/widgets/yawn/icons/DayFair.png b/widgets/yawn/icons/DayFair.png new file mode 120000 index 0000000..8ee94d1 --- /dev/null +++ b/widgets/yawn/icons/DayFair.png @@ -0,0 +1 @@ +DayClear.png \ No newline at end of file diff --git a/widgets/yawn/icons/Drizzle.png b/widgets/yawn/icons/Drizzle.png new file mode 120000 index 0000000..df34463 --- /dev/null +++ b/widgets/yawn/icons/Drizzle.png @@ -0,0 +1 @@ +Rain.png \ No newline at end of file diff --git a/widgets/yawn/icons/Haze.png b/widgets/yawn/icons/Haze.png new file mode 120000 index 0000000..0874a83 --- /dev/null +++ b/widgets/yawn/icons/Haze.png @@ -0,0 +1 @@ +Hail.png \ No newline at end of file diff --git a/widgets/yawn/icons/NightFair.png b/widgets/yawn/icons/NightFair.png new file mode 120000 index 0000000..23df45a --- /dev/null +++ b/widgets/yawn/icons/NightFair.png @@ -0,0 +1 @@ +NightClear.png \ No newline at end of file diff --git a/widgets/yawn/icons/Sleet.png b/widgets/yawn/icons/Sleet.png new file mode 120000 index 0000000..f8f9693 --- /dev/null +++ b/widgets/yawn/icons/Sleet.png @@ -0,0 +1 @@ +SnowShowers.png \ No newline at end of file diff --git a/widgets/yawn/icons/Snow.png b/widgets/yawn/icons/Snow.png new file mode 120000 index 0000000..f8f9693 --- /dev/null +++ b/widgets/yawn/icons/Snow.png @@ -0,0 +1 @@ +SnowShowers.png \ No newline at end of file diff --git a/widgets/yawn/icons/SnowFlurries.png b/widgets/yawn/icons/SnowFlurries.png new file mode 120000 index 0000000..2e090cd --- /dev/null +++ b/widgets/yawn/icons/SnowFlurries.png @@ -0,0 +1 @@ +BlowingSnow.png \ No newline at end of file From d39c745e0ad888a7aefd3850e3ca6390fb0251e6 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 7 Sep 2013 16:51:00 +0200 Subject: [PATCH 088/572] readme updated --- README.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 264c9b0..de2ed65 100644 --- a/README.rst +++ b/README.rst @@ -18,7 +18,9 @@ Read the wiki_ for all the info. Screenshots ----------- -.. image:: +.. image:: http://i.imgur.com/8D9A7lW.png +.. image:: http://i.imgur.com/9Iv3OR3.png +.. image:: http://i.imgur.com/STCPcaJ.png .. _GNU-GPLv2: http://www.gnu.org/licenses/gpl-2.0.html .. _awesome-vain: https://github.com/vain/awesome-vain From 711795327669a153995ac150f9caebd302164da2 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 7 Sep 2013 16:57:07 +0200 Subject: [PATCH 089/572] readme updated --- README.md | 4 ---- README.rst | 8 ++++---- 2 files changed, 4 insertions(+), 8 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 2f3d7af..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -lain -==== - -Next generation Vain diff --git a/README.rst b/README.rst index de2ed65..22d9a27 100644 --- a/README.rst +++ b/README.rst @@ -5,10 +5,10 @@ Lain Layouts, widgets and utilities for Awesome WM --------------------------------------------- -Author: Luke Bonham -Version: 1.0-git -License: GNU-GPLv2_ -Source: https://github.com/copycat-killer/vain +:Author: Luke Bonham +:Version: 1.0-git +:License: GNU-GPLv2_ +:Source: https://github.com/copycat-killer/vain Based on a port of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions in order to improve Awesome usability and configurability. From 7d89def8baf408b1618a18e3a0fe8977c5f669b5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 08:02:39 -0700 Subject: [PATCH 090/572] Created yawn (rest) --- yawn.rest | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 yawn.rest diff --git a/yawn.rest b/yawn.rest new file mode 100644 index 0000000..f8fc130 --- /dev/null +++ b/yawn.rest @@ -0,0 +1,133 @@ +========================================= +Yahoo's Awesome (WM) Weather Notification +========================================= + +---------------- +Lain integration +---------------- + +:Author: Luke Bonham +:License: WTFPLv2_ +:Version: 2.0-git + +Description +----------- + +Yawn is a module for Awesome WM providing brief and compact +weather notification via Naughty and Yahoo! Weather API. + +Originally a port of perceptive_, it became a completely new module after various improvements and style changes. + +----- +Usage +----- + +You can ``register`` Yawn to get a set of widgets, or ``attach`` it to +an existent widget. + +register +^^^^^^^^ + +Call: :: + + lain.widgets.yawn(id, args) + +Arguments: + +``id`` + An integer that defines the WOEID code of your city. + To obtain it you can google 'yahoo weather %CITYNAME%' and follow the first link. + It will look like:: + + http://weather.yahoo.com/united-states/california/san-diego-2487889/ + + and the last number in that link will be the ID you need. +``args`` + An optional table which can contain the following settings: + ``u`` + Units. Type: string. Possible values: "c" (Celsius), "f" (Fahrenheit). Default: "c". + + ``toshow`` + What to show. Type: string. Possible values: "units", "forecast", "both". + Default: "forecast". + + ``units_color`` + Color of units text. Type: string. Possible values: hexadecimal color + codes. + + ``forecast_color`` + Color of forecast text. Type: string. Possible values: hexadecimal color + codes. + + ``notification_color`` + Color of notification text. Type: string. Possible values: hexadecimal color + codes. + + ``spr`` + A separator. Type: string. You can define it when ``toshow`` is set to "both". + + ``footer`` + A footer. Type: string. You can define it when ``toshow`` is set to + "both". + +The function creates an imagebox icon and a textbox widget. Add them to you wibox like this: :: + + right_layout:add(lain.widgets.yawn.icon) + right_layout:add(lain.widgets.yawn.widget) + +Hovering over ``yawn.icon`` will display the notification. + +attach +^^^^^^ + +Call: :: + + lain.widgets.yawn.attach(widget, id, args) + +Arguments: + +``widget`` + The widget which you want to attach yawn to. +``id`` + same as in ``register`` +``args`` + same as in ``register`` + +Hovering over ``widget`` will display the notification. + +-------------- +Popup shortcut +-------------- + +You can also create a keybinding for the weather popup like this: :: + + globalkeys = awful.util.table.join( + ... + awful.key( { "Mod1" }, "w", function () lain.widgets.yawn.show(5) end ) + ... + +where ``show`` argument is an integer defining timeout seconds. + +------------ +Localization +------------ + +Default language is English, but Yawn can be localized. +Move to ``localizations`` subdirectory and fill ``localization_template``. + +Once you're done, rename it like your locale id. In my case: :: + + $ lua + Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio + > print(os.getenv("LANG"):match("(%S*$*)[.]")) + it_IT + > + +hence I named my file "it_IT" (Italian localization). + +**NOTE:** If you create a localization, feel free to send me! I will add it. + +.. _WTFPLv2: http://www.wtfpl.net +.. _perceptive: https://github.com/ioga/perceptive +.. _Tamsyn: http://www.fial.com/~scott/tamsyn-font/ +.. _Rainbow: https://github.com/copycat-killer/awesome-copycats> \ No newline at end of file From cef70fe99fc0a6a868ba76e0509aeeed202f44cf Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 08:11:23 -0700 Subject: [PATCH 091/572] Updated yawn (rest) --- yawn.rest | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/yawn.rest b/yawn.rest index f8fc130..8991040 100644 --- a/yawn.rest +++ b/yawn.rest @@ -1,10 +1,4 @@ -========================================= -Yahoo's Awesome (WM) Weather Notification -========================================= - ----------------- -Lain integration ----------------- +*This is an integration of this* module_. :Author: Luke Bonham :License: WTFPLv2_ @@ -127,6 +121,7 @@ hence I named my file "it_IT" (Italian localization). **NOTE:** If you create a localization, feel free to send me! I will add it. +.. _module: https://github.com/copycat-killer/yawn .. _WTFPLv2: http://www.wtfpl.net .. _perceptive: https://github.com/ioga/perceptive .. _Tamsyn: http://www.fial.com/~scott/tamsyn-font/ From d4707ba3acb85dd10753848d661aa591660aff72 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 08:12:13 -0700 Subject: [PATCH 093/572] Updated yawn (rest) --- yawn.rest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yawn.rest b/yawn.rest index 8991040..4551597 100644 --- a/yawn.rest +++ b/yawn.rest @@ -1,4 +1,4 @@ -*This is an integration of this* module_. +(*Integration of this* module_) :Author: Luke Bonham :License: WTFPLv2_ From 3412fcbd9201a035f948182f0e4b943331c133c4 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 08:12:59 -0700 Subject: [PATCH 094/572] Updated Widgets (markdown) --- Widgets.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index f6fde73..53c6f04 100644 --- a/Widgets.md +++ b/Widgets.md @@ -19,4 +19,5 @@ We say this because, for some widget, `function` return a table to be used for n - [mpd](https://github.com/copycat-killer/lain/wiki/mpd) - [net](https://github.com/copycat-killer/lain/wiki/net) - [sysload](https://github.com/copycat-killer/lain/wiki/sysload) -- [temp](https://github.com/copycat-killer/lain/wiki/temp) \ No newline at end of file +- [temp](https://github.com/copycat-killer/lain/wiki/temp) +- [yawn](https://github.com/copycat-killer/lain/wiki/yawn) \ No newline at end of file From 6a2df832b520db0afb8bcd8ea06913240c29c4ce Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 7 Sep 2013 17:14:10 +0200 Subject: [PATCH 095/572] yawn doc added --- widgets/yawn/README.rst | 133 ---------------------------------------- 1 file changed, 133 deletions(-) delete mode 100644 widgets/yawn/README.rst diff --git a/widgets/yawn/README.rst b/widgets/yawn/README.rst deleted file mode 100644 index d067db3..0000000 --- a/widgets/yawn/README.rst +++ /dev/null @@ -1,133 +0,0 @@ -========================================= -Yahoo's Awesome (WM) Weather Notification -========================================= - ----------------- -Lain integration ----------------- - -:Author: Luke Bonham -:License: WTFPLv2_ -:Version: 2.0-git - -Description ------------ - -Yawn is a module for Awesome WM providing brief and compact -weather notification via Naughty and Yahoo! Weather API. - -Originally a port of perceptive_, it became a completely new module after various improvements and style changes. - ------ -Usage ------ - -You can ``register`` Yawn to get a set of widgets, or ``attach`` it to -an existent widget. - -register -^^^^^^^^ - -Call: :: - - lain.widgets.yawn(id, args) - -Arguments: - -``id`` - An integer that defines the WOEID code of your city. - To obtain it you can google 'yahoo weather %CITYNAME%' and follow the first link. - It will look like:: - - http://weather.yahoo.com/united-states/california/san-diego-2487889/ - - and the last number in that link will be the ID you need. -``args`` - An optional table which can contain the following settings: - ``u`` - Units. Type: string. Possible values: "c" (Celsius), "f" (Fahrenheit). Default: "c". - - ``toshow`` - What to show. Type: string. Possible values: "units", "forecast", "both". - Default: "forecast". - - ``units_color`` - Color of units text. Type: string. Possible values: hexadecimal color - codes. - - ``forecast_color`` - Color of forecast text. Type: string. Possible values: hexadecimal color - codes. - - ``notification_color`` - Color of notification text. Type: string. Possible values: hexadecimal color - codes. - - ``spr`` - A separator. Type: string. You can define it when ``toshow`` is set to "both". - - ``footer`` - A footer. Type: string. You can define it when ``toshow`` is set to - "both". - -The function creates an imagebox icon and a textbox widget. Add them to you wibox like this: :: - - right_layout:add(lain.widgets.yawn.icon) - right_layout:add(lain.widgets.yawn.widget) - -Hovering over ``yawn.icon`` will display the notification. - -attach -^^^^^^ - -Call: :: - - lain.widgets.yawn.attach(widget, id, args) - -Arguments: - -``widget`` - The widget which you want to attach yawn to. -``id`` - same as in ``register`` -``args`` - same as in ``register`` - -Hovering over ``widget`` will display the notification. - --------------- -Popup shortcut --------------- - -You can also create a keybinding for the weather popup like this: :: - - globalkeys = awful.util.table.join( - ... - awful.key( { "Mod1" }, "w", function () lain.widgets.yawn.show(5) end ) - ... - -where ``show`` argument is an integer defining timeout seconds. - ------------- -Localization ------------- - -Default language is English, but Yawn can be localized. -Move to ``localizations`` subdirectory and fill ``localization_template``. - -Once you're done, rename it like your locale id. In my case: :: - - $ lua - Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio - > print(os.getenv("LANG"):match("(%S*$*)[.]")) - it_IT - > - -hence I named my file "it_IT" (Italian localization). - -**NOTE:** If you create a localization, feel free to send me! I will add it. - -.. _WTFPLv2: http://www.wtfpl.net -.. _perceptive: https://github.com/ioga/perceptive -.. _Tamsyn: http://www.fial.com/~scott/tamsyn-font/ -.. _Rainbow: https://github.com/copycat-killer/awesome-copycats> From 0ef5a7d0006868e9c11cad2861435b8f884aa9ac Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 11:32:52 -0700 Subject: [PATCH 096/572] Updated To start (markdown) --- To-start.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/To-start.md b/To-start.md index 36f32a0..a2be5ff 100644 --- a/To-start.md +++ b/To-start.md @@ -1,6 +1,4 @@ -[<- home](https://github.com/copycat-killer/lain/wiki) - -All you have to do is to include the module: +All you have to do to include the module: local lain = require("lain") From 194f362372d5c4098d1f8498d95fe10dd2d506d2 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 11:33:09 -0700 Subject: [PATCH 097/572] Updated Layouts (markdown) --- Layouts.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/Layouts.md b/Layouts.md index f9dd490..7c4ff41 100644 --- a/Layouts.md +++ b/Layouts.md @@ -1,5 +1,3 @@ -[<- home](https://github.com/copycat-killer/lain/wiki) - Currently, there are **7** layouts. lain/layout From 7ff53f54e9a868170c38948c2ddd62fc79222c93 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 11:33:31 -0700 Subject: [PATCH 098/572] Updated Widgets (markdown) --- Widgets.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/Widgets.md b/Widgets.md index 53c6f04..cdcac1b 100644 --- a/Widgets.md +++ b/Widgets.md @@ -1,5 +1,3 @@ -[<- home](https://github.com/copycat-killer/lain/wiki) - Every widget is output by a `function`. Unless otherwise expressly noted, `function` returns a `wibox.widget.textbox`. From c32b6e91edba7d9a6672dbd294f7cfa7bfacc42a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 11:33:45 -0700 Subject: [PATCH 099/572] Updated Utilities (markdown) --- Utilities.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/Utilities.md b/Utilities.md index 8bb7597..3cf188e 100644 --- a/Utilities.md +++ b/Utilities.md @@ -1,5 +1,3 @@ -[<- home](https://github.com/copycat-killer/lain/wiki) - markup ------ From 8d112ea2cd0ed4abab24f16fbca0ae688bb6fc7b Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 11:35:11 -0700 Subject: [PATCH 100/572] Updated Utilities (markdown) --- Utilities.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Utilities.md b/Utilities.md index 3cf188e..cbf8c0f 100644 --- a/Utilities.md +++ b/Utilities.md @@ -49,7 +49,8 @@ menu\_clients\_current\_tags Similar to `awful.menu.clients()`, but this menu only shows the clients of currently visible tags. Use it with a key binding like this: - awful.key({ "Mod1" }, "Tab", function() + awful.key({ "Mod1" }, "Tab", + function() awful.menu.menu_keys.down = { "Down", "Alt_L", "Tab", "j" } awful.menu.menu_keys.up = { "Up", "k" } lain.util.menu_clients_current_tags({ width = 350 }, { keygrabber = true }) From 67a821b750f9ba0bbc990bd6f2f07cec467ab0fc Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 11:36:21 -0700 Subject: [PATCH 101/572] Updated Widgets (markdown) --- Widgets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index cdcac1b..6e6d361 100644 --- a/Widgets.md +++ b/Widgets.md @@ -8,7 +8,7 @@ We say this because, for some widget, `function` return a table to be used for n - [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) - [bat](https://github.com/copycat-killer/lain/wiki/bat) - [borderbox](https://github.com/copycat-killer/lain/wiki/borderbox) -- [calendar](https://github.com/copycat-killer/lain/wiki/caldendar) +- [calendar](https://github.com/copycat-killer/lain/wiki/calendar) - [cpu](https://github.com/copycat-killer/lain/wiki/cpu) - [fs](https://github.com/copycat-killer/lain/wiki/fs) - [imap](https://github.com/copycat-killer/lain/wiki/imap) From 59d91e51b01ff74af47190c0bd9e25ef97f83018 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 16:20:57 -0700 Subject: [PATCH 102/572] Updated calendar (markdown) --- calendar.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/calendar.md b/calendar.md index 182c805..1d63a65 100644 --- a/calendar.md +++ b/calendar.md @@ -1,11 +1,11 @@ Attaches a calendar notification to a widget. - lain.widgets.calendar:attach(mywidget) + lain.widgets.calendar:attach(widget) - Left click: switch to previous month. - Right click: switch to next month. -Optionally you can call the function with background and foreground colors arguments, both or just one: +Optionally you can call the function with bg and fg colors arguments, both or just one: lain.widgets.calendar:attach(mytextclock, "#FFFFFF", "#000000") -- or @@ -13,6 +13,8 @@ Optionally you can call the function with background and foreground colors argum -- or lain.widgets.calendar:attach(mytextclock, nil, "#000000") +default bg and fg colors are `beautiful.bg_normal` and `beautiful.fg_focus`. + Notification will show an icon displaying current day, and formatted output from ``cal`` with current day highlighted. From 54dc002251d1ce8e4304a601533db3df1cdbad6c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 16:35:54 -0700 Subject: [PATCH 104/572] Updated calendar (markdown) --- calendar.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/calendar.md b/calendar.md index 1d63a65..2b75840 100644 --- a/calendar.md +++ b/calendar.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Attaches a calendar notification to a widget. lain.widgets.calendar:attach(widget) From 28de71f2dff723991cae7495ff46026bf64295c7 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 7 Sep 2013 16:37:33 -0700 Subject: [PATCH 105/572] Updated mpd (markdown) --- mpd.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/mpd.md b/mpd.md index 27f3faf..33a0dd6 100644 --- a/mpd.md +++ b/mpd.md @@ -46,24 +46,24 @@ Finally, you can control the widget with key bindings like these: -- MPD control awful.key({ altkey, "Control" }, "Up", - function () - awful.util.spawn_with_shell( "mpc toggle || ncmpcpp toggle || ncmpc toggle || pms toggle", false ) - mympd.notify() - end), + function () + awful.util.spawn_with_shell("mpc toggle || ncmpcpp toggle || ncmpc toggle || pms toggle") + mpdwidget.notify() + end), awful.key({ altkey, "Control" }, "Down", - function () - awful.util.spawn_with_shell( "mpc stop || ncmpcpp stop || ncmpc stop || pms stop", false ) - mympd.notify() - end), + function () + awful.util.spawn_with_shell("mpc stop || ncmpcpp stop || ncmpc stop || pms stop") + mpdwidget.notify() + end), awful.key({ altkey, "Control" }, "Left", - function () - awful.util.spawn_with_shell( "mpc prev || ncmpcpp prev || ncmpc prev || pms prev", false ) - mympd.notify() - end), + function () + awful.util.spawn_with_shell("mpc prev || ncmpcpp prev || ncmpc prev || pms prev") + mpdwidget.notify() + end), awful.key({ altkey, "Control" }, "Right", - function () - awful.util.spawn_with_shell( "mpc next || ncmpcpp next || ncmpc next || pms next", false ) - mympd.notify() - end), + function () + awful.util.spawn_with_shell("mpc next || ncmpcpp next || ncmpc next || pms next") + mpdwidget.notify() + end), where `altkey = "Mod1"`. \ No newline at end of file From d34ff4b11ff7ffe2b26d459977bea173e0db2f65 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 05:01:10 -0700 Subject: [PATCH 106/572] Updated Home (markdown) --- Home.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Home.md b/Home.md index b98a1dd..9342879 100644 --- a/Home.md +++ b/Home.md @@ -2,7 +2,9 @@ Welcome to the Lain wiki! ### Installation -Simply clone this repository into your Awesome directory. +Simply clone this repository into your Awesome directory: + + git clone https://github.com/copycat-killer/lain.git ~/.config/awesome/lain ### Index From 5de0628f0dd7221c11e364c0ad3b3ca169e5e107 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 05:15:50 -0700 Subject: [PATCH 107/572] Updated mpd (markdown) --- mpd.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mpd.md b/mpd.md index 33a0dd6..4b97f05 100644 --- a/mpd.md +++ b/mpd.md @@ -27,8 +27,8 @@ Variable | Meaning | Type | Default `port` | MPD port | string | "6600" `music_dir` | Music directory | string | "~/Music" `refresh_timeout` | Refresh timeout seconds | int | 1 -`color_artist` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" -`color_song` | Song value color | string | `beautiful.fg_focus` or "#FFFFFF" +`header_color` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Song value color | string | `beautiful.fg_focus` or "#FFFFFF" `spr` | Separator text between artist and song values | string | " " `app` | Music program to spawn on click | string | "ncmpcpp" `shadow` | Hide widget when there are no songs playing | boolean | false From 3c0d8fea91aa3fc158c4314bbb96304d6b275f81 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 05:20:21 -0700 Subject: [PATCH 108/572] Updated imap (markdown) --- imap.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imap.md b/imap.md index d7e68b4..47e7b51 100644 --- a/imap.md +++ b/imap.md @@ -40,8 +40,7 @@ Variable | Meaning | Type | Default `refresh_timeout` | Refresh timeout seconds | int | 60 `header` | Text to show before value | string | " Mail " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color_newmail` | New mail value color | string | `beautiful.fg_focus` or "#FFFFFF" -`color_nomail` | No mail value color | string | `beautiful.fg_normal` or "#FFFFFF" +`color` | Mail value color | string | `beautiful.fg_focus` or "#FFFFFF" `mail_encoding` | Mail character encoding | string | autodetected `maxlen` | Maximum chars to display in notification | int | 200 `app` | Mail program to spawn on click | string | "mutt" From 9ceccbb5982ac45646e0dc4ed3ae5fbfa6832f3c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 06:14:11 -0700 Subject: [PATCH 109/572] Updated yawn (rest => markdown) --- yawn.md | 89 +++++++++++++++++++++++++++++++++++++ yawn.rest | 128 ------------------------------------------------------ 2 files changed, 89 insertions(+), 128 deletions(-) create mode 100644 yawn.md delete mode 100644 yawn.rest diff --git a/yawn.md b/yawn.md new file mode 100644 index 0000000..fa6e91c --- /dev/null +++ b/yawn.md @@ -0,0 +1,89 @@ +Yahoo's Awesome Weather notification +----------- + +Yawn provides brief and compact weather notification via Naughty and Yahoo! Weather API. + +Usage +----- + +You can ``register`` Yawn to get a set of widgets, or ``attach`` it to +an existent widget. + +### register + + yawn = lain.widgets.yawn(id, args) + +- ``id`` + + An integer that defines the WOEID code of your city. + To obtain it you can google 'yahoo weather %CITYNAME%' and follow the first link. + It will look like: + + http://weather.yahoo.com/united-states/california/san-diego-2487889/ + + and the last number in that link will be the ID you need. + +- ``args`` + + An optional table which can contain the following settings: + + Variables | Meaning | Type | Possible values | Default value + --- | --- | --- | --- | --- + `u` | Units | string | "c" (Celsius), "f" (Fahrenheit) | "c" + `toshow` | What to show | string | "forecast", "units", "both" | "forecast" + `color` | ``yawn.widget`` color | string | hexadecimal colors | + +The function creates an imagebox icon and a textbox widget. Add them to you wibox like this: + + right_layout:add(yawn.icon) + right_layout:add(yawn.widget) + +Hovering over ``yawn.icon`` will display the notification. + +### attach + + lain.widgets.yawn.attach(widget, id, args) + +Arguments: + +- ``widget`` + + The widget which you want to attach yawn to. + +- ``id`` + + Same as in ``register``. + +- ``args`` + + Same as in ``register``. + +Hovering over ``widget`` will display the notification. + +Popup shortcut +-------------- + +You can also create a keybinding for the weather popup like this: :: + + awful.key( { "Mod1" }, "w", function () yawn.show(5) end ) + +where ``show`` argument is an integer defining timeout seconds. + +Localization +------------ + +Default language is English, but Yawn can be localized. + +Move to `localizations` subdirectory and fill `localization_template`. + +Once you're done, rename it like your locale id. In my case: + + $ lua + Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio + > print(os.getenv("LANG"):match("(%S*$*)[.]")) + it_IT + > + +hence I named my file "it_IT" (Italian localization). + +**NOTE:** If you create a localization, feel free to send me! I will add it. \ No newline at end of file diff --git a/yawn.rest b/yawn.rest deleted file mode 100644 index 4551597..0000000 --- a/yawn.rest +++ /dev/null @@ -1,128 +0,0 @@ -(*Integration of this* module_) - -:Author: Luke Bonham -:License: WTFPLv2_ -:Version: 2.0-git - -Description ------------ - -Yawn is a module for Awesome WM providing brief and compact -weather notification via Naughty and Yahoo! Weather API. - -Originally a port of perceptive_, it became a completely new module after various improvements and style changes. - ------ -Usage ------ - -You can ``register`` Yawn to get a set of widgets, or ``attach`` it to -an existent widget. - -register -^^^^^^^^ - -Call: :: - - lain.widgets.yawn(id, args) - -Arguments: - -``id`` - An integer that defines the WOEID code of your city. - To obtain it you can google 'yahoo weather %CITYNAME%' and follow the first link. - It will look like:: - - http://weather.yahoo.com/united-states/california/san-diego-2487889/ - - and the last number in that link will be the ID you need. -``args`` - An optional table which can contain the following settings: - ``u`` - Units. Type: string. Possible values: "c" (Celsius), "f" (Fahrenheit). Default: "c". - - ``toshow`` - What to show. Type: string. Possible values: "units", "forecast", "both". - Default: "forecast". - - ``units_color`` - Color of units text. Type: string. Possible values: hexadecimal color - codes. - - ``forecast_color`` - Color of forecast text. Type: string. Possible values: hexadecimal color - codes. - - ``notification_color`` - Color of notification text. Type: string. Possible values: hexadecimal color - codes. - - ``spr`` - A separator. Type: string. You can define it when ``toshow`` is set to "both". - - ``footer`` - A footer. Type: string. You can define it when ``toshow`` is set to - "both". - -The function creates an imagebox icon and a textbox widget. Add them to you wibox like this: :: - - right_layout:add(lain.widgets.yawn.icon) - right_layout:add(lain.widgets.yawn.widget) - -Hovering over ``yawn.icon`` will display the notification. - -attach -^^^^^^ - -Call: :: - - lain.widgets.yawn.attach(widget, id, args) - -Arguments: - -``widget`` - The widget which you want to attach yawn to. -``id`` - same as in ``register`` -``args`` - same as in ``register`` - -Hovering over ``widget`` will display the notification. - --------------- -Popup shortcut --------------- - -You can also create a keybinding for the weather popup like this: :: - - globalkeys = awful.util.table.join( - ... - awful.key( { "Mod1" }, "w", function () lain.widgets.yawn.show(5) end ) - ... - -where ``show`` argument is an integer defining timeout seconds. - ------------- -Localization ------------- - -Default language is English, but Yawn can be localized. -Move to ``localizations`` subdirectory and fill ``localization_template``. - -Once you're done, rename it like your locale id. In my case: :: - - $ lua - Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio - > print(os.getenv("LANG"):match("(%S*$*)[.]")) - it_IT - > - -hence I named my file "it_IT" (Italian localization). - -**NOTE:** If you create a localization, feel free to send me! I will add it. - -.. _module: https://github.com/copycat-killer/yawn -.. _WTFPLv2: http://www.wtfpl.net -.. _perceptive: https://github.com/ioga/perceptive -.. _Tamsyn: http://www.fial.com/~scott/tamsyn-font/ -.. _Rainbow: https://github.com/copycat-killer/awesome-copycats> \ No newline at end of file From 2c616b6b27047ef8f807d6edb80c4da005701903 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 06:15:08 -0700 Subject: [PATCH 110/572] Updated yawn (markdown) --- yawn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yawn.md b/yawn.md index fa6e91c..b58846c 100644 --- a/yawn.md +++ b/yawn.md @@ -48,7 +48,7 @@ Arguments: - ``widget`` - The widget which you want to attach yawn to. + The widget which you want to attach Yawn to. - ``id`` From e10db094153d2d2cc605aac179a0f18ed7161929 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 06:19:10 -0700 Subject: [PATCH 111/572] Updated yawn (markdown) --- yawn.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/yawn.md b/yawn.md index b58846c..070bf2e 100644 --- a/yawn.md +++ b/yawn.md @@ -1,7 +1,6 @@ -Yahoo's Awesome Weather notification ------------ +(YAhoo! Weather Notification) -Yawn provides brief and compact weather notification via Naughty and Yahoo! Weather API. +Yawn provides brief and compact Yahoo! Weather notification. Usage ----- @@ -63,7 +62,7 @@ Hovering over ``widget`` will display the notification. Popup shortcut -------------- -You can also create a keybinding for the weather popup like this: :: +You can also create a keybinding for the weather popup like this: awful.key( { "Mod1" }, "w", function () yawn.show(5) end ) From 709a965d73a215fdf8234bc464168280c2d19d6c Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 8 Sep 2013 15:41:11 +0200 Subject: [PATCH 112/572] some fixes --- widgets/calendar.lua | 2 +- widgets/fs.lua | 8 +++---- widgets/imap.lua | 13 ++++++------ widgets/mpd.lua | 17 +++++++-------- widgets/yawn/init.lua | 49 +++++++++++++++++++------------------------ 5 files changed, 41 insertions(+), 48 deletions(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index 4b6d469..38b4d8b 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -29,7 +29,7 @@ local function create(background, foreground) calendar.notify_icon = nil calendar.font_size = 12 calendar.bg = background or beautiful.bg_normal or "#FFFFFF" - calendar.fg = foreground or beautiful.fg_normal or "#FFFFFF" + calendar.fg = foreground or beautiful.fg_focus or "#FFFFFF" end function calendar:hide() diff --git a/widgets/fs.lua b/widgets/fs.lua index 9611617..283771f 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -43,7 +43,7 @@ function fs:show(t_out) notification = naughty.notify({ text = ws, timeout = t_out, - fg = beautiful.fg_focus, + fg = fs.color, }) end @@ -56,8 +56,8 @@ local function worker(args) local refresh_timeout = args.refresh_timeout or 600 local header = args.header or " Hdd " local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or "#FFFFFF" - local footer = args.header or "" + fs.color = args.color or beautiful.fg_focus or "#FFFFFF" + local footer = args.footer or "" local shadow = args.shadow or false local myfs = wibox.widget.textbox() @@ -71,7 +71,7 @@ local function worker(args) local function set_text() local info = fs_info['{' .. partition .. ' used_p}'] myfs:set_markup(markup(header_color, header) - .. markup(color, info .. footer) .. " ") + .. markup(fs.color, info .. footer)) end for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount) diff --git a/widgets/imap.lua b/widgets/imap.lua index 94652b6..5f8667d 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -35,8 +35,7 @@ function worker(args) local refresh_timeout = args.refresh_timeout or 60 local header = args.header or " Mail " local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color_newmail = args.color_newmail or beautiful.fg_focus or "#FFFFFF" - local color_nomail = args.color_nomail or beautiful.fg_normal or "#FFFFFF" + local color = args.color or beautiful.fg_focus or "#FFFFFF" local mail_encoding = args.mail_encoding or nil local maxlen = args.maxlen or 200 local app = args.app or "mutt" @@ -63,7 +62,7 @@ function worker(args) then myimapcheck:set_text('') else - myimapcheck:set_markup(markup(color_nomail, " no mail ")) + myimapcheck:set_markup(markup(color, " no mail ")) end end @@ -97,8 +96,8 @@ function worker(args) elseif ws:find("CheckMailError: invalid credentials") ~= nil then helpers.set_map(mail, true) - myimapcheck.set_markup(markup(header_color, header) .. - markup(color_newmail, "invalid credentials ")) + myimapcheck:set_markup(markup(header_color, header) .. + markup(color, "invalid credentials ")) else mailcount = ws:match("%d") or "?" @@ -109,7 +108,7 @@ function worker(args) end myimapcheck:set_markup(markup(header_color, header) .. - markup(color_newmail, mailcount) .. " ") + markup(color, mailcount) .. " ") if helpers.get_map(mail) then @@ -137,7 +136,7 @@ function worker(args) end naughty.notify({ title = notify_title, - fg = color_newmail, + fg = color, text = ws, icon = beautiful.lain_mail_notify or helpers.icons_dir .. "mail.png", diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 0b9a4c9..9a9c28e 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -33,8 +33,8 @@ function worker(args) local port = args.port or "6600" local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" local refresh_timeout = args.refresh_timeout or 1 - local color_artist = args.color_artist or beautiful.fg_normal or "#FFFFFF" - local color_song = args.color_song or beautiful.fg_focus or "#FFFFFF" + local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" + local color = args.color or beautiful.fg_focus or "#FFFFFF" local spr = args.spr or " " local app = args.app or "ncmpcpp" local shadow = args.shadow or false @@ -53,7 +53,7 @@ function worker(args) then mympd:set_text('') else - mympd:set_markup(markup(color_artist, " mpd "), markup(color_song , "off ")) + mympd:set_markup(markup(header_color, " mpd "), markup(color , "off ")) end end @@ -97,20 +97,19 @@ function worker(args) mpd_state["{Date}"] .. "\n" .. mpd_state["{Title}"], icon = "/tmp/mpdcover.png", - fg = beautiful.fg_focus or "#FFFFFF", - bg = beautiful.bg_normal or "#000000" , + fg = color, timeout = 6, replaces_id = mpd.id }).id end - mympd:set_markup(markup(color_artist, " " .. mpd_state["{Artist}"]) + mympd:set_markup(markup(header_color, " " .. mpd_state["{Artist}"]) .. spr .. - markup(color_song, mpd_state["{Title}"] .. " ")) + markup(color, mpd_state["{Title}"] .. " ")) elseif mpd_state["{state}"] == "pause" then - mympd:set_markup(markup(color_artist, " mpd") + mympd:set_markup(markup(header_color, " mpd") .. spr .. - markup(color_song, "paused ")) + markup(color, "paused ")) else helpers.set_map("current mpd track", nil) set_nompd() diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index f248e25..20c90b1 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -1,11 +1,9 @@ --[[ - - Yahoo's Awesome (WM) Weather Notification - - Licensed under WTFPL v2 - * (c) 2013, Luke Bonham - + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + --]] local markup = require("lain.util.markup") @@ -26,8 +24,7 @@ local tonumber = tonumber local setmetatable = setmetatable --- yawn integration --- https://github.com/copycat-killer/yawn +-- YAhoo! Weather Notification -- lain.widgets.yawn local yawn = { @@ -52,20 +49,19 @@ local update_timer = nil local function fetch_weather(args) local toshow = args.toshow or "forecast" - local spr = args.spr or " " - local footer = args.footer or "" local url = api_url .. units_set .. city_id local f = io.popen("curl --connect-timeout 1 -fsm 2 '" .. url .. "'" ) local text = f:read("*all") - io.close(f) + f:close() -- In case of no connection or invalid city ID -- widgets won't display if text == "" or text:match("City not found") then sky = icon_path .. "na.png" + yawn.icon:set_image(sky) if text == "" then weather_data = "Service not available at the moment." return "N/A" @@ -119,14 +115,14 @@ local function fetch_weather(args) if f == nil then sky = icon_path .. "na.png" else - io.close(f) + f:close() end -- Localization local f = io.open(localizations_path .. language, "r") if language:find("en_") == nil and f ~= nil then - io.close(f) + f:close() for line in io.lines(localizations_path .. language) do word = string.sub(line, 1, line:find("|")-1) @@ -136,18 +132,20 @@ local function fetch_weather(args) end -- Finally setting infos - forecast = weather_data:match(": %S+"):gsub(": ", ""):gsub(",", "") - yawn.forecast = markup(yawn.forecast_color, markup.font(beautiful.font, forecast)) - yawn.units = markup(yawn.units_color, markup.font(beautiful.font, units)) + both = weather_data:match(": %S+.-\n"):gsub(": ", "") + forecast = weather_data:match(": %S+.-,"):gsub(": ", ""):gsub(",", "\n") + units = units:gsub(" ", "") + + yawn.forecast = markup(yawn.color, " " .. markup.font(beautiful.font, forecast) .. " ") + yawn.units = markup(yawn.color, " " .. markup.font(beautiful.font, units)) yawn.icon:set_image(sky) if toshow == "forecast" then return yawn.forecast elseif toshow == "units" then return yawn.units - else -- "both" - return yawn.forecast .. spr - .. yawn.units .. footer + else + return both end end @@ -175,21 +173,16 @@ function yawn.show(t_out) text = weather_data, icon = sky, timeout = t_out, - fg = yawn.notification_color + fg = yawn.color }) end function yawn.register(id, args) local args = args or {} - settings = { args.toshow, args.spr, args.footer } + settings = args - yawn.units_color = args.units_color or - beautiful.fg_normal or "#FFFFFF" - yawn.forecast_color = args.forecast_color or - yawn.units_color - yawn.notification_color = args.notification_color or - beautiful.fg_focus or "#FFFFFF" + yawn.color = args.color or beautiful.fg_normal or "#FFFFFF" if args.u == "f" then units_set = '?u=f&w=' end @@ -208,6 +201,8 @@ function yawn.register(id, args) yawn.icon:connect_signal("mouse::leave", function() yawn.hide() end) + + return yawn end function yawn.attach(widget, id, args) From 24144da70de059d5eb5b81d0bd6bf61ce6b36dd6 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:12:28 -0700 Subject: [PATCH 113/572] Updated calendar (markdown) --- calendar.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/calendar.md b/calendar.md index 2b75840..5b4587d 100644 --- a/calendar.md +++ b/calendar.md @@ -7,7 +7,7 @@ Attaches a calendar notification to a widget. - Left click: switch to previous month. - Right click: switch to next month. -Optionally you can call the function with bg and fg colors arguments, both or just one: +Optionally you can call the function with fg and bg colors arguments, both or just one: lain.widgets.calendar:attach(mytextclock, "#FFFFFF", "#000000") -- or @@ -15,7 +15,7 @@ Optionally you can call the function with bg and fg colors arguments, both or ju -- or lain.widgets.calendar:attach(mytextclock, nil, "#000000") -default bg and fg colors are `beautiful.bg_normal` and `beautiful.fg_focus`. +default fg and fb colors are `beautiful.fg_focus` and `beautiful.bg_normal`. Notification will show an icon displaying current day, and formatted output from ``cal`` with current day highlighted. From 87e14e029c7112a6628d0ef149d65d675ef5c5c6 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:29:56 -0700 Subject: [PATCH 114/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index 9dcc894..7f7cd82 100644 --- a/cpu.md +++ b/cpu.md @@ -9,7 +9,7 @@ The function takes a table as optional argument, which can contain: Variable | Meaning | Type | Default --- | --- | --- | --- `refresh_timeout` | Refresh timeout seconds | int | 10 -`header` | Text to show before value | string | " Cpu " +`header` | Text to show before value | string | "Cpu" `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `footer` | Text to add after value | string | "%" From c0d4434ee153a9dcc7d9ee471ab34a12d5abfa79 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:30:21 -0700 Subject: [PATCH 115/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index 7f7cd82..8a3d5d8 100644 --- a/cpu.md +++ b/cpu.md @@ -9,7 +9,7 @@ The function takes a table as optional argument, which can contain: Variable | Meaning | Type | Default --- | --- | --- | --- `refresh_timeout` | Refresh timeout seconds | int | 10 -`header` | Text to show before value | string | "Cpu" +`header` | Text to show before value | string | "Cpu " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `footer` | Text to add after value | string | "%" From cd5dc23194baf0c769e2ee78537529b1815cb083 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:30:32 -0700 Subject: [PATCH 116/572] Updated bat (markdown) --- bat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bat.md b/bat.md index 79c17da..2d80786 100644 --- a/bat.md +++ b/bat.md @@ -14,7 +14,7 @@ Variable | Meaning | Type | Default `battery` | Identifier of the battery | string | "BAT0" `show_all` | Show all values (true), or only remaining capacity (false) | boolean | false `refresh_timeout` | Refresh timeout seconds | int | 30 -`header` | Text to show before value | string | " Bat " +`header` | Text to show before value | string | "Bat " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `shadow` | Hide the widget when battery is not present | boolean | false \ No newline at end of file From 41d5a985db4af03af4f658ce69e97e599d97106e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:31:22 -0700 Subject: [PATCH 117/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index 4946fe7..ccb7386 100644 --- a/fs.md +++ b/fs.md @@ -12,7 +12,7 @@ Variable | Meaning | Type | Default --- | --- | --- | --- `partition` | Partition to monitor | string | "/" `refresh_timeout` | Refresh timeout seconds | int | 600 -`header` | Text to show before value | string | " Hdd " +`header` | Text to show before value | string | "Hdd " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `footer` | Text to show after value | string | "%" From 07040e6db6de9fba139c9a60d0c453962dc4276e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:33:20 -0700 Subject: [PATCH 118/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index 47e7b51..e30f688 100644 --- a/imap.md +++ b/imap.md @@ -38,7 +38,7 @@ Variable | Meaning | Type | Default --- | --- | --- | --- `port` | IMAP port | int | 993 `refresh_timeout` | Refresh timeout seconds | int | 60 -`header` | Text to show before value | string | " Mail " +`header` | Text to show before value | string | "Mail " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Mail value color | string | `beautiful.fg_focus` or "#FFFFFF" `mail_encoding` | Mail character encoding | string | autodetected From 787612387af2e39504084d3cde7f7d69eb16d442 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:34:36 -0700 Subject: [PATCH 119/572] Updated mem (markdown) --- mem.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mem.md b/mem.md index 173452d..69db14b 100644 --- a/mem.md +++ b/mem.md @@ -13,7 +13,7 @@ Variable | Meaning | Type | Default `refresh_timeout` | Refresh timeout seconds | int | 10 `show_swap` | Show amount of used swap space? | boolean | false `show_total` | Show amout of total memory? | boolean | false -`header` | Text to show before value | string | " Mem " +`header` | Text to show before value | string | "Mem " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `footer` | Text to show after value | string | "MB" From 806d7f3a97b19235c49240bd8d718cd0150fa08e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:51:36 -0700 Subject: [PATCH 120/572] Updated bat (markdown) --- bat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bat.md b/bat.md index 2d80786..79c17da 100644 --- a/bat.md +++ b/bat.md @@ -14,7 +14,7 @@ Variable | Meaning | Type | Default `battery` | Identifier of the battery | string | "BAT0" `show_all` | Show all values (true), or only remaining capacity (false) | boolean | false `refresh_timeout` | Refresh timeout seconds | int | 30 -`header` | Text to show before value | string | "Bat " +`header` | Text to show before value | string | " Bat " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `shadow` | Hide the widget when battery is not present | boolean | false \ No newline at end of file From 09c8c2d740ff589236ea02416d7b81e65ab1338d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:51:51 -0700 Subject: [PATCH 121/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index 8a3d5d8..9dcc894 100644 --- a/cpu.md +++ b/cpu.md @@ -9,7 +9,7 @@ The function takes a table as optional argument, which can contain: Variable | Meaning | Type | Default --- | --- | --- | --- `refresh_timeout` | Refresh timeout seconds | int | 10 -`header` | Text to show before value | string | "Cpu " +`header` | Text to show before value | string | " Cpu " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `footer` | Text to add after value | string | "%" From c07a1c8721596823a948b76f48feb61a6b309fee Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:52:01 -0700 Subject: [PATCH 122/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index 9dcc894..1dce16e 100644 --- a/cpu.md +++ b/cpu.md @@ -12,6 +12,6 @@ Variable | Meaning | Type | Default `header` | Text to show before value | string | " Cpu " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to add after value | string | "%" +`footer` | Text to add after value | string | "% " **Note**: `footer` color is `color`. \ No newline at end of file From 4986ccc0192fac14ffe0f6a9d69ad99325ea98a9 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:52:39 -0700 Subject: [PATCH 123/572] Updated fs (markdown) --- fs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs.md b/fs.md index ccb7386..eb67110 100644 --- a/fs.md +++ b/fs.md @@ -12,10 +12,10 @@ Variable | Meaning | Type | Default --- | --- | --- | --- `partition` | Partition to monitor | string | "/" `refresh_timeout` | Refresh timeout seconds | int | 600 -`header` | Text to show before value | string | "Hdd " +`header` | Text to show before value | string | " Hdd " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to show after value | string | "%" +`footer` | Text to show after value | string | " " `shadow` | Hide the widget if `partition` < 90 | boolean | false **Note**: `footer` color is `color`. From 57a0abbbf759c0a4ced125a9ff0ada943851d5ae Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:54:06 -0700 Subject: [PATCH 124/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index e30f688..47e7b51 100644 --- a/imap.md +++ b/imap.md @@ -38,7 +38,7 @@ Variable | Meaning | Type | Default --- | --- | --- | --- `port` | IMAP port | int | 993 `refresh_timeout` | Refresh timeout seconds | int | 60 -`header` | Text to show before value | string | "Mail " +`header` | Text to show before value | string | " Mail " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Mail value color | string | `beautiful.fg_focus` or "#FFFFFF" `mail_encoding` | Mail character encoding | string | autodetected From 29157ca037eb6d2ab785fd7024bc1a116a9e8a87 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 09:55:18 -0700 Subject: [PATCH 125/572] Updated mem (markdown) --- mem.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mem.md b/mem.md index 69db14b..68c6748 100644 --- a/mem.md +++ b/mem.md @@ -13,9 +13,9 @@ Variable | Meaning | Type | Default `refresh_timeout` | Refresh timeout seconds | int | 10 `show_swap` | Show amount of used swap space? | boolean | false `show_total` | Show amout of total memory? | boolean | false -`header` | Text to show before value | string | "Mem " +`header` | Text to show before value | string | " Mem " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to show after value | string | "MB" +`footer` | Text to show after value | string | "MB " **Note**: `footer` color is `color`. \ No newline at end of file From 5ab75a15300f5e3eda4ee444dc3702a8eecbff69 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 8 Sep 2013 19:19:41 +0200 Subject: [PATCH 126/572] some other space fixes --- widgets/calendar.lua | 6 +++--- widgets/cpu.lua | 4 ++-- widgets/fs.lua | 2 +- widgets/imap.lua | 6 +++--- widgets/maildir.lua | 2 +- widgets/mem.lua | 8 ++++---- widgets/mpd.lua | 11 ++++++----- 7 files changed, 20 insertions(+), 19 deletions(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index 38b4d8b..e5f6e88 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -23,7 +23,7 @@ local setmetatable = setmetatable local calendar = {} local notification = nil -local function create(background, foreground) +local function create(foreground, background) calendar.offset = 0 calendar.icons_dir = icons_dir .. "cal/white/" -- default calendar.notify_icon = nil @@ -111,8 +111,8 @@ function calendar:show(t_out, inc_offset) timeout = tims }) end -function calendar:attach(widget, background, foreground) - create(background, foreground) +function calendar:attach(widget, foreground, background) + create(foreground, background) widget:connect_signal("mouse::enter", function () calendar:show() end) widget:connect_signal("mouse::leave", function () calendar:hide() end) widget:buttons(awful.util.table.join( awful.button({ }, 1, function () diff --git a/widgets/cpu.lua b/widgets/cpu.lua index cf0b76c..3890e5e 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -32,7 +32,7 @@ function worker(args) local header = args.header or " Cpu " local header_color = args.header or beautiful.fg_normal or "#FFFFFF" local color = args.color or beautiful.fg_focus or "#FFFFFF" - local footer = args.footer or "%" + local footer = args.footer or "% " local w = wibox.widget.textbox() @@ -62,7 +62,7 @@ function worker(args) local dtotal = total - cpu.last_total local dta = math.ceil((dactive / dtotal) * 100) - w:set_markup(markup(header_color, header) .. markup(color, dta .. footer) .. " ") + w:set_markup(markup(header_color, header) .. markup(color, dta .. footer)) -- Save current data for the next run. cpu.last_active = active diff --git a/widgets/fs.lua b/widgets/fs.lua index 283771f..344bd87 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -57,7 +57,7 @@ local function worker(args) local header = args.header or " Hdd " local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" fs.color = args.color or beautiful.fg_focus or "#FFFFFF" - local footer = args.footer or "" + local footer = args.footer or " " local shadow = args.shadow or false local myfs = wibox.widget.textbox() diff --git a/widgets/imap.lua b/widgets/imap.lua index 5f8667d..f06660b 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -33,7 +33,7 @@ function worker(args) local port = args.port or "993" local refresh_timeout = args.refresh_timeout or 60 - local header = args.header or " Mail " + local header = args.header or "Mail " local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" local color = args.color or beautiful.fg_focus or "#FFFFFF" local mail_encoding = args.mail_encoding or nil @@ -96,7 +96,7 @@ function worker(args) elseif ws:find("CheckMailError: invalid credentials") ~= nil then helpers.set_map(mail, true) - myimapcheck:set_markup(markup(header_color, header) .. + myimapcheck:set_markup(" " .. markup(header_color, header) .. markup(color, "invalid credentials ")) else mailcount = ws:match("%d") or "?" @@ -107,7 +107,7 @@ function worker(args) helpers.set_map(mail .. " count", mailcount) end - myimapcheck:set_markup(markup(header_color, header) .. + myimapcheck:set_markup(" " .. markup(header_color, header) .. markup(color, mailcount) .. " ") if helpers.get_map(mail) diff --git a/widgets/maildir.lua b/widgets/maildir.lua index b5437bd..98de091 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -108,7 +108,7 @@ function worker(args) myimapcheck:set_markup(markup(color_nomail, " no mail ")) end else - myimapcheck:set_markup(markup(header_color, header) .. + myimapcheck:set_markup(" " .. markup(header_color, header) .. markup(color_newmail, newmail) .. " ") end end diff --git a/widgets/mem.lua b/widgets/mem.lua index 09be00f..3034e89 100644 --- a/widgets/mem.lua +++ b/widgets/mem.lua @@ -35,7 +35,7 @@ function worker(args) local header = args.header or " Mem " local header_color = args.header or beautiful.fg_normal or "#FFFFFF" local color = args.color or beautiful.fg_focus or "#FFFFFF" - local footer = args.footer or "MB" + local footer = args.footer or "MB " local widg = wibox.widget.textbox() @@ -62,17 +62,17 @@ function worker(args) then local fmt = "%" .. string.len(mem.total) .. ".0f/%.0f" widg:set_markup(markup(header_color, header) .. - markup(color, string.format(fmt, used, mem.total) .. footer .. " ")) + markup(color, string.format(fmt, used, mem.total) .. footer)) else widg:set_markup(markup(header_color, header) .. - markup(color, used .. footer .. " ")) + markup(color, used .. footer)) end if show_swap then widg:set_markup(widg._layout.text .. ' (' .. string.format('%.0f '.. footer, swapused) - .. ') ') + .. ')') end end diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 9a9c28e..8db62ae 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -36,6 +36,7 @@ function worker(args) local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" local color = args.color or beautiful.fg_focus or "#FFFFFF" local spr = args.spr or " " + local footer = args.footer or "" local app = args.app or "ncmpcpp" local shadow = args.shadow or false @@ -53,7 +54,7 @@ function worker(args) then mympd:set_text('') else - mympd:set_markup(markup(header_color, " mpd "), markup(color , "off ")) + mympd:set_markup(markup(header_color, "mpd ") .. markup(color , "off") .. footer) end end @@ -102,14 +103,14 @@ function worker(args) replaces_id = mpd.id }).id end - mympd:set_markup(markup(header_color, " " .. mpd_state["{Artist}"]) + mympd:set_markup(markup(header_color, mpd_state["{Artist}"]) .. spr .. - markup(color, mpd_state["{Title}"] .. " ")) + markup(color, mpd_state["{Title}"]) .. footer) elseif mpd_state["{state}"] == "pause" then - mympd:set_markup(markup(header_color, " mpd") + mympd:set_markup(markup(header_color, "mpd") .. spr .. - markup(color, "paused ")) + markup(color, "paused") .. footer) else helpers.set_map("current mpd track", nil) set_nompd() From 825ea53e63a016ed60e4342353ed0c4521a3ec8b Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 10:20:49 -0700 Subject: [PATCH 127/572] Updated mpd (markdown) --- mpd.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mpd.md b/mpd.md index 4b97f05..4a3398a 100644 --- a/mpd.md +++ b/mpd.md @@ -29,11 +29,12 @@ Variable | Meaning | Type | Default `refresh_timeout` | Refresh timeout seconds | int | 1 `header_color` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Song value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to append to values | string | "" `spr` | Separator text between artist and song values | string | " " `app` | Music program to spawn on click | string | "ncmpcpp" `shadow` | Hide widget when there are no songs playing | boolean | false -**Note**: `spr` can be a markup text. +**Note**: `footer` and `spr` can be markup text. `lain.widgets.mpd` outputs the following table: From f075850c6b45229efa768dc62a776420fed5b420 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 10:21:51 -0700 Subject: [PATCH 128/572] Updated mpd (markdown) --- mpd.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mpd.md b/mpd.md index 4a3398a..1d35f02 100644 --- a/mpd.md +++ b/mpd.md @@ -29,12 +29,12 @@ Variable | Meaning | Type | Default `refresh_timeout` | Refresh timeout seconds | int | 1 `header_color` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Song value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to append to values | string | "" `spr` | Separator text between artist and song values | string | " " +`footer` | Text to append after values | string | "" `app` | Music program to spawn on click | string | "ncmpcpp" `shadow` | Hide widget when there are no songs playing | boolean | false -**Note**: `footer` and `spr` can be markup text. +**Note**: `spr` and `footer` can be markup text. `lain.widgets.mpd` outputs the following table: From 13e970ca857ef64905ab64883d5621d326a36319 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 16:42:15 -0700 Subject: [PATCH 129/572] Updated net (markdown) --- net.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net.md b/net.md index b02c239..82772d7 100644 --- a/net.md +++ b/net.md @@ -14,11 +14,12 @@ Variable | Meaning | Type | Default `spr` | Separator text between download and upload values | string | " " `header` | Text to show before value | string | `iface` `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" +`footer` | Text to append after value | string | "" `color_up` | Upload value color | string | `beautiful.fg_focus` or "#FFFFFF" `color_down` | Download value color | string | `beautiful.fg_focus` or "#FFFFFF" `app` | Net program to spawn on click | string | "sudo wifi-menu" -**Note**: `spr` can be a markup text. +**Note**: `spr` and `footer` can be a markup text. Possible value for `units` are stored in table `lain.widgets.net.units`, which contains: From a9073b7f86fe7540bad749c5d035f43c7ddd183d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 16:51:10 -0700 Subject: [PATCH 130/572] Updated alsabar (markdown) --- alsabar.md | 1 + 1 file changed, 1 insertion(+) diff --git a/alsabar.md b/alsabar.md index 9338ff8..9b5a711 100644 --- a/alsabar.md +++ b/alsabar.md @@ -42,6 +42,7 @@ Variable | Meaning | Type | Default --- | --- | --- | --- `font` | Notifications font | string | The one defined in `beautiful.font` `font_size` | Notifications font size | string | "11" +`color` | Notifications color | string | `beautiful.fg_focus` `bar_size` | Wibox height | int | 18 It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height, From 04138e56b6341984b8a27af50f88d38ffb9a67da Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 9 Sep 2013 01:58:31 +0200 Subject: [PATCH 131/572] readme updated --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 22d9a27..2524de3 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ Layouts, widgets and utilities for Awesome WM :Author: Luke Bonham :Version: 1.0-git :License: GNU-GPLv2_ -:Source: https://github.com/copycat-killer/vain +:Source: https://github.com/copycat-killer/lain Based on a port of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions in order to improve Awesome usability and configurability. From 14886c85add2201b0fee20692f609a610502f450 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 8 Sep 2013 17:09:36 -0700 Subject: [PATCH 132/572] Updated mpd (markdown) --- mpd.md | 1 + 1 file changed, 1 insertion(+) diff --git a/mpd.md b/mpd.md index 1d35f02..7640b4c 100644 --- a/mpd.md +++ b/mpd.md @@ -27,6 +27,7 @@ Variable | Meaning | Type | Default `port` | MPD port | string | "6600" `music_dir` | Music directory | string | "~/Music" `refresh_timeout` | Refresh timeout seconds | int | 1 +`pre` | Text before values | string | "" `header_color` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Song value color | string | `beautiful.fg_focus` or "#FFFFFF" `spr` | Separator text between artist and song values | string | " " From 33f0fe93e0a581dedf4991e2cccacb82396e6eb0 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 04:52:53 -0700 Subject: [PATCH 133/572] Updated alsa (markdown) --- alsa.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/alsa.md b/alsa.md index 4cfa8f3..337f7e8 100644 --- a/alsa.md +++ b/alsa.md @@ -17,8 +17,11 @@ Variable | Meaning | Type | Default `header` | Text to show before value | string | " Vol " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to append after value | string | "" -and outputs the following table: +*Note*: `footer` can be markup text. + +`lain.widgets.alsa` outputs the following table: Variable | Meaning | Type --- | --- | --- From babddf023fba21f391c7309f30b48d82de92ea3f Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 04:53:58 -0700 Subject: [PATCH 134/572] Updated alsa (markdown) --- alsa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsa.md b/alsa.md index 337f7e8..2ca1746 100644 --- a/alsa.md +++ b/alsa.md @@ -17,7 +17,7 @@ Variable | Meaning | Type | Default `header` | Text to show before value | string | " Vol " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to append after value | string | "" +`footer` | Text to append after value | string | " " *Note*: `footer` can be markup text. From 33b02c39b04508303a01a91a3481c254a8227fe5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 04:58:26 -0700 Subject: [PATCH 135/572] Updated bat (markdown) --- bat.md | 1 + 1 file changed, 1 insertion(+) diff --git a/bat.md b/bat.md index 79c17da..5d89b14 100644 --- a/bat.md +++ b/bat.md @@ -17,4 +17,5 @@ Variable | Meaning | Type | Default `header` | Text to show before value | string | " Bat " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to append after value | string | " " `shadow` | Hide the widget when battery is not present | boolean | false \ No newline at end of file From 131ccc38a7f306a19c6b756dbf3d203f4b6d34e3 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 04:59:05 -0700 Subject: [PATCH 136/572] Updated bat (markdown) --- bat.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bat.md b/bat.md index 5d89b14..8b24151 100644 --- a/bat.md +++ b/bat.md @@ -18,4 +18,6 @@ Variable | Meaning | Type | Default `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" `footer` | Text to append after value | string | " " -`shadow` | Hide the widget when battery is not present | boolean | false \ No newline at end of file +`shadow` | Hide the widget when battery is not present | boolean | false + +**Note**: `footer` can be markup text. \ No newline at end of file From 9f9b4c959dfbcb6ae82d56cf1cedb7eb04f791e8 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 05:00:23 -0700 Subject: [PATCH 137/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index eb67110..7ee1f5c 100644 --- a/fs.md +++ b/fs.md @@ -18,7 +18,7 @@ Variable | Meaning | Type | Default `footer` | Text to show after value | string | " " `shadow` | Hide the widget if `partition` < 90 | boolean | false -**Note**: `footer` color is `color`. +**Note**: `footer` can be markup text. `lain.widgets.fs` outputs the following table: From d685704da2cabc0af5425066a599c2ce2ffd90d6 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 05:01:17 -0700 Subject: [PATCH 138/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index 7ee1f5c..eb67110 100644 --- a/fs.md +++ b/fs.md @@ -18,7 +18,7 @@ Variable | Meaning | Type | Default `footer` | Text to show after value | string | " " `shadow` | Hide the widget if `partition` < 90 | boolean | false -**Note**: `footer` can be markup text. +**Note**: `footer` color is `color`. `lain.widgets.fs` outputs the following table: From 4e5236d8f385f2c629f972c091633551c6e20615 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 05:03:26 -0700 Subject: [PATCH 139/572] Updated imap (markdown) --- imap.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imap.md b/imap.md index 47e7b51..97cd437 100644 --- a/imap.md +++ b/imap.md @@ -41,12 +41,15 @@ Variable | Meaning | Type | Default `header` | Text to show before value | string | " Mail " `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color` | Mail value color | string | `beautiful.fg_focus` or "#FFFFFF" +`footer` | Text to append after value | string | " " `mail_encoding` | Mail character encoding | string | autodetected `maxlen` | Maximum chars to display in notification | int | 200 `app` | Mail program to spawn on click | string | "mutt" `shadow` | Hide widget when there are no mails | boolean | false `is_plain` | Define whether `password` is a plain password (true) or a function that retrieves it (false) | boolean | false +**Note**: `footer` can be markup text. + Let's focus better on `is_plain`. You can just set your password like this: From 2a11ae6544d4bf2f1c0e3f772aa3c4cc1797788a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 05:06:06 -0700 Subject: [PATCH 140/572] Updated maildir (markdown) --- maildir.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/maildir.md b/maildir.md index c35b2f9..bd81c02 100644 --- a/maildir.md +++ b/maildir.md @@ -33,5 +33,8 @@ Variable | Meaning | Type | Default `header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" `color_newmail` | New mail value color | string | `beautiful.fg_focus` or "#FFFFFF" `color_nomail` | No mail value color | string | `beautiful.fg_normal` or "#FFFFFF" +`footer` | Text to append after value | string | " " `app` | Mail program to spawn on click | string | "mutt"| boolean | false -`shadow` | Hide widget when there are no mails | boolean | false \ No newline at end of file +`shadow` | Hide widget when there are no mails | boolean | false + +**Note**: `footer` can be markup text. \ No newline at end of file From 199853fdda10f110417f50312a7b6b0d598de25c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 05:06:43 -0700 Subject: [PATCH 141/572] Updated maildir (markdown) --- maildir.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/maildir.md b/maildir.md index bd81c02..a30e59f 100644 --- a/maildir.md +++ b/maildir.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + Shows maildirs status in a textbox. Maildirs are structured as follows: From 38e27c67b35942ab98d5aea4dbe855f56d88eb73 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 05:14:40 -0700 Subject: [PATCH 142/572] Updated mpd (markdown) --- mpd.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mpd.md b/mpd.md index 7640b4c..2a0ba32 100644 --- a/mpd.md +++ b/mpd.md @@ -27,9 +27,9 @@ Variable | Meaning | Type | Default `port` | MPD port | string | "6600" `music_dir` | Music directory | string | "~/Music" `refresh_timeout` | Refresh timeout seconds | int | 1 -`pre` | Text before values | string | "" -`header_color` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Song value color | string | `beautiful.fg_focus` or "#FFFFFF" +`header` | Text before values | string | "" +`artist_color` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" +`song_color` | Song value color | string | `beautiful.fg_focus` or "#FFFFFF" `spr` | Separator text between artist and song values | string | " " `footer` | Text to append after values | string | "" `app` | Music program to spawn on click | string | "ncmpcpp" From 096ca0ee5a5ba0e395562096ec6f98ef4c192bc2 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 9 Sep 2013 14:54:04 -0700 Subject: [PATCH 143/572] Updated Home (markdown) --- Home.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Home.md b/Home.md index 9342879..6c93aae 100644 --- a/Home.md +++ b/Home.md @@ -1,5 +1,14 @@ Welcome to the Lain wiki! +### Dependencies + +Package | Requested by +--- | --- +alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) +curl | widget types accessing network resources +imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) +python3 | [imap](https://github.com/copycat-killer/lain/wiki/imap) + ### Installation Simply clone this repository into your Awesome directory: From da6e722094189b34b4e74e966a3974358ca4af24 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 12:24:16 -0700 Subject: [PATCH 144/572] Destroyed To start (markdown) --- To-start.md | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 To-start.md diff --git a/To-start.md b/To-start.md deleted file mode 100644 index a2be5ff..0000000 --- a/To-start.md +++ /dev/null @@ -1,26 +0,0 @@ -All you have to do to include the module: - - local lain = require("lain") - -Some widgets require a terminal, lain default is `xterm`, but can be changed: - - lain.widgets.terminal = "urxvtc" - -or - - lain.widgets.terminal = terminal - -providing you have something like this: - - terminal = "urxvtc" - -in your `rc.lua`. - -`terminal` may also be a lua function that accepts one parameter. -Something like this: - - function footerm(cmd) - -- elaborate cmd - end - - lain.widgets.terminal = footerm From 166c95e88afacd2e19f3848cbf2c7d9e07fd3f0e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 12:25:53 -0700 Subject: [PATCH 145/572] Updated Home (markdown) --- Home.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Home.md b/Home.md index 6c93aae..74f336f 100644 --- a/Home.md +++ b/Home.md @@ -15,9 +15,12 @@ Simply clone this repository into your Awesome directory: git clone https://github.com/copycat-killer/lain.git ~/.config/awesome/lain -### Index +then include it in your `rc.lua`: + + local lain = require("lain") + +### Submodules -- [To start](https://github.com/copycat-killer/lain/wiki/To-start) - [Layouts](https://github.com/copycat-killer/lain/wiki/Layouts) - [Widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - [Utilities](https://github.com/copycat-killer/lain/wiki/Utilities) \ No newline at end of file From 31c8cd320082db6d9ed48916e4fcc34a03c7effa Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 12:31:48 -0700 Subject: [PATCH 146/572] Updated Widgets (markdown) --- Widgets.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Widgets.md b/Widgets.md index 6e6d361..86c1f46 100644 --- a/Widgets.md +++ b/Widgets.md @@ -4,6 +4,8 @@ Unless otherwise expressly noted, `function` returns a `wibox.widget.textbox`. We say this because, for some widget, `function` return a table to be used for notification and update purposes. +Almost all widgets can be set by an input function called `settings`: you can markup textboxes and do other customizations within it. + - [alsa](https://github.com/copycat-killer/lain/wiki/alsa) - [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) - [bat](https://github.com/copycat-killer/lain/wiki/bat) From 333f61b04331afe07de8dd3f5aa54241d4895371 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 12:32:17 -0700 Subject: [PATCH 147/572] Updated Widgets (markdown) --- Widgets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index 86c1f46..8accde9 100644 --- a/Widgets.md +++ b/Widgets.md @@ -4,7 +4,7 @@ Unless otherwise expressly noted, `function` returns a `wibox.widget.textbox`. We say this because, for some widget, `function` return a table to be used for notification and update purposes. -Almost all widgets can be set by an input function called `settings`: you can markup textboxes and do other customizations within it. +Almost all widgets can be set by an input function called `settings`: you can markup textboxes and do whatever customization within it. - [alsa](https://github.com/copycat-killer/lain/wiki/alsa) - [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) From 4ec5d224ab2c2f4e019c9bc832d090ef22729872 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 12:32:50 -0700 Subject: [PATCH 148/572] Updated Widgets (markdown) --- Widgets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index 8accde9..0772360 100644 --- a/Widgets.md +++ b/Widgets.md @@ -2,7 +2,7 @@ Every widget is output by a `function`. Unless otherwise expressly noted, `function` returns a `wibox.widget.textbox`. -We say this because, for some widget, `function` return a table to be used for notification and update purposes. +We say this because, for some widget, `function` returns a table to be used for notification and update purposes. Almost all widgets can be set by an input function called `settings`: you can markup textboxes and do whatever customization within it. From 8bc29ccaa72dc1d05b3d42d714182a5dd4bebde8 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 12:56:10 -0700 Subject: [PATCH 149/572] Updated Widgets (markdown) --- Widgets.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Widgets.md b/Widgets.md index 0772360..2138b27 100644 --- a/Widgets.md +++ b/Widgets.md @@ -2,9 +2,22 @@ Every widget is output by a `function`. Unless otherwise expressly noted, `function` returns a `wibox.widget.textbox`. -We say this because, for some widget, `function` returns a table to be used for notification and update purposes. +This is said because, for some widgets, `function` returns a table to be used for notification and update purposes. -Almost all widgets can be set by an input function called `settings`: you can markup textboxes and do whatever customization within it. +Every widget may take either a table or a list of variables as argument. + +If it takes a table, you have to define a function variable called `settings` in it: with this you can markup textboxes using predefined variables and do whatever customization you want. + +I'll give an example: + + mycpu = lain.widgets.cpu({ + timeout = 4, + settings = function() + widgets:set_markup("Cpu " .. usage) + end + }) + +check the sections for all the details. - [alsa](https://github.com/copycat-killer/lain/wiki/alsa) - [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) From 25c6bd19e3742e78df8585004d8dd71f59d168ee Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 12:58:14 -0700 Subject: [PATCH 150/572] Updated Widgets (markdown) --- Widgets.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Widgets.md b/Widgets.md index 2138b27..42021bd 100644 --- a/Widgets.md +++ b/Widgets.md @@ -8,7 +8,7 @@ Every widget may take either a table or a list of variables as argument. If it takes a table, you have to define a function variable called `settings` in it: with this you can markup textboxes using predefined variables and do whatever customization you want. -I'll give an example: +I'll give an example just to take a grasp, see the sections for all the details: mycpu = lain.widgets.cpu({ timeout = 4, @@ -17,8 +17,6 @@ I'll give an example: end }) -check the sections for all the details. - - [alsa](https://github.com/copycat-killer/lain/wiki/alsa) - [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) - [bat](https://github.com/copycat-killer/lain/wiki/bat) From 8b11927a993ae71df4a7e36ddde366f872c9c6d7 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:00:23 -0700 Subject: [PATCH 151/572] Updated Widgets (markdown) --- Widgets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index 42021bd..a798c67 100644 --- a/Widgets.md +++ b/Widgets.md @@ -8,7 +8,7 @@ Every widget may take either a table or a list of variables as argument. If it takes a table, you have to define a function variable called `settings` in it: with this you can markup textboxes using predefined variables and do whatever customization you want. -I'll give an example just to take a grasp, see the sections for all the details: +Here follows a simple example, see the sections for all the details: mycpu = lain.widgets.cpu({ timeout = 4, From 4f5402652ab7896eef7eda6f4cd1bcab0fe62495 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:01:39 -0700 Subject: [PATCH 152/572] Updated Widgets (markdown) --- Widgets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index a798c67..c0a7dd6 100644 --- a/Widgets.md +++ b/Widgets.md @@ -13,7 +13,7 @@ Here follows a simple example, see the sections for all the details: mycpu = lain.widgets.cpu({ timeout = 4, settings = function() - widgets:set_markup("Cpu " .. usage) + widget:set_markup("Cpu " .. usage) end }) From d29477dac35903da00e1fe6669a2a3e90b8f1096 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:19:34 -0700 Subject: [PATCH 153/572] Updated Widgets (markdown) --- Widgets.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Widgets.md b/Widgets.md index c0a7dd6..7130cc3 100644 --- a/Widgets.md +++ b/Widgets.md @@ -6,9 +6,15 @@ This is said because, for some widgets, `function` returns a table to be used fo Every widget may take either a table or a list of variables as argument. -If it takes a table, you have to define a function variable called `settings` in it: with this you can markup textboxes using predefined variables and do whatever customization you want. +If it takes a table, you have to define a function variable called `settings` in it, in order to make your customizations. -Here follows a simple example, see the sections for all the details: +To markup the textbox, call `widget:set_markup(...)` within `settings`. + +You can feed `set_markup` with predefined arguments, see the sections for all the details. + +`widget` is a textbox, so you can also threat it like any other `wibox.widget.textbox`. + +Here follows an example: mycpu = lain.widgets.cpu({ timeout = 4, @@ -17,6 +23,8 @@ Here follows a simple example, see the sections for all the details: end }) +--- + - [alsa](https://github.com/copycat-killer/lain/wiki/alsa) - [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) - [bat](https://github.com/copycat-killer/lain/wiki/bat) From f654775d456afe4f5868288007ff17a0887ddd8d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:25:23 -0700 Subject: [PATCH 154/572] Updated alsa (markdown) --- alsa.md | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/alsa.md b/alsa.md index 2ca1746..3e31c74 100644 --- a/alsa.md +++ b/alsa.md @@ -4,43 +4,39 @@ Shows and controls alsa volume with a textbox. myvolume = lain.widgets.alsa() -* Left click: Launch `alsamixer` in your `terminal`. -* Right click: Mute/unmute. -* Scroll wheel: Increase/decrase volume. - -The function takes a table as optional argument, which can contain: +### input table Variable | Meaning | Type | Default --- | --- | --- | --- +`timeout` | Refresh timeout seconds | int | 5 `channel` | Mixer channel | string | "Master" -`step` | Step at which volume is increased/decreased | string | "1%" -`header` | Text to show before value | string | " Vol " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to append after value | string | " " +`settings` | User settings | function | empty function -*Note*: `footer` can be markup text. +`settings` can be fed with the following variables: -`lain.widgets.alsa` outputs the following table: +Variable | Meaning | Type | Values +--- | --- | --- | --- +volume.level | Self explained | int | 0-100 +volume.status | Device status | string | "on", "off" + +### output table Variable | Meaning | Type --- | --- | --- `widget` | The widget | `wibox.widget.textbox` -`channel` | Alsa channel | string -`step` | Increase/decrease step | string -`notify` | Update `widget` | function +`notify` | Force update `widget` | function Finally, you can control the widget with key bindings like these: -- Volume control awful.key({ altkey }, "Up", function () - awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "+") + awful.util.spawn("amixer sset Master 1%+") volume.notify() end), awful.key({ altkey }, "Down", function () - awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "-") + awful.util.spawn("amixer sset Master 1%-") volume.notify() end), awful.key({ altkey }, "m", From a28129e686929438f8d0115cab638b62ddd79bc5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:28:54 -0700 Subject: [PATCH 155/572] Updated alsabar (markdown) --- alsabar.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/alsabar.md b/alsabar.md index 9b5a711..549b28a 100644 --- a/alsabar.md +++ b/alsabar.md @@ -1,12 +1,6 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -Shows and controls alsa volume with a progressbar. - -Dependencies: - -- alsa-utils (of course) - -Plus tooltips, notifications, and color changes at mute/unmute switch. +Shows and controls alsa volume with a progressbar and provides tooltips, notifications, and color changes at mute/unmute switch. myvolumebar = lain.widgets.alsabar() @@ -48,7 +42,7 @@ Variable | Meaning | Type | Default It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height, **if** you have set it different than default (18). -`lain.widgets.alsabar` outputs the following table: +### output table Variable | Meaning | Type --- | --- | --- @@ -57,7 +51,7 @@ Variable | Meaning | Type `step` | Increase/decrease step | string `notify` | The notification | function -Finally, you can control the widget with key bindings like these: +You can control the widget with key bindings like these: -- Volume control awful.key({ altkey }, "Up", From f75714659a5564a6b287d73887d0e0a7d4e6c878 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:29:07 -0700 Subject: [PATCH 156/572] Updated alsa (markdown) --- alsa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsa.md b/alsa.md index 3e31c74..2029e8c 100644 --- a/alsa.md +++ b/alsa.md @@ -26,7 +26,7 @@ Variable | Meaning | Type `widget` | The widget | `wibox.widget.textbox` `notify` | Force update `widget` | function -Finally, you can control the widget with key bindings like these: +You can control the widget with key bindings like these: -- Volume control awful.key({ altkey }, "Up", From afd328fe2598ea9d8621fe17abdd098f30a731e2 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:31:03 -0700 Subject: [PATCH 157/572] Updated alsa (markdown) --- alsa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsa.md b/alsa.md index 2029e8c..7ad0a6e 100644 --- a/alsa.md +++ b/alsa.md @@ -2,7 +2,7 @@ Shows and controls alsa volume with a textbox. - myvolume = lain.widgets.alsa() + volume = lain.widgets.alsa() ### input table From cb04a2e7413ce1f09734218e10e6193cabfc23ac Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:32:32 -0700 Subject: [PATCH 158/572] Updated bat (markdown) --- bat.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/bat.md b/bat.md index 8b24151..1f8bf1f 100644 --- a/bat.md +++ b/bat.md @@ -7,17 +7,14 @@ Displays a notification when battery is low or critical. mybattery = lain.widgets.bat() -The function takes a table as optional argument, which can contain: +### input table Variable | Meaning | Type | Default --- | --- | --- | --- +`timeout` | Refresh timeout seconds | int | 30 `battery` | Identifier of the battery | string | "BAT0" -`show_all` | Show all values (true), or only remaining capacity (false) | boolean | false -`refresh_timeout` | Refresh timeout seconds | int | 30 -`header` | Text to show before value | string | " Bat " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to append after value | string | " " -`shadow` | Hide the widget when battery is not present | boolean | false +`settings` | User settings | function | empty function -**Note**: `footer` can be markup text. \ No newline at end of file +### output + +A textbox. \ No newline at end of file From 79d92fa9a967508614b76a49ecf7c3035e85756e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:40:31 -0700 Subject: [PATCH 159/572] Updated calendar (markdown) --- calendar.md | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/calendar.md b/calendar.md index 5b4587d..fa4e563 100644 --- a/calendar.md +++ b/calendar.md @@ -2,37 +2,27 @@ Attaches a calendar notification to a widget. - lain.widgets.calendar:attach(widget) + lain.widgets.calendar:attach(widget, args) - Left click: switch to previous month. - Right click: switch to next month. -Optionally you can call the function with fg and bg colors arguments, both or just one: +`args` is an optional table which can contain: - lain.widgets.calendar:attach(mytextclock, "#FFFFFF", "#000000") - -- or - lain.widgets.calendar:attach(mytextclock, "#FFFFFF") - -- or - lain.widgets.calendar:attach(mytextclock, nil, "#000000") +Variable | Meaning | Type | Default +--- | --- | --- | --- +`icons` | Path to calendar icons | string | [lain/icons/cal/white](https://github.com/copycat-killer/lain/tree/master/icons/cal/white) +`font_size` | Calendar font size | int | 12 +`fg` | Calendar foreground color | string | `beautiful.fg_normal` +`bg` | Calendar background color | string | `beautiful.bg_normal` +`position` | Calendar position | string | "top_right" -default fg and fb colors are `beautiful.fg_focus` and `beautiful.bg_normal`. +`position` possible values are defined [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify). Notification will show an icon displaying current day, and formatted output from ``cal`` with current day highlighted. -Calendar icons are placed in [lain/icons/cal](https://github.com/copycat-killer/lain/tree/master/icons/cal), default set being ``white``. - -You can add your own set, and tell lain to use it like this: - - lain.widgets.calendar.icons_dir = lain.widgets.icons_dir .. "cal/myicons" - -also, you can set notification font size: - - lain.widgets.calendar.font_size = 14 - -default is 12. - -Finally, you can call the notification with a key binding like this: +You can call the notification with a key binding like this: awful.key({ altkey }, "c", function () lain.widgets.calendar:show(7) end), From ef94494c302809eaab16cee7241113613464713e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:42:18 -0700 Subject: [PATCH 160/572] Updated cpu (markdown) --- cpu.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cpu.md b/cpu.md index 1dce16e..3c49f64 100644 --- a/cpu.md +++ b/cpu.md @@ -4,14 +4,13 @@ Shows in a textbox the average CPU usage percent for a given amount of time. mycpuusage = lain.widgets.cpu() -The function takes a table as optional argument, which can contain: +### input table Variable | Meaning | Type | Default --- | --- | --- | --- -`refresh_timeout` | Refresh timeout seconds | int | 10 -`header` | Text to show before value | string | " Cpu " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to add after value | string | "% " +`timeout` | Refresh timeout seconds | int | 10 +`settings` | User settings | function | empty function -**Note**: `footer` color is `color`. \ No newline at end of file +### output + +A textbox. \ No newline at end of file From 70c9def8dac705aeecb2cef133e5dc862e89419d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:43:13 -0700 Subject: [PATCH 161/572] Updated cpu (markdown) --- cpu.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpu.md b/cpu.md index 3c49f64..5cafceb 100644 --- a/cpu.md +++ b/cpu.md @@ -11,6 +11,8 @@ Variable | Meaning | Type | Default `timeout` | Refresh timeout seconds | int | 10 `settings` | User settings | function | empty function +`settings` can be fed with `usage`, which is the cpu use percentage. + ### output A textbox. \ No newline at end of file From 9f2ae8e9f97d7b385af4f4356ea59de768ea59a9 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:46:24 -0700 Subject: [PATCH 162/572] Updated bat (markdown) --- bat.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bat.md b/bat.md index 1f8bf1f..04c80dd 100644 --- a/bat.md +++ b/bat.md @@ -15,6 +15,8 @@ Variable | Meaning | Type | Default `battery` | Identifier of the battery | string | "BAT0" `settings` | User settings | function | empty function +`settings` can be fed with `bat_now` table, which contains the following strings: `status`, `perc`, `time`, `watt`. + ### output A textbox. \ No newline at end of file From 4774effb291e18881a3b1b9d5f8ceb9a501e156c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 13:47:26 -0700 Subject: [PATCH 163/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index 5cafceb..4994e1d 100644 --- a/cpu.md +++ b/cpu.md @@ -11,7 +11,7 @@ Variable | Meaning | Type | Default `timeout` | Refresh timeout seconds | int | 10 `settings` | User settings | function | empty function -`settings` can be fed with `usage`, which is the cpu use percentage. +`settings` can be fed with the string `usage`, which means the cpu use percentage. ### output From 2746279ac013321d0c551320be38bc24765c798c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:00:43 -0700 Subject: [PATCH 164/572] Updated fs (markdown) --- fs.md | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/fs.md b/fs.md index eb67110..f1aa353 100644 --- a/fs.md +++ b/fs.md @@ -6,21 +6,30 @@ Displays a notification when the partition is full or has low space. mypartition = lain.widgets.fs() -The function takes a table as optional argument, which can contain: +### input table Variable | Meaning | Type | Default --- | --- | --- | --- +`timeout` | Refresh timeout seconds -| int | 600 `partition` | Partition to monitor | string | "/" -`refresh_timeout` | Refresh timeout seconds | int | 600 -`header` | Text to show before value | string | " Hdd " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to show after value | string | " " -`shadow` | Hide the widget if `partition` < 90 | boolean | false +`settings` | User settings | function | empty function -**Note**: `footer` color is `color`. +`settings` can use the following `partition` related value strings: `used`, `available`, `size_mb`, `size_gb`. -`lain.widgets.fs` outputs the following table: +It can also use value strings in these formats: + + fs_info[p .. "used_p"] + fs_info[p .. "avail_p"] + fs_info[p .. "size_mb"] + fs_info[p .. "size_gb"] + +where `p` is the "mount" column of the output of `df` command (`/`, `/home`, `/boot`, ...). + +This means you can set the widget for a certain partition, but you can look up at others too. + +Finally, `settings` can modify `notification_preset` table too. This table will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. + +### output table Variable | Meaning | Type --- | --- | --- From 267315c413ae0724c2ea63347a599eae167e4793 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:00:59 -0700 Subject: [PATCH 165/572] Updated alsa (markdown) --- alsa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsa.md b/alsa.md index 7ad0a6e..f632717 100644 --- a/alsa.md +++ b/alsa.md @@ -12,7 +12,7 @@ Variable | Meaning | Type | Default `channel` | Mixer channel | string | "Master" `settings` | User settings | function | empty function -`settings` can be fed with the following variables: +`settings` can use the following variables: Variable | Meaning | Type | Values --- | --- | --- | --- From 2135b08bbd2792edec90f96a5641d10b22bf8476 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:01:35 -0700 Subject: [PATCH 166/572] Updated bat (markdown) --- bat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bat.md b/bat.md index 04c80dd..ec10057 100644 --- a/bat.md +++ b/bat.md @@ -15,7 +15,7 @@ Variable | Meaning | Type | Default `battery` | Identifier of the battery | string | "BAT0" `settings` | User settings | function | empty function -`settings` can be fed with `bat_now` table, which contains the following strings: `status`, `perc`, `time`, `watt`. +`settings` can use the `bat_now` table, which contains the following strings: `status`, `perc`, `time`, `watt`. ### output From eb8cec907a50f3fd6df4b14ae10b910444017f92 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 10 Sep 2013 23:02:11 +0200 Subject: [PATCH 167/572] totally reworked widgets --- README.rst | 2 +- helpers.lua | 46 ++++-------- widgets/alsa.lua | 103 ++++++++----------------- widgets/alsabar.lua | 43 ++++++----- widgets/bat.lua | 102 +++++++++---------------- widgets/calendar.lua | 27 +++---- widgets/cpu.lua | 31 ++++---- widgets/fs.lua | 102 ++++++++++++------------- widgets/imap.lua | 170 +++++++++++++++++------------------------- widgets/init.lua | 6 +- widgets/maildir.lua | 60 ++++----------- widgets/mem.lua | 45 +++-------- widgets/mpd.lua | 121 ++++++++++++------------------ widgets/net.lua | 133 ++++++++++----------------------- widgets/sysload.lua | 44 +++-------- widgets/temp.lua | 31 +++----- widgets/yawn/init.lua | 88 ++++++++-------------- 17 files changed, 415 insertions(+), 739 deletions(-) diff --git a/README.rst b/README.rst index 2524de3..6ce1c47 100644 --- a/README.rst +++ b/README.rst @@ -10,7 +10,7 @@ Layouts, widgets and utilities for Awesome WM :License: GNU-GPLv2_ :Source: https://github.com/copycat-killer/lain -Based on a port of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions in order to improve Awesome usability and +Successor of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions in order to improve Awesome usability and configurability. Read the wiki_ for all the info. diff --git a/helpers.lua b/helpers.lua index 7677768..a8c4cd7 100644 --- a/helpers.lua +++ b/helpers.lua @@ -4,14 +4,12 @@ Licensed under GNU General Public License v2 * (c) 2013, Luke Bonham * (c) 2010-2012, Peter Hofmann - * (c) 2010, Adrian C. --]] -local awful = require("awful") local debug = require("debug") -local pairs = pairs local rawget = rawget +local io = { open = io.open } -- Lain helper functions for internal use -- lain.helpers @@ -30,33 +28,6 @@ end -- }}} --- {{{ --- If lain.terminal is a string, e.g. "xterm", then "xterm -e " .. cmd is --- run. But if lain.terminal is a function, then terminal(cmd) is run. - -function helpers.run_in_terminal(cmd) - if type(terminal) == "function" - then - terminal(cmd) - elseif type(terminal) == "string" - then - awful.util.spawn(terminal .. ' -e ' .. cmd) - end -end - --- }}} - --- {{{ Format units to one decimal point - -function helpers.uformat(array, key, value, unit) - for u, v in pairs(unit) do - array["{"..key.."_"..u.."}"] = string.format("%.1f", value/v) - end - return array -end - --- }}} - -- {{{ Read the first line of a file or return nil. function helpers.first_line(f) @@ -73,6 +44,21 @@ end -- }}} +-- {{{ Timer maker + +helpers.timer_table = {} + +function helpers.newtimer(name, timeout, fun, nostart) + helpers.timer_table[name] = timer({ timeout = timeout }) + helpers.timer_table[name]:connect_signal("timeout", fun) + helpers.timer_table[name]:start() + if not nostart then + helpers.timer_table[name]:emit_signal("timeout") + end +end + +-- }}} + -- {{{ A map utility helpers.map_table = {} diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 7c26908..8571ec6 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -2,102 +2,65 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann - * (c) 2010, Adrian C. + * (c) 2013, Luke Bonham + * (c) 2010, Adrian C. --]] -local markup = require("lain.util.markup") -local run_in_terminal = require("lain.helpers").run_in_terminal +local newtimer = require("lain.helpers").newtimer -local awful = require("awful") -local beautiful = require("beautiful") local wibox = require("wibox") -local io = io -local string = { format = string.format, - match = string.match } +local io = { popen = io.popen } +local string = { match = string.match } local setmetatable = setmetatable --- ALSA volume infos --- nain.widgets.alsa -local alsa = { - volume = 0, - mute = false, -} +-- ALSA volume +-- lain.widgets.alsa +local alsa = {} -function worker(args) - local args = args or {} - local channel = args.channel or "Master" - local step = args.step or "1%" - local header = args.header or " Vol " - local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or "#FFFFFF" +local function worker(args) + local args = args or {} + local timeout = args.timeout or 5 + local channel = args.channel or "Master" + local settings = args.settings or function() end - local myvolume = wibox.widget.textbox() - local myvolumeupdate = function() + widget = wibox.widget.textbox('') + + function update() local f = io.popen('amixer get ' .. channel) local mixer = f:read("*all") f:close() - local volume, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") + volume = {} - if volume == nil + volume.level, volume.status = string.match(mixer, "([%d]+)%%.*%[([%l]*)") + + if volume.level == nil then - alsa.volume = 0 - else - alsa.volume = volume + volume.level = 0 + volume.status = "off" end - if mute == nil or mute == 'on' + if volume.status == "" then - alsa.mute = true - mute = '' - else - alsa.mute = false - mute = 'M' + if volume.level == 0 + then + volume.status = "off" + else + volume.status = "on" + end end - local ret = markup(color, string.format("%d%s", volume, mute)) - myvolume:set_markup(markup(header_color, header) .. ret .. " ") + settings() end - local myvolumetimer = timer({ timeout = 5 }) - myvolumetimer:connect_signal("timeout", myvolumeupdate) - myvolumetimer:start() - myvolumetimer:emit_signal("timeout") + newtimer("alsa", timeout, update) - myvolume:buttons(awful.util.table.join( - awful.button({}, 1, - function() - run_in_terminal('alsamixer') - end), - awful.button({}, 3, - function() - awful.util.spawn('amixer sset ' .. channel ' toggle') - end), + output = { widget = widget, notify = update } - awful.button({}, 4, - function() - awful.util.spawn('amixer sset ' .. channel .. ' ' .. step '+') - myvolumeupdate() - end), - - awful.button({}, 5, - function() - awful.util.spawn('amixer sset ' .. channel .. ' ' .. step '-') - myvolumeupdate() - end) - )) - - alsa.widget = myvolume - alsa.channel = channel - alsa.step = step - alsa.notify = myvolumeupdate - - return setmetatable(alsa, { __index = alsa.widget }) + return setmetatable(output, { __index = output.widget }) end return setmetatable(alsa, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 0421f5c..7f5fe87 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -6,6 +6,8 @@ * (c) 2013, Rman --]] +local newtimer = require("lain.helpers").newtimer + local awful = require("awful") local beautiful = require("beautiful") local naughty = require("naughty") @@ -32,12 +34,14 @@ local alsabar = unmute = "#A4CE8A" }, + terminal = terminal or "xterm", mixer = terminal .. " -e alsamixer", notifications = { font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), font_size = "11", + color = beautiful.fg_focus, bar_size = 18 -- Awesome default }, @@ -49,9 +53,9 @@ function alsabar:notify() local preset = { title = "", text = "", - timeout = 3, + timeout = 15, font = alsabar.notifications.font .. " " .. alsabar.notifications.font_size, - fg = beautiful.fg_focus + fg = alsabar.notifications.color } if alsabar._muted then @@ -72,7 +76,7 @@ function alsabar:notify() end end -function worker(args) +local function worker(args) local args = args or {} local width = args.width or 63 local height = args.heigth or 1 @@ -85,6 +89,7 @@ function worker(args) alsabar.notifications = args.notifications or alsabar.notifications alsabar.bar = awful.widget.progressbar() + alsabar.bar:set_background_color(alsabar.colors.background) alsabar.bar:set_color(alsabar.colors.unmute) alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } }) @@ -97,18 +102,18 @@ function worker(args) alsabar.bar:set_vertical(true) end - local myvolumebarupdate = function() + function update() -- Get mixer control contents local f = io.popen("amixer get " .. alsabar.channel) local mixer = f:read("*all") f:close() -- Capture mixer control state: [5%] ... ... [on] - local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") - -- Handle mixers without data + local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") + if volu == nil then - volu = 0 - mute = "off" + volu = 0 + mute = "off" end alsabar._current_level = tonumber(volu) / 100 @@ -126,10 +131,7 @@ function worker(args) end end - local myvolumebartimer = timer({ timeout = 5 }) - myvolumebartimer:connect_signal("timeout", myvolumebarupdate) - myvolumebartimer:start() - myvolumebartimer:emit_signal("timeout") + newtimer("alsabar", 5, update) alsabar.bar:buttons (awful.util.table.join ( awful.button ({}, 1, function() @@ -151,14 +153,15 @@ function worker(args) end) )) - return { widget = alsabar.bar, - channel = alsabar.channel, - step = alsabar.step, - notify = function() - myvolumebarupdate() - alsabar.notify() - end - } + return { + widget = alsabar.bar, + channel = alsabar.channel, + step = alsabar.step, + notify = function() + update() + alsabar.notify() + end + } end return setmetatable(alsabar, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/bat.lua b/widgets/bat.lua index 0461607..5a811f0 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -7,10 +7,9 @@ --]] -local markup = require("lain.util.markup") +local newtimer = require("lain.helpers").newtimer local first_line = require("lain.helpers").first_line -local beautiful = require("beautiful") local naughty = require("naughty") local wibox = require("wibox") @@ -21,25 +20,24 @@ local setmetatable = setmetatable -- Battery infos -- lain.widgets.bat -local bat = { - status = "not present", - perc = "N/A", - time = "N/A", -} +local bat = { id = nil } -function worker(args) +local function worker(args) local args = args or {} + local timeout = args.timeout or 30 local battery = args.battery or "BAT0" - local show_all = args.show_all or false - local refresh_timeout = args.refresh_timeout or 30 - local header = args.header or " Bat " - local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or "#FFFFFF" - local shadow = args.shadow or false + local settings = args.settings or function() end - local mybattery = wibox.widget.textbox() + bat_now = { + status = "not present", + perc = "N/A", + time = "N/A", + watt = "N/A" + } - local mybatteryupdate = function() + widget = wibox.widget.textbox('') + + function update() local present = first_line("/sys/class/power_supply/" .. battery .. "/present") @@ -58,90 +56,62 @@ function worker(args) local tot = first_line("/sys/class/power_supply/" .. battery .. "/energy_full") - bat.status = first_line("/sys/class/power_supply/" + bat_now.status = first_line("/sys/class/power_supply/" .. battery .. "/status") local time_rat = 0 - if bat.status == "Charging" + if bat_now.status == "Charging" then - status = "(+)" time_rat = (tot - rem) / rate - elseif bat.status == "Discharging" + elseif bat_now.status == "Discharging" then - status = "(-)" time_rat = rem / rate - else - status = "(.)" end local hrs = math.floor(time_rat) local min = (time_rat - hrs) * 60 - bat.time = string.format("%02d:%02d", hrs, min) - local amount = (rem / tot) * 100 - - if shadow - then - bat.perc = string.format("%d", amount) - else - bat.perc = string.format("%d%%", amount) - end - - local watt = string.format("%.2fW", (rate * ratev) / 1e12) - - if show_all - then - text = watt .. " " .. bat.perc .. " " .. bat.time .. " " .. bat.status - else - text = bat.perc - end + bat_now.time = string.format("%02d:%02d", hrs, min) + bat_now.perc = (rem / tot) * 100 + bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) -- notifications for low and critical states - if amount <= 5 + if bat_now.perc <= 5 then - naughty.notify{ + bat.id = naughty.notify({ text = "shutdown imminent", title = "battery nearly exhausted", position = "top_right", timeout = 15, fg="#000000", bg="#ffffff", - ontop = true - } - elseif amount <= 15 + ontop = true, + replaces_id = bat.id + }).id + elseif bat.perc <= 15 then - old_id = naughty.notify{ + bat.id = naughty.notify({ text = "plug the cable", title = "battery low", position = "top_right", - timeout = 5, + timeout = 15, fg="#202020", bg="#cdcdcd", - ontop = true - } + ontop = true, + replaces_id = bat.id + }).id end - else - text = "none" + + bat_now.perc = string.format("%d", bat_now.perc) end - if shadow - then - mybattery:set_text('') - else - mybattery:set_markup(markup(header_color, header) - .. markup(color, text) .. " ") - end + settings() end - local mybatterytimer = timer({ timeout = refresh_timeout }) - mybatterytimer:connect_signal("timeout", mybatteryupdate) - mybatterytimer:start() - mybatterytimer:emit_signal("timeout") + newtimer("bat", timeout, update) - bat.widget = mybattery - - return setmetatable(bat, { __index = bat.widget }) + return widget end return setmetatable(bat, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index e5f6e88..e28e735 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -13,7 +13,7 @@ local beautiful = require("beautiful") local naughty = require("naughty") local io = io -local os = { date = os.date } +local os = { date = os.date } local tonumber = tonumber local setmetatable = setmetatable @@ -23,15 +23,6 @@ local setmetatable = setmetatable local calendar = {} local notification = nil -local function create(foreground, background) - calendar.offset = 0 - calendar.icons_dir = icons_dir .. "cal/white/" -- default - calendar.notify_icon = nil - calendar.font_size = 12 - calendar.bg = background or beautiful.bg_normal or "#FFFFFF" - calendar.fg = foreground or beautiful.fg_focus or "#FFFFFF" -end - function calendar:hide() if notification ~= nil then naughty.destroy(notification) @@ -59,7 +50,7 @@ function calendar:show(t_out, inc_offset) end calendar.offset = 0 - calendar.notify_icon = calendar.icons_dir .. today .. ".png" + calendar.notify_icon = calendar.icons .. today .. ".png" -- bg and fg inverted to highlight today f = io.popen( init_t .. today .. @@ -106,13 +97,23 @@ function calendar:show(t_out, inc_offset) notification = naughty.notify({ text = c_text, icon = calendar.notify_icon, + position = calendar.position, fg = calendar.fg, bg = calendar.bg, timeout = tims }) end -function calendar:attach(widget, foreground, background) - create(foreground, background) +function calendar:attach(widget, args) + local args = args or {} + calendar.icons = args.icons or icons_dir .. "cal/white/" + calendar.font_size = tonumber(args.font_size) or 12 + calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF" + calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF" + calendar.position = args.position or "top_right" + + calendar.offset = 0 + calendar.notify_icon = nil + widget:connect_signal("mouse::enter", function () calendar:show() end) widget:connect_signal("mouse::leave", function () calendar:hide() end) widget:buttons(awful.util.table.join( awful.button({ }, 1, function () diff --git a/widgets/cpu.lua b/widgets/cpu.lua index 3890e5e..f9bbe72 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -7,15 +7,15 @@ --]] -local markup = require("lain.util.markup") local first_line = require("lain.helpers").first_line +local newtimer = require("lain.helpers").newtimer -local beautiful = require("beautiful") local wibox = require("wibox") local math = { ceil = math.ceil } local string = { format = string.format, gmatch = string.gmatch } +local tostring = tostring local setmetatable = setmetatable @@ -26,17 +26,14 @@ local cpu = { last_active = 0 } -function worker(args) - local args = args or {} - local refresh_timeout = args.refresh_timeout or 5 - local header = args.header or " Cpu " - local header_color = args.header or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or "#FFFFFF" - local footer = args.footer or "% " +local function worker(args) + local args = args or {} + local timeout = args.timeout or 5 + local settings = args.settings or function() end - local w = wibox.widget.textbox() + widget = wibox.widget.textbox('') - local cpuusageupdate = function() + function update() -- Read the amount of time the CPUs have spent performing -- different kinds of work. Read the first line of /proc/stat -- which is the sum of all CPUs. @@ -60,21 +57,19 @@ function worker(args) -- Read current data and calculate relative values. local dactive = active - cpu.last_active local dtotal = total - cpu.last_total - local dta = math.ceil((dactive / dtotal) * 100) - w:set_markup(markup(header_color, header) .. markup(color, dta .. footer)) + usage = tostring(math.ceil((dactive / dtotal) * 100)) + + settings() -- Save current data for the next run. cpu.last_active = active cpu.last_total = total end - local cpuusagetimer = timer({ timeout = refresh_timeout }) - cpuusagetimer:connect_signal("timeout", cpuusageupdate) - cpuusagetimer:start() - cpuusagetimer:emit_signal("timeout") + newtimer("cpu", timeout, update) - return w + return widget end return setmetatable(cpu, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/fs.lua b/widgets/fs.lua index 344bd87..f934248 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -8,7 +8,6 @@ --]] -local markup = require("lain.util.markup") local helpers = require("lain.helpers") local beautiful = require("beautiful") @@ -16,14 +15,16 @@ local wibox = require("wibox") local naughty = require("naughty") local io = io -local string = { match = string.match } +local pairs = pairs +local string = { match = string.match, + format = string.format } local tonumber = tonumber local setmetatable = setmetatable -- File system disk space usage -- lain.widgets.fs -local fs = {} +local fs = { notification_preset = {} } local notification = nil function fs:hide() @@ -41,38 +42,29 @@ function fs:show(t_out) f:close() notification = naughty.notify({ + preset = fs.notification_preset, text = ws, - timeout = t_out, - fg = fs.color, + timeout = t_out }) end --- Variable definitions +-- Units definitions local unit = { ["mb"] = 1024, ["gb"] = 1024^2 } local function worker(args) - local args = args or {} + local args = args or {} local partition = args.partition or "/" - local refresh_timeout = args.refresh_timeout or 600 - local header = args.header or " Hdd " - local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - fs.color = args.color or beautiful.fg_focus or "#FFFFFF" - local footer = args.footer or " " - local shadow = args.shadow or false + local timeout = args.timeout or 600 + local settings = args.settings or function() end - local myfs = wibox.widget.textbox() + widget = wibox.widget.textbox('') helpers.set_map("fs", false) - local fsupdate = function() - local fs_info = {} -- Get data from df - local f = io.popen("LC_ALL=C df -kP") + function update() + fs_info = {} - local function set_text() - local info = fs_info['{' .. partition .. ' used_p}'] - myfs:set_markup(markup(header_color, header) - .. markup(fs.color, info .. footer)) - end + local f = io.popen("LC_ALL=C df -kP") for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount) local s = string.match(line, "^.-[%s]([%d]+)") @@ -80,55 +72,57 @@ local function worker(args) local m = string.match(line, "%%[%s]([%p%w]+)") if u and m then -- Handle 1st line and broken regexp - helpers.uformat(fs_info, m .. " used", u, unit) - fs_info["{" .. m .. " used_p}"] = tonumber(p) + fs_info[m .. " size_mb"] = string.format("%.1f", tonumber(s) / unit["mb"]) + fs_info[m .. " size_gb"] = string.format("%.1f", tonumber(s) / unit["gb"]) + fs_info[m .. " used_p"] = tonumber(p) + fs_info[m .. " avail_p"] = 100 - tonumber(p) end end f:close() - if shadow + -- chosen partition easy stuff + -- you can however check whatever partition else + used = fs_info[partition .. " used_p"] + available = fs_info[partition .. " avail_p"] + size_mb = fs_info[partition .. " size_mb"] + size_gb = fs_info[partition .. " size_gb"] + + notification_preset = { fg = beautiful.fg_normal } + + settings() + + fs.notification_preset = notification_preset + + if used >= 99 and not helpers.get_map("fs") then - myfs:set_text('') + naughty.notify({ + title = "warning", + text = partition .. " ran out!\nmake some room", + timeout = 8, + fg = "#000000", + bg = "#FFFFFF" + }) + helpers.set_map("fs", true) else - set_text() - end - - local part = fs_info['{' .. partition .. ' used_p}'] - - if part >= 90 then - if part >= 99 and not helpers.get_map("fs") then - naughty.notify({ title = "warning", - text = partition .. " ran out!\n" - .. "make some room", - timeout = 8, - position = "top_right", - fg = beautiful.fg_urgent, - bg = beautiful.bg_urgent }) - helpers.set_map("fs", true) - end - if shadow then set_text() end + helpers.set_map("fs", false) end end - local fstimer = timer({ timeout = refresh_timeout }) - fstimer:connect_signal("timeout", fsupdate) - fstimer:start() - fstimer:emit_signal("timeout") + helpers.newtimer("fs " .. partition, timeout, update) - myfs:connect_signal('mouse::enter', function () fs:show(0) end) - myfs:connect_signal('mouse::leave', function () fs:hide() end) + widget:connect_signal('mouse::enter', function () fs:show(0) end) + widget:connect_signal('mouse::leave', function () fs:hide() end) - local fs_out = - { - widget = myfs, + output = { + widget = widget, show = function(t_out) - fsupdate() + update() fs:show(t_out) end } - return setmetatable(fs_out, { __index = fs_out.widget }) + return setmetatable(output, { __index = output.widget }) end return setmetatable(fs, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/imap.lua b/widgets/imap.lua index f06660b..2c7067c 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -6,160 +6,126 @@ --]] -local markup = require("lain.util.markup") local helpers = require("lain.helpers") -local awful = require("awful") -local beautiful = require("beautiful") local naughty = require("naughty") local wibox = require("wibox") -local io = io +local io = { popen = io.popen } local tonumber = tonumber -local string = string +local string = { len = string.len, + format = string.format } local setmetatable = setmetatable --- Mail imap check +-- Mail IMAP check -- lain.widgets.imap -local imap = {} +local imap = { stored = nil } function worker(args) - local args = args or {} + local args = args or {} - local server = args.server - local mail = args.mail + local server = args.server + local mail = args.mail local password = args.password - local port = args.port or "993" - local refresh_timeout = args.refresh_timeout or 60 - local header = args.header or "Mail " - local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or "#FFFFFF" - local mail_encoding = args.mail_encoding or nil - local maxlen = args.maxlen or 200 - local app = args.app or "mutt" + local port = args.port or "993" + local timeout = args.timeout or 60 + local encoding = args.encoding or nil + local maxlen = args.maxlen or 200 local is_plain = args.is_plain or false - local shadow = args.shadow or false + local settings = args.settings or function() end + + local checkmail = helpers.scripts_dir .. "checkmail" helpers.set_map(mail, true) helpers.set_map(mail .. " count", "0") - local checkmail = helpers.scripts_dir .. "checkmail" - if not is_plain then - local f = io.popen(password) - password = f:read("*all"):gsub("\n", ""):gsub("\r", "") - f:close() + if not imap.stored + then + local f = io.popen(password) + password = f:read("*all"):gsub("\n", ""):gsub("\r", "") + f:close() + imap.stored = password + else + password = imap.stored + end end - local myimapcheck = wibox.widget.textbox() + widget = wibox.widget.textbox('') - local myimapcheckupdate = function() - function set_nomail() - if shadow - then - myimapcheck:set_text('') - else - myimapcheck:set_markup(markup(color, " no mail ")) - end - end + function update() + to_execute = string.format("%s -s %s -u %s -p %s --port %s", + checkmail, server, mail, password, port) - conn = io.popen("ip link show") - check_conn = conn:read("*all") - conn:close() - - if not check_conn:find("state UP") then - set_nomail() - return - end - - to_execute = checkmail .. ' -s ' .. server .. - ' -u ' .. mail .. ' -p ' .. password - .. ' --port ' .. port - - if mail_encoding ~= nil + if encoding ~= nil then - to_execute = to_execute .. ' --encoding ' - .. mail_encoding + to_execute = string.format("%s --encoding %s", + to_execute, encoding) end f = io.popen(to_execute) ws = f:read("*all") f:close() + mailcount = "0" + if ws:find("No new messages") ~= nil then helpers.set_map(mail, true) - set_nomail() elseif ws:find("CheckMailError: invalid credentials") ~= nil then helpers.set_map(mail, true) - myimapcheck:set_markup(" " .. markup(header_color, header) .. - markup(color, "invalid credentials ")) + mailcount = "invalid credentials" else - mailcount = ws:match("%d") or "?" - - if helpers.get_map(mail .. " count") ~= mailcount and mailcount ~= "?" + mailcount = ws:match("%d") or "0" + if helpers.get_map(mail .. " count") ~= mailcount and mailcount ~= "0" then helpers.set_map(mail, true) helpers.set_map(mail .. " count", mailcount) end + end - myimapcheck:set_markup(" " .. markup(header_color, header) .. - markup(color, mailcount) .. " ") + notification_preset = { + icon = helpers.icons_dir .. "mail.png", + timeout = 8, + position = "top_left" + } - if helpers.get_map(mail) + settings() + + + if helpers.get_map(mail) and tonumber(mailcount) >= 1 + then + notify_title = ws:match(mail .. " has %d new message.?") + ws = ws:gsub(notify_title, "", 1):gsub("\n", "", 2) + + -- trying to remove useless infos + ws = ws:gsub("--Content.%S+.-\n", "") + ws = ws:gsub("--%d+.-\n", "") + + if string.len(ws) > maxlen then - if mailcount == "?" - -- May happens sometimes using keyrings or other password fetchers. - -- Since this should be automatically fixed in short times, we threat - -- this exception delaying the update to the next timeout. - then - set_nomail() - return - elseif tonumber(mailcount) >= 1 - then - notify_title = ws:match(mail .. " has %d new message.?") - ws = ws:gsub(notify_title, "", 1):gsub("\n", "", 2) - - ws = ws:gsub("--Content.%S+.-\n", "") - ws = ws:gsub("--%d+.-\n", "") - - if string.len(ws) > maxlen - then - ws = ws:sub(1, maxlen) .. "[...]" - end - - notify_title = notify_title:gsub("\n", "") - end - - naughty.notify({ title = notify_title, - fg = color, - text = ws, - icon = beautiful.lain_mail_notify or - helpers.icons_dir .. "mail.png", - timeout = 8, - position = "top_left" }) - - helpers.set_map(mail, false) + ws = ws:sub(1, maxlen) .. "[...]" end + + notify_title = notify_title:gsub("\n", "") + + naughty.notify({ + preset = notification_preset, + title = notify_title, + text = ws + }) + + helpers.set_map(mail, false) end end - local myimapchecktimer = timer({ timeout = refresh_timeout }) - myimapchecktimer:connect_signal("timeout", myimapcheckupdate) - myimapchecktimer:start() - myimapcheck:buttons(awful.util.table.join( - awful.button({}, 0, + helpers.newtimer(mail, timeout, update, true) - function() - helpers.run_in_terminal(app) - end) - )) - - return myimapcheck + return widget end return setmetatable(imap, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/init.lua b/widgets/init.lua index 78cac9b..0e863ba 100644 --- a/widgets/init.lua +++ b/widgets/init.lua @@ -15,10 +15,6 @@ local wrequire = require("lain.helpers").wrequire local setmetatable = setmetatable -local widgets = -{ - _NAME = "lain.widgets", - terminal = "xterm" -- X default -} +local widgets = { _NAME = "lain.widgets" } return setmetatable(widgets, { __index = wrequire }) diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 98de091..00ab771 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -7,11 +7,8 @@ --]] -local markup = require("lain.util.markup") -local run_in_terminal = require("lain.helpers").run_in_terminal +local newtimer = require("lain.helpers").newtimer -local awful = require("awful") -local beautiful = require("beautiful") local wibox = require("wibox") local io = io @@ -28,25 +25,20 @@ local setmetatable = setmetatable local maildir = {} function worker(args) - local args = args or {} - local mailpath = args.mailpath or os.getenv("HOME") .. "/Mail" + local args = args or {} + local timeout = args.timeout or 60 + local mailpath = args.mailpath or os.getenv("HOME") .. "/Mail" local ignore_boxes = args.ignore_boxes or {} - local refresh_timeout = args.refresh_timeout or 60 - local header = args.header or " Mail " - local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color_newmail = args.color_newmail or beautiful.fg_focus or "#FFFFFF" - local color_nomail = args.color_nomail or beautiful.fg_normal or "#FFFFFF" - local app = args.app or "mutt" - local shadow = args.shadow or false + local settings = args.settings or function() end - local mymailcheck = wibox.widget.textbox() - local mymailcheckupdate = function() + widget = wibox.widget.textbox('') + + function update() -- Find pathes to mailboxes. local p = io.popen("find " .. mailpath .. " -mindepth 1 -maxdepth 1 -type d" .. " -not -name .git") local boxes = {} - local line = "" repeat line = p:read("*l") if line ~= nil @@ -73,7 +65,8 @@ function worker(args) table.sort(boxes) - local newmail = "" + newmail = "no mail" + local count = 0 for box, number in pairs(boxes) do @@ -91,39 +84,12 @@ function worker(args) end end - if count == 1 then - -- it will be only executed once - for box, number in pairs(boxes) - do -- it's useless to show only INBOX(x) - if box == "INBOX" then newmail = number end - end - end - - if newmail == "" - then - if shadow - then - mymailcheck:set_text('') - else - myimapcheck:set_markup(markup(color_nomail, " no mail ")) - end - else - myimapcheck:set_markup(" " .. markup(header_color, header) .. - markup(color_newmail, newmail) .. " ") - end + settings() end - local mymailchecktimer = timer({ timeout = refresh_timeout }) - mymailchecktimer:connect_signal("timeout", mymailcheckupdate) - mymailchecktimer:start() - mymailcheck:buttons(awful.util.table.join( - awful.button({}, 0, - function() - run_in_terminal(app) - end) - )) + newtimer(mailpath, timeout, update, true) - return mymailcheck + return widget end return setmetatable(maildir, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/mem.lua b/widgets/mem.lua index 3034e89..d0ff223 100644 --- a/widgets/mem.lua +++ b/widgets/mem.lua @@ -9,10 +9,8 @@ --]] -local markup = require("lain.util.markup") -local run_in_terminal = require("lain.helpers").run_in_terminal +local newtimer = require("lain.helpers").newtimer -local beautiful = require("beautiful") local wibox = require("wibox") local io = { lines = io.lines } @@ -28,19 +26,14 @@ local setmetatable = setmetatable local mem = {} function worker(args) - local args = args or {} - local refresh_timeout = args.refresh_timeout or 10 - local show_swap = args.show_swap or false - local show_total = args.show_total or false - local header = args.header or " Mem " - local header_color = args.header or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or "#FFFFFF" - local footer = args.footer or "MB " + local args = args or {} + local timeout = args.timeout or 3 + local settings = args.settings or function() end - local widg = wibox.widget.textbox() + widget = wibox.widget.textbox('') - local upd = function() - local mem = {} + function update() + mem = {} for line in io.lines("/proc/meminfo") do for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+") @@ -58,30 +51,12 @@ function worker(args) used = mem.total - (mem.free + mem.buf + mem.cache) swapused = mem.swap - mem.swapf - if show_total - then - local fmt = "%" .. string.len(mem.total) .. ".0f/%.0f" - widg:set_markup(markup(header_color, header) .. - markup(color, string.format(fmt, used, mem.total) .. footer)) - else - widg:set_markup(markup(header_color, header) .. - markup(color, used .. footer)) - end - - if show_swap - then - widg:set_markup(widg._layout.text .. ' (' - .. string.format('%.0f '.. footer, swapused) - .. ')') - end + settings() end - local tmr = timer({ timeout = refresh_timeout }) - tmr:connect_signal("timeout", upd) - tmr:start() - tmr:emit_signal("timeout") + newtimer("mem", timeout, update) - return widg + return widget end return setmetatable(mem, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 8db62ae..8ba1cde 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -7,10 +7,9 @@ --]] -local markup = require("lain.util.markup") local helpers = require("lain.helpers") -local awful = require("awful") +local util = require("awful.util") local beautiful = require("beautiful") local naughty = require("naughty") local wibox = require("wibox") @@ -27,111 +26,87 @@ local setmetatable = setmetatable local mpd = { id = nil } function worker(args) - local args = args or {} - local password = args.password or "" - local host = args.host or "127.0.0.1" - local port = args.port or "6600" + local args = args or {} + local timeout = args.timeout or 1 + local password = args.password or "" + local host = args.host or "127.0.0.1" + local port = args.port or "6600" local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" - local refresh_timeout = args.refresh_timeout or 1 - local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or "#FFFFFF" - local spr = args.spr or " " - local footer = args.footer or "" - local app = args.app or "ncmpcpp" - local shadow = args.shadow or false + local settings = args.settings or function() end local mpdcover = helpers.scripts_dir .. "mpdcover" - local mpdh = "telnet://"..host..":"..port - local echo = "echo 'password "..password.."\nstatus\ncurrentsong\nclose'" + local mpdh = "telnet://" .. host .. ":" .. port + local echo = "echo 'password " .. password .. "\nstatus\ncurrentsong\nclose'" - local mympd = wibox.widget.textbox() + widget = wibox.widget.textbox('') helpers.set_map("current mpd track", nil) - local mympdupdate = function() - local function set_nompd() - if shadow - then - mympd:set_text('') - else - mympd:set_markup(markup(header_color, "mpd ") .. markup(color , "off") .. footer) - end - end - - local mpd_state = { - ["{state}"] = "N/A", - ["{file}"] = "N/A", - ["{Artist}"] = "N/A", - ["{Title}"] = "N/A", - ["{Album}"] = "N/A", - ["{Date}"] = "N/A" + function update() + mpd_now = { + state = "N/A", + file = "N/A", + artist = "N/A", + title = "N/A", + album = "N/A", + date = "N/A" } - -- Get data from MPD server local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh) for line in f:lines() do for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do - if k == "state" then mpd_state["{"..k.."}"] = v - elseif k == "file" then mpd_state["{"..k.."}"] = v - elseif k == "Artist" then mpd_state["{"..k.."}"] = awful.util.escape(v) - elseif k == "Title" then mpd_state["{"..k.."}"] = awful.util.escape(v) - elseif k == "Album" then mpd_state["{"..k.."}"] = awful.util.escape(v) - elseif k == "Date" then mpd_state["{"..k.."}"] = awful.util.escape(v) + if k == "state" then mpd_now.state = v + elseif k == "file" then mpd_now.file = v + elseif k == "Artist" then mpd_now.artist = util.escape(v) + elseif k == "Title" then mpd_now.title = util.escape(v) + elseif k == "Album" then mpd_now.album = util.escape(v) + elseif k == "Date" then mpd_now.date = util.escape(v) end end end f:close() - if mpd_state["{state}"] == "play" + notification_preset = { + title = "Now playing", + text = mpd_now.artist .. " (" .. + mpd_now.album .. ") - " .. + mpd_now.date .. "\n" .. + mpd_now.title, + fg = beautiful.fg_normal or "#FFFFFF", + bg = beautiful.bg_normal or "#000000", + timeout = 6 + } + + settings() + + if mpd_now.state == "play" then - if mpd_state["{Title}"] ~= helpers.get_map("current mpd track") + if mpd_now.title ~= helpers.get_map("current mpd track") then - helpers.set_map("current mpd track", mpd_state["{Title}"]) + helpers.set_map("current mpd track", mpd_now.title) + os.execute(mpdcover .. " '" .. music_dir .. "' '" - .. mpd_state["{file}"] .. "'") + .. mpd_now.file .. "'") + mpd.id = naughty.notify({ - title = "Now playing", - text = mpd_state["{Artist}"] .. " (" .. - mpd_state["{Album}"] .. ") - " .. - mpd_state["{Date}"] .. "\n" .. - mpd_state["{Title}"], + preset = notification_preset, icon = "/tmp/mpdcover.png", - fg = color, - timeout = 6, replaces_id = mpd.id }).id end - mympd:set_markup(markup(header_color, mpd_state["{Artist}"]) - .. spr .. - markup(color, mpd_state["{Title}"]) .. footer) - elseif mpd_state["{state}"] == "pause" + elseif mpd_now.state ~= "pause" then - mympd:set_markup(markup(header_color, "mpd") - .. spr .. - markup(color, "paused") .. footer) - else helpers.set_map("current mpd track", nil) - set_nompd() end end - local mympdtimer = timer({ timeout = refresh_timeout }) - mympdtimer:connect_signal("timeout", mympdupdate) - mympdtimer:start() - mympdtimer:emit_signal("timeout") + helpers.newtimer("mpd", timeout, update) - mympd:buttons(awful.util.table.join( - awful.button({}, 0, - function() - helpers.run_in_terminal(app) - end) - )) + output = { widget = widget, notify = update } - local mpd_out = { widget = mympd, notify = mympdupdate } - - return setmetatable(mpd_out, { __index = mpd_out.widget }) + return setmetatable(output, { __index = output.widget }) end return setmetatable(mpd, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/net.lua b/widgets/net.lua index 18727f1..f05235b 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -7,33 +7,24 @@ --]] -local markup = require("lain.util.markup") local helpers = require("lain.helpers") -local awful = require("awful") -local beautiful = require("beautiful") +local notify_fg = require("beautiful").fg_focus +local naughty = require("naughty") local wibox = require("wibox") local io = io local tostring = tostring -local string = { format = string.format } +local string = { format = string.format, + gsub = string.gsub } local setmetatable = setmetatable -- Network infos -- lain.widgets.net local net = { - send = "0", - recv = "0", - last_t = {}, - last_r = {} -} - -net.units = { - ["b"] = 1, - ["kb"] = 1024, - ["mb"] = 1024^2, - ["gb"] = 1024^3 + last_t = 0, + last_r = 0 } function net.get_device() @@ -51,103 +42,61 @@ end function worker(args) local args = args or {} local iface = args.iface or net.get_device() - local delta = args.refresh_timeout or 2 - local units = args.units or net.units["kb"] - local spr = args.spr or " " - local header = args.header or iface - local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color_up = args.color_up or beautiful.fg_focus or "#FFFFFF" - local color_down = args.color_down or beautiful.fg_focus or "#FFFFFF" - local app = args.app or "sudo wifi-menu" + local units = args.units or 1024 --kb + local timeout = args.timeout or 2 + local settings = args.settings or function() end + + widget = wibox.widget.textbox('') helpers.set_map(iface, true) - helpers.set_map("carrier", 0) - local mynet = wibox.widget.textbox() + function update() + if iface == "" then iface = net.get_device() end - local mynetupdate = function() - if iface == "" then - iface = net.get_device() - header = iface - end - - local carrier = helpers.first_line('/sys/class/net/' .. iface .. - '/carrier') or "" - local state = helpers.first_line('/sys/class/net/' .. iface .. - '/operstate') + carrier = helpers.first_line('/sys/class/net/' .. iface .. + '/carrier') or "0" + state = helpers.first_line('/sys/class/net/' .. iface .. + '/operstate') or "down" local now_t = helpers.first_line('/sys/class/net/' .. iface .. - '/statistics/tx_bytes') + '/statistics/tx_bytes') or 0 local now_r = helpers.first_line('/sys/class/net/' .. iface .. - '/statistics/rx_bytes') - local text = '' .. header .. ' ' + '/statistics/rx_bytes') or 0 + + sent = tostring((now_t - net.last_t) / timeout / units) + sent = string.gsub(string.format('%.1f', sent), ",", ".") + + received = tostring((now_r - net.last_r) / timeout / units) + received = string.gsub(string.format('%.1f', received), ",", ".") + + settings() + + net.last_t = now_t + net.last_r = now_r if carrier ~= "1" then if helpers.get_map(iface) then n_title = iface - if n_title == "" then - n_title = "network" - header = "Net" - end - naughty.notify({ title = n_title, text = "no carrier", - timeout = 7, - position = "top_left", - icon = beautiful.lain_no_net_notify or - helpers.icons_dir .. "no_net.png", - fg = beautiful.fg_focus or "#FFFFFF" }) - - mynet:set_markup(markup(header_color, header) .. markup(color_up, " Off")) + if n_title == "" then n_title = "network" end + naughty.notify({ + title = n_title, + text = "no carrier", + timeout = 7, + position = "top_left", + icon = helpers.icons_dir .. "no_net.png", + fg = notify_fg or "#FFFFFF" + }) helpers.set_map(iface, false) end - return else helpers.set_map(iface, true) end - - if state == 'down' or not now_t or not now_r - then - mynet:set_markup(' ' .. text .. '-' .. ' ') - return - end - - if net.last_t[iface] and net.last_t[iface] - then - net.send = tostring((now_t - net.last_t[iface]) / delta / units) - net.recv = tostring((now_r - net.last_r[iface]) / delta / units) - - text = text - .. '' - .. string.format('%.1f', net.send) - .. '' - .. spr - .. '' - .. string.format('%.1f', net.recv) - .. '' - - mynet:set_markup(' ' .. text .. ' ') - else - mynet:set_markup(' ' .. text .. '-' .. ' ') - end - - net.last_t[iface] = now_t - net.last_r[iface] = now_r end - local mynettimer = timer({ timeout = delta }) - mynettimer:connect_signal("timeout", mynetupdate) - mynettimer:start() - mynettimer:emit_signal("timeout") + helpers.newtimer(iface, timeout, update) - mynet:buttons(awful.util.table.join( - awful.button({}, 0, function() - helpers.run_in_terminal(app) - mynetupdate() - end))) - - net.widget = mynet - - return setmetatable(net, { __index = net.widget }) + return widget end return setmetatable(net, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/sysload.lua b/widgets/sysload.lua index eb06828..6167d82 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -7,11 +7,8 @@ --]] -local markup = require("lain.util.markup") -local helpers = require("lain.helpers") +local newtimer = require("lain.helpers").newtimer -local awful = require("awful") -local beautiful = require("beautiful") local wibox = require("wibox") local io = io @@ -26,45 +23,24 @@ local sysload = {} function worker(args) local args = args or {} - local refresh_timeout = args.refresh_timeout or 5 - local show_all = args.show_all or false - local header = args.header or " Load " - local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or "#FFFFFF" - local app = args.app or "top" + local timeout = args.timeout or 5 + local settings = args.settings or function() end - local mysysload = wibox.widget.textbox() + widget = wibox.widget.textbox('') - local mysysloadupdate = function() + function update() local f = io.open("/proc/loadavg") local ret = f:read("*all") f:close() + + a, b, c = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") - if show_all - then - local a, b, c = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") - mysysload:set_text(string.format("%s %s %s", a, b, c)) - else - local a = string.match(ret, "([^%s]+) ") - mysysload:set_text(string.format("%s", a)) - end - mysysload:set_markup(markup(header_color, header) .. - markup(color, mysysload._layout.text .. " ")) + settings() end - local mysysloadtimer = timer({ timeout = refresh_timeout }) - mysysloadtimer:connect_signal("timeout", mysysloadupdate) - mysysloadtimer:start() - mysysloadtimer:emit_signal("timeout") + newtimer("sysload", timeout, update) - mysysload:buttons(awful.util.table.join( - awful.button({}, 0, - function() - helpers.run_in_terminal(app) - end) - )) - - return mysysload + return widget end return setmetatable(sysload, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/temp.lua b/widgets/temp.lua index 301bc1c..5b1ebf5 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -6,9 +6,8 @@ --]] -local markup = require("lain.util.markup") +local newtimer = require("lain.helpers").newtimer -local beautiful = require("beautiful") local wibox = require("wibox") local io = io @@ -21,32 +20,22 @@ local setmetatable = setmetatable local temp = {} function worker(args) - local args = args or {} - local refresh_timeout = args.refresh_timeout or 5 - local header = args.header or " Temp " - local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF" - local color = args.color or beautiful.fg_focus or header_color - local footer = args.footer or "C " + local args = args or {} + local timeout = args.timeout or 5 + local settings = args.settings or function() end - local mytemp = wibox.widget.textbox() + widget = wibox.widget.textbox('') - local mytempupdate = function() + function update() local f = io.open("/sys/class/thermal/thermal_zone0/temp") - local ret = f:read("*all") + coretemp_now = tonumber(f:read("*all")) / 1000 f:close() - - ret = tonumber(ret) / 1000 - - mytemp:set_markup(markup(header_color, header) .. - markup(color, ret .. footer)) + settings() end - local mytemptimer = timer({ timeout = refresh_timeout }) - mytemptimer:connect_signal("timeout", mytempupdate) - mytemptimer:start() - mytemptimer:emit_signal("timeout") + newtimer("coretemp", timeout, update) - return mytemp + return widget end return setmetatable(temp, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 20c90b1..9bed983 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -6,9 +6,8 @@ --]] -local markup = require("lain.util.markup") +local newtimer = require("lain.helpers").newtimer -local beautiful = require("beautiful") local naughty = require("naughty") local wibox = require("wibox") @@ -28,10 +27,9 @@ local setmetatable = setmetatable -- lain.widgets.yawn local yawn = { - units = "", - forecast = "", - icon = wibox.widget.imagebox(), - widget = wibox.widget.textbox() + icon = wibox.widget.imagebox(), + widget = wibox.widget.textbox(''), + notification_preset = {} } local project_path = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]] @@ -44,33 +42,32 @@ local weather_data = nil local notification = nil local city_id = nil local sky = nil -local settings = {} -local update_timer = nil - -local function fetch_weather(args) - local toshow = args.toshow or "forecast" +local settings = function() end +local function fetch_weather() local url = api_url .. units_set .. city_id local f = io.popen("curl --connect-timeout 1 -fsm 2 '" .. url .. "'" ) local text = f:read("*all") f:close() + -- handle no suitable icon found + yawn.icon:set_image(icon_path .. "na.png") + -- In case of no connection or invalid city ID -- widgets won't display if text == "" or text:match("City not found") then - sky = icon_path .. "na.png" - yawn.icon:set_image(sky) if text == "" then weather_data = "Service not available at the moment." - return "N/A" + yawn.widget:set_text("N/A") else weather_data = "City not found!\n" .. "Are you sure " .. city_id .. " is your Yahoo city ID?" - return "?" + yawn.widget:set_text("?") end + return end -- Processing raw data @@ -88,8 +85,8 @@ local function fetch_weather(args) -- Getting info for text widget local now = weather_data:sub(weather_data:find("Now:")+5, weather_data:find("\n")-1) - local forecast = now:sub(1, now:find(",")-1) - local units = now:sub(now:find(",")+2, -2) + forecast = now:sub(1, now:find(",")-1) + units = now:sub(now:find(",")+2, -2) -- Day/Night icon change local hour = tonumber(os.date("%H")) @@ -110,14 +107,6 @@ local function fetch_weather(args) sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png" - -- In case there's no defined icon for current forecast - f = io.popen(sky) - if f == nil then - sky = icon_path .. "na.png" - else - f:close() - end - -- Localization local f = io.open(localizations_path .. language, "r") if language:find("en_") == nil and f ~= nil @@ -132,21 +121,18 @@ local function fetch_weather(args) end -- Finally setting infos - both = weather_data:match(": %S+.-\n"):gsub(": ", "") + yawn.icon:set_image(sky) + widget = wibox.widget.textbox() + forecast = weather_data:match(": %S+.-,"):gsub(": ", ""):gsub(",", "\n") units = units:gsub(" ", "") + notification_preset = {} + -- anche notification preset, con fg, bg e position - yawn.forecast = markup(yawn.color, " " .. markup.font(beautiful.font, forecast) .. " ") - yawn.units = markup(yawn.color, " " .. markup.font(beautiful.font, units)) - yawn.icon:set_image(sky) + settings() - if toshow == "forecast" then - return yawn.forecast - elseif toshow == "units" then - return yawn.units - else - return both - end + yawn.widget = widget + yawn.notification_preset = notification_preset end function yawn.hide() @@ -159,41 +145,29 @@ end function yawn.show(t_out) if yawn.widget._layout.text == "?" then - if update_timer ~= nil - then - update_timer:emit_signal("timeout") - else - fetch_weather(settings) - end + fetch_weather(settings) end yawn.hide() notification = naughty.notify({ + preset = yawn.notification_preset, text = weather_data, icon = sky, - timeout = t_out, - fg = yawn.color + timeout = t_out }) end function yawn.register(id, args) - local args = args or {} - - settings = args - - yawn.color = args.color or beautiful.fg_normal or "#FFFFFF" + local args = args or {} + local timeout = args.timeout or 600 + settings = args.settings or function() end if args.u == "f" then units_set = '?u=f&w=' end city_id = id - update_timer = timer({ timeout = 600 }) -- 10 mins - update_timer:connect_signal("timeout", function() - yawn.widget:set_markup(fetch_weather(settings)) - end) - update_timer:start() - update_timer:emit_signal("timeout") + newtimer("yawn", timeout, fetch_weather) yawn.icon:connect_signal("mouse::enter", function() yawn.show(0) @@ -202,7 +176,7 @@ function yawn.register(id, args) yawn.hide() end) - return yawn + return { icon = yawn.icon, widget = yawn.widget } end function yawn.attach(widget, id, args) @@ -217,6 +191,4 @@ function yawn.attach(widget, id, args) end) end --- }}} - return setmetatable(yawn, { __call = function(_, ...) return yawn.register(...) end }) From ad2bd8dffb902b905b11e2cd6a29ddd152ff69b5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:02:15 -0700 Subject: [PATCH 168/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index 4994e1d..11bf53f 100644 --- a/cpu.md +++ b/cpu.md @@ -11,7 +11,7 @@ Variable | Meaning | Type | Default `timeout` | Refresh timeout seconds | int | 10 `settings` | User settings | function | empty function -`settings` can be fed with the string `usage`, which means the cpu use percentage. +`settings` can use the string `usage`, which is the cpu use percentage. ### output From 2ba0ba631e4bb323de2b26d8d690f3f977d61cec Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:02:56 -0700 Subject: [PATCH 169/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index f1aa353..07f59a6 100644 --- a/fs.md +++ b/fs.md @@ -23,7 +23,7 @@ It can also use value strings in these formats: fs_info[p .. "size_mb"] fs_info[p .. "size_gb"] -where `p` is the "mount" column of the output of `df` command (`/`, `/home`, `/boot`, ...). +where `p` is the "mount" column of the output of `df` command ("/", "/home", "/boot", ...). This means you can set the widget for a certain partition, but you can look up at others too. From 49e226be45dd4178d37bd99848b8a7e72684bee4 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:03:36 -0700 Subject: [PATCH 170/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index 07f59a6..6525e41 100644 --- a/fs.md +++ b/fs.md @@ -23,7 +23,7 @@ It can also use value strings in these formats: fs_info[p .. "size_mb"] fs_info[p .. "size_gb"] -where `p` is the "mount" column of the output of `df` command ("/", "/home", "/boot", ...). +where `p` is the last column of the output of `df` ("/", "/home", "/boot", ...). This means you can set the widget for a certain partition, but you can look up at others too. From 609b11882958381f668e25316ba1b575fd1096af Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:04:23 -0700 Subject: [PATCH 171/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index 6525e41..bb57c3a 100644 --- a/fs.md +++ b/fs.md @@ -23,7 +23,7 @@ It can also use value strings in these formats: fs_info[p .. "size_mb"] fs_info[p .. "size_gb"] -where `p` is the last column of the output of `df` ("/", "/home", "/boot", ...). +where `p` is the last column of `df` ("/", "/home", "/boot", ...). This means you can set the widget for a certain partition, but you can look up at others too. From ae93d3bd3d0e9b0d5adea7861a97e95e05787fa0 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:13:33 -0700 Subject: [PATCH 172/572] Updated fs (markdown) --- fs.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs.md b/fs.md index bb57c3a..883008d 100644 --- a/fs.md +++ b/fs.md @@ -27,7 +27,9 @@ where `p` is the last column of `df` ("/", "/home", "/boot", ...). This means you can set the widget for a certain partition, but you can look up at others too. -Finally, `settings` can modify `notification_preset` table too. This table will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. +Finally, `settings` can modify `notification_preset` table too. This table will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: + + notification_preset = { fg = beautiful.fg_normal } ### output table From b8adbea6d8f24316b8f41897ddda67f3ffbc8965 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:14:30 -0700 Subject: [PATCH 173/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index 883008d..46bcbc2 100644 --- a/fs.md +++ b/fs.md @@ -23,7 +23,7 @@ It can also use value strings in these formats: fs_info[p .. "size_mb"] fs_info[p .. "size_gb"] -where `p` is the last column of `df` ("/", "/home", "/boot", ...). +where `p` is the last column of `df` command ("/", "/home", "/boot", ...). This means you can set the widget for a certain partition, but you can look up at others too. From 37c3546f5143dbb71985dc0adf47ef5c8c38ca26 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:17:21 -0700 Subject: [PATCH 174/572] Updated imap (markdown) --- imap.md | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/imap.md b/imap.md index 97cd437..7b8e761 100644 --- a/imap.md +++ b/imap.md @@ -2,10 +2,6 @@ Shows mail status in a textbox over IMAP protocol. -Dependencies: - -- python3 - New mails are notified through a notification like this: +---------------------------------------------------+ @@ -26,29 +22,22 @@ Text will be cut if the mail is too long. The function takes a table as argument. Required table parameters are: -Variable | Type ---- | --- -`server` | string -`mail` | string -`password` | string +Variable | Meaning | Type +--- | --- | --- +`server` | Mail server | string +`mail` | User mail | string +`password` | User password | string while the optional are: Variable | Meaning | Type | Default --- | --- | --- | --- `port` | IMAP port | int | 993 -`refresh_timeout` | Refresh timeout seconds | int | 60 -`header` | Text to show before value | string | " Mail " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Mail value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to append after value | string | " " -`mail_encoding` | Mail character encoding | string | autodetected +`timeout` | Refresh timeout seconds | int | 60 +`encoding` | Mail character encoding | string | autodetected `maxlen` | Maximum chars to display in notification | int | 200 -`app` | Mail program to spawn on click | string | "mutt" -`shadow` | Hide widget when there are no mails | boolean | false `is_plain` | Define whether `password` is a plain password (true) or a function that retrieves it (false) | boolean | false - -**Note**: `footer` can be markup text. +`settings` | User settings | function Let's focus better on `is_plain`. @@ -65,6 +54,20 @@ and you'll have the same security provided by `~/.netrc`. When `is_plain == false`, it *executes* `password` before using it, so you can also use whatever password fetching solution you want. -You can also define your custom icon for the naughty notification. Just set `lain_mail_notify` into `theme.lua`: +`settings` can use the string `mailcount`, whose possible values are: - theme.lain_mail_notify = "/path/to/my/icon" \ No newline at end of file +- "0" +- "invalid credentials" +- string number + +and can modify `notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: + + notification _preset = { + icon = lain/icons/mail.png, + timeout = 8, + position = "top_left" + } + +### output + +A textbox. \ No newline at end of file From fb5ef55cba1b3dc5b6dac1efb3cdecc4b63bf90b Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:25:32 -0700 Subject: [PATCH 175/572] Updated imap (markdown) --- imap.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imap.md b/imap.md index 7b8e761..501ffac 100644 --- a/imap.md +++ b/imap.md @@ -1,5 +1,7 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) +**Please be warned**: as for now, this works fine in normal link situations, but is discouraged to use it if your connection is sobbing, since it may cause some short freezes. I am at work to solve this. + Shows mail status in a textbox over IMAP protocol. New mails are notified through a notification like this: From 00d2e82a82a918bef76e59c018ec9ef9b3570379 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:26:48 -0700 Subject: [PATCH 176/572] Updated imap (markdown) --- imap.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imap.md b/imap.md index 501ffac..87a69e9 100644 --- a/imap.md +++ b/imap.md @@ -1,6 +1,8 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -**Please be warned**: as for now, this works fine in normal link situations, but is discouraged to use it if your connection is sobbing, since it may cause some short freezes. I am at work to solve this. +**Please be warned**: as for now, this works fine in normal link situations, but is discouraged to use it if your connection is sobbing, since it may cause some short freezes. I am working on socket libraries to solve this. If you're a Python programmer, feel free to lend a hand. + +--- Shows mail status in a textbox over IMAP protocol. From 4f366fef945fcecdc0a8e8d58ca5ccdfe6a93c26 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:27:24 -0700 Subject: [PATCH 177/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index 87a69e9..cf5324d 100644 --- a/imap.md +++ b/imap.md @@ -1,6 +1,6 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -**Please be warned**: as for now, this works fine in normal link situations, but is discouraged to use it if your connection is sobbing, since it may cause some short freezes. I am working on socket libraries to solve this. If you're a Python programmer, feel free to lend a hand. +**Please be warned**: as for now, this works fine in normal link situations, but is discouraged to use it if your connection is sobbing, since it may cause some short freezes due to timeout issues. I am working on socket libraries to solve this. If you're a Python programmer, feel free to lend a hand. --- From ff0865c837bfbcd4073ee1bbaa4652d5dd64898c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:28:03 -0700 Subject: [PATCH 178/572] Updated imap (markdown) --- imap.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imap.md b/imap.md index cf5324d..e583410 100644 --- a/imap.md +++ b/imap.md @@ -1,6 +1,8 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -**Please be warned**: as for now, this works fine in normal link situations, but is discouraged to use it if your connection is sobbing, since it may cause some short freezes due to timeout issues. I am working on socket libraries to solve this. If you're a Python programmer, feel free to lend a hand. +**Please be warned**: as for now, this works fine in normal link situations, but is discouraged to use it if your connection is sobbing, since it may cause some short freezes due to timeout issues. I am working on socket libraries to solve this. + +If you're a Python programmer, feel free to lend a hand. --- From 0e9db489f57aa77474e33cb0355936301254d421 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:31:01 -0700 Subject: [PATCH 179/572] Updated maildir (markdown) --- maildir.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/maildir.md b/maildir.md index a30e59f..355ecdd 100644 --- a/maildir.md +++ b/maildir.md @@ -24,19 +24,16 @@ If there's new mails, the textbox will say something like "mail: bugs(3), system mymaildir = lain.widgets.maildir("/path/to/my/maildir") -The function takes a table as optional argument, which can contain: +### input table Variable | Meaning | Type | Default --- | --- | --- | --- +`timeout` | Refresh timeout seconds | int | 60 `mailpath` | Path to your maildir | string | "~/Mail" -`ignore_boxes` | A list of boxes to ignore | table | empty table -`refresh_timeout` | Refresh timeout seconds | int | 60 -`header` | Text to show before value | string | " Mail " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color_newmail` | New mail value color | string | `beautiful.fg_focus` or "#FFFFFF" -`color_nomail` | No mail value color | string | `beautiful.fg_normal` or "#FFFFFF" -`footer` | Text to append after value | string | " " -`app` | Mail program to spawn on click | string | "mutt"| boolean | false -`shadow` | Hide widget when there are no mails | boolean | false +`settings` | User settings | function | empty function -**Note**: `footer` can be markup text. \ No newline at end of file +`settings` can use the string `newmail`, which format will be something like defined above, or "no mail". + +### output + +A textbox. \ No newline at end of file From 78a106822996d3a32b63282bbd4a2f385973cea0 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:33:06 -0700 Subject: [PATCH 180/572] Updated mem (markdown) --- mem.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/mem.md b/mem.md index 68c6748..067dc25 100644 --- a/mem.md +++ b/mem.md @@ -10,12 +10,11 @@ contain: Variable | Meaning | Type | Default --- | --- | --- | --- -`refresh_timeout` | Refresh timeout seconds | int | 10 -`show_swap` | Show amount of used swap space? | boolean | false -`show_total` | Show amout of total memory? | boolean | false -`header` | Text to show before value | string | " Mem " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to show after value | string | "MB " +`timeout` | Refresh timeout seconds | int | 10 +`settings` | User settings | function | empty function -**Note**: `footer` color is `color`. \ No newline at end of file +`settings` can use the strings `used` (memory used MB) and `swapused` (swap used MB). + +### output + +A textbox. \ No newline at end of file From 7c26a6028abe49d5976bd941e3b131460ded3f3d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:40:31 -0700 Subject: [PATCH 181/572] Updated Widgets (markdown) --- Widgets.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Widgets.md b/Widgets.md index 7130cc3..1a26b80 100644 --- a/Widgets.md +++ b/Widgets.md @@ -1,8 +1,6 @@ Every widget is output by a `function`. -Unless otherwise expressly noted, `function` returns a `wibox.widget.textbox`. - -This is said because, for some widgets, `function` returns a table to be used for notification and update purposes. +For some widgets, `function` returns a `wibox.widget.textbox`, for others a table to be used for notification and update purposes. Every widget may take either a table or a list of variables as argument. From fdf4eabebbf43e519528686df8c155ae56282982 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:47:19 -0700 Subject: [PATCH 183/572] Updated mpd (markdown) --- mpd.md | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/mpd.md b/mpd.md index 2a0ba32..ab36d15 100644 --- a/mpd.md +++ b/mpd.md @@ -2,7 +2,7 @@ Shows MPD status in a textbox. - mympd = lain.widgets.mpd() + mpdwidget = lain.widgets.mpd() Now playing songs are notified like this: @@ -14,37 +14,47 @@ Now playing songs are notified like this: | +-------+ | +--------------------------------------------------------+ -Dependencies - -- imagemagick - The function takes a table as optional argument, which can contain: Variable | Meaning | Type | Default --- | --- | --- | --- +`timeout` | Refresh timeout seconds | int | 1 `password` | MPD password | string | "" `host` | MPD server | string | "127.0.0.1" `port` | MPD port | string | "6600" `music_dir` | Music directory | string | "~/Music" -`refresh_timeout` | Refresh timeout seconds | int | 1 -`header` | Text before values | string | "" -`artist_color` | Artist value color | string | `beautiful.fg_normal` or "#FFFFFF" -`song_color` | Song value color | string | `beautiful.fg_focus` or "#FFFFFF" -`spr` | Separator text between artist and song values | string | " " -`footer` | Text to append after values | string | "" -`app` | Music program to spawn on click | string | "ncmpcpp" -`shadow` | Hide widget when there are no songs playing | boolean | false +`settings` | User settings | function | empty function -**Note**: `spr` and `footer` can be markup text. +`settings` can use `mpd_now` table, which contains the following string values: -`lain.widgets.mpd` outputs the following table: +- state +- file +- artist +- title +- album +- date + +and can modify `notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: + + notification _preset = { + title = "Now playing", + text = mpd_now.artist .. " (" .. + mpd_now.album .. ") - " .. + mpd_now.date .. "\n" .. + mpd_now.title, + fg = beautiful.fg_normal or "#FFFFFF", + bg = beautiful.bg_normal or "#000000", + timeout = 6 + } + +### output table Variable | Meaning | Type --- | --- | --- `widget` | The textbox | `wibox.widget.textbox` `notify` | The notification | function -Finally, you can control the widget with key bindings like these: +You can control the widget with key bindings like these: -- MPD control awful.key({ altkey, "Control" }, "Up", From 5fbbc64b81283c74a09f19db03647cf8e74ce736 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:52:25 -0700 Subject: [PATCH 184/572] Updated mpd (markdown) --- mpd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpd.md b/mpd.md index ab36d15..8b35e81 100644 --- a/mpd.md +++ b/mpd.md @@ -14,7 +14,7 @@ Now playing songs are notified like this: | +-------+ | +--------------------------------------------------------+ -The function takes a table as optional argument, which can contain: +### input table Variable | Meaning | Type | Default --- | --- | --- | --- From f2a9d548e6172987c554cdd1261c1008e2670328 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:55:52 -0700 Subject: [PATCH 185/572] Updated net (markdown) --- net.md | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/net.md b/net.md index 82772d7..096b6a0 100644 --- a/net.md +++ b/net.md @@ -4,26 +4,15 @@ Monitors network interfaces and shows current traffic in a textbox. mynet = lain.widgets.net() -The function takes a table as optional argument, which can contain: +### input table Variable | Meaning | Type | Default --- | --- | --- | --- +`timeout` | Refresh timeout seconds | int | 2 `iface` | Network device | string | autodetected -`refresh_timeout` | Refresh timeout seconds | int | 2 `units` | Units | int | 1024 (kilobytes) -`spr` | Separator text between download and upload values | string | " " -`header` | Text to show before value | string | `iface` -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`footer` | Text to append after value | string | "" -`color_up` | Upload value color | string | `beautiful.fg_focus` or "#FFFFFF" -`color_down` | Download value color | string | `beautiful.fg_focus` or "#FFFFFF" -`app` | Net program to spawn on click | string | "sudo wifi-menu" +`settings` | User settings | function | empty function -**Note**: `spr` and `footer` can be a markup text. +Possible other values for `units` are 1 (byte) or multiple of 1024: 1024^2 (mb), 1024^3 (gb), ... . -Possible value for `units` are stored in table `lain.widgets.net.units`, which contains: - - ["b"] = 1, - ["kb"] = 1024, - ["mb"] = 1024^2, - ["gb"] = 1024^3 \ No newline at end of file +`settings` can use the following `iface` strings: `carrier`, `state`, `sent`, `received`. \ No newline at end of file From 8f907725c6bc5016c27da6b384a79200167af346 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 14:56:45 -0700 Subject: [PATCH 186/572] Updated net (markdown) --- net.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net.md b/net.md index 096b6a0..bace937 100644 --- a/net.md +++ b/net.md @@ -15,4 +15,8 @@ Variable | Meaning | Type | Default Possible other values for `units` are 1 (byte) or multiple of 1024: 1024^2 (mb), 1024^3 (gb), ... . -`settings` can use the following `iface` strings: `carrier`, `state`, `sent`, `received`. \ No newline at end of file +`settings` can use the following `iface` strings: `carrier`, `state`, `sent`, `received`. + +### output + +A textbox. \ No newline at end of file From 8c08dcd844dae10295858419e95babe7072e4910 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 15:00:37 -0700 Subject: [PATCH 187/572] Updated sysload (markdown) --- sysload.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sysload.md b/sysload.md index 65b5eec..234770b 100644 --- a/sysload.md +++ b/sysload.md @@ -4,13 +4,15 @@ Show the current system load in a textbox. mysysload = lain.widgets.sysload() -The function takes a table as optional argument, which can contain: +### input table Variable | Meaning | Type | Default --- | --- | --- | --- -`show_all` | Show all the three values (true), or only the first one (false) | boolean | false -`refresh_timeout` | Refresh timeout seconds | int | 5 -`header` | Text to show before value | string | " Load " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`app` | Proc program to spawn on click | string | "top" \ No newline at end of file +`timeout` | Refresh timeout seconds | int | 5 +`settings` | User settings | function | empty function + +`settings` can use strings `a`, `b` and `c`, which are loadavg over 1, 5, and 15 minutes. + +### output + +A textbox. \ No newline at end of file From bc2e09d6d9e0d88a8175a337397af9b535a31624 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 15:02:23 -0700 Subject: [PATCH 188/572] Updated temp (markdown) --- temp.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/temp.md b/temp.md index 92d7d06..f7315b6 100644 --- a/temp.md +++ b/temp.md @@ -10,8 +10,7 @@ The function takes a table as optional argument, which can contain: Variable | Meaning | Type | Default --- | --- | --- | --- -`refresh_timeout` | Refresh timeout seconds | int | 5 -`header` | Text to show before value | string | " Temp " -`header_color` | Header color | string | `beautiful.fg_normal` or "#FFFFFF" -`color` | Value color | string | `beautiful.fg_focus` or "#FFFFFF" -`footer` | Text to show after value | string | "C " \ No newline at end of file +`timeout` | Refresh timeout seconds | int | 5 +`settings` | User settings | function | empty function + +`settings` can use the string `coretemp_now`, which means current core temperature, expressed in Celsius (linux standard). \ No newline at end of file From e996c58363672b7ca530b02bbd38010adfc2a9e9 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 15:03:57 -0700 Subject: [PATCH 189/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index 11bf53f..ae490b0 100644 --- a/cpu.md +++ b/cpu.md @@ -8,7 +8,7 @@ Shows in a textbox the average CPU usage percent for a given amount of time. Variable | Meaning | Type | Default --- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 10 +`timeout` | Refresh timeout seconds | int | 5 `settings` | User settings | function | empty function `settings` can use the string `usage`, which is the cpu use percentage. From 62bc3c8be1eaf8668f8139c853864beeed8fa3b1 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 15:04:34 -0700 Subject: [PATCH 190/572] Updated mem (markdown) --- mem.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mem.md b/mem.md index 067dc25..80e6a88 100644 --- a/mem.md +++ b/mem.md @@ -10,7 +10,7 @@ contain: Variable | Meaning | Type | Default --- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 10 +`timeout` | Refresh timeout seconds | int | 3 `settings` | User settings | function | empty function `settings` can use the strings `used` (memory used MB) and `swapused` (swap used MB). From c6b46f1382933684c6ae33741e188e11ac609cde Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 10 Sep 2013 15:10:43 -0700 Subject: [PATCH 191/572] Updated yawn (markdown) --- yawn.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/yawn.md b/yawn.md index 070bf2e..6a087cc 100644 --- a/yawn.md +++ b/yawn.md @@ -24,15 +24,18 @@ an existent widget. - ``args`` - An optional table which can contain the following settings: + A required table which can contain: Variables | Meaning | Type | Possible values | Default value --- | --- | --- | --- | --- `u` | Units | string | "c" (Celsius), "f" (Fahrenheit) | "c" - `toshow` | What to show | string | "forecast", "units", "both" | "forecast" - `color` | ``yawn.widget`` color | string | hexadecimal colors | + `timeout` | Refresh timeout seconds | int | integers | 600 + `settings` | User settings | function | function | empty function -The function creates an imagebox icon and a textbox widget. Add them to you wibox like this: + `settings` can use strings `forecast`, `units', and can modify `notification_preset` table, which + will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. + +The function `register` creates an imagebox icon and a textbox widget. Add them to you wibox like this: right_layout:add(yawn.icon) right_layout:add(yawn.widget) From 68aa86654dc5e48af7f4ed896c89926646135afa Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 11 Sep 2013 00:10:53 +0200 Subject: [PATCH 192/572] wiki updated --- widgets/fs.lua | 2 +- widgets/net.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/fs.lua b/widgets/fs.lua index f934248..3a36bf3 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -53,8 +53,8 @@ local unit = { ["mb"] = 1024, ["gb"] = 1024^2 } local function worker(args) local args = args or {} - local partition = args.partition or "/" local timeout = args.timeout or 600 + local partition = args.partition or "/" local settings = args.settings or function() end widget = wibox.widget.textbox('') diff --git a/widgets/net.lua b/widgets/net.lua index f05235b..e086c4b 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -41,9 +41,9 @@ end function worker(args) local args = args or {} + local timeout = args.timeout or 2 local iface = args.iface or net.get_device() local units = args.units or 1024 --kb - local timeout = args.timeout or 2 local settings = args.settings or function() end widget = wibox.widget.textbox('') From 11b916170373c3fab2707613f051c8ab72ef0db8 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 05:46:07 -0700 Subject: [PATCH 193/572] Updated Utilities (markdown) --- Utilities.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Utilities.md b/Utilities.md index cbf8c0f..7e18683 100644 --- a/Utilities.md +++ b/Utilities.md @@ -1,11 +1,11 @@ markup ------ -This is a submodule which helps you markupping your text. +Made markup easier! First, require it like this: - local markup = require("lain.util.markup") + local markup = lain.util.markup then you can call its functions: From cb3a0d0927c8dd6acc2ee5eea6fdd9dfa5b4a7ca Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 05:46:54 -0700 Subject: [PATCH 194/572] Updated Utilities (markdown) --- Utilities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities.md b/Utilities.md index 7e18683..6afff16 100644 --- a/Utilities.md +++ b/Utilities.md @@ -46,7 +46,7 @@ they all take one argument, which is the text to markup, except `fg.color` and ` menu\_clients\_current\_tags ---------------------------- -Similar to `awful.menu.clients()`, but this menu only shows the clients +Similar to `awful.menu.clients`, but this menu only shows the clients of currently visible tags. Use it with a key binding like this: awful.key({ "Mod1" }, "Tab", From c7f82ee59ad1edb2126b8e933bf4c24e602d5ef1 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 07:09:56 -0700 Subject: [PATCH 195/572] Updated mpd (markdown) --- mpd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpd.md b/mpd.md index 8b35e81..bd7232e 100644 --- a/mpd.md +++ b/mpd.md @@ -27,7 +27,7 @@ Variable | Meaning | Type | Default `settings` can use `mpd_now` table, which contains the following string values: -- state +- state (possible values: "play", "pause", "stop") - file - artist - title From 1a8b3a69e7b8a6969e0798046e9d30c56fe626c7 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 07:19:34 -0700 Subject: [PATCH 196/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index 46bcbc2..44be2b2 100644 --- a/fs.md +++ b/fs.md @@ -14,7 +14,7 @@ Variable | Meaning | Type | Default `partition` | Partition to monitor | string | "/" `settings` | User settings | function | empty function -`settings` can use the following `partition` related value strings: `used`, `available`, `size_mb`, `size_gb`. +`settings` can use the following `partition` related float values: `used` and `available`, `size_mb`, `size_gb`. It can also use value strings in these formats: From 1273f51f1c9242eb8b5c9e0774707e67bc210617 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 07:28:25 -0700 Subject: [PATCH 197/572] Updated yawn (markdown) --- yawn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yawn.md b/yawn.md index 6a087cc..5b111bd 100644 --- a/yawn.md +++ b/yawn.md @@ -32,7 +32,7 @@ an existent widget. `timeout` | Refresh timeout seconds | int | integers | 600 `settings` | User settings | function | function | empty function - `settings` can use strings `forecast`, `units', and can modify `notification_preset` table, which + `settings` can use strings `forecast`, `units`, and can modify `notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. The function `register` creates an imagebox icon and a textbox widget. Add them to you wibox like this: From b31152ab6e56233a9c8589c53a08068d065a3480 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 09:36:42 -0700 Subject: [PATCH 198/572] Updated imap (markdown) --- imap.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/imap.md b/imap.md index e583410..6590ee7 100644 --- a/imap.md +++ b/imap.md @@ -1,8 +1,6 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -**Please be warned**: as for now, this works fine in normal link situations, but is discouraged to use it if your connection is sobbing, since it may cause some short freezes due to timeout issues. I am working on socket libraries to solve this. - -If you're a Python programmer, feel free to lend a hand. +**Please be warned**: this is a temporary solution, since it works fine in normal situations but causes little freezes if connection is sobbing. I am working on something much more solid. --- From c5ddfd66999bdaf0fa48a60f4ad4f2f1afa52c0c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 09:39:38 -0700 Subject: [PATCH 199/572] Updated alsa (markdown) --- alsa.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/alsa.md b/alsa.md index f632717..af1139a 100644 --- a/alsa.md +++ b/alsa.md @@ -24,7 +24,7 @@ volume.status | Device status | string | "on", "off" Variable | Meaning | Type --- | --- | --- `widget` | The widget | `wibox.widget.textbox` -`notify` | Force update `widget` | function +`update` | Update `widget` | function You can control the widget with key bindings like these: @@ -32,22 +32,22 @@ You can control the widget with key bindings like these: awful.key({ altkey }, "Up", function () awful.util.spawn("amixer sset Master 1%+") - volume.notify() + volume.update() end), awful.key({ altkey }, "Down", function () awful.util.spawn("amixer sset Master 1%-") - volume.notify() + volume.update() end), awful.key({ altkey }, "m", function () awful.util.spawn("amixer set Master playback toggle") - volume.notify() + volume.update() end), awful.key({ altkey, "Control" }, "m", function () awful.util.spawn("amixer set Master playback 100%", false ) - volume.notify() + volume.update() end), where `altkey = "Mod1"`. \ No newline at end of file From a5fea2962eb61b0c26000cf07e30148f2e95becc Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 09:40:33 -0700 Subject: [PATCH 200/572] Updated alsa (markdown) --- alsa.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alsa.md b/alsa.md index af1139a..65314d2 100644 --- a/alsa.md +++ b/alsa.md @@ -31,12 +31,12 @@ You can control the widget with key bindings like these: -- Volume control awful.key({ altkey }, "Up", function () - awful.util.spawn("amixer sset Master 1%+") + awful.util.spawn("amixer set Master 1%+") volume.update() end), awful.key({ altkey }, "Down", function () - awful.util.spawn("amixer sset Master 1%-") + awful.util.spawn("amixer set Master 1%-") volume.update() end), awful.key({ altkey }, "m", From 274515ca18170fbe39613c600de2e21f842b71ea Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 09:41:14 -0700 Subject: [PATCH 201/572] Updated alsabar (markdown) --- alsabar.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alsabar.md b/alsabar.md index 549b28a..7763fe4 100644 --- a/alsabar.md +++ b/alsabar.md @@ -56,12 +56,12 @@ You can control the widget with key bindings like these: -- Volume control awful.key({ altkey }, "Up", function () - awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "+") + awful.util.spawn("amixer set " .. volume.channel .. " " .. volume.step .. "+") volume.notify() end), awful.key({ altkey }, "Down", function () - awful.util.spawn("amixer sset " .. volume.channel .. " " .. volume.step .. "-") + awful.util.spawn("amixer set " .. volume.channel .. " " .. volume.step .. "-") volume.notify() end), awful.key({ altkey }, "m", From 45187b81f5c1e87d0a45150e9d7e2783dc26a74a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 10:06:31 -0700 Subject: [PATCH 202/572] Updated mpd (markdown) --- mpd.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/mpd.md b/mpd.md index bd7232e..2f7a24c 100644 --- a/mpd.md +++ b/mpd.md @@ -38,13 +38,9 @@ and can modify `notification_preset` table, which will be the preset for the nau notification _preset = { title = "Now playing", - text = mpd_now.artist .. " (" .. - mpd_now.album .. ") - " .. - mpd_now.date .. "\n" .. - mpd_now.title, - fg = beautiful.fg_normal or "#FFFFFF", - bg = beautiful.bg_normal or "#000000", - timeout = 6 + timeout = 6, + text = string.format("%s (%s) - %s\n%s", mpd_now.artist, + mpd_now.album, mpd_now.date, mpd_now.title) } ### output table From 5694a737cba6bc0eba866ceff01ae05f28241bf8 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 10:10:07 -0700 Subject: [PATCH 203/572] Updated yawn (markdown) --- yawn.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yawn.md b/yawn.md index 5b111bd..a9a1a7b 100644 --- a/yawn.md +++ b/yawn.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + (YAhoo! Weather Notification) Yawn provides brief and compact Yahoo! Weather notification. From e73a70c2ab26caf981d356756d4f83ad8bfbdb5a Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 11 Sep 2013 19:39:14 +0200 Subject: [PATCH 206/572] refresh widget fix --- widgets/alsa.lua | 10 +++--- widgets/bat.lua | 13 ++++---- widgets/cpu.lua | 9 +++--- widgets/fs.lua | 33 ++++++++++--------- widgets/imap.lua | 26 +++++++-------- widgets/maildir.lua | 11 ++++--- widgets/mem.lua | 11 ++++--- widgets/mpd.lua | 46 ++++++++++++--------------- widgets/net.lua | 11 ++++--- widgets/sysload.lua | 11 ++++--- widgets/temp.lua | 11 ++++--- widgets/yawn/icons/LightRain.png | 1 + widgets/yawn/init.lua | 54 +++++++++++++++++--------------- 13 files changed, 124 insertions(+), 123 deletions(-) create mode 120000 widgets/yawn/icons/LightRain.png diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 8571ec6..887f398 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -26,9 +26,9 @@ local function worker(args) local channel = args.channel or "Master" local settings = args.settings or function() end - widget = wibox.widget.textbox('') + alsa.widget = wibox.widget.textbox('') - function update() + function alsa.update() local f = io.popen('amixer get ' .. channel) local mixer = f:read("*all") f:close() @@ -56,11 +56,9 @@ local function worker(args) settings() end - newtimer("alsa", timeout, update) + newtimer("alsa", timeout, alsa.update) - output = { widget = widget, notify = update } - - return setmetatable(output, { __index = output.widget }) + return setmetatable(alsa, { __index = alsa.widget }) end return setmetatable(alsa, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/bat.lua b/widgets/bat.lua index 5a811f0..fa61c34 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -20,7 +20,7 @@ local setmetatable = setmetatable -- Battery infos -- lain.widgets.bat -local bat = { id = nil } +local bat = {} local function worker(args) local args = args or {} @@ -28,6 +28,8 @@ local function worker(args) local battery = args.battery or "BAT0" local settings = args.settings or function() end + bat.widget = wibox.widget.textbox('') + bat_now = { status = "not present", perc = "N/A", @@ -35,9 +37,7 @@ local function worker(args) watt = "N/A" } - widget = wibox.widget.textbox('') - - function update() + function bat.update() local present = first_line("/sys/class/power_supply/" .. battery .. "/present") @@ -106,12 +106,13 @@ local function worker(args) bat_now.perc = string.format("%d", bat_now.perc) end + widget = bat.widget settings() end - newtimer("bat", timeout, update) + newtimer("bat", timeout, bat.update) - return widget + return bat.widget end return setmetatable(bat, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/cpu.lua b/widgets/cpu.lua index f9bbe72..f307b26 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -31,9 +31,9 @@ local function worker(args) local timeout = args.timeout or 5 local settings = args.settings or function() end - widget = wibox.widget.textbox('') + cpu.widget = wibox.widget.textbox('') - function update() + function cpu.update() -- Read the amount of time the CPUs have spent performing -- different kinds of work. Read the first line of /proc/stat -- which is the sum of all CPUs. @@ -60,6 +60,7 @@ local function worker(args) usage = tostring(math.ceil((dactive / dtotal) * 100)) + widget = cpu.widget settings() -- Save current data for the next run. @@ -67,9 +68,9 @@ local function worker(args) cpu.last_total = total end - newtimer("cpu", timeout, update) + newtimer("cpu", timeout, cpu.update) - return widget + return cpu.widget end return setmetatable(cpu, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/fs.lua b/widgets/fs.lua index 3a36bf3..b580010 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -24,8 +24,10 @@ local setmetatable = setmetatable -- File system disk space usage -- lain.widgets.fs -local fs = { notification_preset = {} } -local notification = nil +local fs = {} + +local notification = nil +notification_preset = { fg = beautiful.fg_normal } function fs:hide() if notification ~= nil then @@ -42,7 +44,7 @@ function fs:show(t_out) f:close() notification = naughty.notify({ - preset = fs.notification_preset, + preset = notification_preset, text = ws, timeout = t_out }) @@ -57,11 +59,11 @@ local function worker(args) local partition = args.partition or "/" local settings = args.settings or function() end - widget = wibox.widget.textbox('') + fs.widget = wibox.widget.textbox('') helpers.set_map("fs", false) - function update() + function fs.update() fs_info = {} local f = io.popen("LC_ALL=C df -kP") @@ -83,17 +85,14 @@ local function worker(args) -- chosen partition easy stuff -- you can however check whatever partition else - used = fs_info[partition .. " used_p"] - available = fs_info[partition .. " avail_p"] - size_mb = fs_info[partition .. " size_mb"] - size_gb = fs_info[partition .. " size_gb"] - - notification_preset = { fg = beautiful.fg_normal } + used = tonumber(fs_info[partition .. " used_p"]) + available = tonumber(fs_info[partition .. " avail_p"]) + size_mb = tonumber(fs_info[partition .. " size_mb"]) + size_gb = tonumber(fs_info[partition .. " size_gb"]) + widget = fs.widget settings() - fs.notification_preset = notification_preset - if used >= 99 and not helpers.get_map("fs") then naughty.notify({ @@ -109,16 +108,16 @@ local function worker(args) end end - helpers.newtimer("fs " .. partition, timeout, update) + helpers.newtimer(partition, timeout, fs.update) widget:connect_signal('mouse::enter', function () fs:show(0) end) widget:connect_signal('mouse::leave', function () fs:hide() end) output = { - widget = widget, + widget = fs.widget, show = function(t_out) - update() - fs:show(t_out) + fs.update() + fs:show(t_out) end } diff --git a/widgets/imap.lua b/widgets/imap.lua index 2c7067c..9821cb3 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -20,9 +20,9 @@ local setmetatable = setmetatable -- Mail IMAP check -- lain.widgets.imap -local imap = { stored = nil } +local imap = {} -function worker(args) +local function worker(args) local args = args or {} local server = args.server @@ -54,9 +54,15 @@ function worker(args) end end - widget = wibox.widget.textbox('') + imap.widget = wibox.widget.textbox('') - function update() + notification_preset = { + icon = helpers.icons_dir .. "mail.png", + timeout = 8, + position = "top_left" + } + + function imap.update() to_execute = string.format("%s -s %s -u %s -p %s --port %s", checkmail, server, mail, password, port) @@ -88,15 +94,9 @@ function worker(args) end end - notification_preset = { - icon = helpers.icons_dir .. "mail.png", - timeout = 8, - position = "top_left" - } - + widget = imap.widget settings() - if helpers.get_map(mail) and tonumber(mailcount) >= 1 then notify_title = ws:match(mail .. " has %d new message.?") @@ -123,9 +123,9 @@ function worker(args) end end - helpers.newtimer(mail, timeout, update, true) + helpers.newtimer(mail, timeout, imap.update, true) - return widget + return imap.widget end return setmetatable(imap, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 00ab771..4ac34bc 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -24,16 +24,16 @@ local setmetatable = setmetatable -- lain.widgets.maildir local maildir = {} -function worker(args) +local function worker(args) local args = args or {} local timeout = args.timeout or 60 local mailpath = args.mailpath or os.getenv("HOME") .. "/Mail" local ignore_boxes = args.ignore_boxes or {} local settings = args.settings or function() end - widget = wibox.widget.textbox('') + maildir.widget = wibox.widget.textbox('') - function update() + function maildir.update() -- Find pathes to mailboxes. local p = io.popen("find " .. mailpath .. " -mindepth 1 -maxdepth 1 -type d" .. @@ -84,12 +84,13 @@ function worker(args) end end + widget = maildir.widget settings() end - newtimer(mailpath, timeout, update, true) + newtimer(mailpath, timeout, maildir.update, true) - return widget + return maildir.widget end return setmetatable(maildir, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/mem.lua b/widgets/mem.lua index d0ff223..f014149 100644 --- a/widgets/mem.lua +++ b/widgets/mem.lua @@ -25,14 +25,14 @@ local setmetatable = setmetatable -- lain.widgets.mem local mem = {} -function worker(args) +local function worker(args) local args = args or {} local timeout = args.timeout or 3 local settings = args.settings or function() end - widget = wibox.widget.textbox('') + mem.widget = wibox.widget.textbox('') - function update() + function mem.update() mem = {} for line in io.lines("/proc/meminfo") do @@ -51,12 +51,13 @@ function worker(args) used = mem.total - (mem.free + mem.buf + mem.cache) swapused = mem.swap - mem.swapf + widget = mem.widget settings() end - newtimer("mem", timeout, update) + newtimer("mem", timeout, mem.update) - return widget + return mem.widget end return setmetatable(mem, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 8ba1cde..016f2a3 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -10,24 +10,24 @@ local helpers = require("lain.helpers") local util = require("awful.util") -local beautiful = require("beautiful") local naughty = require("naughty") local wibox = require("wibox") -local io = io +local io = { popen = io.popen } local os = { execute = os.execute, getenv = os.getenv } -local string = { gmatch = string.gmatch } +local string = { format = string.format, + gmatch = string.gmatch } local setmetatable = setmetatable -- MPD infos -- lain.widgets.mpd -local mpd = { id = nil } +local mpd = {} -function worker(args) +local function worker(args) local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 2 local password = args.password or "" local host = args.host or "127.0.0.1" local port = args.port or "6600" @@ -38,11 +38,16 @@ function worker(args) local mpdh = "telnet://" .. host .. ":" .. port local echo = "echo 'password " .. password .. "\nstatus\ncurrentsong\nclose'" - widget = wibox.widget.textbox('') + mpd.widget = wibox.widget.textbox('') + + notification_preset = { + title = "Now playing", + timeout = 6 + } helpers.set_map("current mpd track", nil) - function update() + function mpd.update() mpd_now = { state = "N/A", file = "N/A", @@ -52,7 +57,7 @@ function worker(args) date = "N/A" } - local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh) + local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 1 " .. mpdh) for line in f:lines() do for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do @@ -68,17 +73,9 @@ function worker(args) f:close() - notification_preset = { - title = "Now playing", - text = mpd_now.artist .. " (" .. - mpd_now.album .. ") - " .. - mpd_now.date .. "\n" .. - mpd_now.title, - fg = beautiful.fg_normal or "#FFFFFF", - bg = beautiful.bg_normal or "#000000", - timeout = 6 - } - + notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist, + mpd_now.album, mpd_now.date, mpd_now.title) + widget = mpd.widget settings() if mpd_now.state == "play" @@ -87,8 +84,7 @@ function worker(args) then helpers.set_map("current mpd track", mpd_now.title) - os.execute(mpdcover .. " '" .. music_dir .. "' '" - .. mpd_now.file .. "'") + os.execute(string.format("%s %q %q", mpdcover, music_dir, mpd_now.file)) mpd.id = naughty.notify({ preset = notification_preset, @@ -102,11 +98,9 @@ function worker(args) end end - helpers.newtimer("mpd", timeout, update) + helpers.newtimer("mpd", timeout, mpd.update) - output = { widget = widget, notify = update } - - return setmetatable(output, { __index = output.widget }) + return setmetatable(mpd, { __index = mpd.widget }) end return setmetatable(mpd, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/net.lua b/widgets/net.lua index e086c4b..d692df1 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -39,18 +39,18 @@ function net.get_device() end end -function worker(args) +local function worker(args) local args = args or {} local timeout = args.timeout or 2 local iface = args.iface or net.get_device() local units = args.units or 1024 --kb local settings = args.settings or function() end - widget = wibox.widget.textbox('') + net.widget = wibox.widget.textbox('') helpers.set_map(iface, true) - function update() + function net.update() if iface == "" then iface = net.get_device() end carrier = helpers.first_line('/sys/class/net/' .. iface .. @@ -68,6 +68,7 @@ function worker(args) received = tostring((now_r - net.last_r) / timeout / units) received = string.gsub(string.format('%.1f', received), ",", ".") + widget = net.widget settings() net.last_t = now_t @@ -94,9 +95,9 @@ function worker(args) end end - helpers.newtimer(iface, timeout, update) + helpers.newtimer(iface, timeout, net.update) - return widget + return net.widget end return setmetatable(net, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/sysload.lua b/widgets/sysload.lua index 6167d82..90bdedf 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -21,26 +21,27 @@ local setmetatable = setmetatable -- lain.widgets.sysload local sysload = {} -function worker(args) +local function worker(args) local args = args or {} local timeout = args.timeout or 5 local settings = args.settings or function() end - widget = wibox.widget.textbox('') + sysload.widget = wibox.widget.textbox('') - function update() + function sysload.update() local f = io.open("/proc/loadavg") local ret = f:read("*all") f:close() a, b, c = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") + widget = sysload.widget settings() end - newtimer("sysload", timeout, update) + newtimer("sysload", timeout, sysload.update) - return widget + return sysload.widget end return setmetatable(sysload, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/temp.lua b/widgets/temp.lua index 5b1ebf5..e568138 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -19,23 +19,24 @@ local setmetatable = setmetatable -- lain.widgets.temp local temp = {} -function worker(args) +local function worker(args) local args = args or {} local timeout = args.timeout or 5 local settings = args.settings or function() end - widget = wibox.widget.textbox('') + temp.widget = wibox.widget.textbox('') - function update() + function temp.update() local f = io.open("/sys/class/thermal/thermal_zone0/temp") coretemp_now = tonumber(f:read("*all")) / 1000 f:close() + widget = temp.widget settings() end - newtimer("coretemp", timeout, update) + newtimer("coretemp", timeout, temp.update) - return widget + return temp.widget end return setmetatable(temp, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/yawn/icons/LightRain.png b/widgets/yawn/icons/LightRain.png new file mode 120000 index 0000000..df34463 --- /dev/null +++ b/widgets/yawn/icons/LightRain.png @@ -0,0 +1 @@ +Rain.png \ No newline at end of file diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 9bed983..e0e6f68 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -27,33 +27,31 @@ local setmetatable = setmetatable -- lain.widgets.yawn local yawn = { - icon = wibox.widget.imagebox(), - widget = wibox.widget.textbox(''), - notification_preset = {} + icon = wibox.widget.imagebox(), + widget = wibox.widget.textbox('') } -local project_path = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]] -local localizations_path = project_path .. 'localizations/' -local icon_path = project_path .. 'icons/' -local api_url = 'http://weather.yahooapis.com/forecastrss' -local units_set = '?u=c&w=' -- Default is Celsius -local language = string.match(os.getenv("LANG"), "(%S*$*)[.]") -local weather_data = nil -local notification = nil -local city_id = nil -local sky = nil -local settings = function() end +local project_path = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]] +local localizations_path = project_path .. 'localizations/' +local icon_path = project_path .. 'icons/' +local api_url = 'http://weather.yahooapis.com/forecastrss' +local units_set = '?u=c&w=' -- Default is Celsius +local language = string.match(os.getenv("LANG"), "(%S*$*)[.]") +local weather_data = nil +local notification = nil +local city_id = nil +local sky = nil +local settings = function() end + +notification_preset = {} local function fetch_weather() local url = api_url .. units_set .. city_id - local f = io.popen("curl --connect-timeout 1 -fsm 2 '" + local f = io.popen("curl --connect-timeout 1 -fsm 1 '" .. url .. "'" ) local text = f:read("*all") f:close() - -- handle no suitable icon found - yawn.icon:set_image(icon_path .. "na.png") - -- In case of no connection or invalid city ID -- widgets won't display if text == "" or text:match("City not found") @@ -107,6 +105,14 @@ local function fetch_weather() sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png" + -- In case there's no defined icon for current forecast + f = io.popen(sky) + if f == nil then + sky = icon_path .. "na.png" + else + io.close(f) + end + -- Localization local f = io.open(localizations_path .. language, "r") if language:find("en_") == nil and f ~= nil @@ -122,17 +128,13 @@ local function fetch_weather() -- Finally setting infos yawn.icon:set_image(sky) - widget = wibox.widget.textbox() + widget = yawn.widget forecast = weather_data:match(": %S+.-,"):gsub(": ", ""):gsub(",", "\n") units = units:gsub(" ", "") - notification_preset = {} - -- anche notification preset, con fg, bg e position + -- notification_preset = {} settings() - - yawn.widget = widget - yawn.notification_preset = notification_preset end function yawn.hide() @@ -151,7 +153,7 @@ function yawn.show(t_out) yawn.hide() notification = naughty.notify({ - preset = yawn.notification_preset, + preset = notification_preset, text = weather_data, icon = sky, timeout = t_out @@ -176,7 +178,7 @@ function yawn.register(id, args) yawn.hide() end) - return { icon = yawn.icon, widget = yawn.widget } + return yawn end function yawn.attach(widget, id, args) From bf7ba2df9868eea04447aa27b8e938a0dbbee5cb Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 10:40:47 -0700 Subject: [PATCH 207/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index 6590ee7..491bc31 100644 --- a/imap.md +++ b/imap.md @@ -1,6 +1,6 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -**Please be warned**: this is a temporary solution, since it works fine in normal situations but causes little freezes if connection is sobbing. I am working on something much more solid. +**Please be warned**: this is a temporary solution, since it works fine in normal situations but may causes little freezes if connection is sobbing. I am working on something much more solid. --- From a6965bed5eea11416503e17fb1b419724dff7b84 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 11 Sep 2013 19:46:52 +0200 Subject: [PATCH 208/572] readme updated --- README.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 6ce1c47..cbad31c 100644 --- a/README.rst +++ b/README.rst @@ -10,8 +10,10 @@ Layouts, widgets and utilities for Awesome WM :License: GNU-GPLv2_ :Source: https://github.com/copycat-killer/lain -Successor of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions in order to improve Awesome usability and -configurability. +Successor of awesome-vain_, this costantly evolving module +provides new layouts, a set of widgets and utility functions +in order to improve [Awesome](http://awesome.naquadah.org/) +usability and configurability. Read the wiki_ for all the info. From c3710289e82623e3f6cb659f050ccb099f43d13d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 10:51:45 -0700 Subject: [PATCH 209/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index 491bc31..3063bec 100644 --- a/imap.md +++ b/imap.md @@ -1,6 +1,6 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -**Please be warned**: this is a temporary solution, since it works fine in normal situations but may causes little freezes if connection is sobbing. I am working on something much more solid. +**Please be warned**: this is a temporary solution, I am working on something much more solid. --- From 5dcb340bc32738d7a9cc9df08a3465380fa3f063 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 10:54:18 -0700 Subject: [PATCH 210/572] Updated Widgets (markdown) --- Widgets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index 1a26b80..e812db2 100644 --- a/Widgets.md +++ b/Widgets.md @@ -10,7 +10,7 @@ To markup the textbox, call `widget:set_markup(...)` within `settings`. You can feed `set_markup` with predefined arguments, see the sections for all the details. -`widget` is a textbox, so you can also threat it like any other `wibox.widget.textbox`. +`widget` is a textbox, so you can threat it like any other `wibox.widget.textbox`. Here follows an example: From 45fc98005980d5f53c0a862f466ea688e993c035 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 11 Sep 2013 19:54:54 +0200 Subject: [PATCH 211/572] readme updated --- README.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.rst b/README.rst index cbad31c..dcd0d93 100644 --- a/README.rst +++ b/README.rst @@ -10,6 +10,9 @@ Layouts, widgets and utilities for Awesome WM :License: GNU-GPLv2_ :Source: https://github.com/copycat-killer/lain +Description +----------- + Successor of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions in order to improve [Awesome](http://awesome.naquadah.org/) From 19ea09feadacb8b67d5c0900224259aa01c0c71b Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 11 Sep 2013 19:56:06 +0200 Subject: [PATCH 212/572] readme updated --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index dcd0d93..779428d 100644 --- a/README.rst +++ b/README.rst @@ -15,8 +15,7 @@ Description Successor of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions -in order to improve [Awesome](http://awesome.naquadah.org/) -usability and configurability. +in order to improve Awesome_ usability and configurability. Read the wiki_ for all the info. @@ -29,4 +28,5 @@ Screenshots .. _GNU-GPLv2: http://www.gnu.org/licenses/gpl-2.0.html .. _awesome-vain: https://github.com/vain/awesome-vain +.. _Awesome: http://awesome.naquadah.org/ .. _wiki: https://github.com/copycat-killer/lain/wiki From e475ad70ef8504d795e6966343d59c93589673bd Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 16:17:09 -0700 Subject: [PATCH 213/572] Updated imap (markdown) --- imap.md | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/imap.md b/imap.md index 3063bec..af29cb3 100644 --- a/imap.md +++ b/imap.md @@ -1,28 +1,16 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -**Please be warned**: this is a temporary solution, I am working on something much more solid. - ---- - Shows mail status in a textbox over IMAP protocol. + myimapcheck = lain.widgets.imap(args) + New mails are notified through a notification like this: - +---------------------------------------------------+ - | +---+ | - | |\ /| donald@disney.org has 3 new messages | - | +---+ | - | Latest From: Mickey Mouse | - | Subject: Re: pay raise | - | | - | Not after what you did yesterday. | - | Daisy told me everything [...] | - | | - +---------------------------------------------------+ - -Text will be cut if the mail is too long. - - myimapcheck = lain.widgets.imap(args) + +--------------------------------------------+ + | +---+ | + | |\ /| donald@disney.org has 3 new messages | + | +---+ | + +--------------------------------------------+ The function takes a table as argument. Required table parameters are: @@ -38,8 +26,6 @@ Variable | Meaning | Type | Default --- | --- | --- | --- `port` | IMAP port | int | 993 `timeout` | Refresh timeout seconds | int | 60 -`encoding` | Mail character encoding | string | autodetected -`maxlen` | Maximum chars to display in notification | int | 200 `is_plain` | Define whether `password` is a plain password (true) or a function that retrieves it (false) | boolean | false `settings` | User settings | function @@ -58,20 +44,17 @@ and you'll have the same security provided by `~/.netrc`. When `is_plain == false`, it *executes* `password` before using it, so you can also use whatever password fetching solution you want. -`settings` can use the string `mailcount`, whose possible values are: +`settings` can use the value `mailcount`, an integer greater or equal to zero, and can modify `notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. -- "0" -- "invalid credentials" -- string number - -and can modify `notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: +Default definition: notification _preset = { icon = lain/icons/mail.png, - timeout = 8, position = "top_left" } +Note that `mailcount` is 0 either if there are no new mails or credentials are invalid, so make sure you get the right settings. + ### output A textbox. \ No newline at end of file From ab90053aabc49930e1e6f599a4521a12ef1ccf2a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 17:25:35 -0700 Subject: [PATCH 214/572] Updated imap (markdown) --- imap.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imap.md b/imap.md index af29cb3..7b232a1 100644 --- a/imap.md +++ b/imap.md @@ -1,10 +1,10 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -Shows mail status in a textbox over IMAP protocol. +Shows mail count in a textbox fetching over IMAP. myimapcheck = lain.widgets.imap(args) -New mails are notified through a notification like this: +New mails are notified like this: +--------------------------------------------+ | +---+ | From 70023036714a2485bfd1c7e44869ea06ebe6b037 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 11 Sep 2013 17:26:08 -0700 Subject: [PATCH 215/572] Updated Home (markdown) --- Home.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Home.md b/Home.md index 74f336f..6b7b58d 100644 --- a/Home.md +++ b/Home.md @@ -7,7 +7,6 @@ Package | Requested by alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) curl | widget types accessing network resources imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) -python3 | [imap](https://github.com/copycat-killer/lain/wiki/imap) ### Installation From 4cd75de2ed52f4bc39ad52eee7d5155c6036ce0e Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 12 Sep 2013 02:26:48 +0200 Subject: [PATCH 216/572] new imap widget --- scripts/checkmail | 104 ------------------ widgets/bat.lua | 14 +-- widgets/imap.lua | 101 +++++------------ widgets/yawn/icons/ThunderintheVicinity.png | 1 + widgets/yawn/init.lua | 1 - widgets/yawn/localizations/it_IT | 1 + .../yawn/localizations/localization_template | 1 + 7 files changed, 38 insertions(+), 185 deletions(-) delete mode 100755 scripts/checkmail create mode 120000 widgets/yawn/icons/ThunderintheVicinity.png diff --git a/scripts/checkmail b/scripts/checkmail deleted file mode 100755 index 67c5206..0000000 --- a/scripts/checkmail +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/python - -# Simple email checker -# -# Wrote by copycat-killer on a rainy day of august 2013 -# to be used in Lain. -# -# https://github.com/copycat-killer/lain - -import sys, getopt, locale, imaplib - -def main(argv): - usage = "usage: checkmail -s -u -p [--port ] [--encoding ] [--cut]" - server = "" - user = "" - password = "" - port = 993 - cut = False - encoding = locale.getdefaultlocale()[1] - output = "" - - try: - opts, args = getopt.getopt(argv, "hs:u:p:", ["port=", "encoding=", "cut"]) - except getopt.GetoptError: - print(usage) - sys.exit(2) - - if len(argv) == 0: - print(usage) - sys.exit() - - for opt, arg in opts: - if opt == "-h": - print(usage) - sys.exit() - elif opt == "-s": - server = arg - elif opt == "-u": - user = arg - elif opt == "-p": - password = arg - elif opt == "--port": - port = int(arg) - elif opt == "--cut": - cut = True - elif opt == "--encoding": - encoding = arg - - try: - mail = imaplib.IMAP4_SSL(server, port) - mail.login(user, password) - except imaplib.IMAP4.error: - print("CheckMailError: invalid credentials") - sys.exit(2) - - status, counts = mail.status("Inbox","(MESSAGES UNSEEN)") - - unread = int(counts[0].split()[4][:-1]) - - if status == "OK" and unread: - mail.select("Inbox", readonly = 1) - ret, messages = mail.uid("search", None, "(UNSEEN)") - - if ret == "OK": - latest_email_uid = messages[0].split()[-1] - - ret_header, new_mail_header = mail.uid("fetch", latest_email_uid, - "(BODY.PEEK[HEADER.FIELDS (SUBJECT FROM)])") - ret_text, new_mail_text = mail.uid("fetch", latest_email_uid, "(BODY[TEXT])") - - if ret_header == "OK" and ret_text == "OK": - try: # not all the servers like this, that's why we try - mail.store(latest_email_uid, "-FLAGS", "\\Seen") - except imaplib.IMAP4.error: - # this simply means the server refused to - # toggle Seen flag from mail - print("[+Seen]\n") - - nm_header = new_mail_header[0][1].decode(encoding, "replace").strip() - nm_text = new_mail_text[0][1].decode(encoding, "replace").strip() - - if unread == 1: - print(user, "has 1 new message\n") - else: - print(user, "has", unread, "new messages\n") - nm_header.replace("From:", "Latest from:", 1) - - print(nm_header, "\n") - - if cut: - if len(nm_text) <= 100: - print(nm_text) - else: - print(nm_text[0:100]) - print("[...]") - else: - print(nm_text) - else: - print("No new messages") - - mail.logout() - -if __name__ == "__main__": - main(sys.argv[1:]) diff --git a/widgets/bat.lua b/widgets/bat.lua index fa61c34..ba1fa58 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -30,14 +30,14 @@ local function worker(args) bat.widget = wibox.widget.textbox('') - bat_now = { - status = "not present", - perc = "N/A", - time = "N/A", - watt = "N/A" - } - function bat.update() + bat_now = { + status = "not present", + perc = "N/A", + time = "N/A", + watt = "N/A" + } + local present = first_line("/sys/class/power_supply/" .. battery .. "/present") diff --git a/widgets/imap.lua b/widgets/imap.lua index 9821cb3..4df3610 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -11,10 +11,9 @@ local helpers = require("lain.helpers") local naughty = require("naughty") local wibox = require("wibox") -local io = { popen = io.popen } -local tonumber = tonumber -local string = { len = string.len, - format = string.format } +local io = { popen = io.popen } +local string = { format = string.format, + gsub = string.gsub } local setmetatable = setmetatable @@ -29,102 +28,58 @@ local function worker(args) local mail = args.mail local password = args.password - local port = args.port or "993" + local port = args.port or 993 local timeout = args.timeout or 60 - local encoding = args.encoding or nil - local maxlen = args.maxlen or 200 local is_plain = args.is_plain or false local settings = args.settings or function() end - local checkmail = helpers.scripts_dir .. "checkmail" + local head_command = "curl --connect-timeout 1 -fsm 3" + local request = "-X 'SEARCH (UNSEEN)'" - helpers.set_map(mail, true) - helpers.set_map(mail .. " count", "0") + helpers.set_map(mail, 0) if not is_plain then - if not imap.stored - then - local f = io.popen(password) - password = f:read("*all"):gsub("\n", ""):gsub("\r", "") - f:close() - imap.stored = password - else - password = imap.stored - end + local f = io.popen(password) + password = f:read("*all"):gsub("\n", "") + f:close() end imap.widget = wibox.widget.textbox('') - notification_preset = { - icon = helpers.icons_dir .. "mail.png", - timeout = 8, - position = "top_left" - } - function imap.update() - to_execute = string.format("%s -s %s -u %s -p %s --port %s", - checkmail, server, mail, password, port) + notification_preset = { + icon = helpers.icons_dir .. "mail.png", + position = "top_left" + } + + curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%s %s -k", + head_command, server, port, mail, password, request) - if encoding ~= nil - then - to_execute = string.format("%s --encoding %s", - to_execute, encoding) - end - - f = io.popen(to_execute) + f = io.popen(curl) ws = f:read("*all") f:close() - mailcount = "0" - - if ws:find("No new messages") ~= nil - then - helpers.set_map(mail, true) - elseif ws:find("CheckMailError: invalid credentials") ~= nil - then - helpers.set_map(mail, true) - mailcount = "invalid credentials" - else - mailcount = ws:match("%d") or "0" - if helpers.get_map(mail .. " count") ~= mailcount and mailcount ~= "0" - then - helpers.set_map(mail, true) - helpers.set_map(mail .. " count", mailcount) - end - end + t, mailcount = string.gsub(ws, "%d", "") + t = nil -- because it's useless widget = imap.widget settings() - if helpers.get_map(mail) and tonumber(mailcount) >= 1 + if mailcount > helpers.get_map(mail) and mailcount >= 1 then - notify_title = ws:match(mail .. " has %d new message.?") - ws = ws:gsub(notify_title, "", 1):gsub("\n", "", 2) - - -- trying to remove useless infos - ws = ws:gsub("--Content.%S+.-\n", "") - ws = ws:gsub("--%d+.-\n", "") - - if string.len(ws) > maxlen - then - ws = ws:sub(1, maxlen) .. "[...]" + if mailcount == 1 then + nt = mail .. " has one new message" + else + nt = mail .. " has " .. mailcount .. " new messages" end - - notify_title = notify_title:gsub("\n", "") - - naughty.notify({ - preset = notification_preset, - title = notify_title, - text = ws - }) - - helpers.set_map(mail, false) + naughty.notify({ preset = notification_preset, text = nt }) end + + helpers.set_map(mail, mailcount) end helpers.newtimer(mail, timeout, imap.update, true) - return imap.widget end diff --git a/widgets/yawn/icons/ThunderintheVicinity.png b/widgets/yawn/icons/ThunderintheVicinity.png new file mode 120000 index 0000000..1fb3b9c --- /dev/null +++ b/widgets/yawn/icons/ThunderintheVicinity.png @@ -0,0 +1 @@ +Cloudy.png \ No newline at end of file diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index e0e6f68..4d14966 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -132,7 +132,6 @@ local function fetch_weather() forecast = weather_data:match(": %S+.-,"):gsub(": ", ""):gsub(",", "\n") units = units:gsub(" ", "") - -- notification_preset = {} settings() end diff --git a/widgets/yawn/localizations/it_IT b/widgets/yawn/localizations/it_IT index 0b74b60..6435eff 100644 --- a/widgets/yawn/localizations/it_IT +++ b/widgets/yawn/localizations/it_IT @@ -14,6 +14,7 @@ Isolated Thunderstorms|Temporali Isolati Scattered Thunderstorms|Temporali Sparsi Thundershowers|Rovesci Temporaleschi Thunderstorms|Temporali +Thunder in the Vicinity|Temporale In Arrivo Thunder|Temporale AM|In Mattinata PM|Nel Pomeriggio diff --git a/widgets/yawn/localizations/localization_template b/widgets/yawn/localizations/localization_template index 98d527d..fd28868 100644 --- a/widgets/yawn/localizations/localization_template +++ b/widgets/yawn/localizations/localization_template @@ -14,6 +14,7 @@ Isolated Thunderstorms| Scattered Thunderstorms| Thundershowers| Thunderstorms| +Thunder in the Vicinity| Thunder| AM| PM| From b339c79167c772f40d57c0dcd8864ae52c53431a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 08:04:28 -0700 Subject: [PATCH 217/572] Updated alsabar (markdown) --- alsabar.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/alsabar.md b/alsabar.md index 7763fe4..ad5b1bf 100644 --- a/alsabar.md +++ b/alsabar.md @@ -1,6 +1,6 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -Shows and controls alsa volume with a progressbar and provides tooltips, notifications, and color changes at mute/unmute switch. +Shows and controls alsa volume with a progressbar; provides tooltips, notifications, and color changes at mute/unmute switch. myvolumebar = lain.widgets.alsabar() @@ -12,6 +12,7 @@ The function takes a table as optional argument, which can contain: Variable | Meaning | Type | Default --- | --- | --- | --- +`timeout` | Refresh timeout seconds | int | 4 `width` | Bar width | int | 63 `height` | Bar height | int | 1 `ticks` | Set bar ticks on | boolean | true From e9e2e6ccd594290df2ccf310d3ca4a632e0c882c Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 12 Sep 2013 17:18:08 +0200 Subject: [PATCH 219/572] small fixes --- init.lua | 3 +- widgets/alsabar.lua | 99 ++++++++++++++++---------------- widgets/yawn/localizations/it_IT | 2 +- 3 files changed, 53 insertions(+), 51 deletions(-) diff --git a/init.lua b/init.lua index 3abf9f6..155d6cc 100644 --- a/init.lua +++ b/init.lua @@ -5,8 +5,7 @@ Layouts, widgets and utilities for Awesome WM Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann + * (c) 2013, Luke Bonham --]] diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 7f5fe87..8331c54 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -4,6 +4,7 @@ Licensed under GNU General Public License v2 * (c) 2013, Luke Bonham * (c) 2013, Rman + --]] local newtimer = require("lain.helpers").newtimer @@ -12,10 +13,11 @@ local awful = require("awful") local beautiful = require("beautiful") local naughty = require("naughty") -local io = io -local math = { modf = math.modf } -local string = { match = string.match, - rep = string.rep } +local io = { popen = io.popen } +local math = { modf = math.modf } +local string = { format = string.format, + match = string.match, + rep = string.rep } local tonumber = tonumber local setmetatable = setmetatable @@ -25,64 +27,77 @@ local setmetatable = setmetatable local alsabar = { channel = "Master", - step = "5%", + step = "5%", colors = { background = beautiful.bg_normal, - mute = "#EB8F8F", - unmute = "#A4CE8A" + mute = "#EB8F8F", + unmute = "#A4CE8A" }, terminal = terminal or "xterm", - mixer = terminal .. " -e alsamixer", + mixer = terminal .. " -e alsamixer", notifications = { - font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), + font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), font_size = "11", - color = beautiful.fg_focus, - bar_size = 18 -- Awesome default + color = beautiful.fg_focus, + bar_size = 18 }, _current_level = 0, - _muted = false + _muted = false } -function alsabar:notify() +function alsabar.notify() + alsabar.update() + local preset = { - title = "", text = "", - timeout = 15, - font = alsabar.notifications.font .. " " .. alsabar.notifications.font_size, - fg = alsabar.notifications.color + title = "", + text = "", + timeout = 4, + font = alsabar.notifications.font .. " " .. + alsabar.notifications.font_size, + fg = alsabar.notifications.color } - if alsabar._muted then + if alsabar._muted + then preset.title = alsabar.channel .. " - Muted" else preset.title = alsabar.channel .. " - " .. alsabar._current_level * 100 .. "%" end - local int = math.modf(alsabar._current_level * alsabar.notifications.bar_size) - preset.text = "[" .. string.rep("|", int) - .. string.rep(" ", alsabar.notifications.bar_size - int) .. "]" + int = math.modf(alsabar._current_level * alsabar.notifications.bar_size) + preset.text = "[" + .. string.rep("|", int) + .. string.rep(" ", alsabar.notifications.bar_size - int) + .. "]" if alsabar._notify ~= nil then - alsabar._notify = naughty.notify ({ replaces_id = alsabar._notify.id, - preset = preset }) + alsabar._notify = naughty.notify ({ + replaces_id = alsabar._notify.id, + preset = preset + }) else - alsabar._notify = naughty.notify ({ preset = preset }) + alsabar._notify = naughty.notify ({ + preset = preset + }) end end local function worker(args) local args = args or {} + local timeout = args.timeout or 4 local width = args.width or 63 local height = args.heigth or 1 local ticks = args.ticks or true local ticks_size = args.ticks_size or 7 local vertical = args.vertical or false + alsabar.channel = args.channel or alsabar.channel alsabar.step = args.step or alsabar.step alsabar.colors = args.colors or alsabar.colors @@ -98,11 +113,9 @@ local function worker(args) alsabar.bar:set_ticks(ticks) alsabar.bar:set_ticks_size(ticks_size) - if vertical then - alsabar.bar:set_vertical(true) - end + if vertical then alsabar.bar:set_vertical(true) end - function update() + function alsabar.update() -- Get mixer control contents local f = io.popen("amixer get " .. alsabar.channel) local mixer = f:read("*all") @@ -119,49 +132,39 @@ local function worker(args) alsabar._current_level = tonumber(volu) / 100 alsabar.bar:set_value(alsabar._current_level) - if mute == "" and volu == "0" or mute == "off" + if not mute and tonumber(volu) == 0 or mute == "off" then alsabar._muted = true alsabar.tooltip:set_text (" [Muted] ") alsabar.bar:set_color(alsabar.colors.mute) else alsabar._muted = false - alsabar.tooltip:set_text(" " .. alsabar.channel .. ": " .. volu .. "% ") + alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu)) alsabar.bar:set_color(alsabar.colors.unmute) end end - newtimer("alsabar", 5, update) + newtimer("alsabar", timeout, alsabar.update) alsabar.bar:buttons (awful.util.table.join ( awful.button ({}, 1, function() awful.util.spawn(alsabar.mixer) end), awful.button ({}, 3, function() - awful.util.spawn("amixer sset " .. alsabar.channel .. " toggle") - myvolumebarupdate() + awful.util.spawn(string.format("amixer set %s toggle", alsabar.channel)) + alsabar.update() end), awful.button ({}, 4, function() - awful.util.spawn("amixer sset " .. alsabar.channel .. " " - .. alsabar.step .. "+") - myvolumebarupdate() + awful.util.spawn(string.format("amixer set %s %s+", alsabar.channel, alsabar.step)) + alsabar.update() end), awful.button ({}, 5, function() - awful.util.spawn("amixer sset " .. alsabar.channel .. " " - .. alsabar.step .. "-") - myvolumebarupdate() + awful.util.spawn(string.format("amixer set %s %s-", alsabar.channel, alsabar.step)) + alsabar.update() end) )) - return { - widget = alsabar.bar, - channel = alsabar.channel, - step = alsabar.step, - notify = function() - update() - alsabar.notify() - end - } + return alsabar end return setmetatable(alsabar, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/yawn/localizations/it_IT b/widgets/yawn/localizations/it_IT index 6435eff..2276e4b 100644 --- a/widgets/yawn/localizations/it_IT +++ b/widgets/yawn/localizations/it_IT @@ -14,7 +14,7 @@ Isolated Thunderstorms|Temporali Isolati Scattered Thunderstorms|Temporali Sparsi Thundershowers|Rovesci Temporaleschi Thunderstorms|Temporali -Thunder in the Vicinity|Temporale In Arrivo +Thunder in the Vicinity|Tuoni in avvicinamento Thunder|Temporale AM|In Mattinata PM|Nel Pomeriggio From 2330b7d079c29caa3064e40a8b64939af90e30da Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 08:43:38 -0700 Subject: [PATCH 220/572] Updated fs (markdown) --- fs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs.md b/fs.md index 44be2b2..5588ca7 100644 --- a/fs.md +++ b/fs.md @@ -27,9 +27,9 @@ where `p` is the last column of `df` command ("/", "/home", "/boot", ...). This means you can set the widget for a certain partition, but you can look up at others too. -Finally, `settings` can modify `notification_preset` table too. This table will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: +Finally, `settings` can modify `fs_notification_preset` table too. This table will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: - notification_preset = { fg = beautiful.fg_normal } + fs_notification_preset = { fg = beautiful.fg_normal } ### output table From f397b6a1b17682514d68c3c70012b5d6952b951f Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 08:44:22 -0700 Subject: [PATCH 221/572] Updated imap (markdown) --- imap.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imap.md b/imap.md index 7b232a1..ba92d0f 100644 --- a/imap.md +++ b/imap.md @@ -44,11 +44,11 @@ and you'll have the same security provided by `~/.netrc`. When `is_plain == false`, it *executes* `password` before using it, so you can also use whatever password fetching solution you want. -`settings` can use the value `mailcount`, an integer greater or equal to zero, and can modify `notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. +`settings` can use the value `mailcount`, an integer greater or equal to zero, and can modify `mail_notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: - notification _preset = { + mail_notification _preset = { icon = lain/icons/mail.png, position = "top_left" } From b88ee61d325c2afcc43ee25ba79c07a7c991d0d5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 08:47:10 -0700 Subject: [PATCH 222/572] Updated mpd (markdown) --- mpd.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mpd.md b/mpd.md index 2f7a24c..51467e1 100644 --- a/mpd.md +++ b/mpd.md @@ -34,9 +34,9 @@ Variable | Meaning | Type | Default - album - date -and can modify `notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: +and can modify `mpd_notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: - notification _preset = { + mpd_notification _preset = { title = "Now playing", timeout = 6, text = string.format("%s (%s) - %s\n%s", mpd_now.artist, From 08b707a1589e2328dfa25e13026c63567f8404c5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 08:52:53 -0700 Subject: [PATCH 223/572] Updated yawn (markdown) --- yawn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yawn.md b/yawn.md index a9a1a7b..30d160c 100644 --- a/yawn.md +++ b/yawn.md @@ -34,7 +34,7 @@ an existent widget. `timeout` | Refresh timeout seconds | int | integers | 600 `settings` | User settings | function | function | empty function - `settings` can use strings `forecast`, `units`, and can modify `notification_preset` table, which + `settings` can use strings `forecast`, `units`, and can modify `yawn_notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. The function `register` creates an imagebox icon and a textbox widget. Add them to you wibox like this: From dc7eb86389b2d9ebd515029328c61313af73af66 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 09:07:46 -0700 Subject: [PATCH 224/572] Updated alsabar (markdown) --- alsabar.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alsabar.md b/alsabar.md index ad5b1bf..7a90478 100644 --- a/alsabar.md +++ b/alsabar.md @@ -67,12 +67,12 @@ You can control the widget with key bindings like these: end), awful.key({ altkey }, "m", function () - awful.util.spawn("amixer set Master playback toggle") + awful.util.spawn("amixer set " .. volume.channel .. " playback toggle") volume.notify() end), awful.key({ altkey, "Control" }, "m", function () - awful.util.spawn("amixer set Master playback 100%", false ) + awful.util.spawn("amixer set " .. volume.channel .. " playback 100%", false ) volume.notify() end), From f439acc2f30b1d6c81ce2d2621bbc080a691c4e8 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 09:15:04 -0700 Subject: [PATCH 225/572] Updated mpd (markdown) --- mpd.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mpd.md b/mpd.md index 51467e1..de945b4 100644 --- a/mpd.md +++ b/mpd.md @@ -56,22 +56,22 @@ You can control the widget with key bindings like these: awful.key({ altkey, "Control" }, "Up", function () awful.util.spawn_with_shell("mpc toggle || ncmpcpp toggle || ncmpc toggle || pms toggle") - mpdwidget.notify() + mpdwidget.update() end), awful.key({ altkey, "Control" }, "Down", function () awful.util.spawn_with_shell("mpc stop || ncmpcpp stop || ncmpc stop || pms stop") - mpdwidget.notify() + mpdwidget.update() end), awful.key({ altkey, "Control" }, "Left", function () awful.util.spawn_with_shell("mpc prev || ncmpcpp prev || ncmpc prev || pms prev") - mpdwidget.notify() + mpdwidget.update() end), awful.key({ altkey, "Control" }, "Right", function () awful.util.spawn_with_shell("mpc next || ncmpcpp next || ncmpc next || pms next") - mpdwidget.notify() + mpdwidget.update() end), where `altkey = "Mod1"`. \ No newline at end of file From 8f1b80f2843b9c13d68d56fd82c9f5eada721bfd Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 09:37:19 -0700 Subject: [PATCH 226/572] Updated alsa (markdown) --- alsa.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/alsa.md b/alsa.md index 65314d2..6cc8b59 100644 --- a/alsa.md +++ b/alsa.md @@ -16,8 +16,8 @@ Variable | Meaning | Type | Default Variable | Meaning | Type | Values --- | --- | --- | --- -volume.level | Self explained | int | 0-100 -volume.status | Device status | string | "on", "off" +volume_now.level | Self explained | int | 0-100 +volume_now.status | Device status | string | "on", "off" ### output table @@ -32,22 +32,22 @@ You can control the widget with key bindings like these: awful.key({ altkey }, "Up", function () awful.util.spawn("amixer set Master 1%+") - volume.update() + volumewidget.update() end), awful.key({ altkey }, "Down", function () awful.util.spawn("amixer set Master 1%-") - volume.update() + volumewidget.update() end), awful.key({ altkey }, "m", function () awful.util.spawn("amixer set Master playback toggle") - volume.update() + volumewidget.update() end), awful.key({ altkey, "Control" }, "m", function () awful.util.spawn("amixer set Master playback 100%", false ) - volume.update() + volumewidget.update() end), where `altkey = "Mod1"`. \ No newline at end of file From e24890443bbe0ed8c17376038f2cf3040f1b4663 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 09:37:35 -0700 Subject: [PATCH 227/572] Updated alsa (markdown) --- alsa.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsa.md b/alsa.md index 6cc8b59..abe82b8 100644 --- a/alsa.md +++ b/alsa.md @@ -2,7 +2,7 @@ Shows and controls alsa volume with a textbox. - volume = lain.widgets.alsa() + volumewidget = lain.widgets.alsa() ### input table From 54f3782d4b02a2818e5f168597f038186c185de0 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 09:37:54 -0700 Subject: [PATCH 228/572] Updated alsa (markdown) --- alsa.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alsa.md b/alsa.md index abe82b8..daf4016 100644 --- a/alsa.md +++ b/alsa.md @@ -16,8 +16,8 @@ Variable | Meaning | Type | Default Variable | Meaning | Type | Values --- | --- | --- | --- -volume_now.level | Self explained | int | 0-100 -volume_now.status | Device status | string | "on", "off" +`volume_now.level` | Self explained | int | 0-100 +`volume_now.status` | Device status | string | "on", "off" ### output table From 264c9bbed32bd3c012c4b4ba369ac747b7498749 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 09:57:10 -0700 Subject: [PATCH 230/572] Updated alsabar (markdown) --- alsabar.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/alsabar.md b/alsabar.md index 7a90478..711c8ce 100644 --- a/alsabar.md +++ b/alsabar.md @@ -58,22 +58,22 @@ You can control the widget with key bindings like these: awful.key({ altkey }, "Up", function () awful.util.spawn("amixer set " .. volume.channel .. " " .. volume.step .. "+") - volume.notify() + myvolumebar.notify() end), awful.key({ altkey }, "Down", function () awful.util.spawn("amixer set " .. volume.channel .. " " .. volume.step .. "-") - volume.notify() + myvolumeba.notify() end), awful.key({ altkey }, "m", function () awful.util.spawn("amixer set " .. volume.channel .. " playback toggle") - volume.notify() + myvolumebar.notify() end), awful.key({ altkey, "Control" }, "m", function () awful.util.spawn("amixer set " .. volume.channel .. " playback 100%", false ) - volume.notify() + myvolumebar.notify() end), where `altkey = "Mod1"`. \ No newline at end of file From 98a5a66ac0944bcbf0745520ab75612ec553db0d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 12:32:27 -0700 Subject: [PATCH 231/572] Updated net (markdown) --- net.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net.md b/net.md index bace937..a1b6d35 100644 --- a/net.md +++ b/net.md @@ -13,9 +13,9 @@ Variable | Meaning | Type | Default `units` | Units | int | 1024 (kilobytes) `settings` | User settings | function | empty function -Possible other values for `units` are 1 (byte) or multiple of 1024: 1024^2 (mb), 1024^3 (gb), ... . +Possible other values for `units` are 1 (byte) or multiple of 1024: 1024^2 (mb), 1024^3 (gb), and so on. -`settings` can use the following `iface` strings: `carrier`, `state`, `sent`, `received`. +`settings` can use the following `iface` strings: `carrier` ("0", "1"), `state` ("up", "down"), `sent`, `received` (numbers). ### output From 86223d5eed3657032571f1166266a39021061b9f Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 12:33:04 -0700 Subject: [PATCH 232/572] Updated net (markdown) --- net.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net.md b/net.md index a1b6d35..f1cd095 100644 --- a/net.md +++ b/net.md @@ -15,7 +15,11 @@ Variable | Meaning | Type | Default Possible other values for `units` are 1 (byte) or multiple of 1024: 1024^2 (mb), 1024^3 (gb), and so on. -`settings` can use the following `iface` strings: `carrier` ("0", "1"), `state` ("up", "down"), `sent`, `received` (numbers). +`settings` can use the following `iface` strings: + +- `carrier` ("0", "1"); +- `state` ("up", "down"); +- `sent` and `received` (numbers). ### output From cbeeb53e91b72faa7ae03fee8f3647060c95062c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 12:34:21 -0700 Subject: [PATCH 233/572] Updated bat (markdown) --- bat.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bat.md b/bat.md index ec10057..27a0d32 100644 --- a/bat.md +++ b/bat.md @@ -15,7 +15,12 @@ Variable | Meaning | Type | Default `battery` | Identifier of the battery | string | "BAT0" `settings` | User settings | function | empty function -`settings` can use the `bat_now` table, which contains the following strings: `status`, `perc`, `time`, `watt`. +`settings` can use the `bat_now` table, which contains the following strings: + +- `status` ("Not present", "Charging", "Discharging"); +-`perc`; +- `time`; +- `watt`. ### output From eedc61870026beb0e3ffed7e2c54f395a07a5072 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 12:34:40 -0700 Subject: [PATCH 234/572] Updated bat (markdown) --- bat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bat.md b/bat.md index 27a0d32..50c14e8 100644 --- a/bat.md +++ b/bat.md @@ -18,7 +18,7 @@ Variable | Meaning | Type | Default `settings` can use the `bat_now` table, which contains the following strings: - `status` ("Not present", "Charging", "Discharging"); --`perc`; +- `perc`; - `time`; - `watt`. From c7780c093a218f82d7a2bcdc9dac2d62ed88153b Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 12:47:57 -0700 Subject: [PATCH 235/572] Updated mem (markdown) --- mem.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mem.md b/mem.md index 80e6a88..1079ca5 100644 --- a/mem.md +++ b/mem.md @@ -13,7 +13,7 @@ Variable | Meaning | Type | Default `timeout` | Refresh timeout seconds | int | 3 `settings` | User settings | function | empty function -`settings` can use the strings `used` (memory used MB) and `swapused` (swap used MB). +`settings` can use the strings `mem_now.used` (memory used MB) and `mem_now.swapused` (swap used MB). ### output From 8e38f676fff8bd8de4dc0ce51dc32a259d57dc0e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 12:49:36 -0700 Subject: [PATCH 236/572] Updated sysload (markdown) --- sysload.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysload.md b/sysload.md index 234770b..4ed61a8 100644 --- a/sysload.md +++ b/sysload.md @@ -11,7 +11,7 @@ Variable | Meaning | Type | Default `timeout` | Refresh timeout seconds | int | 5 `settings` | User settings | function | empty function -`settings` can use strings `a`, `b` and `c`, which are loadavg over 1, 5, and 15 minutes. +`settings` can use strings `load_1`, `load_5` and `load_15`, which are loadavg over 1, 5, and 15 minutes. ### output From 669112020d022b3b9cb023c82230e21d36aa88cf Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 13 Sep 2013 00:07:44 +0200 Subject: [PATCH 237/572] widgets fix --- helpers.lua | 6 ++++-- widgets/alsa.lua | 21 +++++++++++---------- widgets/bat.lua | 6 +++--- widgets/calendar.lua | 20 ++++++++++---------- widgets/cpu.lua | 4 ++-- widgets/fs.lua | 18 +++++------------- widgets/imap.lua | 8 ++++---- widgets/maildir.lua | 5 ++--- widgets/mem.lua | 34 ++++++++++++++++------------------ widgets/mpd.lua | 8 ++++---- widgets/net.lua | 21 +++++++++++---------- widgets/sysload.lua | 7 +++---- widgets/temp.lua | 5 ++--- widgets/yawn/init.lua | 5 +++-- 14 files changed, 80 insertions(+), 88 deletions(-) diff --git a/helpers.lua b/helpers.lua index a8c4cd7..81910d2 100644 --- a/helpers.lua +++ b/helpers.lua @@ -8,8 +8,10 @@ --]] local debug = require("debug") -local rawget = rawget + +local capi = { timer = timer } local io = { open = io.open } +local rawget = rawget -- Lain helper functions for internal use -- lain.helpers @@ -49,7 +51,7 @@ end helpers.timer_table = {} function helpers.newtimer(name, timeout, fun, nostart) - helpers.timer_table[name] = timer({ timeout = timeout }) + helpers.timer_table[name] = capi.timer({ timeout = timeout }) helpers.timer_table[name]:connect_signal("timeout", fun) helpers.timer_table[name]:start() if not nostart then diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 887f398..3e025bb 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -29,30 +29,31 @@ local function worker(args) alsa.widget = wibox.widget.textbox('') function alsa.update() - local f = io.popen('amixer get ' .. channel) + local f = assert(io.popen('amixer get ' .. channel)) local mixer = f:read("*all") f:close() - volume = {} + volume_now = {} - volume.level, volume.status = string.match(mixer, "([%d]+)%%.*%[([%l]*)") + volume_now.level, volume_now.status = string.match(mixer, "([%d]+)%%.*%[([%l]*)") - if volume.level == nil + if volume_now.level == nil then - volume.level = 0 - volume.status = "off" + volume_now.level = "0" + volume_now.status = "off" end - if volume.status == "" + if volume_now.status == "" then - if volume.level == 0 + if volume_now.level == "0" then - volume.status = "off" + volume_now.status = "off" else - volume.status = "on" + volume_now.status = "on" end end + widget = alsa.widget settings() end diff --git a/widgets/bat.lua b/widgets/bat.lua index ba1fa58..09b135f 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -30,9 +30,9 @@ local function worker(args) bat.widget = wibox.widget.textbox('') - function bat.update() + function update() bat_now = { - status = "not present", + status = "Not present", perc = "N/A", time = "N/A", watt = "N/A" @@ -110,7 +110,7 @@ local function worker(args) settings() end - newtimer("bat", timeout, bat.update) + newtimer("bat", timeout, update) return bat.widget end diff --git a/widgets/calendar.lua b/widgets/calendar.lua index e28e735..57fadd9 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -21,12 +21,12 @@ local setmetatable = setmetatable -- Calendar notification -- lain.widgets.calendar local calendar = {} -local notification = nil +local cal_notification = nil function calendar:hide() - if notification ~= nil then - naughty.destroy(notification) - notification = nil + if cal_notification ~= nil then + naughty.destroy(cal_notification) + cal_notification = nil end end @@ -95,12 +95,12 @@ function calendar:show(t_out, inc_offset) .. "" f:close() - notification = naughty.notify({ text = c_text, - icon = calendar.notify_icon, - position = calendar.position, - fg = calendar.fg, - bg = calendar.bg, - timeout = tims }) + cal_notification = naughty.notify({ text = c_text, + icon = calendar.notify_icon, + position = calendar.position, + fg = calendar.fg, + bg = calendar.bg, + timeout = tims }) end function calendar:attach(widget, args) diff --git a/widgets/cpu.lua b/widgets/cpu.lua index f307b26..55a3799 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -33,7 +33,7 @@ local function worker(args) cpu.widget = wibox.widget.textbox('') - function cpu.update() + function update() -- Read the amount of time the CPUs have spent performing -- different kinds of work. Read the first line of /proc/stat -- which is the sum of all CPUs. @@ -68,7 +68,7 @@ local function worker(args) cpu.last_total = total end - newtimer("cpu", timeout, cpu.update) + newtimer("cpu", timeout, update) return cpu.widget end diff --git a/widgets/fs.lua b/widgets/fs.lua index b580010..17037c4 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -27,7 +27,7 @@ local setmetatable = setmetatable local fs = {} local notification = nil -notification_preset = { fg = beautiful.fg_normal } +fs_notification_preset = { fg = beautiful.fg_normal } function fs:hide() if notification ~= nil then @@ -44,7 +44,7 @@ function fs:show(t_out) f:close() notification = naughty.notify({ - preset = notification_preset, + preset = fs_notification_preset, text = ws, timeout = t_out }) @@ -63,7 +63,7 @@ local function worker(args) helpers.set_map("fs", false) - function fs.update() + function update() fs_info = {} local f = io.popen("LC_ALL=C df -kP") @@ -108,20 +108,12 @@ local function worker(args) end end - helpers.newtimer(partition, timeout, fs.update) + helpers.newtimer(partition, timeout, update) widget:connect_signal('mouse::enter', function () fs:show(0) end) widget:connect_signal('mouse::leave', function () fs:hide() end) - output = { - widget = fs.widget, - show = function(t_out) - fs.update() - fs:show(t_out) - end - } - - return setmetatable(output, { __index = output.widget }) + return setmetatable(fs, { __index = fs.widget }) end return setmetatable(fs, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/imap.lua b/widgets/imap.lua index 4df3610..6574276 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -47,8 +47,8 @@ local function worker(args) imap.widget = wibox.widget.textbox('') - function imap.update() - notification_preset = { + function update() + mail_notification_preset = { icon = helpers.icons_dir .. "mail.png", position = "top_left" } @@ -73,13 +73,13 @@ local function worker(args) else nt = mail .. " has " .. mailcount .. " new messages" end - naughty.notify({ preset = notification_preset, text = nt }) + naughty.notify({ preset = mail_notification_preset, text = nt }) end helpers.set_map(mail, mailcount) end - helpers.newtimer(mail, timeout, imap.update, true) + helpers.newtimer(mail, timeout, update, true) return imap.widget end diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 4ac34bc..d460881 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -33,7 +33,7 @@ local function worker(args) maildir.widget = wibox.widget.textbox('') - function maildir.update() + function update() -- Find pathes to mailboxes. local p = io.popen("find " .. mailpath .. " -mindepth 1 -maxdepth 1 -type d" .. @@ -88,8 +88,7 @@ local function worker(args) settings() end - newtimer(mailpath, timeout, maildir.update, true) - + newtimer(mailpath, timeout, update, true) return maildir.widget end diff --git a/widgets/mem.lua b/widgets/mem.lua index f014149..78ed3e0 100644 --- a/widgets/mem.lua +++ b/widgets/mem.lua @@ -1,12 +1,10 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann - * (c) 2010, Adrian C. - * (c) 2009, Lucas de Vries - + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + --]] local newtimer = require("lain.helpers").newtimer @@ -32,30 +30,30 @@ local function worker(args) mem.widget = wibox.widget.textbox('') - function mem.update() - mem = {} + function update() + mem_now = {} for line in io.lines("/proc/meminfo") do for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+") do - if k == "MemTotal" then mem.total = math.floor(v / 1024) - elseif k == "MemFree" then mem.free = math.floor(v / 1024) - elseif k == "Buffers" then mem.buf = math.floor(v / 1024) - elseif k == "Cached" then mem.cache = math.floor(v / 1024) - elseif k == "SwapTotal" then mem.swap = math.floor(v / 1024) - elseif k == "SwapFree" then mem.swapf = math.floor(v / 1024) + if k == "MemTotal" then mem_now.total = math.floor(v / 1024) + elseif k == "MemFree" then mem_now.free = math.floor(v / 1024) + elseif k == "Buffers" then mem_now.buf = math.floor(v / 1024) + elseif k == "Cached" then mem_now.cache = math.floor(v / 1024) + elseif k == "SwapTotal" then mem_now.swap = math.floor(v / 1024) + elseif k == "SwapFree" then mem_now.swapf = math.floor(v / 1024) end end end - used = mem.total - (mem.free + mem.buf + mem.cache) - swapused = mem.swap - mem.swapf + mem_now.used = mem_now.total - (mem_now.free + mem_now.buf + mem_now.cache) + mem_now.swapused = mem_now.swap - mem_now.swapf widget = mem.widget settings() end - newtimer("mem", timeout, mem.update) + newtimer("mem", timeout, update) return mem.widget end diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 016f2a3..cd97b37 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -40,7 +40,7 @@ local function worker(args) mpd.widget = wibox.widget.textbox('') - notification_preset = { + mpd_notification_preset = { title = "Now playing", timeout = 6 } @@ -73,8 +73,8 @@ local function worker(args) f:close() - notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist, - mpd_now.album, mpd_now.date, mpd_now.title) + mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist, + mpd_now.album, mpd_now.date, mpd_now.title) widget = mpd.widget settings() @@ -87,7 +87,7 @@ local function worker(args) os.execute(string.format("%s %q %q", mpdcover, music_dir, mpd_now.file)) mpd.id = naughty.notify({ - preset = notification_preset, + preset = mpd_notification_preset, icon = "/tmp/mpdcover.png", replaces_id = mpd.id }).id diff --git a/widgets/net.lua b/widgets/net.lua index d692df1..b3deca6 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -50,23 +50,25 @@ local function worker(args) helpers.set_map(iface, true) - function net.update() + function update() + net_now = {} + if iface == "" then iface = net.get_device() end - carrier = helpers.first_line('/sys/class/net/' .. iface .. + net_now.carrier = helpers.first_line('/sys/class/net/' .. iface .. '/carrier') or "0" - state = helpers.first_line('/sys/class/net/' .. iface .. + net_now.state = helpers.first_line('/sys/class/net/' .. iface .. '/operstate') or "down" local now_t = helpers.first_line('/sys/class/net/' .. iface .. '/statistics/tx_bytes') or 0 local now_r = helpers.first_line('/sys/class/net/' .. iface .. '/statistics/rx_bytes') or 0 - sent = tostring((now_t - net.last_t) / timeout / units) - sent = string.gsub(string.format('%.1f', sent), ",", ".") + net_now.sent = tostring((now_t - net.last_t) / timeout / units) + net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ",", ".") - received = tostring((now_r - net.last_r) / timeout / units) - received = string.gsub(string.format('%.1f', received), ",", ".") + net_now.received = tostring((now_r - net.last_r) / timeout / units) + net_now.received = string.gsub(string.format('%.1f', net_now.received), ",", ".") widget = net.widget settings() @@ -74,7 +76,7 @@ local function worker(args) net.last_t = now_t net.last_r = now_r - if carrier ~= "1" + if net_now.carrier ~= "1" then if helpers.get_map(iface) then @@ -95,8 +97,7 @@ local function worker(args) end end - helpers.newtimer(iface, timeout, net.update) - + helpers.newtimer(iface, timeout, update) return net.widget end diff --git a/widgets/sysload.lua b/widgets/sysload.lua index 90bdedf..868398c 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -28,19 +28,18 @@ local function worker(args) sysload.widget = wibox.widget.textbox('') - function sysload.update() + function update() local f = io.open("/proc/loadavg") local ret = f:read("*all") f:close() - a, b, c = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") + load_1, load_5, load_15 = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") widget = sysload.widget settings() end - newtimer("sysload", timeout, sysload.update) - + newtimer("sysload", timeout, update) return sysload.widget end diff --git a/widgets/temp.lua b/widgets/temp.lua index e568138..b57c477 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -26,7 +26,7 @@ local function worker(args) temp.widget = wibox.widget.textbox('') - function temp.update() + function update() local f = io.open("/sys/class/thermal/thermal_zone0/temp") coretemp_now = tonumber(f:read("*all")) / 1000 f:close() @@ -34,8 +34,7 @@ local function worker(args) settings() end - newtimer("coretemp", timeout, temp.update) - + newtimer("coretemp", timeout, update) return temp.widget end diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 4d14966..4c90df4 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -43,7 +43,7 @@ local city_id = nil local sky = nil local settings = function() end -notification_preset = {} +yawn_notification_preset = {} local function fetch_weather() local url = api_url .. units_set .. city_id @@ -56,6 +56,7 @@ local function fetch_weather() -- widgets won't display if text == "" or text:match("City not found") then + yawn.icon:set_image(icon_path .. "na.png") if text == "" then weather_data = "Service not available at the moment." yawn.widget:set_text("N/A") @@ -152,7 +153,7 @@ function yawn.show(t_out) yawn.hide() notification = naughty.notify({ - preset = notification_preset, + preset = yawn_notification_preset, text = weather_data, icon = sky, timeout = t_out From c0ce11202cad1ea905765e6af7fa491b4d8274c7 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 15:15:22 -0700 Subject: [PATCH 238/572] Updated net (markdown) --- net.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net.md b/net.md index f1cd095..6a1c52d 100644 --- a/net.md +++ b/net.md @@ -17,9 +17,9 @@ Possible other values for `units` are 1 (byte) or multiple of 1024: 1024^2 (mb), `settings` can use the following `iface` strings: -- `carrier` ("0", "1"); -- `state` ("up", "down"); -- `sent` and `received` (numbers). +- `net_now.carrier` ("0", "1"); +- `net_now.state` ("up", "down"); +- `net_now.sent` and `net_now.received` (numbers). ### output From d3d29c7640ce2eeea578e28838b853ac152dc88d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 15:26:46 -0700 Subject: [PATCH 239/572] Updated cpu (markdown) --- cpu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu.md b/cpu.md index ae490b0..e42180c 100644 --- a/cpu.md +++ b/cpu.md @@ -11,7 +11,7 @@ Variable | Meaning | Type | Default `timeout` | Refresh timeout seconds | int | 5 `settings` | User settings | function | empty function -`settings` can use the string `usage`, which is the cpu use percentage. +`settings` can use the string `cpu_now.usage`, which is the cpu use percentage. ### output From 0eb70991d480b7e3104832b877c6f2afbf778542 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 15:27:04 -0700 Subject: [PATCH 240/572] Updated Widgets (markdown) --- Widgets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index e812db2..8395445 100644 --- a/Widgets.md +++ b/Widgets.md @@ -17,7 +17,7 @@ Here follows an example: mycpu = lain.widgets.cpu({ timeout = 4, settings = function() - widget:set_markup("Cpu " .. usage) + widget:set_markup("Cpu " .. cpu_now.usage) end }) From 4c5a81537a6bff59550b4b41223201ea8b826b64 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 15:38:37 -0700 Subject: [PATCH 241/572] Updated alsabar (markdown) --- alsabar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsabar.md b/alsabar.md index 711c8ce..e50b5c7 100644 --- a/alsabar.md +++ b/alsabar.md @@ -47,7 +47,7 @@ It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height, Variable | Meaning | Type --- | --- | --- -`widget` | The widget | `awful.widget.progressbar` +`bar` | The widget | `awful.widget.progressbar` `channel` | Alsa channel | string `step` | Increase/decrease step | string `notify` | The notification | function From 547487e7309966c5ceab7d57fea97590c5bb013c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 17:29:55 -0700 Subject: [PATCH 242/572] Updated temp (markdown) --- temp.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/temp.md b/temp.md index f7315b6..91f3031 100644 --- a/temp.md +++ b/temp.md @@ -1,16 +1,20 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -Show the current core temperature in a textbox. +Shows the current core temperature in a textbox. Reads from `/sys/class/thermal`, so value is expressed in Celsius. mytemp = lain.widgets.temp() -The function takes a table as optional argument, which can contain: +### input table Variable | Meaning | Type | Default --- | --- | --- | --- `timeout` | Refresh timeout seconds | int | 5 `settings` | User settings | function | empty function -`settings` can use the string `coretemp_now`, which means current core temperature, expressed in Celsius (linux standard). \ No newline at end of file +`settings` can use the string `coretemp_now`, which means current core temperature, expressed in Celsius (linux standard). + +### output + +A textbox. \ No newline at end of file From d34fda22b4d7174a52fc5fb214f2af9f1865ee7b Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 17:31:12 -0700 Subject: [PATCH 243/572] Updated sysload (markdown) --- sysload.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysload.md b/sysload.md index 4ed61a8..3e53881 100644 --- a/sysload.md +++ b/sysload.md @@ -1,6 +1,6 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -Show the current system load in a textbox. +Shows the current system load. mysysload = lain.widgets.sysload() From 6be1560149f3883e24bb68f5f7e4450851fba347 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 17:32:07 -0700 Subject: [PATCH 244/572] Updated net (markdown) --- net.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net.md b/net.md index 6a1c52d..f857239 100644 --- a/net.md +++ b/net.md @@ -15,7 +15,7 @@ Variable | Meaning | Type | Default Possible other values for `units` are 1 (byte) or multiple of 1024: 1024^2 (mb), 1024^3 (gb), and so on. -`settings` can use the following `iface` strings: +`settings` can use the following `iface` related strings: - `net_now.carrier` ("0", "1"); - `net_now.state` ("up", "down"); From ea28dce997a7656df7821a1e0a7e8d955a43f8f1 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 17:33:41 -0700 Subject: [PATCH 245/572] Updated mpd (markdown) --- mpd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpd.md b/mpd.md index de945b4..8a25d04 100644 --- a/mpd.md +++ b/mpd.md @@ -48,7 +48,7 @@ and can modify `mpd_notification_preset` table, which will be the preset for the Variable | Meaning | Type --- | --- | --- `widget` | The textbox | `wibox.widget.textbox` -`notify` | The notification | function +`update` | The notification | function You can control the widget with key bindings like these: From b0c5550824b4a51f07ac74d6a032cee46978abc3 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 17:34:20 -0700 Subject: [PATCH 246/572] Updated mem (markdown) --- mem.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mem.md b/mem.md index 1079ca5..ba37923 100644 --- a/mem.md +++ b/mem.md @@ -4,9 +4,7 @@ Shows memory status (in MiB) in a textbox. mymem = lain.widgets.mem() - -The function takes a table as an optional argument. That table may -contain: +# input table Variable | Meaning | Type | Default --- | --- | --- | --- From bcd63c82008752f00d732ac7ff70ebde01829bd6 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 17:34:34 -0700 Subject: [PATCH 247/572] Updated mem (markdown) --- mem.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mem.md b/mem.md index ba37923..84b7ad2 100644 --- a/mem.md +++ b/mem.md @@ -4,7 +4,7 @@ Shows memory status (in MiB) in a textbox. mymem = lain.widgets.mem() -# input table +### input table Variable | Meaning | Type | Default --- | --- | --- | --- From 7a95e1868808f2222dc0841135cd866b6eca3a67 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 17:38:16 -0700 Subject: [PATCH 248/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index 5588ca7..e30c473 100644 --- a/fs.md +++ b/fs.md @@ -14,7 +14,7 @@ Variable | Meaning | Type | Default `partition` | Partition to monitor | string | "/" `settings` | User settings | function | empty function -`settings` can use the following `partition` related float values: `used` and `available`, `size_mb`, `size_gb`. +`settings` can use the following `partition` related float values: `used`, `available`, `size_mb`, `size_gb`. It can also use value strings in these formats: From fb09ee4af8c314eed06a01b1aa147f5b6a5a442e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 12 Sep 2013 17:41:39 -0700 Subject: [PATCH 249/572] Updated alsabar (markdown) --- alsabar.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/alsabar.md b/alsabar.md index e50b5c7..6dea44f 100644 --- a/alsabar.md +++ b/alsabar.md @@ -40,8 +40,7 @@ Variable | Meaning | Type | Default `color` | Notifications color | string | `beautiful.fg_focus` `bar_size` | Wibox height | int | 18 -It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height, -**if** you have set it different than default (18). +It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height. ### output table From 8af4a03c754fa1bcac24736633f1b3be8ce8888c Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 13 Sep 2013 18:15:25 +0200 Subject: [PATCH 250/572] small fixes --- helpers.lua | 12 ++++++------ layout/uselesstile.lua | 2 +- util/init.lua | 22 +++++++++++----------- util/markup.lua | 12 ++++++------ widgets/alsa.lua | 10 +++++----- widgets/alsabar.lua | 6 +++--- widgets/cpu.lua | 3 ++- widgets/fs.lua | 4 ++-- widgets/imap.lua | 4 +++- widgets/mem.lua | 10 +++++----- widgets/net.lua | 2 +- widgets/sysload.lua | 2 +- 12 files changed, 46 insertions(+), 43 deletions(-) diff --git a/helpers.lua b/helpers.lua index 81910d2..97cb797 100644 --- a/helpers.lua +++ b/helpers.lua @@ -1,10 +1,10 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann - + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + --]] local debug = require("debug") @@ -46,7 +46,7 @@ end -- }}} --- {{{ Timer maker +-- {{{ Timer maker helpers.timer_table = {} diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index b82c97e..cd288ed 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -11,7 +11,7 @@ local tag = require("awful.tag") local beautiful = require("beautiful") local ipairs = ipairs -local math = { floor = math.floor, +local math = { floor = math.floor, max = math.max, min = math.min } local tonumber = tonumber diff --git a/util/init.lua b/util/init.lua index a44d52c..26f50ae 100644 --- a/util/init.lua +++ b/util/init.lua @@ -1,15 +1,15 @@ --[[ - - Lain - Layouts, widgets and utilities for Awesome WM - - Utilities section - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann - + + Lain + Layouts, widgets and utilities for Awesome WM + + Utilities section + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + --]] local awful = require("awful") @@ -17,7 +17,7 @@ local beautiful = require("beautiful") local math = { sqrt = math.sqrt } local mouse = mouse local pairs = pairs -local string = string +local string = { gsub = string.gsub } local client = client local screen = screen local tonumber = tonumber diff --git a/util/markup.lua b/util/markup.lua index dbb8529..d367bca 100644 --- a/util/markup.lua +++ b/util/markup.lua @@ -1,11 +1,11 @@ --[[ - - Licensed under MIT License - * (c) 2013, Luke Bonham - * (c) 2009, Uli Schlachter - * (c) 2009, Majic - + + Licensed under MIT License + * (c) 2013, Luke Bonham + * (c) 2009, Uli Schlachter + * (c) 2009, Majic + --]] local beautiful = require("beautiful") diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 3e025bb..28bb05c 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -1,10 +1,10 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010, Adrian C. - + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010, Adrian C. + --]] local newtimer = require("lain.helpers").newtimer diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 8331c54..d8f1731 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -15,7 +15,7 @@ local naughty = require("naughty") local io = { popen = io.popen } local math = { modf = math.modf } -local string = { format = string.format, +local string = { format = string.format, match = string.match, rep = string.rep } local tonumber = tonumber @@ -44,7 +44,7 @@ local alsabar = font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), font_size = "11", color = beautiful.fg_focus, - bar_size = 18 + bar_size = 18 }, _current_level = 0, @@ -122,7 +122,7 @@ local function worker(args) f:close() -- Capture mixer control state: [5%] ... ... [on] - local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") + local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") if volu == nil then volu = 0 diff --git a/widgets/cpu.lua b/widgets/cpu.lua index 55a3799..0b21edc 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -58,7 +58,8 @@ local function worker(args) local dactive = active - cpu.last_active local dtotal = total - cpu.last_total - usage = tostring(math.ceil((dactive / dtotal) * 100)) + cpu_now = {} + cpu_now.usage = tostring(math.ceil((dactive / dtotal) * 100)) widget = cpu.widget settings() diff --git a/widgets/fs.lua b/widgets/fs.lua index 17037c4..b434056 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -64,7 +64,7 @@ local function worker(args) helpers.set_map("fs", false) function update() - fs_info = {} + fs_info = {} local f = io.popen("LC_ALL=C df -kP") @@ -95,7 +95,7 @@ local function worker(args) if used >= 99 and not helpers.get_map("fs") then - naughty.notify({ + naughty.notify({ title = "warning", text = partition .. " ran out!\nmake some room", timeout = 8, diff --git a/widgets/imap.lua b/widgets/imap.lua index 6574276..605c1c4 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -14,6 +14,7 @@ local wibox = require("wibox") local io = { popen = io.popen } local string = { format = string.format, gsub = string.gsub } +local tonumber = tonumber local setmetatable = setmetatable @@ -52,7 +53,7 @@ local function worker(args) icon = helpers.icons_dir .. "mail.png", position = "top_left" } - + curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%s %s -k", head_command, server, port, mail, password, request) @@ -62,6 +63,7 @@ local function worker(args) t, mailcount = string.gsub(ws, "%d", "") t = nil -- because it's useless + mailcount = tonumber(mailcount) widget = imap.widget settings() diff --git a/widgets/mem.lua b/widgets/mem.lua index 78ed3e0..986fa76 100644 --- a/widgets/mem.lua +++ b/widgets/mem.lua @@ -1,10 +1,10 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann - + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + --]] local newtimer = require("lain.helpers").newtimer diff --git a/widgets/net.lua b/widgets/net.lua index b3deca6..d79e117 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -50,7 +50,7 @@ local function worker(args) helpers.set_map(iface, true) - function update() + function update() net_now = {} if iface == "" then iface = net.get_device() end diff --git a/widgets/sysload.lua b/widgets/sysload.lua index 868398c..015573c 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -32,7 +32,7 @@ local function worker(args) local f = io.open("/proc/loadavg") local ret = f:read("*all") f:close() - + load_1, load_5, load_15 = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") widget = sysload.widget From b87b05203ed0b2f6c0dcfc342de0916e15547f17 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 13 Sep 2013 20:08:51 +0200 Subject: [PATCH 251/572] yawn: forecast string fix --- widgets/yawn/init.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 4c90df4..d37fc44 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -131,9 +131,11 @@ local function fetch_weather() yawn.icon:set_image(sky) widget = yawn.widget - forecast = weather_data:match(": %S+.-,"):gsub(": ", ""):gsub(",", "\n") + forecast = weather_data:match(": %S.-,"):gsub(": ", ""):gsub(",", "") units = units:gsub(" ", "") + naughty.notify({text=forecast, timeout=10}) + naughty.notify({text=units, timeout=10}) settings() end From db1fb613b32c3ae3d7ea3e41bf16bedb58552d27 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 13 Sep 2013 20:15:45 +0200 Subject: [PATCH 252/572] yawn: forgot to remove debug strings --- widgets/yawn/init.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index d37fc44..2306fed 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -134,8 +134,6 @@ local function fetch_weather() forecast = weather_data:match(": %S.-,"):gsub(": ", ""):gsub(",", "") units = units:gsub(" ", "") - naughty.notify({text=forecast, timeout=10}) - naughty.notify({text=units, timeout=10}) settings() end From 72bc5d131a4f85474d95b3b5895085ab521bb47e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Fri, 13 Sep 2013 14:00:43 -0700 Subject: [PATCH 253/572] Updated alsabar (markdown) --- alsabar.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/alsabar.md b/alsabar.md index 6dea44f..f694c69 100644 --- a/alsabar.md +++ b/alsabar.md @@ -2,7 +2,7 @@ Shows and controls alsa volume with a progressbar; provides tooltips, notifications, and color changes at mute/unmute switch. - myvolumebar = lain.widgets.alsabar() + volume = lain.widgets.alsabar() * Left click: Launch `alsamixer` in your `terminal`. * Right click: Mute/unmute. @@ -53,26 +53,26 @@ Variable | Meaning | Type You can control the widget with key bindings like these: - -- Volume control + -- ALSA volume control awful.key({ altkey }, "Up", - function () - awful.util.spawn("amixer set " .. volume.channel .. " " .. volume.step .. "+") - myvolumebar.notify() - end), + function () + awful.util.spawn("amixer -q set " .. volume.channel .. " " .. volume.step .. "+") + volume.notify() + end), awful.key({ altkey }, "Down", - function () - awful.util.spawn("amixer set " .. volume.channel .. " " .. volume.step .. "-") - myvolumeba.notify() - end), + function () + awful.util.spawn("amixer -q set " .. volume.channel .. " " .. volume.step .. "-") + volume.notify() + end), awful.key({ altkey }, "m", - function () - awful.util.spawn("amixer set " .. volume.channel .. " playback toggle") - myvolumebar.notify() - end), - awful.key({ altkey, "Control" }, "m", - function () - awful.util.spawn("amixer set " .. volume.channel .. " playback 100%", false ) - myvolumebar.notify() - end), + function () + awful.util.spawn("amixer -q set " .. volume.channel .. " playback toggle") + volume.notify() + end), + awful.key({ altkey, "Control" }, "m", + function () + awful.util.spawn("amixer -q set " .. volume.channel .. " playback 100%") + volume.notify() + end), where `altkey = "Mod1"`. \ No newline at end of file From 18af84d88ecbdedee3048e65aa6ff2df130252e9 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Fri, 13 Sep 2013 14:11:07 -0700 Subject: [PATCH 254/572] Updated Widgets (markdown) --- Widgets.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Widgets.md b/Widgets.md index 8395445..981e4e1 100644 --- a/Widgets.md +++ b/Widgets.md @@ -21,6 +21,8 @@ Here follows an example: end }) +If you want to see more complex applications, check [awesome-copycats](https://github.com/copycat-killer/awesome-copycats). + --- - [alsa](https://github.com/copycat-killer/lain/wiki/alsa) From a8eb652fd64299d64c9e831544263eabac0476ab Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 14 Sep 2013 00:01:00 +0200 Subject: [PATCH 255/572] mpd: cover_size option added --- scripts/mpdcover | 12 +++++------- widgets/mpd.lua | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/scripts/mpdcover b/scripts/mpdcover index 38b43e9..7ba9439 100755 --- a/scripts/mpdcover +++ b/scripts/mpdcover @@ -21,9 +21,6 @@ MUSIC_DIR=$1 # Song file file=$2 -# The default cover to use (optional) -DEFAULT_ART=$3 - # Regex expression used for image search IMG_REG="(front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif)$" @@ -31,7 +28,11 @@ IMG_REG="(front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif)$" TEMP_PATH="/tmp/mpdcover.png" # Resize cover -COVER_RESIZE="100x100" +COVER_RESIZE="$3x$3" + +if [ $COVER_RESIZE == "x" ]; then + COVER_RESIZE="100x100" +fi # Thumbnail background (transparent) COVER_BACKGROUND="none" @@ -48,9 +49,6 @@ art="$MUSIC_DIR/${file%/*}" # cover. cover="$(find "$art/" -maxdepth 1 -type f | egrep -i -m1 "$IMG_REG")" -# when no cover is found, use DEFAULT_ART as cover -cover="${cover:=$DEFAULT_ART}" - # check if art is available if [[ -n $cover ]]; then if [[ -n $COVER_RESIZE ]]; then diff --git a/widgets/mpd.lua b/widgets/mpd.lua index cd97b37..82db92c 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -26,13 +26,14 @@ local setmetatable = setmetatable local mpd = {} local function worker(args) - local args = args or {} - local timeout = args.timeout or 2 - local password = args.password or "" - local host = args.host or "127.0.0.1" - local port = args.port or "6600" - local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" - local settings = args.settings or function() end + local args = args or {} + local timeout = args.timeout or 2 + local password = args.password or "" + local host = args.host or "127.0.0.1" + local port = args.port or "6600" + local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" + local cover_size = args.cover_size or 100 + local settings = args.settings or function() end local mpdcover = helpers.scripts_dir .. "mpdcover" local mpdh = "telnet://" .. host .. ":" .. port @@ -84,7 +85,8 @@ local function worker(args) then helpers.set_map("current mpd track", mpd_now.title) - os.execute(string.format("%s %q %q", mpdcover, music_dir, mpd_now.file)) + os.execute(string.format("%s %q %q %d", mpdcover, music_dir, + mpd_now.file, cover_size)) mpd.id = naughty.notify({ preset = mpd_notification_preset, From 7cc2212955829ddf925e11e9f9744679b8a4336a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Fri, 13 Sep 2013 15:04:30 -0700 Subject: [PATCH 256/572] Updated mpd (markdown) --- mpd.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mpd.md b/mpd.md index 8a25d04..70a7938 100644 --- a/mpd.md +++ b/mpd.md @@ -14,6 +14,12 @@ Now playing songs are notified like this: | +-------+ | +--------------------------------------------------------+ +You need a file like this + + "(front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif)$" + +in the album folder in order to show album art in the notification too. + ### input table Variable | Meaning | Type | Default @@ -23,6 +29,7 @@ Variable | Meaning | Type | Default `host` | MPD server | string | "127.0.0.1" `port` | MPD port | string | "6600" `music_dir` | Music directory | string | "~/Music" +`cover_size` | Album art notification size | int | 100 `settings` | User settings | function | empty function `settings` can use `mpd_now` table, which contains the following string values: From 938c23eea12ae13dd709007ff5e75b80902eeafc Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Fri, 13 Sep 2013 15:05:37 -0700 Subject: [PATCH 257/572] Updated mpd (markdown) --- mpd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpd.md b/mpd.md index 70a7938..62d6e4b 100644 --- a/mpd.md +++ b/mpd.md @@ -16,7 +16,7 @@ Now playing songs are notified like this: You need a file like this - "(front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif)$" + (front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif)$ in the album folder in order to show album art in the notification too. From 8e18573717b105546da6ab785bb2479c52d61044 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Fri, 13 Sep 2013 15:05:58 -0700 Subject: [PATCH 258/572] Updated mpd (markdown) --- mpd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpd.md b/mpd.md index 62d6e4b..44d7826 100644 --- a/mpd.md +++ b/mpd.md @@ -18,7 +18,7 @@ You need a file like this (front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif)$ -in the album folder in order to show album art in the notification too. +in the album folder in order to show album art too. ### input table From 1d9cf86d9368646cc11d1fca3ee3445026a26261 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Fri, 13 Sep 2013 15:06:13 -0700 Subject: [PATCH 259/572] Updated mpd (markdown) --- mpd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpd.md b/mpd.md index 44d7826..7db0498 100644 --- a/mpd.md +++ b/mpd.md @@ -16,7 +16,7 @@ Now playing songs are notified like this: You need a file like this - (front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif)$ + (front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif) in the album folder in order to show album art too. From c179b2461995ca465bd55c022f30b6a3d0d92589 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 14 Sep 2013 14:15:57 +0200 Subject: [PATCH 260/572] bat: rem nil value fixed --- widgets/bat.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 09b135f..7b14a9a 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -89,7 +89,7 @@ local function worker(args) ontop = true, replaces_id = bat.id }).id - elseif bat.perc <= 15 + elseif bat_now.perc <= 15 then bat.id = naughty.notify({ text = "plug the cable", From 94d05ef9e159e1322e76313c1a9bf87c553f1406 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 14 Sep 2013 08:11:13 -0700 Subject: [PATCH 261/572] Updated Layouts (markdown) --- Layouts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Layouts.md b/Layouts.md index 7c4ff41..07184a4 100644 --- a/Layouts.md +++ b/Layouts.md @@ -247,7 +247,7 @@ you have to add an item called `useless_gap_width` in your `theme.lua`. If it doesn't exist, the width will default to 0. Example: - theme.useless_gap_width = "5" + theme.useless_gap_width = 5 What about layout icons? ======================== From 4ca808f3e3239e1bbdb24e28d0bee877791dfa77 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 15 Sep 2013 16:17:33 +0200 Subject: [PATCH 262/572] small code fixes --- layout/cascadetile.lua | 6 +----- layout/centerwork.lua | 6 +----- layout/termfair.lua | 32 ++++---------------------------- layout/uselessfair.lua | 8 ++------ layout/uselesspiral.lua | 32 ++++++++++++++------------------ layout/uselesstile.lua | 6 +----- 6 files changed, 23 insertions(+), 67 deletions(-) diff --git a/layout/cascadetile.lua b/layout/cascadetile.lua index a94bbed..98821e3 100644 --- a/layout/cascadetile.lua +++ b/layout/cascadetile.lua @@ -43,11 +43,7 @@ function cascadetile.arrange(p) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width. - local useless_gap = tonumber(beautiful.useless_gap_width) - if useless_gap == nil - then - useless_gap = 0 - end + local useless_gap = tonumber(beautiful.useless_gap_width) or 0 -- Screen. local wa = p.workarea diff --git a/layout/centerwork.lua b/layout/centerwork.lua index 2035c65..b8175ea 100644 --- a/layout/centerwork.lua +++ b/layout/centerwork.lua @@ -24,11 +24,7 @@ local centerwork = function centerwork.arrange(p) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width . - local useless_gap = tonumber(beautiful.useless_gap_width) - if useless_gap == nil - then - useless_gap = 0 - end + local useless_gap = tonumber(beautiful.useless_gap_width) or 0 -- Screen. local wa = p.workarea diff --git a/layout/termfair.lua b/layout/termfair.lua index 62eef9a..4beab8f 100644 --- a/layout/termfair.lua +++ b/layout/termfair.lua @@ -14,15 +14,7 @@ local math = { ceil = math.ceil, max = math.max } local tonumber = tonumber -local termfair = -{ - name = "termfair", - - -- You can set the number of columns and rows, - -- -- otherwise they are read from awful.tag - nmaster = 0, -- columns - ncol = 0 -- rows -} +local termfair = { name = "termfair" } function termfair.arrange(p) -- Layout with fixed number of vertical columns (read from nmaster). @@ -45,11 +37,7 @@ function termfair.arrange(p) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width. - local useless_gap = tonumber(beautiful.useless_gap_width) - if useless_gap == nil - then - useless_gap = 0 - end + local useless_gap = tonumber(beautiful.useless_gap_width) or 0 -- Screen. local wa = p.workarea @@ -57,22 +45,10 @@ function termfair.arrange(p) -- How many vertical columns? local t = tag.selected(p.screen) - local num_x - if termfair.nmaster ~= 0 - then - num_x = termfair.nmaster - else - num_x = tag.getnmaster(t) - end + local num_x = termfair.nmaster or tag.getnmaster(t) -- Do at least "desired_y" rows. - local desired_y - if termfair.ncol ~= 0 - then - desired_y = termfair.ncol - else - desired_y = tag.getncol(t) - end + local desired_y = termfair.ncol or tag.getncol(t) if #cls > 0 then diff --git a/layout/uselessfair.lua b/layout/uselessfair.lua index 92e8d45..7499d91 100644 --- a/layout/uselessfair.lua +++ b/layout/uselessfair.lua @@ -18,11 +18,7 @@ local uselessfair = {} local function fair(p, orientation) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width. - local useless_gap = tonumber(beautiful.useless_gap_width) - if useless_gap == nil - then - useless_gap = 0 - end + local useless_gap = tonumber(beautiful.useless_gap_width) or 0 local wa = p.workarea local cls = p.clients @@ -88,7 +84,7 @@ local function fair(p, orientation) g.height = g.height - 2 * useless_gap g.y = g.y + useless_gap else - g.height = g.height - useless_gap + g.height = g.height - useless_gap end end -- End of useless gap. diff --git a/layout/uselesspiral.lua b/layout/uselesspiral.lua index 695728c..ad2ba04 100644 --- a/layout/uselesspiral.lua +++ b/layout/uselesspiral.lua @@ -17,11 +17,7 @@ local uselesspiral = {} local function spiral(p, spiral) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width. - local useless_gap = tonumber(beautiful.useless_gap_width) - if useless_gap == nil - then - useless_gap = 0 - end + local useless_gap = tonumber(beautiful.useless_gap_width) or 0 local wa = p.workarea local cls = p.clients @@ -69,26 +65,26 @@ local function spiral(p, spiral) left = false if wa2.y == static_wa.y then - top = true + top = true end if wa2.x == static_wa.x then - left = true + left = true end - if top then - wa2.height = wa2.height - 2 * useless_gap - wa2.y = wa2.y + useless_gap + if top then + wa2.height = wa2.height - 2 * useless_gap + wa2.y = wa2.y + useless_gap else - wa2.height = wa2.height - useless_gap - end + wa2.height = wa2.height - useless_gap + end - if left then - wa2.width = wa2.width - 2 * useless_gap - wa2.x = wa2.x + useless_gap - else - wa2.width = wa2.width - useless_gap - end + if left then + wa2.width = wa2.width - 2 * useless_gap + wa2.x = wa2.x + useless_gap + else + wa2.width = wa2.width - useless_gap + end end -- End of useless gap. diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index cd288ed..78f7bec 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -21,11 +21,7 @@ local uselesstile = {} local function tile_group(cls, wa, orientation, fact, group) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width . - local useless_gap = tonumber(beautiful.useless_gap_width) - if useless_gap == nil - then - useless_gap = 0 - end + local useless_gap = tonumber(beautiful.useless_gap_width) or 0 -- get our orientation right local height = "height" From c2d27aec72f3db1a795b9fce4828049cbf91dacd Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 16 Sep 2013 13:49:14 +0200 Subject: [PATCH 263/572] little fix --- widgets/mpd.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 82db92c..3ebc761 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -9,7 +9,7 @@ local helpers = require("lain.helpers") -local util = require("awful.util") +local escape_f = require("awful.util").escape local naughty = require("naughty") local wibox = require("wibox") @@ -64,10 +64,10 @@ local function worker(args) 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 == "Artist" then mpd_now.artist = util.escape(v) - elseif k == "Title" then mpd_now.title = util.escape(v) - elseif k == "Album" then mpd_now.album = util.escape(v) - elseif k == "Date" then mpd_now.date = util.escape(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) end end end From f28575f988791b7a7fa632d9a00c8d3edcac3df1 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 17 Sep 2013 15:14:40 -0700 Subject: [PATCH 264/572] Updated Home (markdown) --- Home.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Home.md b/Home.md index 6b7b58d..63ede55 100644 --- a/Home.md +++ b/Home.md @@ -8,6 +8,8 @@ alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar] curl | widget types accessing network resources imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) +*(Why ImageMagick? Because Cairo doesn't do high quality filtering at the moment)* + ### Installation Simply clone this repository into your Awesome directory: From b91dae564d5a5358c94375bfa160121dcc408b86 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 17 Sep 2013 15:15:07 -0700 Subject: [PATCH 265/572] Updated Home (markdown) --- Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Home.md b/Home.md index 63ede55..78f40c6 100644 --- a/Home.md +++ b/Home.md @@ -8,7 +8,7 @@ alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar] curl | widget types accessing network resources imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) -*(Why ImageMagick? Because Cairo doesn't do high quality filtering at the moment)* +*(Why ImageMagick? Because Cairo doesn't do high quality filtering at the moment.)* ### Installation From a14469d9f649e9d95956c6c460313b8708537a92 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 17 Sep 2013 15:26:32 -0700 Subject: [PATCH 266/572] Updated mpd (markdown) --- mpd.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mpd.md b/mpd.md index 7db0498..0e2eca5 100644 --- a/mpd.md +++ b/mpd.md @@ -16,7 +16,7 @@ Now playing songs are notified like this: You need a file like this - (front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif) + (Front|front|Cover|cover|Art|art|Folder|folder)\.(jpg|jpeg|png|gif) in the album folder in order to show album art too. @@ -30,6 +30,7 @@ Variable | Meaning | Type | Default `port` | MPD port | string | "6600" `music_dir` | Music directory | string | "~/Music" `cover_size` | Album art notification size | int | 100 +`default_art` | Default art | string | "" `settings` | User settings | function | empty function `settings` can use `mpd_now` table, which contains the following string values: From f31c5cc856640aa4cd5a7299974ba02abacd95a7 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 18 Sep 2013 00:27:46 +0200 Subject: [PATCH 267/572] mpd: default art added --- scripts/mpdcover | 10 ++++++++-- widgets/mpd.lua | 21 +++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/scripts/mpdcover b/scripts/mpdcover index 7ba9439..f9f6577 100755 --- a/scripts/mpdcover +++ b/scripts/mpdcover @@ -11,7 +11,7 @@ # # Dependencies: imagemagick. # -# Usage: mpdcover +# Usage: mpdcover # Configuration------------------------------------------------------- @@ -22,7 +22,7 @@ MUSIC_DIR=$1 file=$2 # Regex expression used for image search -IMG_REG="(front|cover|art|Folder|folder)\.(jpg|jpeg|png|gif)$" +IMG_REG="(Front|front|Cover|cover|Art|art|Folder|folder)\.(jpg|jpeg|png|gif)$" # Path of temporary resized cover TEMP_PATH="/tmp/mpdcover.png" @@ -34,6 +34,9 @@ if [ $COVER_RESIZE == "x" ]; then COVER_RESIZE="100x100" fi +# The default cover to use (optional) +DEFAULT_ART=$4 + # Thumbnail background (transparent) COVER_BACKGROUND="none" @@ -49,6 +52,9 @@ art="$MUSIC_DIR/${file%/*}" # cover. cover="$(find "$art/" -maxdepth 1 -type f | egrep -i -m1 "$IMG_REG")" +# when no cover is found, use DEFAULT_ART as cover +cover="${cover:=$DEFAULT_ART}" + # check if art is available if [[ -n $cover ]]; then if [[ -n $COVER_RESIZE ]]; then diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 3ebc761..41233cd 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -26,14 +26,15 @@ local setmetatable = setmetatable local mpd = {} local function worker(args) - local args = args or {} - local timeout = args.timeout or 2 - local password = args.password or "" - local host = args.host or "127.0.0.1" - local port = args.port or "6600" - local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" - local cover_size = args.cover_size or 100 - local settings = args.settings or function() end + local args = args or {} + local timeout = args.timeout or 2 + local password = args.password or "" + local host = args.host or "127.0.0.1" + local port = args.port or "6600" + 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 settings = args.settings or function() end local mpdcover = helpers.scripts_dir .. "mpdcover" local mpdh = "telnet://" .. host .. ":" .. port @@ -85,8 +86,8 @@ local function worker(args) then helpers.set_map("current mpd track", mpd_now.title) - os.execute(string.format("%s %q %q %d", mpdcover, music_dir, - mpd_now.file, cover_size)) + os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir, + mpd_now.file, cover_size, default_art)) mpd.id = naughty.notify({ preset = mpd_notification_preset, From 782da3605278f67cc13fbd408324aaf3b86a7eba Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 18 Sep 2013 06:53:48 -0700 Subject: [PATCH 268/572] Updated Utilities (markdown) --- Utilities.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Utilities.md b/Utilities.md index 6afff16..de9f56b 100644 --- a/Utilities.md +++ b/Utilities.md @@ -127,4 +127,27 @@ You can use it with a key binding like this: awful.key({ modkey, "Shift" }, "r", function () lain.util.prompt_rename_tag(mypromptbox) end) -Credits goes to [minism](https://bbs.archlinux.org/viewtopic.php?pid=1315135#p1315135). \ No newline at end of file +Credits goes to [minism](https://bbs.archlinux.org/viewtopic.php?pid=1315135#p1315135). + +useless\_gaps\_resize +--------------------- + +Changes `beautiful.useless_gaps_width` on the fly, if present. + +The function takes an integer argument, being the amount of pixel to add/remove to gaps. + +You could use it with these keybindings: + + -- On the fly useless gaps change + awful.key({ altkey, "Control" }, "+", function () lain.util.useless_gaps_resize(1) end), + awful.key({ altkey, "Control" }, "-", function () lain.util.useless_gaps_resize(-1) end), + +where `altkey=Mod1`, or you could use it as a button like this: + + mywidget:buttons(awful.util.table.join ( + awful.button({}, 4, function() lain.util.useless_gaps_resize(-1) end), + awful.button({}, 5, function() lain.util.useless_gaps_resize(1) end) + end) + )) + +so when hovering the mouse over `mywidget`, you can adjust useless gaps size by scrolling with the mouse wheel. \ No newline at end of file From ac945dddbed50cd0db89763a3380937598647e84 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 18 Sep 2013 06:54:08 -0700 Subject: [PATCH 269/572] Updated Utilities (markdown) --- Utilities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities.md b/Utilities.md index de9f56b..3f00c35 100644 --- a/Utilities.md +++ b/Utilities.md @@ -132,7 +132,7 @@ Credits goes to [minism](https://bbs.archlinux.org/viewtopic.php?pid=1315135#p13 useless\_gaps\_resize --------------------- -Changes `beautiful.useless_gaps_width` on the fly, if present. +Changes `beautiful.useless_gaps_width` on the fly. The function takes an integer argument, being the amount of pixel to add/remove to gaps. From 388ca69c813c312b295ecbbefc5308eded243026 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 18 Sep 2013 06:55:03 -0700 Subject: [PATCH 270/572] Updated Utilities (markdown) --- Utilities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities.md b/Utilities.md index 3f00c35..a5c29ac 100644 --- a/Utilities.md +++ b/Utilities.md @@ -142,7 +142,7 @@ You could use it with these keybindings: awful.key({ altkey, "Control" }, "+", function () lain.util.useless_gaps_resize(1) end), awful.key({ altkey, "Control" }, "-", function () lain.util.useless_gaps_resize(-1) end), -where `altkey=Mod1`, or you could use it as a button like this: +where `altkey=Mod1`, or you could use it like this: mywidget:buttons(awful.util.table.join ( awful.button({}, 4, function() lain.util.useless_gaps_resize(-1) end), From c397afd0c78e2bc708d6dd6f8d6ea778e3c4a7d4 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 18 Sep 2013 15:58:17 +0200 Subject: [PATCH 271/572] added useless gaps change on the fly --- icons/layout/default/browse.png | Bin 190 -> 0 bytes icons/layout/default/browsew.png | Bin 190 -> 0 bytes icons/layout/default/gimp.png | Bin 289 -> 0 bytes icons/layout/default/gimpw.png | Bin 289 -> 0 bytes icons/layout/zenburn/browse.png | Bin 269 -> 0 bytes icons/layout/zenburn/gimp.png | Bin 3424 -> 0 bytes util/init.lua | 8 ++++++++ 7 files changed, 8 insertions(+) delete mode 100644 icons/layout/default/browse.png delete mode 100644 icons/layout/default/browsew.png delete mode 100644 icons/layout/default/gimp.png delete mode 100644 icons/layout/default/gimpw.png delete mode 100644 icons/layout/zenburn/browse.png delete mode 100644 icons/layout/zenburn/gimp.png diff --git a/icons/layout/default/browse.png b/icons/layout/default/browse.png deleted file mode 100644 index c063ca09de3e77e8a605ab39bef9b9c21c5bacda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt&q zurz(=c_77D666=m;PC858ivL>4nJa0`PlBg3pY5H=O z_B)KS0!qA}lg;YFU978nDC;#AQ<(bjL&g1Z*p|Q5W=z-pm6rLz^{?Ox({Zts_ XZ!gY%>+x_hP(6dEtDnm{r-UW|pPn$+ diff --git a/icons/layout/default/browsew.png b/icons/layout/default/browsew.png deleted file mode 100644 index 9b0b2b3141a857c618202685f759ee37925e4dd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt)< z|NmclbN*eBbV-n3FoVOh8)+a;lDE4HLkFv@2av;A;1OBOz`!jG!i)^F=12eq*-Jcq zUD@w2%J6B5nRIWs3=~rFba4#PIG_B3pOt4u4?B;;hla-50;30dM^bpA%=tr)KlW2$ YkiWe+`>n^r$w2iCp00i_>zopr0ADUNL;wH) diff --git a/icons/layout/default/gimp.png b/icons/layout/default/gimp.png deleted file mode 100644 index 207ab406ffb43518ba1a537ae5c0f22cf4d97a8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRF%}28J29*~C-V}>VGHmHaRt&q zurz(=c_77D666=m;PC858ivL>4nJa0`PlBg3pY5H=O z_B)KS0xB$bW`vyt3blK>IEHAPUwUaHFS8;K>xKSx1t&Soxn{>o^ae^i^x_hE{wGzb zmBV${jw(_4TIpBK`5^^Q>|A8|*SZ9}ZHZ`5+_vE625}W7#)%dUy)PUTZhhULXwuK| zyl1VR;#0Ln)8;qS9B>lfu--3&Z_h>czQ!rC;epnI)-%o-ZNC0nrgi>hu78nFe|f~M X@LS8-mC1Vu=p+VDS3j3^P6@jRF%}28J29*~C-V}>VGHmHaRt)< z|NmclbN*eBbV-n3FoVOh8)+a;lDE4HLkFv@2av;A;1OBOz`!jG!i)^F=12eq*-Jcq zUD@w2%J6Bb{E2xO3>0ejba4#PIKTALMqXw`9@Y!}>k3YCm~+jJmFNwWc<99?^88P# zQY(k+t{qjP^0m^hn)5>np4hp_@~?FXc-s=uptxA$Qs5#&yzG1yz2H&2G?0t<>WWxik1+8bCGunLpw@mB&%Uu5=pZ@ZQ YTj95svn!ML5YR~sp00i_>zopr055%EXaE2J diff --git a/icons/layout/zenburn/browse.png b/icons/layout/zenburn/browse.png deleted file mode 100644 index f0bd177143266961916a20d295faeccc73c58ba0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 269 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPgg4PHABl-j7F`rvZg}JzX3_DsH{K zxskU)LBJu_c&_`t?$76QU-zwZj_D6vcQz8Q*;B7I$lVP5CGWC!CF~3UH>S!7@Xz7b4%)a)B3i!xV(JdycvJRPiLT^ zG~Yy>T=d8eYo&c(UH4Z?rF@lCx|M>3hV&qeG2w|(bbc!V7N)`f+OstWt31D_SjplL zX8lf{%?F3epZhc$neEr-2`BuAP1)%O%IBBAUn@6hnnV9D{(*}jVYuv#uw#C+V}3Q! z&?-2)G`9Nrs}@hOXz0Wt??U2#2g)qXtKKDu{&884w?w(NU}$LQ5&R1VC;?mj4$2^G zei?WH1$2AWjmff|z$e$g-jyYu7CW;M9c~NxXDrCpTng-3umU0G`?+0liKscq`S(JN z7@QyV!^EQUss0%<#Q%X6c5Pt30S;A(f&NouQ!?EB<{Sa~kF zd=#M3r(^dce5&2~P5#4Wi%I03x-sqAv7kSJwPXDg=f%x44+hXIARr{^#{&u1G6MOH z-);C(1ZrAmCGJ;^c?hSesp+wEUE)Iz-EIkveGYeGJ)uGY1Gj$9Vg9Qprx$W~5Q^lK zRpV=2RaI37^8bkKbgnCJIKpRqTWOn+T@ZzvEr;1J5iZ|zv^i8~AVSM$H#T1#D<7g? zY!8rQNB{#^lk#4Y;BzLjF`mj~ye8F3Z6FU{lEAjYBvU#yzyUN< zo?3xl3S10_QX5F&#VYm;97m(Orb5tZah=;TxVf#0Q}K=_Il`s_KP*F76w11JKOhVa zhS{O`>k0d5&h~`i^iWoTpBtx)fPs+UH}6AmwMOi>e2x$3`A?0*-qFzou@$xn>rWLzc_sdS~t3 zBSBT1j@;WE>Jt$mcMq42$2G*vd-q7~R5` z%gaUyY}*#r{{{ykCOniD&A4q+SJ$%*447PBP>*a?6U}GiH@Rz_9b1;0h6A(F8k}P& zYOdmK>o1$;cku4#6&;S3zC}?#_}7hnBLI%Ox{S+JCD1=;6)7Vi{VTc{@t${){&xNo5Sfz5r?D#{#w8la+H0$Rqr{3<9A z-iWXD{{3S`MgQ!q*41_aI()c_jA`|-q2e1L$klG)@QI}SKhEJSaJO_^o^akCXIs^b zzE~IX6JI;&bmQw4l2pYfUY%{IPhpjcFdN_o7S!C)F$6m4 zQtLD!@)~_>4{$_R7XtweM4UnS38GmFm^>Uc-+Zu@z)FK5RjlZ*6U?Sim4ji!6Ews1v!rj7D0fyN3{1r}{?z3@| za1P*={42_+^sN&@h7;MkTfy!4#O(*Nd3dp&*5cyg8NGvR-R{8<4VOZjB zsY9Od=T;Aj^huWU=a2UJuG=pQUd)3n76KWFq&mqiUKpZSwyzhG0~W>u=vjXp)D+wN%c17rh~T()MjuBw#A7cY;%%^O&^e- zM+-hagyzyZD9{}(NNT-v-57@M?q{j+F2KkOv~bY^KC2Evr%zPE_ZsX5%}XZfJWb;j zF*FYq6coIhyN2GUx-6mr9=AU2RbK=83R2wgDN&`c5MURY^8wJp@iIcFo04(oD#vn0 z7@L)yomkl%^{)C~c~%g8MBDr3J^ba%m%n6mF-(tt+560$mO+B+02si6-Ii^mu{V=w z4uy%W5rB-%PSaP-^e6m>^mv`mZ*rz2_;JmT5OUw6+u;}y6c!g3onS-sMy~j1MaHFn zNbqE45WOoOw10P=dPa$2sF8|4NKJep9{)NFik!Loha6zm>fxB1ot;9EWi{W)&U?{V zyi!J%Kd)HD0U0pd^nRyJJzP^5nh_wBPmBbz2TBnVD!?7<` ze{Dro#IOjd+CC#4H!iJpYGv+!H62MAci)Lrw2n9BjYN4~vD1@lxR=Qu^fz=h5DRou zI>|`mnk*zzc3BXk+Y@(YXJ-!|*3@*jx3?doQmMjX-X4}?N|MU+Uy6f%Bgo(iUhHYE z$#5EZ#D@f*Zqp^G`QJ517)a>6cIIw{IQc&8HAY%pEU@-uS|`sS+=JJ;VEsj|7cXx1 zrb{btH&7%5Hq})vsvrQq;^LWgev2aseaPN%MBE5-D~Nh0?AWA_$7Ea@H05#16bw~9 zJt~}dWTdhWj|;sKHRUAS;T6aeLP@^*dBfz#W0 zHlolPI5r~MaH9Nr?XI~L!dKcyh}Qq zE%S1Lg?}9doB~b_L`YTeCI?KDpNfjOsD>4nm09T)riHQs=mH>!j%@1igtuE{2y4pUZCnmFXM%iSg*qyS$t1yTgZBl} z+5t0MZ8LePTq|=JiW~>}_TDxauO??!+vaZ5{oE*(WcREF-^-VKwUurMpi8d{=uDBS z?P5kXh_b)FzP^*gUHj46+B)+Nyo{|B_lnt=QRyj;3t1fl)?6e235(H|GyU!h&gUCa=20w0ky&vCU0#(z3HW9NkLd37=4JMGVXqipS{o-8DJj!aO{DnKEN&Pw#vnxW)5)$$JeSpWO;bT_j zORS-xvytCE)UtEA*UfUcZpc2HD;-O9JM$Xe;U{93e9f`>3@mB~=)sF*xV1Esm}0PP s4-AV)O8UMXv82iVuYb7uO|S!GcOK2W=X+d5)cyciYe%am81K~o16-VQGynhq diff --git a/util/init.lua b/util/init.lua index 26f50ae..c0545b6 100644 --- a/util/init.lua +++ b/util/init.lua @@ -171,4 +171,12 @@ function util.prompt_rename_tag(mypromptbox) end) end +-- On the fly useless gaps change +function util.useless_gaps_resize(thatmuch) + if beautiful.useless_gap_width then + beautiful.useless_gap_width = tonumber(beautiful.useless_gap_width) + thatmuch + awful.layout.arrange(mouse.screen) + end +end + return setmetatable(util, { __index = wrequire }) From 1b929ba3aaa4534a5569c62620bebc3fe71137d6 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 18 Sep 2013 07:55:30 -0700 Subject: [PATCH 272/572] Updated Utilities (markdown) --- Utilities.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Utilities.md b/Utilities.md index a5c29ac..3797f3c 100644 --- a/Utilities.md +++ b/Utilities.md @@ -70,8 +70,7 @@ the currently used layout. Use it with a client keybinding like this: ... ) -If you want to "de-magnify" it, just reset the clients floating state to -`false` (hit `Mod4`+`CTRL`+`Space`, for example). +If you want to "de-magnify" it, just retype the keybinding. niceborder\_{focus, unfocus} ---------------------------- From 74f4507743e694cc17b85746247ec7a816d6924d Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 18 Sep 2013 16:56:02 +0200 Subject: [PATCH 273/572] util.magnify_client: toggle mode added --- util/init.lua | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/util/init.lua b/util/init.lua index c0545b6..4e82cd7 100644 --- a/util/init.lua +++ b/util/init.lua @@ -84,17 +84,21 @@ end -- Magnify a client: Set it to "float" and resize it. function util.magnify_client(c) - awful.client.floating.set(c, true) + if not awful.client.floating.get(c) then + awful.client.floating.set(c, true) - local mg = screen[mouse.screen].geometry - local tag = awful.tag.selected(mouse.screen) - local mwfact = awful.tag.getmwfact(tag) - local g = {} - g.width = math.sqrt(mwfact) * mg.width - g.height = math.sqrt(mwfact) * mg.height - g.x = mg.x + (mg.width - g.width) / 2 - g.y = mg.y + (mg.height - g.height) / 2 - c:geometry(g) + local mg = screen[mouse.screen].geometry + local tag = awful.tag.selected(mouse.screen) + local mwfact = awful.tag.getmwfact(tag) + local g = {} + g.width = math.sqrt(mwfact) * mg.width + g.height = math.sqrt(mwfact) * mg.height + g.x = mg.x + (mg.width - g.width) / 2 + g.y = mg.y + (mg.height - g.height) / 2 + c:geometry(g) + else + awful.client.floating.set(c, false) + end end -- Read the nice value of pid from /proc. From ed32756a35e1cd4ca8141966a634910c1e5a4e0a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 05:01:28 -0700 Subject: [PATCH 274/572] Updated Home (markdown) --- Home.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Home.md b/Home.md index 78f40c6..aad783f 100644 --- a/Home.md +++ b/Home.md @@ -2,11 +2,11 @@ Welcome to the Lain wiki! ### Dependencies -Package | Requested by ---- | --- -alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) -curl | widget types accessing network resources -imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) +Package | Requested by | Reason +--- | --- | --- +alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) | / +curl | widgets accessing network resources | Lua socket is not a core library. +imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) | Cairo doesn't do high quality filtering. *(Why ImageMagick? Because Cairo doesn't do high quality filtering at the moment.)* From c97650a177d4c3c6fbac039cbfc9876249fcf878 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 05:02:06 -0700 Subject: [PATCH 275/572] Updated Home (markdown) --- Home.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Home.md b/Home.md index aad783f..5afbc2c 100644 --- a/Home.md +++ b/Home.md @@ -2,9 +2,9 @@ Welcome to the Lain wiki! ### Dependencies -Package | Requested by | Reason +Package | Requested by | Reason of choice --- | --- | --- -alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) | / +alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) | / curl | widgets accessing network resources | Lua socket is not a core library. imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) | Cairo doesn't do high quality filtering. From a14dd68ecd7141173323f5a73b37391c0bc1ad3c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 05:04:08 -0700 Subject: [PATCH 276/572] Updated Home (markdown) --- Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Home.md b/Home.md index 5afbc2c..bc479c0 100644 --- a/Home.md +++ b/Home.md @@ -5,7 +5,7 @@ Welcome to the Lain wiki! Package | Requested by | Reason of choice --- | --- | --- alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) | / -curl | widgets accessing network resources | Lua socket is not a core library. +curl | widgets accessing network resources | LuaSocket is not a core library. LuaSSL is out of date. imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) | Cairo doesn't do high quality filtering. *(Why ImageMagick? Because Cairo doesn't do high quality filtering at the moment.)* From 3e324fd005797905bbf7b83be884f1e0a948931e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 06:24:58 -0700 Subject: [PATCH 277/572] Updated borderbox (markdown) --- borderbox.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/borderbox.md b/borderbox.md index e4d7afb..5ac0b04 100644 --- a/borderbox.md +++ b/borderbox.md @@ -40,7 +40,7 @@ adds a borderbox on top of them: ... -- Most likely, you'll want to do this as well: - awful.screen.padding(screen[s], { bottom = 1 }) + awful.screen.padding(screen[s], "bottom") -- Create the box and place it above the existing box. lain.widgets.borderbox(mywibox[s], s, { position = "above" } ) From 1f35c5057ff4efca355c0f5b6f5e0bbec2ee6d99 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 06:27:57 -0700 Subject: [PATCH 278/572] Updated borderbox (markdown) --- borderbox.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/borderbox.md b/borderbox.md index 5ac0b04..9fd138c 100644 --- a/borderbox.md +++ b/borderbox.md @@ -15,7 +15,7 @@ Variable | Meaning | Type | Default `color` | Color of the additional box | string | `#FFFFFF` `size` | Size in pixels of the additional box | int | 1 -Possible values for `.position`: `above`, `below`, `left` and `right`. +Possible values for `.position`: `top`, `bottom`, `left` and `right`. ### Example usage From 1368b031aa5d4b29a30c8f24b4bebde2f9d08ece Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 06:55:39 -0700 Subject: [PATCH 279/572] Updated borderbox (markdown) --- borderbox.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/borderbox.md b/borderbox.md index 9fd138c..a56026a 100644 --- a/borderbox.md +++ b/borderbox.md @@ -43,7 +43,7 @@ adds a borderbox on top of them: awful.screen.padding(screen[s], "bottom") -- Create the box and place it above the existing box. - lain.widgets.borderbox(mywibox[s], s, { position = "above" } ) + lain.widgets.borderbox(mywibox[s], s ) ... end \ No newline at end of file From 0b6de84ac137d74efd9eeaaf38267fd16bec9dd1 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 11:27:46 -0700 Subject: [PATCH 280/572] Updated Home (markdown) --- Home.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/Home.md b/Home.md index bc479c0..a7bee69 100644 --- a/Home.md +++ b/Home.md @@ -8,8 +8,6 @@ alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar] curl | widgets accessing network resources | LuaSocket is not a core library. LuaSSL is out of date. imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) | Cairo doesn't do high quality filtering. -*(Why ImageMagick? Because Cairo doesn't do high quality filtering at the moment.)* - ### Installation Simply clone this repository into your Awesome directory: From 53208723736b34e4b6c2c23fd77757fd46c436cf Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 19 Sep 2013 20:51:28 +0200 Subject: [PATCH 281/572] full dynamic tagging and wiki added --- .gitmodules | 3 +++ util/init.lua | 33 ++++++++++++++++++++++++++++----- widgets/borderbox.lua | 6 +++--- wiki | 1 + 4 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 .gitmodules create mode 160000 wiki diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..350c0f8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "wiki"] + path = wiki + url = https://github.com/copycat-killer/lain.wiki.git diff --git a/util/init.lua b/util/init.lua index 4e82cd7..73818b6 100644 --- a/util/init.lua +++ b/util/init.lua @@ -163,7 +163,22 @@ function util.tag_view_nonempty(direction, sc) end end --- Dynamically rename the current tag you have focused. +-- {{{ Dynamic tagging +-- +-- Add a new tag +function util.prompt_add_tag(mypromptbox) + awful.prompt.run({prompt="New tag name: "}, mypromptbox[mouse.screen].widget, + function(text) + if text:len() > 0 then + props = { selected = true } + tag = awful.tag.add(new_name, props) + tag.name = text + tag:emit_signal("property::name") + end + end) +end + +-- Rename current tag function util.prompt_rename_tag(mypromptbox) local tag = awful.tag.selected(mouse.screen) awful.prompt.run({prompt="Rename tag: "}, mypromptbox[mouse.screen].widget, @@ -175,12 +190,20 @@ function util.prompt_rename_tag(mypromptbox) end) end +-- Delete current tag (if empty) +-- Any rule set on the tag shall be broken +function util.remove_tag() + local tag = awful.tag.selected(mouse.screen) + local prevtag = awful.tag.gettags(mouse.screen)[awful.tag.getidx(tag) - 1] + awful.tag.delete(tag, prevtag) +end +-- +-- }}} + -- On the fly useless gaps change function util.useless_gaps_resize(thatmuch) - if beautiful.useless_gap_width then - beautiful.useless_gap_width = tonumber(beautiful.useless_gap_width) + thatmuch - awful.layout.arrange(mouse.screen) - end + beautiful.useless_gap_width = tonumber(beautiful.useless_gap_width) + thatmuch + awful.layout.arrange(mouse.screen) end return setmetatable(util, { __index = wrequire }) diff --git a/widgets/borderbox.lua b/widgets/borderbox.lua index 150c1c3..c251ea8 100644 --- a/widgets/borderbox.lua +++ b/widgets/borderbox.lua @@ -15,7 +15,7 @@ local setmetatable = setmetatable local borderbox = {} local function worker(relbox, s, args) - local where = args.position or 'above' + local where = args.position or 'top' local color = args.color or '#FFFFFF' local size = args.size or 1 local box = nil @@ -24,14 +24,14 @@ local function worker(relbox, s, args) bg = color } - if where == 'above' + if where == 'top' then wiboxarg.width = relbox.width wiboxarg.height = size box = wibox(wiboxarg) box.x = relbox.x box.y = relbox.y - size - elseif where == 'below' + elseif where == 'bottom' then wiboxarg.width = relbox.width wiboxarg.height = size diff --git a/wiki b/wiki new file mode 160000 index 0000000..1368b03 --- /dev/null +++ b/wiki @@ -0,0 +1 @@ +Subproject commit 1368b031aa5d4b29a30c8f24b4bebde2f9d08ece From f92b3ac0c9dec3a6c8d046ce3d97add99a3a1e5e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 12:06:19 -0700 Subject: [PATCH 282/572] Updated Utilities (markdown) --- Utilities.md | 112 +++++++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/Utilities.md b/Utilities.md index 3797f3c..3ab9245 100644 --- a/Utilities.md +++ b/Utilities.md @@ -43,6 +43,64 @@ they all take one argument, which is the text to markup, except `fg.color` and ` markup.fg.color(text, color) markup.bg.color(text, color) +dynamic tagging +--------------- + +That is: + +- create a new tag; +- rename current tag; +- delete current tag. + +If you delete a tag, any rule set on it shall be broken, so be careful. + +Use it with key bindings like these: + + awful.key({ modkey, "Shift" }, "n", function () lain.util.create_tag(mypromptbox) end), + awful.key({ modkey, "Shift" }, "r", function () lain.util.rename_tag(mypromptbox) end), + awful.key({ modkey, "Shift" }, "d", function () lain.util.delete_tag() end), + +useless\_gaps\_resize +--------------------- + +Changes `beautiful.useless_gaps_width` on the fly. + +The function takes an integer argument, being the amount of pixel to add/remove to gaps. + +You could use it with these keybindings: + + -- On the fly useless gaps change + awful.key({ altkey, "Control" }, "+", function () lain.util.useless_gaps_resize(1) end), + awful.key({ altkey, "Control" }, "-", function () lain.util.useless_gaps_resize(-1) end), + +where `altkey=Mod1`, or you could use it like this: + + mywidget:buttons(awful.util.table.join ( + awful.button({}, 4, function() lain.util.useless_gaps_resize(-1) end), + awful.button({}, 5, function() lain.util.useless_gaps_resize(1) end) + end) + )) + +so when hovering the mouse over `mywidget`, you can adjust useless gaps size by scrolling with the mouse wheel. + +tag\_view\_nonempty +------------------- + +This function lets you jump to the next/previous non-empty tag. +It takes two arguments: + +* `direction`: `1` for next non-empty tag, `-1` for previous. +* `sc`: Screen which the taglist is in. Default is `mouse.screen` or `1`. This + argument is optional. + +You can use it with key bindings like these: + + -- Non-empty tag browsing + awful.key({ altkey }, "Left", function () lain.util.tag_view_nonempty(-1) end), + awful.key({ altkey }, "Right", function () lain.util.tag_view_nonempty(1) end), + +where `altkey = "Mod1"`. + menu\_clients\_current\_tags ---------------------------- @@ -97,56 +155,4 @@ This requires to define additional colors in your `theme.lua`. For example: theme.border_normal_highprio = "#A03333" theme.border_focus_lowprio = "#3333FF" - theme.border_normal_lowprio = "#333366" - -tag\_view\_nonempty -------------------- - -This function lets you jump to the next/previous non-empty tag. -It takes two arguments: - -* `direction`: `1` for next non-empty tag, `-1` for previous. -* `sc`: Screen which the taglist is in. Default is `mouse.screen` or `1`. This - argument is optional. - -You can use it with key bindings like these: - - -- Non-empty tag browsing - awful.key({ altkey }, "Left", function () lain.util.tag_view_nonempty(-1) end), - awful.key({ altkey }, "Right", function () lain.util.tag_view_nonempty(1) end), - -where `altkey = "Mod1"`. - -prompt\_rename\_tag -------------------- - -This function enables you to dynamically rename the current tag you have focused. - -You can use it with a key binding like this: - - awful.key({ modkey, "Shift" }, "r", function () lain.util.prompt_rename_tag(mypromptbox) end) - -Credits goes to [minism](https://bbs.archlinux.org/viewtopic.php?pid=1315135#p1315135). - -useless\_gaps\_resize ---------------------- - -Changes `beautiful.useless_gaps_width` on the fly. - -The function takes an integer argument, being the amount of pixel to add/remove to gaps. - -You could use it with these keybindings: - - -- On the fly useless gaps change - awful.key({ altkey, "Control" }, "+", function () lain.util.useless_gaps_resize(1) end), - awful.key({ altkey, "Control" }, "-", function () lain.util.useless_gaps_resize(-1) end), - -where `altkey=Mod1`, or you could use it like this: - - mywidget:buttons(awful.util.table.join ( - awful.button({}, 4, function() lain.util.useless_gaps_resize(-1) end), - awful.button({}, 5, function() lain.util.useless_gaps_resize(1) end) - end) - )) - -so when hovering the mouse over `mywidget`, you can adjust useless gaps size by scrolling with the mouse wheel. \ No newline at end of file + theme.border_normal_lowprio = "#333366" \ No newline at end of file From 622a3581dd721476cecce4f267737b8034d2b676 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 19 Sep 2013 21:07:17 +0200 Subject: [PATCH 283/572] wiki updated --- util/init.lua | 5 +++-- wiki | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/util/init.lua b/util/init.lua index 73818b6..06db0d4 100644 --- a/util/init.lua +++ b/util/init.lua @@ -166,7 +166,7 @@ end -- {{{ Dynamic tagging -- -- Add a new tag -function util.prompt_add_tag(mypromptbox) +function util.add_tag(mypromptbox) awful.prompt.run({prompt="New tag name: "}, mypromptbox[mouse.screen].widget, function(text) if text:len() > 0 then @@ -179,7 +179,8 @@ function util.prompt_add_tag(mypromptbox) end -- Rename current tag -function util.prompt_rename_tag(mypromptbox) +-- @author: minism +function util.rename_tag(mypromptbox) local tag = awful.tag.selected(mouse.screen) awful.prompt.run({prompt="Rename tag: "}, mypromptbox[mouse.screen].widget, function(text) diff --git a/wiki b/wiki index 1368b03..f92b3ac 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 1368b031aa5d4b29a30c8f24b4bebde2f9d08ece +Subproject commit f92b3ac0c9dec3a6c8d046ce3d97add99a3a1e5e From c2c9b33024fc905f900ca861189bb3ef5f7d7468 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 16:49:45 -0700 Subject: [PATCH 285/572] Updated alsabar (markdown) --- alsabar.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/alsabar.md b/alsabar.md index f694c69..39506b0 100644 --- a/alsabar.md +++ b/alsabar.md @@ -13,6 +13,7 @@ The function takes a table as optional argument, which can contain: Variable | Meaning | Type | Default --- | --- | --- | --- `timeout` | Refresh timeout seconds | int | 4 +`settings` | User settings | function | empty function `width` | Bar width | int | 63 `height` | Bar height | int | 1 `ticks` | Set bar ticks on | boolean | true @@ -42,6 +43,8 @@ Variable | Meaning | Type | Default It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height. +`settings` can use the integer `alsa_level` and `alsa_status`. + ### output table Variable | Meaning | Type From 36a0534651749f23bf9786ba47912b498938c103 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 16:54:37 -0700 Subject: [PATCH 286/572] Updated alsabar (markdown) --- alsabar.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/alsabar.md b/alsabar.md index 39506b0..31a7b23 100644 --- a/alsabar.md +++ b/alsabar.md @@ -43,8 +43,12 @@ Variable | Meaning | Type | Default It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height. -`settings` can use the integer `alsa_level` and `alsa_status`. +`settings` can use the following variables: +Variable | Meaning | Type | Values +--- | --- | --- | --- +`volume_now.level` | Self explained | int | 0-100 +`volume_now.status` | Device status | string | "on", "off" ### output table Variable | Meaning | Type From aacefc209e47c019f69a8234770e79b7c08e0b29 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 20 Sep 2013 03:01:04 +0200 Subject: [PATCH 287/572] alsabar: added user settings function --- widgets/alsabar.lua | 6 ++++++ widgets/sysload.lua | 2 +- wiki | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index d8f1731..b0bf150 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -92,6 +92,7 @@ end local function worker(args) local args = args or {} local timeout = args.timeout or 4 + local settings = args.settings or function() end local width = args.width or 63 local height = args.heigth or 1 local ticks = args.ticks or true @@ -142,6 +143,11 @@ local function worker(args) alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu)) alsabar.bar:set_color(alsabar.colors.unmute) end + + volume_now = {} + volume_now.level = tonumber(volu) + volume_now.status = mute + settings() end newtimer("alsabar", timeout, alsabar.update) diff --git a/widgets/sysload.lua b/widgets/sysload.lua index 015573c..2abac33 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -11,7 +11,7 @@ local newtimer = require("lain.helpers").newtimer local wibox = require("wibox") -local io = io +local io = { open = io.open } local string = { format = string.format, match = string.match } diff --git a/wiki b/wiki index f92b3ac..36a0534 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit f92b3ac0c9dec3a6c8d046ce3d97add99a3a1e5e +Subproject commit 36a0534651749f23bf9786ba47912b498938c103 From 968b2eafa31c35c3a95dfc727c7403c972c4bb69 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 20 Sep 2013 03:04:17 +0200 Subject: [PATCH 288/572] alsabar: notifications.color change --- widgets/alsabar.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index b0bf150..90d3a0d 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -43,7 +43,7 @@ local alsabar = { font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), font_size = "11", - color = beautiful.fg_focus, + color = beautiful.fg_normal, bar_size = 18 }, From 476e9f57bb66cec635ce61170a57f49299e6c715 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 19 Sep 2013 18:05:20 -0700 Subject: [PATCH 289/572] Updated alsabar (markdown) --- alsabar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsabar.md b/alsabar.md index 31a7b23..fa5f209 100644 --- a/alsabar.md +++ b/alsabar.md @@ -38,7 +38,7 @@ Variable | Meaning | Type | Default --- | --- | --- | --- `font` | Notifications font | string | The one defined in `beautiful.font` `font_size` | Notifications font size | string | "11" -`color` | Notifications color | string | `beautiful.fg_focus` +`color` | Notifications color | string | `beautiful.fg_normal` `bar_size` | Wibox height | int | 18 It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height. From 27a388f374e06b637138b088c956d81fe740a325 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 20 Sep 2013 03:05:50 +0200 Subject: [PATCH 290/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index 36a0534..476e9f5 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 36a0534651749f23bf9786ba47912b498938c103 +Subproject commit 476e9f57bb66cec635ce61170a57f49299e6c715 From 2c6a5794b20e757292825450557750df595d1868 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 21 Sep 2013 21:59:05 +0200 Subject: [PATCH 291/572] yawn: new icon --- widgets/imap.lua | 2 +- widgets/yawn/icons/HeavyRain.png | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 120000 widgets/yawn/icons/HeavyRain.png diff --git a/widgets/imap.lua b/widgets/imap.lua index 605c1c4..b3f281d 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -62,7 +62,7 @@ local function worker(args) f:close() t, mailcount = string.gsub(ws, "%d", "") - t = nil -- because it's useless + t = nil mailcount = tonumber(mailcount) widget = imap.widget diff --git a/widgets/yawn/icons/HeavyRain.png b/widgets/yawn/icons/HeavyRain.png new file mode 120000 index 0000000..ace2a94 --- /dev/null +++ b/widgets/yawn/icons/HeavyRain.png @@ -0,0 +1 @@ +Showers.png \ No newline at end of file From b5c1b95be234987449a79ab0767d215a54e325ac Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 24 Sep 2013 09:15:38 -0700 Subject: [PATCH 292/572] Updated Home (markdown) --- Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Home.md b/Home.md index a7bee69..e8271f3 100644 --- a/Home.md +++ b/Home.md @@ -6,7 +6,7 @@ Package | Requested by | Reason of choice --- | --- | --- alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) | / curl | widgets accessing network resources | LuaSocket is not a core library. LuaSSL is out of date. -imagemagick | [mpd](https://github.com/copycat-killer/lain/wiki/mpd) | Cairo doesn't do high quality filtering. +imagemagick | album arts in [mpd](https://github.com/copycat-killer/lain/wiki/mpd) notifications | Cairo doesn't do high quality filtering. ### Installation From 9c0b22dc88439954fc899a731e840fd98f25ddf9 Mon Sep 17 00:00:00 2001 From: Jan Xie Date: Wed, 25 Sep 2013 09:35:38 +0800 Subject: [PATCH 293/572] create task widget template, based on calendar widget --- widgets/task.lua | 126 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 widgets/task.lua diff --git a/widgets/task.lua b/widgets/task.lua new file mode 100644 index 0000000..31499f1 --- /dev/null +++ b/widgets/task.lua @@ -0,0 +1,126 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Jan Xie + +--]] + +local icons_dir = require("lain.helpers").icons_dir + +local awful = require("awful") +local beautiful = require("beautiful") +local naughty = require("naughty") + +local io = io +local os = { date = os.date } +local tonumber = tonumber + +local setmetatable = setmetatable + +-- task notification +-- lain.widgets.task +local task = {} +local task_notification = nil + +function task:hide() + if task_notification ~= nil then + naughty.destroy(task_notification) + task_notification = nil + end +end + +function task:show(t_out, inc_offset) + task:hide() + + local offs = inc_offset or 0 + local tims = t_out or 0 + local f, c_text + local today = tonumber(os.date('%d')) + local init_t = '/usr/bin/cal | sed -r -e "s/(^| )( ' + -- let's take font only, font size is set in task table + local font = beautiful.font:sub(beautiful.font:find(""), + beautiful.font:find(" ")) + + if offs == 0 + then -- current month showing, today highlighted + if today >= 10 + then + init_t = '/usr/bin/cal | sed -r -e "s/(^| )(' + end + + task.offset = 0 + task.notify_icon = task.icons .. today .. ".png" + + -- bg and fg inverted to highlight today + f = io.popen( init_t .. today .. + ')($| )/\\1\\2<\\/span><\\/b>\\3/"' ) + + else -- no current month showing, no day to highlight + local month = tonumber(os.date('%m')) + local year = tonumber(os.date('%Y')) + + task.offset = task.offset + offs + month = month + task.offset + + if month > 12 then + month = month % 12 + year = year + 1 + if month <= 0 then + month = 12 + end + elseif month < 1 then + month = month + 12 + year = year - 1 + if month <= 0 then + month = 1 + end + end + + task.notify_icon = nil + + f = io.popen('/usr/bin/cal ' .. month .. ' ' .. year) + end + + + --c_text = "" + --.. f:read() .. "\n\n" + --.. f:read() .. "\n" + --.. f:read("*all"):gsub("\n*$", "") + --.. "" + c_text = "hello tasks!" + f:close() + + task_notification = naughty.notify({ text = c_text, + icon = task.notify_icon, + position = task.position, + fg = task.fg, + bg = task.bg, + timeout = tims }) +end + +function task:attach(widget, args) + local args = args or {} + task.icons = args.icons or icons_dir .. "cal/white/" + task.font_size = tonumber(args.font_size) or 12 + 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.offset = 0 + task.notify_icon = nil + + widget:connect_signal("mouse::enter", function () task:show() end) + widget:connect_signal("mouse::leave", function () task:hide() end) + widget:buttons(awful.util.table.join( awful.button({ }, 1, function () + task:show(0, -1) end), + awful.button({ }, 3, function () + task:show(0, 1) end) )) +end + +return setmetatable(task, { __call = function(_, ...) return create(...) end }) From 1a31a15405c5f125f526f6d1554ea12b55940018 Mon Sep 17 00:00:00 2001 From: Jan Xie Date: Wed, 25 Sep 2013 10:03:11 +0800 Subject: [PATCH 294/572] clean a little bit --- widgets/task.lua | 70 +++++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 49 deletions(-) diff --git a/widgets/task.lua b/widgets/task.lua index 31499f1..cf84cbc 100644 --- a/widgets/task.lua +++ b/widgets/task.lua @@ -30,10 +30,9 @@ function task:hide() end end -function task:show(t_out, inc_offset) +function task:show(t_out) task:hide() - local offs = inc_offset or 0 local tims = t_out or 0 local f, c_text local today = tonumber(os.date('%d')) @@ -42,50 +41,23 @@ function task:show(t_out, inc_offset) local font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")) - if offs == 0 - then -- current month showing, today highlighted - if today >= 10 - then - init_t = '/usr/bin/cal | sed -r -e "s/(^| )(' - end - - task.offset = 0 - task.notify_icon = task.icons .. today .. ".png" - - -- bg and fg inverted to highlight today - f = io.popen( init_t .. today .. - ')($| )/\\1\\2<\\/span><\\/b>\\3/"' ) - - else -- no current month showing, no day to highlight - local month = tonumber(os.date('%m')) - local year = tonumber(os.date('%Y')) - - task.offset = task.offset + offs - month = month + task.offset - - if month > 12 then - month = month % 12 - year = year + 1 - if month <= 0 then - month = 12 - end - elseif month < 1 then - month = month + 12 - year = year - 1 - if month <= 0 then - month = 1 - end - end - - task.notify_icon = nil - - f = io.popen('/usr/bin/cal ' .. month .. ' ' .. year) + if today >= 10 + then + init_t = '/usr/bin/cal | sed -r -e "s/(^| )(' end + task.offset = 0 + --task.notify_icon = task.icons .. today .. ".png" + + -- bg and fg inverted to highlight today + --f = io.popen( init_t .. today .. + --')($| )/\\1\\2<\\/span><\\/b>\\3/"' ) + + --c_text = "" @@ -94,13 +66,13 @@ function task:show(t_out, inc_offset) --.. f:read("*all"):gsub("\n*$", "") --.. "" c_text = "hello tasks!" - f:close() + --f:close() task_notification = naughty.notify({ text = c_text, - icon = task.notify_icon, - position = task.position, - fg = task.fg, - bg = task.bg, + --icon = task.notify_icon, + --position = task.position, + --fg = task.fg, + --bg = task.bg, timeout = tims }) end From 37b61468dd884e5bc8a4bcee51f63cfbab425544 Mon Sep 17 00:00:00 2001 From: Jan Xie Date: Wed, 25 Sep 2013 10:24:54 +0800 Subject: [PATCH 295/572] show next tasks --- widgets/task.lua | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/widgets/task.lua b/widgets/task.lua index cf84cbc..b313e8d 100644 --- a/widgets/task.lua +++ b/widgets/task.lua @@ -13,7 +13,6 @@ local beautiful = require("beautiful") local naughty = require("naughty") local io = io -local os = { date = os.date } local tonumber = tonumber local setmetatable = setmetatable @@ -35,38 +34,19 @@ function task:show(t_out) local tims = t_out or 0 local f, c_text - local today = tonumber(os.date('%d')) - local init_t = '/usr/bin/cal | sed -r -e "s/(^| )( ' -- let's take font only, font size is set in task table local font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")) - if today >= 10 - then - init_t = '/usr/bin/cal | sed -r -e "s/(^| )(' - end - task.offset = 0 --task.notify_icon = task.icons .. today .. ".png" - -- bg and fg inverted to highlight today - --f = io.popen( init_t .. today .. - --')($| )/\\1\\2<\\/span><\\/b>\\3/"' ) - - - - --c_text = "" - --.. f:read() .. "\n\n" - --.. f:read() .. "\n" - --.. f:read("*all"):gsub("\n*$", "") - --.. "" - c_text = "hello tasks!" - --f:close() + f = io.popen('task') + c_text = "[Next Tasks]\n" + .. f:read("*all") .. "\n" + .. "" + f:close() task_notification = naughty.notify({ text = c_text, --icon = task.notify_icon, From f143ba3231276a21911dd49450033a3f2d182ea3 Mon Sep 17 00:00:00 2001 From: Jan Xie Date: Wed, 25 Sep 2013 10:51:01 +0800 Subject: [PATCH 296/572] add icon for task widget --- icons/taskwarrior.png | Bin 0 -> 1280 bytes widgets/task.lua | 18 ++++++++---------- 2 files changed, 8 insertions(+), 10 deletions(-) create mode 100644 icons/taskwarrior.png diff --git a/icons/taskwarrior.png b/icons/taskwarrior.png new file mode 100644 index 0000000000000000000000000000000000000000..171af60260bcba14cafa18f1530935841d6f38b4 GIT binary patch literal 1280 zcmV+b1^@bqP)WFU8GbZ8()Nlj2>E@cM*00d-7L_t(I%XL&;XcSiz z{?5HSJIN&3S=Oz)M7Bw65K{%U4~A|^9$L~C3|OS-Tg`(%eJCg<_$GmZ(ozdrXi<{~ zp;%1BK&VY(=;D5Q!bZVbY1sWB9R!Zs;c@c8jUUkz{QIf z(b3TX03ZP9?d`>Z0|x*Au~_Vw<2avIRaHfp*>GJKm6eqyGb5kRt3n83X3aFsIU&UF z+qZB31po#H2C!$(9?+RHXK?iBQ2;g9i`Ng9i_e8HSMwhr=J0iD7wp`L~ggksS>U4SIcj zy*@rZ-keUSuP`&18LFzjQ(Ig6xoz8<+uPfB5fLaBiv=9V>DP6=LDRI2%nTwzI-S1T z)YSAL-h`N#m>BZ={U4VKr_<@X%pBUXWy?mfxVX4W)3mVH>s?>|PBSwz-{Sw_CK8G7 z%VRZ7+bo25e&^1eLn0Uqe(AbyR!Ui2o^|r%$-mzsh)5*z*fh=6yQ-@GbUHl~3WW~Q zZECkHD-a9@FElnbIxC5Cc6RnxpU+n#gm`U~R8@`Gww(|} z#BXbD+qP{T$z<|J0K#=$Yi@3?tGT)PE7x_a*Tyn45fKZ^vfOMoOXVaHA(2Q-u84LK zk;BaKojZ5_1OSF%Oso|&P4kJAa)U5Ua}$>?8naky#ba!_r*R-^H&SWwv$8jE)xid6PdpDIz^$6E>Z`!u~ z+%(NuA_6l*)3myW4ZUYb{=kaE;`#IEKbW4Lj_JC7SV}1Xz_Ki(P$(2$zI=Hc z0GB>POifLVEG#Tc)YaAPRTRZnwgBMudf~b*Gc!pk%ilWl^y$;SU@%D6u3h_D(==ON zy?Pb>{r$YKu+Z1u-o7`R%@!QTnfG`+>*XtyS|%wagb=W8JD161?q@QY*_xV~^ySN! zzd3Q@gn8q}jaTbyaBvX2ckf0|Pfx|xty}l{{r>NY#p0tvq3}Y}wA$+G>M#H{3}ZHz z%Pm$`R&F4o(DL%~@v*V7>z$pQ_R!D}+S=McZ<%TD=;-M2Kp@b;%swH+la<}sNJR6= qWb#5Z8vPkS@$A{NICA93YT|!n4[Next Tasks]\n" + .. task.font_size+2 .. "'>Tasks next\n" + .. "" .. f:read("*all") .. "\n" .. "" f:close() task_notification = naughty.notify({ text = c_text, - --icon = task.notify_icon, - --position = task.position, - --fg = task.fg, - --bg = task.bg, + icon = task.notify_icon, + position = task.position, + fg = task.fg, + bg = task.bg, timeout = tims }) end function task:attach(widget, args) local args = args or {} - task.icons = args.icons or icons_dir .. "cal/white/" task.font_size = tonumber(args.font_size) or 12 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.offset = 0 - task.notify_icon = nil + task.notify_icon = icons_dir .. "taskwarrior.png" widget:connect_signal("mouse::enter", function () task:show() end) widget:connect_signal("mouse::leave", function () task:hide() end) From a45d345b60cd0268def1dde24d7618b6ab1b8070 Mon Sep 17 00:00:00 2001 From: Jan Xie Date: Wed, 25 Sep 2013 11:20:13 +0800 Subject: [PATCH 297/572] add prompt function for task widget --- widgets/task.lua | 66 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/widgets/task.lua b/widgets/task.lua index fdf439a..f2b49f4 100644 --- a/widgets/task.lua +++ b/widgets/task.lua @@ -29,20 +29,15 @@ function task:hide() end end -function task:show(t_out) +function task:show() task:hide() - local tims = t_out or 0 local f, c_text - -- let's take font only, font size is set in task table - local font = beautiful.font:sub(beautiful.font:find(""), - beautiful.font:find(" ")) - f = io.popen('task') - c_text = "Tasks next\n" - .. "" .. f:read("*all") .. "\n" .. "" @@ -53,15 +48,68 @@ function task:show(t_out) position = task.position, fg = task.fg, bg = task.bg, - timeout = tims }) + timeout = task.timeout }) +end + +function task:add(...) + local f = io.popen("task add " .. ...) + c_text = "" + .. f:read("*all") .. "\n" + .. "" + + naughty.notify({ text = c_text, + icon = task.notify_icon, + position = task.position, + fg = task.fg, + bg = task.bg, + timeout = task.timeout}) +end + +function task:prompt_add() + awful.prompt.run( { prompt = "Add task: " }, + mypromptbox[mouse.screen].widget, + function (...) + task:add(...) + end, + nil, + awful.util.getdir("cache") .. "/history_task_add") +end + +function task:execute(...) + local f = io.popen("task " .. ...) + c_text = "" + .. f:read("*all") .. "\n" + .. "" + + naughty.notify({ text = c_text, + icon = task.notify_icon, + position = task.position, + fg = task.fg, + bg = task.bg, + timeout = task.timeout}) +end + +function task:prompt() + awful.prompt.run( { prompt = "Task: " }, + mypromptbox[mouse.screen].widget, + function (...) + task:execute(...) + end, + nil, + awful.util.getdir("cache") .. "/history_task") end 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.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.notify_icon = icons_dir .. "taskwarrior.png" From 8622f98860287bb756b083fe73ebb9ff3a586e64 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 25 Sep 2013 03:30:55 -0700 Subject: [PATCH 298/572] Updated Home (markdown) --- Home.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Home.md b/Home.md index e8271f3..6cdae23 100644 --- a/Home.md +++ b/Home.md @@ -1,6 +1,7 @@ Welcome to the Lain wiki! -### Dependencies +Dependencies +------------------ Package | Requested by | Reason of choice --- | --- | --- @@ -8,17 +9,25 @@ alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar] curl | widgets accessing network resources | LuaSocket is not a core library. LuaSSL is out of date. imagemagick | album arts in [mpd](https://github.com/copycat-killer/lain/wiki/mpd) notifications | Cairo doesn't do high quality filtering. -### Installation +Installation +--------------- -Simply clone this repository into your Awesome directory: +### Arch Linux + +[AUR package](https://aur.archlinux.org/packages/lain/) + +### Other distributions git clone https://github.com/copycat-killer/lain.git ~/.config/awesome/lain -then include it in your `rc.lua`: +Usage +-------- + +First, include it in your `rc.lua`: local lain = require("lain") -### Submodules +Then check out the submodules you want: - [Layouts](https://github.com/copycat-killer/lain/wiki/Layouts) - [Widgets](https://github.com/copycat-killer/lain/wiki/Widgets) From 2882ef92c6b9454ca153f729003fa2374fb7ef55 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 25 Sep 2013 06:05:56 -0700 Subject: [PATCH 299/572] Created task (markdown) --- task.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 task.md diff --git a/task.md b/task.md new file mode 100644 index 0000000..8c68ac0 --- /dev/null +++ b/task.md @@ -0,0 +1,30 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + +Attaches a [taskwarrior](http://taskwarrior.org/projects/show/taskwarrior) notification to a widget, and lets to add/search tasks from the promptbox. + + lain.widgets.contrib.task:attach(widget, args) + +`args` is an optional table which can contain: + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`font_size` | Calendar font size | int | 12 +`fg` | Calendar foreground color | string | `beautiful.fg_normal` +`bg` | Calendar background color | string | `beautiful.bg_normal` +`position` | Calendar position | string | "top_right" +`timeout` | Notification timeout seconds | int | 7 + +`position` possible values are defined [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify). + +Notification will show the output of `task` command. + +You can call the notification with a key binding like this: + + awful.key({ modkey, altkey }, "t", lain.widgets.task.show), + +where ``altkey = "Mod1"``. + +And you can prompt to add/search a task with key bindings like these: + + awful.key({ modkey, }, "t", lain.widgets.contrib.task.prompt_add), + awful.key({ modkey, "Shift" }, "t", lain.widgets.contrib.task.prompt_search), \ No newline at end of file From fbe1673b191642a54c673c4f96947dab707dfdfe Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 25 Sep 2013 06:06:11 -0700 Subject: [PATCH 300/572] Updated Widgets (markdown) --- Widgets.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Widgets.md b/Widgets.md index 981e4e1..b534f15 100644 --- a/Widgets.md +++ b/Widgets.md @@ -1,3 +1,6 @@ +General usage +------------- + Every widget is output by a `function`. For some widgets, `function` returns a `wibox.widget.textbox`, for others a table to be used for notification and update purposes. @@ -23,7 +26,8 @@ Here follows an example: If you want to see more complex applications, check [awesome-copycats](https://github.com/copycat-killer/awesome-copycats). ---- +Index +----- - [alsa](https://github.com/copycat-killer/lain/wiki/alsa) - [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) @@ -39,4 +43,9 @@ If you want to see more complex applications, check [awesome-copycats](https://g - [net](https://github.com/copycat-killer/lain/wiki/net) - [sysload](https://github.com/copycat-killer/lain/wiki/sysload) - [temp](https://github.com/copycat-killer/lain/wiki/temp) -- [yawn](https://github.com/copycat-killer/lain/wiki/yawn) \ No newline at end of file +- [yawn](https://github.com/copycat-killer/lain/wiki/yawn) + +User contributed widgets +------------------------ + +- [task](https://github.com/copycat-killer/lain/wiki/task) \ No newline at end of file From 91217d6bad68401ee926ca79d3ef917525507321 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 25 Sep 2013 06:06:43 -0700 Subject: [PATCH 301/572] Updated Widgets (markdown) --- Widgets.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Widgets.md b/Widgets.md index b534f15..acb7075 100644 --- a/Widgets.md +++ b/Widgets.md @@ -45,7 +45,7 @@ Index - [temp](https://github.com/copycat-killer/lain/wiki/temp) - [yawn](https://github.com/copycat-killer/lain/wiki/yawn) -User contributed widgets ------------------------- +User contributed +---------------- - [task](https://github.com/copycat-killer/lain/wiki/task) \ No newline at end of file From e4c5d756c98141bfeeeda7a75be33b87ccca6a26 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 25 Sep 2013 15:08:11 +0200 Subject: [PATCH 302/572] contrib section started\! --- README.rst | 17 +++++ icons/taskwarrior.png | Bin 1280 -> 0 bytes icons/taskwarrior/task.png | Bin 0 -> 1212 bytes icons/taskwarrior/tasksmall.png | Bin 0 -> 941 bytes widgets/calendar.lua | 1 - widgets/contrib/init.lua | 20 +++++ widgets/contrib/task.lua | 131 ++++++++++++++++++++++++++++++++ widgets/mpd.lua | 2 +- widgets/task.lua | 124 ------------------------------ wiki | 2 +- 10 files changed, 170 insertions(+), 127 deletions(-) delete mode 100644 icons/taskwarrior.png create mode 100644 icons/taskwarrior/task.png create mode 100755 icons/taskwarrior/tasksmall.png create mode 100644 widgets/contrib/init.lua create mode 100644 widgets/contrib/task.lua delete mode 100644 widgets/task.lua diff --git a/README.rst b/README.rst index 779428d..66d846c 100644 --- a/README.rst +++ b/README.rst @@ -19,6 +19,23 @@ in order to improve Awesome_ usability and configurability. Read the wiki_ for all the info. +Contributions +------------- + +Any contribution is welcome! Feel free to make a pull request. + +Just make sure that: + +- Your code fits with the general style of the module. In particular, you should use the same indentation pattern that the code uses, and also avoid adding space at the ends of lines. + +- Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions or using `lain.helpers`. If something is unclear, and you can't write it in such a way that it will be clear, explain it with a comment. + +- You test your changes before submitting to make sure that not only your code work, but have not broken other parts of the module too! + +- You update `wiki` submodule with a thorough section. + +Contributed widgets have to be put it in `lain/widget/contrib`. + Screenshots ----------- diff --git a/icons/taskwarrior.png b/icons/taskwarrior.png deleted file mode 100644 index 171af60260bcba14cafa18f1530935841d6f38b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1280 zcmV+b1^@bqP)WFU8GbZ8()Nlj2>E@cM*00d-7L_t(I%XL&;XcSiz z{?5HSJIN&3S=Oz)M7Bw65K{%U4~A|^9$L~C3|OS-Tg`(%eJCg<_$GmZ(ozdrXi<{~ zp;%1BK&VY(=;D5Q!bZVbY1sWB9R!Zs;c@c8jUUkz{QIf z(b3TX03ZP9?d`>Z0|x*Au~_Vw<2avIRaHfp*>GJKm6eqyGb5kRt3n83X3aFsIU&UF z+qZB31po#H2C!$(9?+RHXK?iBQ2;g9i`Ng9i_e8HSMwhr=J0iD7wp`L~ggksS>U4SIcj zy*@rZ-keUSuP`&18LFzjQ(Ig6xoz8<+uPfB5fLaBiv=9V>DP6=LDRI2%nTwzI-S1T z)YSAL-h`N#m>BZ={U4VKr_<@X%pBUXWy?mfxVX4W)3mVH>s?>|PBSwz-{Sw_CK8G7 z%VRZ7+bo25e&^1eLn0Uqe(AbyR!Ui2o^|r%$-mzsh)5*z*fh=6yQ-@GbUHl~3WW~Q zZECkHD-a9@FElnbIxC5Cc6RnxpU+n#gm`U~R8@`Gww(|} z#BXbD+qP{T$z<|J0K#=$Yi@3?tGT)PE7x_a*Tyn45fKZ^vfOMoOXVaHA(2Q-u84LK zk;BaKojZ5_1OSF%Oso|&P4kJAa)U5Ua}$>?8naky#ba!_r*R-^H&SWwv$8jE)xid6PdpDIz^$6E>Z`!u~ z+%(NuA_6l*)3myW4ZUYb{=kaE;`#IEKbW4Lj_JC7SV}1Xz_Ki(P$(2$zI=Hc z0GB>POifLVEG#Tc)YaAPRTRZnwgBMudf~b*Gc!pk%ilWl^y$;SU@%D6u3h_D(==ON zy?Pb>{r$YKu+Z1u-o7`R%@!QTnfG`+>*XtyS|%wagb=W8JD161?q@QY*_xV~^ySN! zzd3Q@gn8q}jaTbyaBvX2ckf0|Pfx|xty}l{{r>NY#p0tvq3}Y}wA$+G>M#H{3}ZHz z%Pm$`R&F4o(DL%~@v*V7>z$pQ_R!D}+S=McZ<%TD=;-M2Kp@b;%swH+la<}sNJR6= qWb#5Z8vPkS@$A{NICA93YT|!n4PfQfvSK1W8Fm zK~#9!?VL?k8%Gew|J9CJ+S=62!VAF(Bu=2=0!CaQA146k0ud*$IYAz|05TT{oPf~@ zA{JT9^dd4#ExNMM$QF9U8M=FVdU&dx^pLvvsj9lVs(OH(JSo)1qD7&HN?{Dhfe7^h z91`Kp)}P&rU`{0W0OiKu&ot%y#erGDkPjj>egZ-*5y1nIOpT$BO+%s(K#1^(2qT~0 zD}q}QOwyEZItNB;Jpu4r!|X4N!6Z$25j~iq&^;ndeOt+QWCkq9%fIA}O0PX?&w9Z{zYQR6ZD3zwX(7K$iOPV5BBnf}qh6iA%6b@a0Z38d{cL4J3 zf4VI7G11yuWSS(&BDlo>Uu(Tr>(|Uob**g!*xT(h4H0etnHxj%rvUu7K3X<#o-ilV zR=`yC-haNm<5p{R`;q?M2loE*p^Ni&ou<5~%)FAdRRTR2cmijY5zc-mYhCD<%yH@2od7aJ#5%yaL^9&`d zT}x~IK`Gp!esj;M3FxauD;6KCH6rFRomDprZ^U98T;mkL|0aV<;mo$S?9%sg24l=# zW81NF09CTz8ko47ZqyzaKn`NXV%vrE1cnCjT8w?C)U~PKLyNL= zuce5r1y`aDfN5b21V9JC&?qRF%6A7Huo$bUDizvy+e!4E?@rcWMCha|U_@{n1Wa|X zd*2l>L>N`6MYCX(k}*0a&(&GIbT_iq**3;x=$>Q&EC!>;O}6NR?}NzmYC2Y6(vLGj(mr8+H#Y`Z3^REm zxHblv>rGm34YxGqMUrp^;G#t?=SjlH(OoZISr4B9auPD`tk#kfW}bM*Awb_&ee zdXj`QV{nAkEUvZN7=xoE;p3(UAeGkTt588QP5FkI_l?1k2(D{>>5>B4O(ZlrW$ z&7$Dazd+Z;l~#rLV^K;#3pUO>m!Mz_lDw~rnTez3$Gn+4Ne*0?_wIY=e($^Yob#Qb zBs46>$oY9;V8FkGj=k;nkdO8Q6Q?GW6*YX;CP zUIg?LiH`v;+?N0n00arI0RG~=`+3y>=6T$iWw--iONrNBNyQQG!@aTqvy!as%`*Hg zVROlK`ho0jp4-u`F&N{2JwRm!ULou*+~gkym!CXYw{q8 zAprXUi~!gTU@L%WKo0;u0B~2rqY&I=y;Pnhd8OvB<*!pqBhPc0<>ReBzt}L#$IVP- z-YF3ztV$e<(Jr)e?qam_62~M=x233CIj^-+$4h2*f_!ttx$VWuz@~bo%AWual7NKy zZlxJD<;BBN-^&>D;T7cBs8o4P>dU4&{!v!|k_ydNB>JUnB1SvE1h~s2Zq-!GJ2GQa zay2tG^=xCM(l@iz{M;M{wrz8HQ+GHD;MS5_rYJrSAv{gSV5QP~Xoc^1e|CPkN6Bm` zaV6n_baIOTG@4i}=)071i^MmHgM?ovZpRNL188QW=z^KWZ<7EdaYjN?JyYxO^g|MW z5>Iu5L5Zgm0mS#Ue3^#Dx*yj4b`CHEcT>`_MtsRmn4(Hs< zRq5)ycV~;D*aP74;" .. f:read() .. "\n\n" diff --git a/widgets/contrib/init.lua b/widgets/contrib/init.lua new file mode 100644 index 0000000..81321c6 --- /dev/null +++ b/widgets/contrib/init.lua @@ -0,0 +1,20 @@ + +--[[ + + Lain + Layouts, widgets and utilities for Awesome WM + + User contributed widgets section + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local wrequire = require("lain.helpers").wrequire +local setmetatable = setmetatable + +local widgets = { _NAME = "lain.widgets.contrib" } + +return setmetatable(widgets, { __index = wrequire }) diff --git a/widgets/contrib/task.lua b/widgets/contrib/task.lua new file mode 100644 index 0000000..88baa71 --- /dev/null +++ b/widgets/contrib/task.lua @@ -0,0 +1,131 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2013, Jan Xie + +--]] + +local icons_dir = require("lain.helpers").icons_dir + +local awful = require("awful") +local beautiful = require("beautiful") +local naughty = require("naughty") + +local io = io +local string = { len = string.len } +local tonumber = tonumber + +local setmetatable = setmetatable + +-- Taskwarrior notification +-- lain.widgets.task +local task = {} + +local task_notification = nil + +function task:hide() + if task_notification ~= nil then + naughty.destroy(task_notification) + task_notification = nil + end +end + +function task:show() + task:hide() + + local f, c_text + + f = io.popen('task') + c_text = "" + .. f:read("*all"):gsub("\n*$", "") + .. "" + f:close() + + task_notification = naughty.notify({ title = "[task next]", + text = c_text, + icon = task.notify_icon, + position = task.position, + fg = task.fg, + bg = task.bg, + timeout = task.timeout }) +end + +function task:prompt_add() + awful.prompt.run({ prompt = "Add task: " }, + mypromptbox[mouse.screen].widget, + function (...) + local f = io.popen("task add " .. ...) + c_text = "\n" + .. f:read("*all") + .. "" + + naughty.notify({ + text = c_text, + icon = task.notify_icon, + position = task.position, + fg = task.fg, + bg = task.bg, + timeout = task.timeout + }) + end, + nil, + awful.util.getdir("cache") .. "/history_task_add") +end + +function task:prompt_search() + awful.prompt.run({ prompt = "Search task: " }, + mypromptbox[mouse.screen].widget, + function (...) + local f = io.popen("task " .. ...) + c_text = f:read("*all") + f:close() + + if string.len(c_text) == 0 + then + c_text = "No results found." + else + c_text = "" + .. c_text .. "\n" + .. "" + end + + naughty.notify({ + text = c_text, + icon = task.notify_icon, + position = task.position, + fg = task.fg, + bg = task.bg, + timeout = task.timeout + }) + end, + nil, + awful.util.getdir("cache") .. "/history_task") +end + +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.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.notify_icon = icons_dir .. "/taskwarrior/task.png" + task.notify_icon_small = icons_dir .. "/taskwarrior/tasksmall.png" + + widget:connect_signal("mouse::enter", function () task:show() end) + widget:connect_signal("mouse::leave", function () task:hide() end) +end + +return setmetatable(task, { __call = function(_, ...) return create(...) end }) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 41233cd..e3ed50d 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -28,7 +28,7 @@ local mpd = {} local function worker(args) local args = args or {} local timeout = args.timeout or 2 - local password = args.password or "" + local password = args.password or "\"\"" local host = args.host or "127.0.0.1" local port = args.port or "6600" local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" diff --git a/widgets/task.lua b/widgets/task.lua deleted file mode 100644 index f2b49f4..0000000 --- a/widgets/task.lua +++ /dev/null @@ -1,124 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Jan Xie - ---]] - -local icons_dir = require("lain.helpers").icons_dir - -local awful = require("awful") -local beautiful = require("beautiful") -local naughty = require("naughty") - -local io = io -local tonumber = tonumber - -local setmetatable = setmetatable - --- task notification --- lain.widgets.task -local task = {} -local task_notification = nil - -function task:hide() - if task_notification ~= nil then - naughty.destroy(task_notification) - task_notification = nil - end -end - -function task:show() - task:hide() - - local f, c_text - - f = io.popen('task') - c_text = "Tasks next\n" - .. "" - .. f:read("*all") .. "\n" - .. "" - f:close() - - task_notification = naughty.notify({ text = c_text, - icon = task.notify_icon, - position = task.position, - fg = task.fg, - bg = task.bg, - timeout = task.timeout }) -end - -function task:add(...) - local f = io.popen("task add " .. ...) - c_text = "" - .. f:read("*all") .. "\n" - .. "" - - naughty.notify({ text = c_text, - icon = task.notify_icon, - position = task.position, - fg = task.fg, - bg = task.bg, - timeout = task.timeout}) -end - -function task:prompt_add() - awful.prompt.run( { prompt = "Add task: " }, - mypromptbox[mouse.screen].widget, - function (...) - task:add(...) - end, - nil, - awful.util.getdir("cache") .. "/history_task_add") -end - -function task:execute(...) - local f = io.popen("task " .. ...) - c_text = "" - .. f:read("*all") .. "\n" - .. "" - - naughty.notify({ text = c_text, - icon = task.notify_icon, - position = task.position, - fg = task.fg, - bg = task.bg, - timeout = task.timeout}) -end - -function task:prompt() - awful.prompt.run( { prompt = "Task: " }, - mypromptbox[mouse.screen].widget, - function (...) - task:execute(...) - end, - nil, - awful.util.getdir("cache") .. "/history_task") -end - -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.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.notify_icon = icons_dir .. "taskwarrior.png" - - widget:connect_signal("mouse::enter", function () task:show() end) - widget:connect_signal("mouse::leave", function () task:hide() end) - widget:buttons(awful.util.table.join( awful.button({ }, 1, function () - task:show(0, -1) end), - awful.button({ }, 3, function () - task:show(0, 1) end) )) -end - -return setmetatable(task, { __call = function(_, ...) return create(...) end }) diff --git a/wiki b/wiki index 476e9f5..91217d6 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 476e9f57bb66cec635ce61170a57f49299e6c715 +Subproject commit 91217d6bad68401ee926ca79d3ef917525507321 From 807599b7446b4866a8a2030b9a0fb4fd4f9ce754 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 25 Sep 2013 06:10:33 -0700 Subject: [PATCH 303/572] Updated Widgets (markdown) --- Widgets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index acb7075..ebe0810 100644 --- a/Widgets.md +++ b/Widgets.md @@ -45,7 +45,7 @@ Index - [temp](https://github.com/copycat-killer/lain/wiki/temp) - [yawn](https://github.com/copycat-killer/lain/wiki/yawn) -User contributed +Users contributed ---------------- - [task](https://github.com/copycat-killer/lain/wiki/task) \ No newline at end of file From 97f0b4bb88f657b6a87a69e6b0e08e5af0b62a1a Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 25 Sep 2013 15:21:21 +0200 Subject: [PATCH 304/572] contrib section started\! --- widgets/contrib/task.lua | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/widgets/contrib/task.lua b/widgets/contrib/task.lua index 88baa71..a6c9f31 100644 --- a/widgets/contrib/task.lua +++ b/widgets/contrib/task.lua @@ -38,11 +38,11 @@ function task:show() local f, c_text f = io.popen('task') - c_text = "" .. f:read("*all"):gsub("\n*$", "") - .. "" + .. "" f:close() task_notification = naughty.notify({ title = "[task next]", @@ -59,19 +59,20 @@ function task:prompt_add() mypromptbox[mouse.screen].widget, function (...) local f = io.popen("task add " .. ...) - c_text = "\n" .. f:read("*all") - .. "" + .. "" + f:close() naughty.notify({ - text = c_text, - icon = task.notify_icon, + text = c_text, + icon = task.notify_icon, position = task.position, - fg = task.fg, - bg = task.bg, - timeout = task.timeout + fg = task.fg, + bg = task.bg, + timeout = task.timeout }) end, nil, @@ -83,27 +84,28 @@ function task:prompt_search() mypromptbox[mouse.screen].widget, function (...) local f = io.popen("task " .. ...) - c_text = f:read("*all") + c_text = f:read("*all"):gsub(" \n*$", "") f:close() if string.len(c_text) == 0 then c_text = "No results found." else - c_text = "" - .. c_text .. "\n" - .. "" + .. c_text + .. "" end naughty.notify({ - text = c_text, - icon = task.notify_icon, + title = "[task next " .. ... .. "]", + text = c_text, + icon = task.notify_icon, position = task.position, - fg = task.fg, - bg = task.bg, - timeout = task.timeout + fg = task.fg, + bg = task.bg, + timeout = task.timeout }) end, nil, From 7a642c036d29566ac8c8c4356b6ad71c0cd315ed Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 25 Sep 2013 15:22:41 +0200 Subject: [PATCH 305/572] readme updated --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 66d846c..7ee0025 100644 --- a/README.rst +++ b/README.rst @@ -28,7 +28,7 @@ Just make sure that: - Your code fits with the general style of the module. In particular, you should use the same indentation pattern that the code uses, and also avoid adding space at the ends of lines. -- Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions or using `lain.helpers`. If something is unclear, and you can't write it in such a way that it will be clear, explain it with a comment. +- Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions or using ``lain.helpers``. If something is unclear, and you can't write it in such a way that it will be clear, explain it with a comment. - You test your changes before submitting to make sure that not only your code work, but have not broken other parts of the module too! From ece950240fd5ad695b2b95801e582f7f12721718 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 25 Sep 2013 15:23:50 +0200 Subject: [PATCH 306/572] readme updated --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 7ee0025..7f63942 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,7 @@ Just make sure that: - Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions or using ``lain.helpers``. If something is unclear, and you can't write it in such a way that it will be clear, explain it with a comment. -- You test your changes before submitting to make sure that not only your code work, but have not broken other parts of the module too! +- You test your changes before submitting to make sure that not only your code works, but have not broken other parts of the module too! - You update `wiki` submodule with a thorough section. From 4989386869f9a8ddffe5c6c9f3e4681b1218bc71 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 25 Sep 2013 15:24:18 +0200 Subject: [PATCH 307/572] readme updated --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 7f63942..f7e5611 100644 --- a/README.rst +++ b/README.rst @@ -32,9 +32,9 @@ Just make sure that: - You test your changes before submitting to make sure that not only your code works, but have not broken other parts of the module too! -- You update `wiki` submodule with a thorough section. +- You update ``wiki`` submodule with a thorough section. -Contributed widgets have to be put it in `lain/widget/contrib`. +Contributed widgets have to be put it in ``lain/widget/contrib``. Screenshots ----------- From 5e58ee5f2a63d494d9ce50ade32ea9ed9406e333 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 25 Sep 2013 16:36:19 +0200 Subject: [PATCH 308/572] bat: compatibility fix --- widgets/bat.lua | 33 +++++++++++++++------------------ wiki | 2 +- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 7b14a9a..0bb5eff 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -38,27 +38,24 @@ local function worker(args) watt = "N/A" } - local present = first_line("/sys/class/power_supply/" - .. battery - .. "/present") + local bstr = "/sys/class/power_supply/" .. battery + + local present = first_line(bstr .. "/present") if present == "1" then - local rate = first_line("/sys/class/power_supply/" - .. battery .. - "/power_now") - local ratev = first_line("/sys/class/power_supply/" - .. battery .. - "/voltage_now") - local rem = first_line("/sys/class/power_supply/" - .. battery .. - "/energy_now") - local tot = first_line("/sys/class/power_supply/" - .. battery .. - "/energy_full") - bat_now.status = first_line("/sys/class/power_supply/" - .. battery .. - "/status") + local rate = first_line(bstr .. "/power_now") or + first_line(bstr .. "/current_now") + + local ratev = first_line(bstr .. "/voltage_now") + + local rem = first_line(bstr .. "/energy_now") or + first_line(bstr .. "/charge_now") + + local tot = first_line(bstr .. "/energy_full") or + first_line(bstr .. "/charge_full") + + bat_now.status = first_line(bstr .. "/status") or "N/A" local time_rat = 0 if bat_now.status == "Charging" diff --git a/wiki b/wiki index 91217d6..807599b 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 91217d6bad68401ee926ca79d3ef917525507321 +Subproject commit 807599b7446b4866a8a2030b9a0fb4fd4f9ce754 From fcc07d942c009d5089f8d32a61e1f2bafaf2b137 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 25 Sep 2013 08:02:02 -0700 Subject: [PATCH 309/572] Updated Home (markdown) --- Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Home.md b/Home.md index 6cdae23..9ba8362 100644 --- a/Home.md +++ b/Home.md @@ -23,7 +23,7 @@ Installation Usage -------- -First, include it in your `rc.lua`: +First, include it into your `rc.lua`: local lain = require("lain") From fac2ee9c1122e4497ff467a3cdc9289a00fffded Mon Sep 17 00:00:00 2001 From: Conor Heine Date: Thu, 26 Sep 2013 01:20:29 -0400 Subject: [PATCH 310/572] added basic tp_smapi battery widget for thinkpads with hover-expandable status --- widgets/contrib/tpbat/init.lua | 152 ++++++++++++++++++++++++++++++++ widgets/contrib/tpbat/smapi.lua | 99 +++++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 widgets/contrib/tpbat/init.lua create mode 100644 widgets/contrib/tpbat/smapi.lua diff --git a/widgets/contrib/tpbat/init.lua b/widgets/contrib/tpbat/init.lua new file mode 100644 index 0000000..673b66c --- /dev/null +++ b/widgets/contrib/tpbat/init.lua @@ -0,0 +1,152 @@ +--[[ + tpbat.lua + Battery status widget for ThinkPad laptops that use SMAPI + lain.widgets.contrib.tpbat + + More on tp_smapi: http://www.thinkwiki.org/wiki/Tp_smapi + + Licensed under GNU General Public License v2 + * (c) 2013, Conor Heine + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + +--]] + +local newtimer = require("lain.helpers").newtimer +local first_line = require("lain.helpers").first_line +local beautiful = require("beautiful") +local naughty = require("naughty") +local wibox = require("wibox") +local smapi = require("lain.widgets.contrib.tpbat.smapi") -- Ugly :( + +local string = { format = string.format } +local math = { floor = math.floor } +local tostring = tostring +local setmetatable = setmetatable + +-- ThinkPad SMAPI-enabled battery info widget +local tpbat = { } + +local tpbat_notification = nil + +function tpbat:hide() + if tpbat_notification ~= nil then + naughty.destroy(tpbat_notification) + tpbat_notification = nil + end +end + +function tpbat:show(t_out) + tpbat:hide() + + local bat = self.bat + if bat == nil or not bat:installed() then return end + + local mfgr = bat:get('manufacturer') or "no_mfgr" + local model = bat:get('model') or "no_model" + local chem = bat:get('chemistry') or "no_chem" + local status = bat:get('state') or "nil" + local time = bat:remaining_time() + local msg = "\t" + + if status ~= "idle" and status ~= "nil" then + if time == "N/A" then + msg = "...Calculating time remaining..." + else + msg = time .. (status == "charging" and " until charged" or " remaining") + end + else + msg = "On AC Power" + end + + local str = string.format("%s : %s %s (%s)\n", bat.name, mfgr, model, chem) + str = str .. string.format("\n%s \t\t\t %s", status:upper(), msg) + + tpbat_notification = naughty.notify({ + preset = { fg = beautiful.fg_normal }, + text = str, + timeout = t_out + }) +end + +function tpbat.register(args) + local args = args or {} + local timeout = args.timeout or 30 + local battery = args.battery or "BAT0" + local settings = args.settings or function() end + + tpbat.bat = smapi:battery(battery) -- Create a new battery + local bat = tpbat.bat + + tpbat.widget = wibox.widget.textbox('') + + if bat:get('state') == nil then + local n = naughty.notify({ + title = "SMAPI Battery Warning: Unable to read battery state!", + text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths.", + position = "top_right", + timeout = 15, + fg="#202020", + bg="#cdcdcd", + ontop = true + }) + end + + function update() + bat_now = { + status = "Not present", + perc = "N/A", + time = "N/A", + watt = "N/A" + } + + if bat:installed() + then + bat_now.status = bat:status() + bat_now.perc = bat:percent() + bat_now.time = bat:remaining_time() + -- bat_now.watt = string.format("%.2fW", (VOLTS * AMPS) / 1e12) + + -- notifications for low and critical states + if bat_now.perc <= 5 + then + tpbat.id = naughty.notify({ + text = "shutdown imminent", + title = "battery nearly exhausted", + position = "top_right", + timeout = 15, + fg="#000000", + bg="#ffffff", + ontop = true, + replaces_id = tpbat.id + }).id + elseif bat_now.perc <= 15 + then + tpbat.id = naughty.notify({ + text = "plug the cable", + title = "battery low", + position = "top_right", + timeout = 15, + fg="#202020", + bg="#cdcdcd", + ontop = true, + replaces_id = tpbat.id + }).id + end + + bat_now.perc = tostring(bat_now.perc) + end + + widget = tpbat.widget -- 'widget' needed in rc.lua (following convention) + settings() + end + + newtimer("tpbat", timeout, update) + + widget:connect_signal('mouse::enter', function () tpbat:show(0) end) + widget:connect_signal('mouse::leave', function () tpbat:hide() end) + + return tpbat.widget +end + +return setmetatable(tpbat, { __call = function(_, ...) return tpbat.register(...) end }) diff --git a/widgets/contrib/tpbat/smapi.lua b/widgets/contrib/tpbat/smapi.lua new file mode 100644 index 0000000..6024fa9 --- /dev/null +++ b/widgets/contrib/tpbat/smapi.lua @@ -0,0 +1,99 @@ +--[[ + smapi.lua + Interface with thinkpad battery information + + Licensed under GNU General Public License v2 + * (c) 2013, Conor Heine + +--]] + +local first_line = require("lain.helpers").first_line + +local string = { format = string.format } +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?) +local readable = { + barcoding = true, + charging_max_current = true, + charging_max_voltage = true, + chemistry = true, + current_avg = true, + current_now = true, + cycle_count = true, + design_capacity = true, + design_voltage = true, + dump = true, + first_use_date = true, + force_discharge = false, + group0_voltage = true, + group1_voltage = true, + group2_voltage = true, + group3_voltage = true, + inhibit_charge_minutes = false, + installed = true, + last_full_capacity = true, + manufacture_date = true, + manufacturer = true, + model = true, + power_avg = true, + power_now = true, + remaining_capacity = true, + remaining_charging_time = true, + remaining_percent = true, + remaining_percent_error = true, + remaining_running_time = true, + remaining_running_time_now = true, + serial = true, + start_charge_thresh = false, + state = true, + stop_charge_thresh = false, + temperature = true, + voltage = true, +} + +function smapi:battery(name) + local bat = {} + + bat.name = name + bat.path = apipath .. "/" .. name + + function bat:get(item) + return self.path ~= nil and readable[item] and first_line(self.path .. "/" .. item) or nil + end + + function bat:installed() + return self:get("installed") == "1" + end + + function bat:status() + return self:get('state') + end + + -- Remaining time can either be time until battery dies or time until charging completes + function bat:remaining_time() + local time_val = bat_now.status == 'discharging' and 'remaining_running_time' or 'remaining_charging_time' + local mins_left = self:get(time_val) + + if mins_left:find("^%d+") == nil then + return "N/A" + end + + local hrs = mins_left / 60 + local min = mins_left % 60 + return string.format("%02d:%02d", hrs, min) + end + + function bat:percent() + return tonumber(self:get("remaining_percent")) + end + + return setmetatable(bat, {__metatable = false, __newindex = false}) +end + +return smapi \ No newline at end of file From af7558fb163bc37923bd62a88abc5213f3bb5a29 Mon Sep 17 00:00:00 2001 From: Conor Heine Date: Thu, 26 Sep 2013 01:30:39 -0400 Subject: [PATCH 311/572] fixed formatting to follow contrib style --- widgets/contrib/tpbat/init.lua | 24 +++--- widgets/contrib/tpbat/smapi.lua | 130 ++++++++++++++++---------------- 2 files changed, 77 insertions(+), 77 deletions(-) diff --git a/widgets/contrib/tpbat/init.lua b/widgets/contrib/tpbat/init.lua index 673b66c..d46697a 100644 --- a/widgets/contrib/tpbat/init.lua +++ b/widgets/contrib/tpbat/init.lua @@ -65,7 +65,7 @@ function tpbat:show(t_out) tpbat_notification = naughty.notify({ preset = { fg = beautiful.fg_normal }, text = str, - timeout = t_out + timeout = t_out }) end @@ -80,17 +80,17 @@ function tpbat.register(args) tpbat.widget = wibox.widget.textbox('') - if bat:get('state') == nil then - local n = naughty.notify({ - title = "SMAPI Battery Warning: Unable to read battery state!", - text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths.", - position = "top_right", - timeout = 15, - fg="#202020", - bg="#cdcdcd", - ontop = true - }) - end + if bat:get('state') == nil then + local n = naughty.notify({ + title = "SMAPI Battery Warning: Unable to read battery state!", + text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths.", + position = "top_right", + timeout = 15, + fg="#202020", + bg="#cdcdcd", + ontop = true + }) + end function update() bat_now = { diff --git a/widgets/contrib/tpbat/smapi.lua b/widgets/contrib/tpbat/smapi.lua index 6024fa9..3291cc2 100644 --- a/widgets/contrib/tpbat/smapi.lua +++ b/widgets/contrib/tpbat/smapi.lua @@ -19,81 +19,81 @@ local apipath = "/sys/devices/platform/smapi" -- Most are readable values, but some can be written to (not implemented, yet?) local readable = { - barcoding = true, - charging_max_current = true, - charging_max_voltage = true, - chemistry = true, - current_avg = true, - current_now = true, - cycle_count = true, - design_capacity = true, - design_voltage = true, - dump = true, - first_use_date = true, - force_discharge = false, - group0_voltage = true, - group1_voltage = true, - group2_voltage = true, - group3_voltage = true, - inhibit_charge_minutes = false, - installed = true, - last_full_capacity = true, - manufacture_date = true, - manufacturer = true, - model = true, - power_avg = true, - power_now = true, - remaining_capacity = true, - remaining_charging_time = true, - remaining_percent = true, - remaining_percent_error = true, - remaining_running_time = true, - remaining_running_time_now = true, - serial = true, - start_charge_thresh = false, - state = true, - stop_charge_thresh = false, - temperature = true, - voltage = true, + barcoding = true, + charging_max_current = true, + charging_max_voltage = true, + chemistry = true, + current_avg = true, + current_now = true, + cycle_count = true, + design_capacity = true, + design_voltage = true, + dump = true, + first_use_date = true, + force_discharge = false, + group0_voltage = true, + group1_voltage = true, + group2_voltage = true, + group3_voltage = true, + inhibit_charge_minutes = false, + installed = true, + last_full_capacity = true, + manufacture_date = true, + manufacturer = true, + model = true, + power_avg = true, + power_now = true, + remaining_capacity = true, + remaining_charging_time = true, + remaining_percent = true, + remaining_percent_error = true, + remaining_running_time = true, + remaining_running_time_now = true, + serial = true, + start_charge_thresh = false, + state = true, + stop_charge_thresh = false, + temperature = true, + voltage = true, } function smapi:battery(name) - local bat = {} + local bat = {} - bat.name = name - bat.path = apipath .. "/" .. name - - function bat:get(item) - return self.path ~= nil and readable[item] and first_line(self.path .. "/" .. item) or nil - end + bat.name = name + bat.path = apipath .. "/" .. name + + function bat:get(item) + return self.path ~= nil and readable[item] and first_line(self.path .. "/" .. item) or nil + end - function bat:installed() - return self:get("installed") == "1" - end + function bat:installed() + return self:get("installed") == "1" + end - function bat:status() - return self:get('state') - end + function bat:status() + return self:get('state') + end - -- Remaining time can either be time until battery dies or time until charging completes - function bat:remaining_time() - local time_val = bat_now.status == 'discharging' and 'remaining_running_time' or 'remaining_charging_time' - local mins_left = self:get(time_val) + -- Remaining time can either be time until battery dies or time until charging completes + function bat:remaining_time() + local time_val = bat_now.status == 'discharging' and 'remaining_running_time' or 'remaining_charging_time' + local mins_left = self:get(time_val) - if mins_left:find("^%d+") == nil then - return "N/A" - end - - local hrs = mins_left / 60 - local min = mins_left % 60 - return string.format("%02d:%02d", hrs, min) - end + if mins_left:find("^%d+") == nil then + return "N/A" + end + + local hrs = mins_left / 60 + local min = mins_left % 60 + return string.format("%02d:%02d", hrs, min) + end - function bat:percent() - return tonumber(self:get("remaining_percent")) - end + function bat:percent() + return tonumber(self:get("remaining_percent")) + end - return setmetatable(bat, {__metatable = false, __newindex = false}) + return setmetatable(bat, {__metatable = false, __newindex = false}) end return smapi \ No newline at end of file From 64ab76a6b70caea7a3d764b0ef613d17f9f0fe35 Mon Sep 17 00:00:00 2001 From: Conor Heine Date: Thu, 26 Sep 2013 01:49:37 -0400 Subject: [PATCH 312/572] fixed brace style to match project's --- widgets/contrib/tpbat/init.lua | 12 ++++++++---- widgets/contrib/tpbat/smapi.lua | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/widgets/contrib/tpbat/init.lua b/widgets/contrib/tpbat/init.lua index d46697a..1bb6a9b 100644 --- a/widgets/contrib/tpbat/init.lua +++ b/widgets/contrib/tpbat/init.lua @@ -30,7 +30,8 @@ local tpbat = { } local tpbat_notification = nil function tpbat:hide() - if tpbat_notification ~= nil then + if tpbat_notification ~= nil + then naughty.destroy(tpbat_notification) tpbat_notification = nil end @@ -49,8 +50,10 @@ function tpbat:show(t_out) local time = bat:remaining_time() local msg = "\t" - if status ~= "idle" and status ~= "nil" then - if time == "N/A" then + if status ~= "idle" and status ~= "nil" + then + if time == "N/A" + then msg = "...Calculating time remaining..." else msg = time .. (status == "charging" and " until charged" or " remaining") @@ -80,7 +83,8 @@ function tpbat.register(args) tpbat.widget = wibox.widget.textbox('') - if bat:get('state') == nil then + if bat:get('state') == nil + then local n = naughty.notify({ title = "SMAPI Battery Warning: Unable to read battery state!", text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths.", diff --git a/widgets/contrib/tpbat/smapi.lua b/widgets/contrib/tpbat/smapi.lua index 3291cc2..59b916b 100644 --- a/widgets/contrib/tpbat/smapi.lua +++ b/widgets/contrib/tpbat/smapi.lua @@ -80,8 +80,9 @@ function smapi:battery(name) local time_val = bat_now.status == 'discharging' and 'remaining_running_time' or 'remaining_charging_time' local mins_left = self:get(time_val) - if mins_left:find("^%d+") == nil then - return "N/A" + if mins_left:find("^%d+") == nil + then + return "N/A" end local hrs = mins_left / 60 From 22fa9400bc8a1e65c644c692294ba6e5f253b147 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 26 Sep 2013 11:35:59 +0200 Subject: [PATCH 313/572] thinkpad bat widget integrated --- widgets/contrib/init.lua | 2 +- widgets/contrib/tpbat/init.lua | 55 +++++++++++--------- widgets/contrib/tpbat/smapi.lua | 92 +++++++++++++++++---------------- 3 files changed, 79 insertions(+), 70 deletions(-) diff --git a/widgets/contrib/init.lua b/widgets/contrib/init.lua index 81321c6..9a9fa63 100644 --- a/widgets/contrib/init.lua +++ b/widgets/contrib/init.lua @@ -4,7 +4,7 @@ Lain Layouts, widgets and utilities for Awesome WM - User contributed widgets section + Users contributed widgets section Licensed under GNU General Public License v2 * (c) 2013, Luke Bonham diff --git a/widgets/contrib/tpbat/init.lua b/widgets/contrib/tpbat/init.lua index 1bb6a9b..206fd38 100644 --- a/widgets/contrib/tpbat/init.lua +++ b/widgets/contrib/tpbat/init.lua @@ -1,36 +1,41 @@ + --[[ - tpbat.lua - Battery status widget for ThinkPad laptops that use SMAPI - lain.widgets.contrib.tpbat - - More on tp_smapi: http://www.thinkwiki.org/wiki/Tp_smapi - - Licensed under GNU General Public License v2 - * (c) 2013, Conor Heine - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann - + + tpbat.lua + Battery status widget for ThinkPad laptops that use SMAPI + lain.widgets.contrib.tpbat + + More on tp_smapi: http://www.thinkwiki.org/wiki/Tp_smapi + + Licensed under GNU General Public License v2 + * (c) 2013, Conor Heine + * (c) 2013, Luke Bonham + * (c) 2010-2012, Peter Hofmann + --]] +local debug = { getinfo = debug.getinfo } local newtimer = require("lain.helpers").newtimer local first_line = require("lain.helpers").first_line local beautiful = require("beautiful") local naughty = require("naughty") local wibox = require("wibox") -local smapi = require("lain.widgets.contrib.tpbat.smapi") -- Ugly :( local string = { format = string.format } local math = { floor = math.floor } local tostring = tostring local setmetatable = setmetatable --- ThinkPad SMAPI-enabled battery info widget -local tpbat = { } +package.path = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .. "?.lua;" .. package.path +local smapi = require("smapi") +-- ThinkPad SMAPI-enabled battery info widget +-- lain.widgets.contrib.tpbat +local tpbat = { } local tpbat_notification = nil function tpbat:hide() - if tpbat_notification ~= nil + if tpbat_notification ~= nil then naughty.destroy(tpbat_notification) tpbat_notification = nil @@ -39,8 +44,10 @@ end function tpbat:show(t_out) tpbat:hide() - - local bat = self.bat + + local bat = self.bat + local t_out = t_out or 0 + if bat == nil or not bat:installed() then return end local mfgr = bat:get('manufacturer') or "no_mfgr" @@ -50,9 +57,9 @@ function tpbat:show(t_out) local time = bat:remaining_time() local msg = "\t" - if status ~= "idle" and status ~= "nil" + if status ~= "idle" and status ~= "nil" then - if time == "N/A" + if time == "N/A" then msg = "...Calculating time remaining..." else @@ -63,7 +70,7 @@ function tpbat:show(t_out) end local str = string.format("%s : %s %s (%s)\n", bat.name, mfgr, model, chem) - str = str .. string.format("\n%s \t\t\t %s", status:upper(), msg) + .. string.format("\n%s \t\t\t %s", status:upper(), msg) tpbat_notification = naughty.notify({ preset = { fg = beautiful.fg_normal }, @@ -80,10 +87,10 @@ function tpbat.register(args) tpbat.bat = smapi:battery(battery) -- Create a new battery local bat = tpbat.bat - + tpbat.widget = wibox.widget.textbox('') - if bat:get('state') == nil + if bat:get('state') == nil then local n = naughty.notify({ title = "SMAPI Battery Warning: Unable to read battery state!", @@ -141,13 +148,13 @@ function tpbat.register(args) bat_now.perc = tostring(bat_now.perc) end - widget = tpbat.widget -- 'widget' needed in rc.lua (following convention) + widget = tpbat.widget settings() end newtimer("tpbat", timeout, update) - widget:connect_signal('mouse::enter', function () tpbat:show(0) end) + widget:connect_signal('mouse::enter', function () tpbat:show() end) widget:connect_signal('mouse::leave', function () tpbat:hide() end) return tpbat.widget diff --git a/widgets/contrib/tpbat/smapi.lua b/widgets/contrib/tpbat/smapi.lua index 59b916b..862d4cd 100644 --- a/widgets/contrib/tpbat/smapi.lua +++ b/widgets/contrib/tpbat/smapi.lua @@ -1,9 +1,11 @@ ---[[ - smapi.lua - Interface with thinkpad battery information +--[[ + + smapi.lua + Interface with thinkpad battery information + Licensed under GNU General Public License v2 - * (c) 2013, Conor Heine + * (c) 2013, Conor Heine --]] @@ -19,42 +21,42 @@ local apipath = "/sys/devices/platform/smapi" -- Most are readable values, but some can be written to (not implemented, yet?) local readable = { - barcoding = true, - charging_max_current = true, - charging_max_voltage = true, - chemistry = true, - current_avg = true, - current_now = true, - cycle_count = true, - design_capacity = true, - design_voltage = true, - dump = true, - first_use_date = true, - force_discharge = false, - group0_voltage = true, - group1_voltage = true, - group2_voltage = true, - group3_voltage = true, - inhibit_charge_minutes = false, - installed = true, - last_full_capacity = true, - manufacture_date = true, - manufacturer = true, - model = true, - power_avg = true, - power_now = true, - remaining_capacity = true, - remaining_charging_time = true, - remaining_percent = true, - remaining_percent_error = true, - remaining_running_time = true, + barcoding = true, + charging_max_current = true, + charging_max_voltage = true, + chemistry = true, + current_avg = true, + current_now = true, + cycle_count = true, + design_capacity = true, + design_voltage = true, + dump = true, + first_use_date = true, + force_discharge = false, + group0_voltage = true, + group1_voltage = true, + group2_voltage = true, + group3_voltage = true, + inhibit_charge_minutes = false, + installed = true, + last_full_capacity = true, + manufacture_date = true, + manufacturer = true, + model = true, + power_avg = true, + power_now = true, + remaining_capacity = true, + remaining_charging_time = true, + remaining_percent = true, + remaining_percent_error = true, + remaining_running_time = true, remaining_running_time_now = true, - serial = true, - start_charge_thresh = false, - state = true, - stop_charge_thresh = false, - temperature = true, - voltage = true, + serial = true, + start_charge_thresh = false, + state = true, + stop_charge_thresh = false, + temperature = true, + voltage = true, } function smapi:battery(name) @@ -62,7 +64,7 @@ function smapi:battery(name) bat.name = name bat.path = apipath .. "/" .. name - + function bat:get(item) return self.path ~= nil and readable[item] and first_line(self.path .. "/" .. item) or nil end @@ -80,11 +82,11 @@ function smapi:battery(name) local time_val = bat_now.status == 'discharging' and 'remaining_running_time' or 'remaining_charging_time' local mins_left = self:get(time_val) - if mins_left:find("^%d+") == nil - then - return "N/A" + if mins_left:find("^%d+") == nil + then + return "N/A" end - + local hrs = mins_left / 60 local min = mins_left % 60 return string.format("%02d:%02d", hrs, min) @@ -97,4 +99,4 @@ function smapi:battery(name) return setmetatable(bat, {__metatable = false, __newindex = false}) end -return smapi \ No newline at end of file +return smapi From 42fea93dc41c0afb25a30094bea2469a1a9b63db Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 26 Sep 2013 02:51:15 -0700 Subject: [PATCH 314/572] Created tpbat (markdown) --- tpbat.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tpbat.md diff --git a/tpbat.md b/tpbat.md new file mode 100644 index 0000000..38c30c9 --- /dev/null +++ b/tpbat.md @@ -0,0 +1,5 @@ +A battery widget that works with Lenovo ThinkPad laptops using [tp_smapi](http://www.thinkwiki.org/wiki/Tp_smapi. Includes hover notification with more details. + + tpbatwidget = lain.widgets.contrib.tpbat() + +Configuration is identical to [main bat widget's](https://github.com/copycat-killer/lain/wiki/bat). \ No newline at end of file From ae62d5d942b01709b05f32ac3738c692e563e3c8 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 26 Sep 2013 02:51:28 -0700 Subject: [PATCH 315/572] Updated tpbat (markdown) --- tpbat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tpbat.md b/tpbat.md index 38c30c9..cb21a6b 100644 --- a/tpbat.md +++ b/tpbat.md @@ -1,4 +1,4 @@ -A battery widget that works with Lenovo ThinkPad laptops using [tp_smapi](http://www.thinkwiki.org/wiki/Tp_smapi. Includes hover notification with more details. +A battery widget that works with Lenovo ThinkPad laptops using [tp_smapi](http://www.thinkwiki.org/wiki/Tp_smapi). Includes hover notification with more details. tpbatwidget = lain.widgets.contrib.tpbat() From 5d51493ae8c83abcdc9f0087b9b3dbb3cf83b1b5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 26 Sep 2013 02:51:39 -0700 Subject: [PATCH 316/572] Updated tpbat (markdown) --- tpbat.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tpbat.md b/tpbat.md index cb21a6b..7eebc79 100644 --- a/tpbat.md +++ b/tpbat.md @@ -1,4 +1,6 @@ -A battery widget that works with Lenovo ThinkPad laptops using [tp_smapi](http://www.thinkwiki.org/wiki/Tp_smapi). Includes hover notification with more details. +A battery widget that works with Lenovo ThinkPad laptops using [tp_smapi](http://www.thinkwiki.org/wiki/Tp_smapi). + +Includes hover notification with more details. tpbatwidget = lain.widgets.contrib.tpbat() From 9ff45882695f6e0d02d0f5c68a11c7d09d0909cf Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 26 Sep 2013 02:51:59 -0700 Subject: [PATCH 317/572] Updated tpbat (markdown) --- tpbat.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tpbat.md b/tpbat.md index 7eebc79..3d0b0e8 100644 --- a/tpbat.md +++ b/tpbat.md @@ -1,3 +1,5 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + A battery widget that works with Lenovo ThinkPad laptops using [tp_smapi](http://www.thinkwiki.org/wiki/Tp_smapi). Includes hover notification with more details. From 4a81ad47d143e42e8b9de92ebb8cd963d5bd6515 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 26 Sep 2013 02:52:49 -0700 Subject: [PATCH 318/572] Updated Widgets (markdown) --- Widgets.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index ebe0810..8a8945b 100644 --- a/Widgets.md +++ b/Widgets.md @@ -48,4 +48,5 @@ Index Users contributed ---------------- -- [task](https://github.com/copycat-killer/lain/wiki/task) \ No newline at end of file +- [task](https://github.com/copycat-killer/lain/wiki/task) +- [tpbat](https://github.com/copycat-killer/lain/wiki/tpbat) \ No newline at end of file From ab17a2d4960dbabe512cd0dc8cbaea28cc0c41ad Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 26 Sep 2013 11:54:30 +0200 Subject: [PATCH 319/572] tpbat wiki entry added --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index 807599b..4a81ad4 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 807599b7446b4866a8a2030b9a0fb4fd4f9ce754 +Subproject commit 4a81ad47d143e42e8b9de92ebb8cd963d5bd6515 From 82dd3effca595595b8b6183992d70a31afb20f03 Mon Sep 17 00:00:00 2001 From: Conor Heine Date: Thu, 26 Sep 2013 16:01:09 -0400 Subject: [PATCH 320/572] silence warnings when battery is <15%, but charging --- widgets/bat.lua | 49 ++++++++++++++++--------------- widgets/contrib/tpbat/init.lua | 53 ++++++++++++++++++---------------- 2 files changed, 54 insertions(+), 48 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 0bb5eff..789c694 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -74,30 +74,33 @@ local function worker(args) bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) -- notifications for low and critical states - if bat_now.perc <= 5 + if bat_new.status == "Discharging" then - bat.id = naughty.notify({ - text = "shutdown imminent", - title = "battery nearly exhausted", - position = "top_right", - timeout = 15, - fg="#000000", - bg="#ffffff", - ontop = true, - replaces_id = bat.id - }).id - elseif bat_now.perc <= 15 - then - bat.id = naughty.notify({ - text = "plug the cable", - title = "battery low", - position = "top_right", - timeout = 15, - fg="#202020", - bg="#cdcdcd", - ontop = true, - replaces_id = bat.id - }).id + if bat_now.perc <= 5 + then + bat.id = naughty.notify({ + text = "shutdown imminent", + title = "battery nearly exhausted", + position = "top_right", + timeout = 15, + fg="#000000", + bg="#ffffff", + ontop = true, + replaces_id = bat.id + }).id + elseif bat_now.perc <= 15 + then + bat.id = naughty.notify({ + text = "plug the cable", + title = "battery low", + position = "top_right", + timeout = 15, + fg="#202020", + bg="#cdcdcd", + ontop = true, + replaces_id = bat.id + }).id + end end bat_now.perc = string.format("%d", bat_now.perc) diff --git a/widgets/contrib/tpbat/init.lua b/widgets/contrib/tpbat/init.lua index 206fd38..dbf90aa 100644 --- a/widgets/contrib/tpbat/init.lua +++ b/widgets/contrib/tpbat/init.lua @@ -113,36 +113,39 @@ function tpbat.register(args) if bat:installed() then - bat_now.status = bat:status() + bat_now.status = bat:status() or "N/A" bat_now.perc = bat:percent() bat_now.time = bat:remaining_time() -- bat_now.watt = string.format("%.2fW", (VOLTS * AMPS) / 1e12) - -- notifications for low and critical states - if bat_now.perc <= 5 + -- notifications for low and critical states (when discharging) + if bat_now.status == "discharging" then - tpbat.id = naughty.notify({ - text = "shutdown imminent", - title = "battery nearly exhausted", - position = "top_right", - timeout = 15, - fg="#000000", - bg="#ffffff", - ontop = true, - replaces_id = tpbat.id - }).id - elseif bat_now.perc <= 15 - then - tpbat.id = naughty.notify({ - text = "plug the cable", - title = "battery low", - position = "top_right", - timeout = 15, - fg="#202020", - bg="#cdcdcd", - ontop = true, - replaces_id = tpbat.id - }).id + if bat_now.perc <= 5 + then + tpbat.id = naughty.notify({ + text = "shutdown imminent", + title = "battery nearly exhausted", + position = "top_right", + timeout = 15, + fg="#000000", + bg="#ffffff", + ontop = true, + replaces_id = tpbat.id + }).id + elseif bat_now.perc <= 15 + then + tpbat.id = naughty.notify({ + text = "plug the cable", + title = "battery low", + position = "top_right", + timeout = 15, + fg="#202020", + bg="#cdcdcd", + ontop = true, + replaces_id = tpbat.id + }).id + end end bat_now.perc = tostring(bat_now.perc) From efca46a9f4ce0b43c6d9a6a74b3ae6cb7b7871e6 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 27 Sep 2013 13:09:29 +0200 Subject: [PATCH 321/572] counterfix on pull #6 --- widgets/bat.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 789c694..fd99e4d 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -74,7 +74,7 @@ local function worker(args) bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) -- notifications for low and critical states - if bat_new.status == "Discharging" + if bat_now.status == "Discharging" then if bat_now.perc <= 5 then From 4b2bb0b413766b23a9716984566aaaf0597ce961 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 28 Sep 2013 11:50:08 +0200 Subject: [PATCH 322/572] cal: changed default font_size --- README.rst | 2 +- widgets/calendar.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index f7e5611..75ed867 100644 --- a/README.rst +++ b/README.rst @@ -14,7 +14,7 @@ Description ----------- Successor of awesome-vain_, this costantly evolving module -provides new layouts, a set of widgets and utility functions +provides new layouts, a set of widgets and utility functions, in order to improve Awesome_ usability and configurability. Read the wiki_ for all the info. diff --git a/widgets/calendar.lua b/widgets/calendar.lua index 8c707c8..f684fd7 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -105,7 +105,7 @@ end function calendar:attach(widget, args) local args = args or {} calendar.icons = args.icons or icons_dir .. "cal/white/" - calendar.font_size = tonumber(args.font_size) or 12 + calendar.font_size = tonumber(args.font_size) or 11 calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF" calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF" calendar.position = args.position or "top_right" From 089c10dff4317654c8436ddef408d993d617e202 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sat, 28 Sep 2013 04:04:24 -0700 Subject: [PATCH 323/572] Updated Utilities (markdown) --- Utilities.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Utilities.md b/Utilities.md index 3ab9245..84fe3fa 100644 --- a/Utilities.md +++ b/Utilities.md @@ -50,6 +50,7 @@ That is: - create a new tag; - rename current tag; +- move current tag; - delete current tag. If you delete a tag, any rule set on it shall be broken, so be careful. @@ -58,6 +59,8 @@ Use it with key bindings like these: awful.key({ modkey, "Shift" }, "n", function () lain.util.create_tag(mypromptbox) end), awful.key({ modkey, "Shift" }, "r", function () lain.util.rename_tag(mypromptbox) end), + awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(1) end), -- move next tag + awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(-1) end), -- move prev tag awful.key({ modkey, "Shift" }, "d", function () lain.util.delete_tag() end), useless\_gaps\_resize From d97e816e0f613ccbcf20e28ebf0a967e93702824 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 28 Sep 2013 13:05:05 +0200 Subject: [PATCH 324/572] dynamic tagging: move_tag added --- util/init.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/util/init.lua b/util/init.lua index 06db0d4..e380cbb 100644 --- a/util/init.lua +++ b/util/init.lua @@ -191,6 +191,18 @@ function util.rename_tag(mypromptbox) end) end +-- Move current tag +-- pos in {-1, 1} <-> {previous, next} tag position +function util.move_tag(pos) + local tag = awful.tag.selected(mouse.screen) + local idx = awful.tag.getidx(tag) + if tonumber(pos) <= -1 then + awful.tag.move(idx - 1, tag) + else + awful.tag.move(idx + 1, tag) + end +end + -- Delete current tag (if empty) -- Any rule set on the tag shall be broken function util.remove_tag() From a4069c048904af05ba0aaa3c55d7b02596adde29 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 28 Sep 2013 13:06:35 +0200 Subject: [PATCH 325/572] dynamic tagging: move_tag added --- util/init.lua | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/util/init.lua b/util/init.lua index e380cbb..cd1ac5d 100644 --- a/util/init.lua +++ b/util/init.lua @@ -38,10 +38,7 @@ function util.menu_clients_current_tags(menu, args) -- Final list of menu items. local cls_t = {} - if cls_tags == nil - then - return nil - end + if cls_tags == nil then return nil end -- For each selected tag get all clients of that tag and add them to -- the menu. A click on a menu item will raise that client. @@ -63,17 +60,11 @@ function util.menu_clients_current_tags(menu, args) end -- No clients? Then quit. - if #cls_t <= 0 - then - return nil - end + if #cls_t <= 0 then return nil end -- menu may contain some predefined values, otherwise start with a -- fresh menu. - if not menu - then - menu = {} - end + if not menu then menu = {} end -- Set the list of items and show the menu. menu.items = cls_t From d2eb6d9bcf3610d89238f567b5a50f801bcf61dc Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 29 Sep 2013 17:06:28 +0200 Subject: [PATCH 326/572] awesome-copycats: issue #16 fix --- widgets/bat.lua | 16 ++++++++++------ wiki | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index fd99e4d..c5279bd 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -15,6 +15,7 @@ local wibox = require("wibox") local math = { floor = math.floor } local string = { format = string.format } +local tonumber = tonumber local setmetatable = setmetatable @@ -57,6 +58,11 @@ local function worker(args) bat_now.status = first_line(bstr .. "/status") or "N/A" + rate = tonumber(rate) + ratev = tonumber(ratev) + rem = tonumber(rem) + tot = tonumber(tot) + local time_rat = 0 if bat_now.status == "Charging" then @@ -67,16 +73,16 @@ local function worker(args) end local hrs = math.floor(time_rat) - local min = (time_rat - hrs) * 60 + local min = math.floor((time_rat - hrs) * 60) bat_now.time = string.format("%02d:%02d", hrs, min) - bat_now.perc = (rem / tot) * 100 + bat_now.perc = string.format("%d", (rem / tot) * 100) bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) -- notifications for low and critical states if bat_now.status == "Discharging" then - if bat_now.perc <= 5 + if tonumber(bat_now.perc) <= 5 then bat.id = naughty.notify({ text = "shutdown imminent", @@ -88,7 +94,7 @@ local function worker(args) ontop = true, replaces_id = bat.id }).id - elseif bat_now.perc <= 15 + elseif tonumber(bat_now.perc) <= 15 then bat.id = naughty.notify({ text = "plug the cable", @@ -102,8 +108,6 @@ local function worker(args) }).id end end - - bat_now.perc = string.format("%d", bat_now.perc) end widget = bat.widget diff --git a/wiki b/wiki index 4a81ad4..089c10d 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 4a81ad47d143e42e8b9de92ebb8cd963d5bd6515 +Subproject commit 089c10dff4317654c8436ddef408d993d617e202 From 48ea29e3ba2ac052548a15ff7b9946238a4fd081 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 30 Sep 2013 16:29:18 +0200 Subject: [PATCH 327/572] awesome-copycats issue #16 fix --- widgets/bat.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/widgets/bat.lua b/widgets/bat.lua index c5279bd..aa89640 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -73,7 +73,10 @@ local function worker(args) end local hrs = math.floor(time_rat) + if hrs < 0 then hrs = 0 elseif hrs > 23 then hrs = 23 end + local min = math.floor((time_rat - hrs) * 60) + if min < 0 then min = 0 elseif min > 59 then min = 59 end bat_now.time = string.format("%02d:%02d", hrs, min) bat_now.perc = string.format("%d", (rem / tot) * 100) From c752bc0c50e0b9c2df38263d2f67b0ced3242e1e Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 1 Oct 2013 13:45:07 +0200 Subject: [PATCH 328/572] yawn: bad connectivity fix --- widgets/yawn/init.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 2306fed..ecd1314 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -72,6 +72,14 @@ local function fetch_weather() -- Processing raw data weather_data = text:gsub("<.->", "") weather_data = weather_data:match("Current Conditions:.-Full") + + -- may still happens in case of bad connectivity + if weather_data == nil then + yawn.icon:set_image(icon_path .. "na.png") + yawn.widget:set_text("?") + return + end + weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ") weather_data = weather_data:gsub("Forecast:.-\n", "") weather_data = weather_data:gsub("\nFull", "") From 62d5cba13042914027e33814c8fc03906b89aa6b Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 1 Oct 2013 13:47:37 +0200 Subject: [PATCH 329/572] yawn: bad connectivity fix --- widgets/yawn/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index ecd1314..38b741a 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -71,10 +71,10 @@ local function fetch_weather() -- Processing raw data weather_data = text:gsub("<.->", "") - weather_data = weather_data:match("Current Conditions:.-Full") + weather_data = weather_data:match("Current Conditions:.-Full") or "" -- may still happens in case of bad connectivity - if weather_data == nil then + if weather_data == "" then yawn.icon:set_image(icon_path .. "na.png") yawn.widget:set_text("?") return From ea0c45685994189c1ff0a8a8cd3775f52062d951 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 2 Oct 2013 07:14:45 -0700 Subject: [PATCH 330/572] Updated fs (markdown) --- fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs.md b/fs.md index e30c473..1e34f86 100644 --- a/fs.md +++ b/fs.md @@ -14,7 +14,7 @@ Variable | Meaning | Type | Default `partition` | Partition to monitor | string | "/" `settings` | User settings | function | empty function -`settings` can use the following `partition` related float values: `used`, `available`, `size_mb`, `size_gb`. +`settings` can use the following `partition` related float values: `fs_now.used`, `fs_now.available`, `fs_now.size_mb`, `fs_now.size_gb`. It can also use value strings in these formats: From e72deb9de709a9adaa3a239a4e18ed641538de6e Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 2 Oct 2013 16:24:55 +0200 Subject: [PATCH 331/572] issue #7 fix --- widgets/fs.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/widgets/fs.lua b/widgets/fs.lua index b434056..7406e05 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -65,6 +65,7 @@ local function worker(args) function update() fs_info = {} + fs_now = {} local f = io.popen("LC_ALL=C df -kP") @@ -85,15 +86,15 @@ local function worker(args) -- chosen partition easy stuff -- you can however check whatever partition else - used = tonumber(fs_info[partition .. " used_p"]) - available = tonumber(fs_info[partition .. " avail_p"]) - size_mb = tonumber(fs_info[partition .. " size_mb"]) - size_gb = tonumber(fs_info[partition .. " size_gb"]) + fs_now.used = tonumber(fs_info[partition .. " used_p"]) or 0 + fs_now.available = tonumber(fs_info[partition .. " avail_p"]) 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 widget = fs.widget settings() - if used >= 99 and not helpers.get_map("fs") + if fs_now.used >= 99 and not helpers.get_map("fs") then naughty.notify({ title = "warning", From b570fc77aac193cbe0e42763e3285325cf9ea7e5 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Fri, 4 Oct 2013 06:19:52 -0700 Subject: [PATCH 332/572] Updated Layouts (markdown) --- Layouts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Layouts.md b/Layouts.md index 07184a4..d53b945 100644 --- a/Layouts.md +++ b/Layouts.md @@ -247,7 +247,7 @@ you have to add an item called `useless_gap_width` in your `theme.lua`. If it doesn't exist, the width will default to 0. Example: - theme.useless_gap_width = 5 + theme.useless_gap_width = 10 What about layout icons? ======================== From e85974ae28dda46d1f1ad1d5985269ea50ce5e83 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Fri, 4 Oct 2013 09:51:14 -0700 Subject: [PATCH 333/572] Updated Layouts (markdown) --- Layouts.md | 114 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 43 deletions(-) diff --git a/Layouts.md b/Layouts.md index d53b945..fc302d4 100644 --- a/Layouts.md +++ b/Layouts.md @@ -1,11 +1,12 @@ -Currently, there are **7** layouts. +Currently, there are **8** layouts. lain/layout . + |-- termfair + |-- centerfair |-- cascade |-- cascadetile |-- centerwork - |-- termfair |-- uselessfair |-- uselesspiral `-- uselesstile @@ -27,6 +28,74 @@ Or set them on specific tags like this: How do layouts work? ========================= +termfair +-------- + +I do a lot of work on terminals. The common tiling algorithms usually +maximize windows, so you'll end up with a terminal that has about 200 +columns or more. That's way too much. Have you ever read a manpage in a +terminal of this size? + +This layout restricts the size of each window. Each window will have the +same width but is variable in height. Furthermore, windows are +left-aligned. The basic workflow is as follows (the number above the +screen is the number of open windows, the number in a cell is the fixed +number of a client): + + (1) (2) (3) + +---+---+---+ +---+---+---+ +---+---+---+ + | | | | | | | | | | | | + | 1 | | | -> | 2 | 1 | | -> | 3 | 2 | 1 | -> + | | | | | | | | | | | | + +---+---+---+ +---+---+---+ +---+---+---+ + + (4) (5) (6) + +---+---+---+ +---+---+---+ +---+---+---+ + | 4 | | | | 5 | 4 | | | 6 | 5 | 4 | + +---+---+---+ -> +---+---+---+ -> +---+---+---+ + | 3 | 2 | 1 | | 3 | 2 | 1 | | 3 | 2 | 1 | + +---+---+---+ +---+---+---+ +---+---+---+ + +The first client will be located in the left column. When opening +another window, this new window will be placed in the left column while +moving the first window into the middle column. Once a row is full, +another row above it will be created. + +Default number of columns and rows are respectively taken from `nmaster` +and `ncol` values in `awful.tag`, but you can set your own. + +For example, this sets `termfair` to 3 columns and at least 1 row: + + lain.layout.termfair.nmaster = 3 + lain.layout.termfair.ncol = 1 + +centerfair +---------- + +Similar to `termfair`, but with fixed number of vertical columns. Cols are centerded until there is nmaster columns, then windows are stacked in the slave columns, with at most ncol clients per column if possible. + + (1) (2) (3) + +---+---+---+ +-+---+---+-+ +---+---+---+ + | | | | | | | | | | | | | + | | 1 | | -> | | 1 | 2 | | -> | 1 | 2 | 3 | -> + | | | | | | | | | | | | | + +---+---+---+ +-+---+---+-+ +---+---+---+ + + (4) (5) + +---+---+---+ +---+---+---+ + | | | 3 | | | 2 | 4 | + + 1 + 2 +---+ -> + 1 +---+---+ + | | | 4 | | | 3 | 5 | + +---+---+---+ +---+---+---+ + +Like `termfair`, default number of columns and rows are respectively taken from `nmaster` +and `ncol` values in `awful.tag`, but you can set your own. + +For example: + + lain.layout.centerfair.nmaster = 3 + lain.layout.centerfair.ncol = 1 + cascade ------- @@ -174,47 +243,6 @@ Here's an example: ... ) -termfair --------- - -I do a lot of work on terminals. The common tiling algorithms usually -maximize windows, so you'll end up with a terminal that has about 200 -columns or more. That's way too much. Have you ever read a manpage in a -terminal of this size? - -This layout restricts the size of each window. Each window will have the -same width but is variable in height. Furthermore, windows are -left-aligned. The basic workflow is as follows (the number above the -screen is the number of open windows, the number in a cell is the fixed -number of a client): - - (1) (2) (3) - +---+---+---+ +---+---+---+ +---+---+---+ - | | | | | | | | | | | | - | 1 | | | -> | 2 | 1 | | -> | 3 | 2 | 1 | -> - | | | | | | | | | | | | - +---+---+---+ +---+---+---+ +---+---+---+ - - (4) (5) (6) - +---+---+---+ +---+---+---+ +---+---+---+ - | 4 | | | | 5 | 4 | | | 6 | 5 | 4 | - +---+---+---+ -> +---+---+---+ -> +---+---+---+ - | 3 | 2 | 1 | | 3 | 2 | 1 | | 3 | 2 | 1 | - +---+---+---+ +---+---+---+ +---+---+---+ - -The first client will be located in the left column. When opening -another window, this new window will be placed in the left column while -moving the first window into the middle column. Once a row is full, -another row above it will be created. - -Default number of columns and rows are respectively taken from `nmaster` -and `ncol` values in `awful.tag`, but you can set your own. - -For example, this sets `termfair` to 3 columns and at least 1 row: - - lain.layout.termfair.nmaster = 3 - lain.layout.termfair.ncol = 1 - uselessfair, uselesspiral & uselesstile --------------------------------------- These are duplicates of the stock `fair`, `spiral` and `tile` layouts. From 5de6ca283bffbc041eeb094c8b82dfd8d680f04f Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 4 Oct 2013 18:53:33 +0200 Subject: [PATCH 334/572] issue #2 fix attempt; centerfair added; small fixes --- icons/layout/default/centerfair.png | Bin 0 -> 169 bytes icons/layout/default/centerfairw.png | Bin 0 -> 169 bytes icons/layout/zenburn/centerfair.png | Bin 0 -> 399 bytes layout/centerfair.lua | 147 +++++++++++++++++++++++++++ layout/termfair.lua | 13 ++- layout/uselessfair.lua | 11 +- layout/uselesspiral.lua | 10 +- layout/uselesstile.lua | 10 +- wiki | 2 +- 9 files changed, 176 insertions(+), 17 deletions(-) create mode 100644 icons/layout/default/centerfair.png create mode 100644 icons/layout/default/centerfairw.png create mode 100644 icons/layout/zenburn/centerfair.png create mode 100644 layout/centerfair.lua diff --git a/icons/layout/default/centerfair.png b/icons/layout/default/centerfair.png new file mode 100644 index 0000000000000000000000000000000000000000..188c24348eee1dd1efcc5beb7c2c72ff7f5320f0 GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB_V)Sem}`Jdk263GxeO zaCmkj4a7+(lKOItEWyKbLh*2~7Yr Chb7ej literal 0 HcmV?d00001 diff --git a/icons/layout/default/centerfairw.png b/icons/layout/default/centerfairw.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4bcf5cd63ef3f1f3d7df24d941648ac1856f48 GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0P3?wHke>@jRu?6^qxB}__|Nk$&IsYz@#aI&L z7tG-B>_!@hljQC0!qCAg>jC6&7I;J!Gca%qgD@k*tT_@uLG}_)Usv|KTr2{-W(TJv zfsB^%ba4#PIG_B3pOt4u4?9l{k3&=K6vIoBJA^qIjz-K9mWjKl3RK77>FVdQ&MBb@ E00x{Y4FCWD literal 0 HcmV?d00001 diff --git a/icons/layout/zenburn/centerfair.png b/icons/layout/zenburn/centerfair.png new file mode 100644 index 0000000000000000000000000000000000000000..01cda8e89c14980825199778ed2c5defea611305 GIT binary patch literal 399 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP)7mI+hilvrRIs*fvjHioZNX4zUw{7{F3?z zR>3q~ZsF$bA6CR2n5q1Qi%-q1x4|M}5}%O(m*>O(dRjBuKV9C}ATQ*qyKB>j#$s1v zlM52FSu3YYG@BfgYd$l1$?*dximTJ-KIkr+e&q<)X`%ThoMV2*KS5pE?%3B;LX5MPGS^t}1D%ZylES|D zx6aj`;-vN-T?&=oz@qhPd*tGOLbrD&J)by#QdnKJ{@;J^f_^W*dN9IllGpypp}X%% zM6=J_dn}=6uHWbL$MR)Yuj+fcbbqZetJ*649WM=Y<-6Xl2AS&V>gTe~DWM4flk|#Z literal 0 HcmV?d00001 diff --git a/layout/centerfair.lua b/layout/centerfair.lua new file mode 100644 index 0000000..d9ea677 --- /dev/null +++ b/layout/centerfair.lua @@ -0,0 +1,147 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Luke Bonham + * (c) 2012, Nicolas Estibals + * (c) 2010-2012, Peter Hofmann + +--]] + +local tag = require("awful.tag") +local beautiful = require("beautiful") +local math = { ceil = math.ceil, + floor = math.floor, + max = math.max } +local tonumber = tonumber + +local centerfair = { name = "centerfair" } + +function centerfair.arrange(p) + -- Layout with fixed number of vertical columns (read from nmaster). + -- Cols are centerded until there is nmaster columns, then windows + -- are stacked in the slave columns, with at most ncol clients per + -- column if possible. + + -- with nmaster=3 and ncol=1 you'll have + -- (1) (2) (3) + -- +---+---+---+ +-+---+---+-+ +---+---+---+ + -- | | | | | | | | | | | | | + -- | | 1 | | -> | | 1 | 2 | | -> | 1 | 2 | 3 | -> + -- | | | | | | | | | | | | | + -- +---+---+---+ +-+---+---+-+ +---+---+---+ + + -- (4) (5) + -- +---+---+---+ +---+---+---+ + -- | | | 3 | | | 2 | 4 | + -- + 1 + 2 +---+ -> + 1 +---+---+ + -- | | | 4 | | | 3 | 5 | + -- +---+---+---+ +---+---+---+ + + -- A useless gap (like the dwm patch) can be defined with + -- beautiful.useless_gap_width . + local useless_gap = tonumber(beautiful.useless_gap_width) or 0 + + -- Screen. + local wa = p.workarea + local cls = p.clients + + -- How many vertical columns? Read from nmaster on the tag. + local t = tag.selected(p.screen) + local num_x = centerfair.nmaster or tag.getnmaster(t) + local ncol = centerfair.ncol or tag.getncol(t) + + local width = math.floor((wa.width-(num_x+1)*useless_gap) / num_x) + + local offset_y = wa.y + useless_gap + if #cls < num_x + then + -- Less clients than the number of columns, let's center it! + local offset_x = wa.x + useless_gap + (wa.width - #cls*width - (#cls+1)*useless_gap) / 2 + local g = {} + g.width = width + g.height = wa.height - 2*useless_gap - 2 + g.y = offset_y + for i = 1, #cls do + g.x = offset_x + (i - 1) * (width + useless_gap + 2) + cls[i]:geometry(g) + end + else + -- More clients than the number of columns, let's arrange it! + local offset_x = wa.x + if useless_gap > 0 then + offset_x = offset_x + end + + -- Master client deserves a special treatement + local g = {} + g.width = wa.width - (num_x-1)*width -num_x*useless_gap - 2 + g.height = wa.height - 2*useless_gap - 2 + g.x = offset_x + useless_gap + g.y = offset_y + cls[1]:geometry(g) + + -- Treat the other clients + + -- Compute distribution of clients among columns + local num_y ={} + do + local remaining_clients = #cls-1 + local ncol_min = math.ceil(remaining_clients/(num_x-1)) + if ncol >= ncol_min + then + for i = (num_x-1), 1, -1 do + if (remaining_clients-i+1) < ncol + then + num_y[i] = remaining_clients-i + 1 + else + num_y[i] = ncol + end + remaining_clients = remaining_clients - num_y[i] + end + else + local rem = remaining_clients % (num_x-1) + if rem ==0 + then + for i = 1, num_x-1 do + num_y[i] = ncol_min + end + else + for i = 1, num_x-1 do + num_y[i] = ncol_min - 1 + end + for i = 0, rem-1 do + num_y[num_x-1-i] = num_y[num_x-1-i] + 1 + end + end + end + end + + -- Compute geometry of the other clients + local nclient = 2 + g.x = g.x + g.width+useless_gap + 2 + g.width = width + + if useless_gap > 0 then + g.width = g.width - useless_gap/2 - 2 + end + + for i = 1, (num_x-1) do + to_remove = 2 + g.height = math.floor((wa.height-useless_gap)/num_y[i]) + g.y = offset_y + for j = 0, (num_y[i]-2) do + cls[nclient]:geometry(g) + nclient = nclient + 1 + g.y = g.y + g.height+useless_gap + 2 + to_remove = to_remove + 2 + end + g.height = wa.height - num_y[i]*useless_gap - (num_y[i]-1)*g.height - useless_gap - to_remove + cls[nclient]:geometry(g) + nclient = nclient + 1 + g.x = g.x+g.width+useless_gap + 2 + end + end +end + +return centerfair diff --git a/layout/termfair.lua b/layout/termfair.lua index 4beab8f..89a44bb 100644 --- a/layout/termfair.lua +++ b/layout/termfair.lua @@ -89,27 +89,32 @@ function termfair.arrange(p) else g.height = height end + g.x = wa.x + this_x * width g.y = wa.y + this_y * height + if useless_gap > 0 then -- Top and left clients are shrinked by two steps and -- get moved away from the border. Other clients just -- get shrinked in one direction. + + gap_factor = (useless_gap / 100) * 2 + if this_x == 0 then - g.width = g.width - 2 * useless_gap + g.width = g.width - (2 + gap_factor) * useless_gap g.x = g.x + useless_gap else - g.width = g.width - useless_gap + g.width = g.width - (1 + gap_factor) * useless_gap end if this_y == 0 then - g.height = g.height - 2 * useless_gap + g.height = g.height - (2 + gap_factor) * useless_gap g.y = g.y + useless_gap else - g.height = g.height - useless_gap + g.height = g.height - (1 + gap_factor) * useless_gap end end c:geometry(g) diff --git a/layout/uselessfair.lua b/layout/uselessfair.lua index 7499d91..6aa6666 100644 --- a/layout/uselessfair.lua +++ b/layout/uselessfair.lua @@ -71,20 +71,23 @@ local function fair(p, orientation) -- Top and left clients are shrinked by two steps and -- get moved away from the border. Other clients just -- get shrinked in one direction. + + gap_factor = (useless_gap / 100) * 2 + if this_x == 0 then - g.width = g.width - 2 * useless_gap + g.width = g.width - (2 + gap_factor) * useless_gap g.x = g.x + useless_gap else - g.width = g.width - useless_gap + g.width = g.width - (1 + gap_factor) * useless_gap end if this_y == 0 then - g.height = g.height - 2 * useless_gap + g.height = g.height - (2 + gap_factor) * useless_gap g.y = g.y + useless_gap else - g.height = g.height - useless_gap + g.height = g.height - (1 + gap_factor) * useless_gap end end -- End of useless gap. diff --git a/layout/uselesspiral.lua b/layout/uselesspiral.lua index ad2ba04..3164c75 100644 --- a/layout/uselesspiral.lua +++ b/layout/uselesspiral.lua @@ -64,6 +64,8 @@ local function spiral(p, spiral) top = false left = false + gap_factor = (useless_gap / 100) * 2 + if wa2.y == static_wa.y then top = true end @@ -73,17 +75,17 @@ local function spiral(p, spiral) end if top then - wa2.height = wa2.height - 2 * useless_gap + wa2.height = wa2.height - (2 + gap_factor) * useless_gap wa2.y = wa2.y + useless_gap else - wa2.height = wa2.height - useless_gap + wa2.height = wa2.height - (1 + gap_factor) * useless_gap end if left then - wa2.width = wa2.width - 2 * useless_gap + wa2.width = wa2.width - (2 + gap_factor) * useless_gap wa2.x = wa2.x + useless_gap else - wa2.width = wa2.width - useless_gap + wa2.width = wa2.width - (1 + gap_factor) * useless_gap end end -- End of useless gap. diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index 78f7bec..e496500 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -88,6 +88,8 @@ local function tile_group(cls, wa, orientation, fact, group) top = false left = false + gap_factor = (useless_gap / 100) * 2 + if geom[y] == wa[y] then top = true end @@ -97,17 +99,17 @@ local function tile_group(cls, wa, orientation, fact, group) end if top then - geom[height] = geom[height] - 2 * useless_gap + geom[height] = geom[height] - (2 + gap_factor) * useless_gap geom[y] = geom[y] + useless_gap else - geom[height] = geom[height] - useless_gap + geom[height] = geom[height] - (1 + gap_factor) * useless_gap end if left then - geom[width] = geom[width] - 2 * useless_gap + geom[width] = geom[width] - (2 + gap_factor) * useless_gap geom[x] = geom[x] + useless_gap else - geom[width] = geom[width] - useless_gap + geom[width] = geom[width] - (1 + gap_factor) * useless_gap end end -- End of useless gap. diff --git a/wiki b/wiki index 089c10d..e85974a 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 089c10dff4317654c8436ddef408d993d617e202 +Subproject commit e85974ae28dda46d1f1ad1d5985269ea50ce5e83 From 528d51fbc2147d15183d1bf3c75cd19de7f2722b Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 6 Oct 2013 21:16:25 +0200 Subject: [PATCH 335/572] bat: fix issue #17 --- layout/centerfair.lua | 2 +- widgets/bat.lua | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/layout/centerfair.lua b/layout/centerfair.lua index d9ea677..49b4a14 100644 --- a/layout/centerfair.lua +++ b/layout/centerfair.lua @@ -3,7 +3,7 @@ Licensed under GNU General Public License v2 * (c) 2013, Luke Bonham - * (c) 2012, Nicolas Estibals + * (c) 2010, Nicolas Estibals * (c) 2010-2012, Peter Hofmann --]] diff --git a/widgets/bat.lua b/widgets/bat.lua index aa89640..a064e30 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -79,8 +79,21 @@ local function worker(args) if min < 0 then min = 0 elseif min > 59 then min = 59 end bat_now.time = string.format("%02d:%02d", hrs, min) - bat_now.perc = string.format("%d", (rem / tot) * 100) - bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) + + local perc = (rem / tot) * 100 + if perc <= 100 then + bat_now.perc = string.format("%d", perc) + elseif perc > 100 then + bat_now.perc = "100" + elseif perc < 0 then + bat_now.perc = "0" + end + + if rate ~= nil and ratev ~= nil then + bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) + else + bat_not.watt = "N/A" + end -- notifications for low and critical states if bat_now.status == "Discharging" From 88b5c74a5936dce171a0a2723d45adfcd2f4368d Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 7 Oct 2013 00:26:26 +0200 Subject: [PATCH 336/572] little fix --- widgets/bat.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index a064e30..2906de2 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -92,7 +92,7 @@ local function worker(args) if rate ~= nil and ratev ~= nil then bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) else - bat_not.watt = "N/A" + bat_now.watt = "N/A" end -- notifications for low and critical states From fc8a3e72aecc446f534bec9d39e1215202349d8a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 6 Oct 2013 15:49:20 -0700 Subject: [PATCH 337/572] Updated Layouts (markdown) --- Layouts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Layouts.md b/Layouts.md index fc302d4..1ddca95 100644 --- a/Layouts.md +++ b/Layouts.md @@ -72,7 +72,7 @@ For example, this sets `termfair` to 3 columns and at least 1 row: centerfair ---------- -Similar to `termfair`, but with fixed number of vertical columns. Cols are centerded until there is nmaster columns, then windows are stacked in the slave columns, with at most ncol clients per column if possible. +Similar to `termfair`, but with fixed number of vertical columns. Cols are centerded until there are `nmaster` columns, then windows are stacked as slaves, with possibly `ncol` clients per column at most. (1) (2) (3) +---+---+---+ +-+---+---+-+ +---+---+---+ From fa1baa8997253a31c90c3ef363dbf0596b9165fd Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 23 Oct 2013 11:32:34 +0200 Subject: [PATCH 338/572] yawn: localizations and icons updated --- helpers.lua | 2 +- scripts/mpdcover | 2 +- widgets/yawn/icons/Fog.png | 1 + widgets/yawn/localizations/it_IT | 3 ++- widgets/yawn/localizations/localization_template | 1 + 5 files changed, 6 insertions(+), 3 deletions(-) create mode 120000 widgets/yawn/icons/Fog.png diff --git a/helpers.lua b/helpers.lua index 97cb797..c42ce61 100644 --- a/helpers.lua +++ b/helpers.lua @@ -30,7 +30,7 @@ end -- }}} --- {{{ Read the first line of a file or return nil. +-- {{{ Read the first line of a file or return nil function helpers.first_line(f) local fp = io.open(f) diff --git a/scripts/mpdcover b/scripts/mpdcover index f9f6577..20525fd 100755 --- a/scripts/mpdcover +++ b/scripts/mpdcover @@ -1,4 +1,4 @@ -#!/bin/bash +!/bin/bash # # A simple cover fetcher script for current playing song on mpd. # diff --git a/widgets/yawn/icons/Fog.png b/widgets/yawn/icons/Fog.png new file mode 120000 index 0000000..b615645 --- /dev/null +++ b/widgets/yawn/icons/Fog.png @@ -0,0 +1 @@ +Foggy.png \ No newline at end of file diff --git a/widgets/yawn/localizations/it_IT b/widgets/yawn/localizations/it_IT index 2276e4b..688e769 100644 --- a/widgets/yawn/localizations/it_IT +++ b/widgets/yawn/localizations/it_IT @@ -53,6 +53,7 @@ Sleet|Nevischio Drizzle|Pioggerella Freezing Drizzle|Pioggerella Congelantesi Hail|Grandine -Foggy|Nebbia +Fog|Nebbia +Foggy|Nebbioso Haze|Nebbia Light|Leggere diff --git a/widgets/yawn/localizations/localization_template b/widgets/yawn/localizations/localization_template index fd28868..e3a948f 100644 --- a/widgets/yawn/localizations/localization_template +++ b/widgets/yawn/localizations/localization_template @@ -53,6 +53,7 @@ Sleet| Drizzle| Freezing Drizzle| Hail| +Fog| Foggy| Haze| Light| From 937a67d8360a1f1d22696fad12b1fecb9f2fab99 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 1 Nov 2013 11:09:20 +0100 Subject: [PATCH 339/572] issue #9 fix attempt --- init.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/init.lua b/init.lua index 155d6cc..5086435 100644 --- a/init.lua +++ b/init.lua @@ -9,6 +9,8 @@ --]] +package.loaded.lain = nil + local lain = { layout = require("lain.layout"), From 3c56cf123a8b44cdd9a65b4e88432eac6670630e Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 1 Nov 2013 13:17:31 +0100 Subject: [PATCH 340/572] issue #9 2nd attempt fix --- widgets/mpd.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index e3ed50d..58d9430 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -59,7 +59,7 @@ local function worker(args) date = "N/A" } - local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 1 " .. mpdh) + local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh) for line in f:lines() do for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do From 96085317a2e39e7b3594c2df4fe9062a210a6e9b Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 1 Nov 2013 19:27:49 +0100 Subject: [PATCH 341/572] issue #9 semi-fix --- widgets/mpd.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 58d9430..4ee922f 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -42,6 +42,15 @@ local function worker(args) mpd.widget = wibox.widget.textbox('') + mpd_now = { + state = "N/A", + file = "N/A", + artist = "N/A", + title = "N/A", + album = "N/A", + date = "N/A" + } + mpd_notification_preset = { title = "Now playing", timeout = 6 @@ -50,15 +59,6 @@ local function worker(args) helpers.set_map("current mpd track", nil) function mpd.update() - mpd_now = { - state = "N/A", - file = "N/A", - artist = "N/A", - title = "N/A", - album = "N/A", - date = "N/A" - } - local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh) for line in f:lines() do From 3a0aba5a4bd962da9377d126e9565be54074d92e Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 2 Nov 2013 21:05:25 +0100 Subject: [PATCH 342/572] issue #9 fix --- scripts/mpdcover | 4 ++-- widgets/mpd.lua | 38 +++++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/scripts/mpdcover b/scripts/mpdcover index 20525fd..f6cf0d6 100755 --- a/scripts/mpdcover +++ b/scripts/mpdcover @@ -1,4 +1,4 @@ -!/bin/bash +#!/bin/bash # # A simple cover fetcher script for current playing song on mpd. # @@ -58,7 +58,7 @@ cover="${cover:=$DEFAULT_ART}" # check if art is available if [[ -n $cover ]]; then if [[ -n $COVER_RESIZE ]]; then - convert "$cover" -thumbnail $COVER_RESIZE -gravity center -background "$COVER_BACKGROUND" -extent $COVER_RESIZE "$TEMP_PATH" + convert "$cover" -thumbnail $COVER_RESIZE -gravity "center" -background "$COVER_BACKGROUND" -extent $COVER_RESIZE "$TEMP_PATH" cover="$TEMP_PATH" fi else diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 4ee922f..36c3ed7 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -16,7 +16,7 @@ local wibox = require("wibox") local io = { popen = io.popen } local os = { execute = os.execute, getenv = os.getenv } -local string = { format = string.format, +local string = { format = string.format, gmatch = string.gmatch } local setmetatable = setmetatable @@ -28,7 +28,7 @@ local mpd = {} local function worker(args) local args = args or {} local timeout = args.timeout or 2 - local password = args.password or "\"\"" + local password = args.password or "" local host = args.host or "127.0.0.1" local port = args.port or "6600" local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" @@ -38,19 +38,22 @@ local function worker(args) local mpdcover = helpers.scripts_dir .. "mpdcover" local mpdh = "telnet://" .. host .. ":" .. port - local echo = "echo 'password " .. password .. "\nstatus\ncurrentsong\nclose'" + + local echo = nil + + if password == "" then + echo = "(echo -e 'status'; sleep 0.1;" .. + "echo -e 'currentsong'; sleep 0.1;" .. + "echo -e 'close')" + else + echo = "(echo -e 'password " .. password .. "'" .. + "echo -e 'status'; sleep 0.1;" .. + "echo -e 'currentsong'; sleep 0.1;" .. + "echo -e 'close')" + end mpd.widget = wibox.widget.textbox('') - mpd_now = { - state = "N/A", - file = "N/A", - artist = "N/A", - title = "N/A", - album = "N/A", - date = "N/A" - } - mpd_notification_preset = { title = "Now playing", timeout = 6 @@ -59,7 +62,16 @@ local function worker(args) helpers.set_map("current mpd track", nil) function mpd.update() - local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh) + mpd_now = { + state = "N/A", + file = "N/A", + artist = "N/A", + title = "N/A", + album = "N/A", + date = "N/A" + } + + local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 1 " .. mpdh) for line in f:lines() do for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do From 724142977074eae2aeca552e02209a9bae6f0177 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 12 Nov 2013 01:38:47 -0800 Subject: [PATCH 343/572] Updated task (markdown) --- task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/task.md b/task.md index 8c68ac0..b4bc7f0 100644 --- a/task.md +++ b/task.md @@ -20,7 +20,7 @@ Notification will show the output of `task` command. You can call the notification with a key binding like this: - awful.key({ modkey, altkey }, "t", lain.widgets.task.show), + awful.key({ modkey, altkey }, "t", lain.widgets.contrib.task.show), where ``altkey = "Mod1"``. From d746d045f22bd8521b60fed5afb754a9e96bfb1d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 12 Nov 2013 01:38:54 -0800 Subject: [PATCH 344/572] Updated Utilities (markdown) --- Utilities.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Utilities.md b/Utilities.md index 84fe3fa..0e58304 100644 --- a/Utilities.md +++ b/Utilities.md @@ -48,20 +48,20 @@ dynamic tagging That is: -- create a new tag; +- add a new tag; - rename current tag; - move current tag; -- delete current tag. +- remove current tag. If you delete a tag, any rule set on it shall be broken, so be careful. Use it with key bindings like these: - awful.key({ modkey, "Shift" }, "n", function () lain.util.create_tag(mypromptbox) end), + awful.key({ modkey, "Shift" }, "n", function () lain.util.add_tag(mypromptbox) end), awful.key({ modkey, "Shift" }, "r", function () lain.util.rename_tag(mypromptbox) end), awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(1) end), -- move next tag - awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(-1) end), -- move prev tag - awful.key({ modkey, "Shift" }, "d", function () lain.util.delete_tag() end), + awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(-1) end), -- move previous tag + awful.key({ modkey, "Shift" }, "d", function () lain.util.remove_tag() end), useless\_gaps\_resize --------------------- From 3a6a7798f94cffe4677ff70e5b488724398ec507 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 12 Nov 2013 01:39:52 -0800 Subject: [PATCH 345/572] Updated Utilities (markdown) --- Utilities.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Utilities.md b/Utilities.md index 0e58304..e4f114a 100644 --- a/Utilities.md +++ b/Utilities.md @@ -59,8 +59,8 @@ Use it with key bindings like these: awful.key({ modkey, "Shift" }, "n", function () lain.util.add_tag(mypromptbox) end), awful.key({ modkey, "Shift" }, "r", function () lain.util.rename_tag(mypromptbox) end), - awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(1) end), -- move next tag - awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(-1) end), -- move previous tag + awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(1) end), -- move to next tag + awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(-1) end), -- move to previous tag awful.key({ modkey, "Shift" }, "d", function () lain.util.remove_tag() end), useless\_gaps\_resize From fec60d0af7d25b99d7f45ff94438e9d3f0f77ddf Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 12 Nov 2013 10:41:04 +0100 Subject: [PATCH 346/572] issue #11 typos fixed --- util/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/init.lua b/util/init.lua index cd1ac5d..1dfff65 100644 --- a/util/init.lua +++ b/util/init.lua @@ -194,7 +194,7 @@ function util.move_tag(pos) end end --- Delete current tag (if empty) +-- Remove current tag (if empty) -- Any rule set on the tag shall be broken function util.remove_tag() local tag = awful.tag.selected(mouse.screen) From 27923b165d8b31f8614419277fd3eb44123bd6c0 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 12 Nov 2013 01:50:52 -0800 Subject: [PATCH 347/572] Updated Utilities (markdown) --- Utilities.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Utilities.md b/Utilities.md index e4f114a..2171503 100644 --- a/Utilities.md +++ b/Utilities.md @@ -63,6 +63,8 @@ Use it with key bindings like these: awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(-1) end), -- move to previous tag awful.key({ modkey, "Shift" }, "d", function () lain.util.remove_tag() end), +**Note** that these function won't work properly with [Copland theme](https://github.com/copycat-killer/awesome-copycats) or any other configuration that already uses a dynamic tagging module like [Eminent](https://github.com/copycat-killer/awesome-copycats/tree/master/eminent). + useless\_gaps\_resize --------------------- From a7b1e7e0db5db914d519bbe8135f7e29cadfb8b7 Mon Sep 17 00:00:00 2001 From: blueluke Date: Tue, 12 Nov 2013 15:11:54 -0800 Subject: [PATCH 348/572] Removed a misplaced space in mpd_notification_preset variable declaration --- mpd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpd.md b/mpd.md index 0e2eca5..646b690 100644 --- a/mpd.md +++ b/mpd.md @@ -44,7 +44,7 @@ Variable | Meaning | Type | Default and can modify `mpd_notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: - mpd_notification _preset = { + mpd_notification_preset = { title = "Now playing", timeout = 6, text = string.format("%s (%s) - %s\n%s", mpd_now.artist, From feb67f2e7c487125d6814095c549a528863e2938 Mon Sep 17 00:00:00 2001 From: kurumushi Date: Tue, 19 Nov 2013 01:16:36 +0900 Subject: [PATCH 349/572] Change io.popen to io.open so we don't execute image files. --- widgets/yawn/init.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 38b741a..e7aa75d 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -1,4 +1,3 @@ - --[[ Licensed under GNU General Public License v2 @@ -115,7 +114,7 @@ local function fetch_weather() sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png" -- In case there's no defined icon for current forecast - f = io.popen(sky) + f = io.open(sky) if f == nil then sky = icon_path .. "na.png" else From ab32be9ac64831812dd7af22cc7595bbc9324932 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 18 Nov 2013 20:27:48 +0100 Subject: [PATCH 350/572] wiki updated --- widgets/maildir.lua | 1 - widgets/yawn/init.lua | 3 +-- widgets/yawn/localizations/it_IT | 2 +- wiki | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/widgets/maildir.lua b/widgets/maildir.lua index d460881..5cb6840 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -1,4 +1,3 @@ - --[[ Licensed under GNU General Public License v2 diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index e7aa75d..e7953e1 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -114,8 +114,7 @@ local function fetch_weather() sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png" -- In case there's no defined icon for current forecast - f = io.open(sky) - if f == nil then + if io.open(sky) == nil then sky = icon_path .. "na.png" else io.close(f) diff --git a/widgets/yawn/localizations/it_IT b/widgets/yawn/localizations/it_IT index 688e769..f1bfbe2 100644 --- a/widgets/yawn/localizations/it_IT +++ b/widgets/yawn/localizations/it_IT @@ -14,7 +14,7 @@ Isolated Thunderstorms|Temporali Isolati Scattered Thunderstorms|Temporali Sparsi Thundershowers|Rovesci Temporaleschi Thunderstorms|Temporali -Thunder in the Vicinity|Tuoni in avvicinamento +Thunder in the Vicinity|Tuoni in prossimità Thunder|Temporale AM|In Mattinata PM|Nel Pomeriggio diff --git a/wiki b/wiki index e85974a..a7b1e7e 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit e85974ae28dda46d1f1ad1d5985269ea50ce5e83 +Subproject commit a7b1e7e0db5db914d519bbe8135f7e29cadfb8b7 From 6f86540f4d920706ed21ed5ecd6729791650507c Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 18 Nov 2013 20:30:43 +0100 Subject: [PATCH 351/572] wiki updated --- widgets/yawn/init.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index e7953e1..7ab76fe 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -116,8 +116,6 @@ local function fetch_weather() -- In case there's no defined icon for current forecast if io.open(sky) == nil then sky = icon_path .. "na.png" - else - io.close(f) end -- Localization From 65c1a3ab6e411aec30c3145178fac9f7fdbab87f Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 28 Nov 2013 00:48:22 -0800 Subject: [PATCH 352/572] Updated Utilities (markdown) --- Utilities.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Utilities.md b/Utilities.md index 2171503..99588b9 100644 --- a/Utilities.md +++ b/Utilities.md @@ -59,8 +59,8 @@ Use it with key bindings like these: awful.key({ modkey, "Shift" }, "n", function () lain.util.add_tag(mypromptbox) end), awful.key({ modkey, "Shift" }, "r", function () lain.util.rename_tag(mypromptbox) end), - awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(1) end), -- move to next tag - awful.key({ modkey, "Shift" }, "r", function () lain.util.move_tag(-1) end), -- move to previous tag + awful.key({ modkey, "Shift" }, "Left", function () lain.util.move_tag(1) end), -- move to next tag + awful.key({ modkey, "Shift" }, "Right", function () lain.util.move_tag(-1) end), -- move to previous tag awful.key({ modkey, "Shift" }, "d", function () lain.util.remove_tag() end), **Note** that these function won't work properly with [Copland theme](https://github.com/copycat-killer/awesome-copycats) or any other configuration that already uses a dynamic tagging module like [Eminent](https://github.com/copycat-killer/awesome-copycats/tree/master/eminent). From ead1c33e11e353e9fb0ed175312af0fa72f4549a Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 28 Nov 2013 09:56:18 +0100 Subject: [PATCH 353/572] wiki updated --- README.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 75ed867..8eba2fb 100644 --- a/README.rst +++ b/README.rst @@ -13,9 +13,7 @@ Layouts, widgets and utilities for Awesome WM Description ----------- -Successor of awesome-vain_, this costantly evolving module -provides new layouts, a set of widgets and utility functions, -in order to improve Awesome_ usability and configurability. +Successor of awesome-vain_, this module provides new layouts, a set of widgets and utility functions, in order to improve Awesome_ usability and configurability. Read the wiki_ for all the info. From 3f62fea68c2ada475a000cc92fd8dac5029dda84 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 28 Nov 2013 09:57:16 +0100 Subject: [PATCH 354/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index a7b1e7e..65c1a3a 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit a7b1e7e0db5db914d519bbe8135f7e29cadfb8b7 +Subproject commit 65c1a3ab6e411aec30c3145178fac9f7fdbab87f From c8204dc90e4d345768870d56a631b9f3e7968460 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 30 Nov 2013 10:19:52 +0100 Subject: [PATCH 355/572] added icon for #13 --- widgets/yawn/icons/LightSnow.png | 1 + widgets/yawn/icons/Mist.png | 1 + 2 files changed, 2 insertions(+) create mode 120000 widgets/yawn/icons/LightSnow.png create mode 120000 widgets/yawn/icons/Mist.png diff --git a/widgets/yawn/icons/LightSnow.png b/widgets/yawn/icons/LightSnow.png new file mode 120000 index 0000000..aa8b28e --- /dev/null +++ b/widgets/yawn/icons/LightSnow.png @@ -0,0 +1 @@ +LightSnowShowers.png \ No newline at end of file diff --git a/widgets/yawn/icons/Mist.png b/widgets/yawn/icons/Mist.png new file mode 120000 index 0000000..b615645 --- /dev/null +++ b/widgets/yawn/icons/Mist.png @@ -0,0 +1 @@ +Foggy.png \ No newline at end of file From c9634bf976a9d8b5f9606fdb8e2373f7e3bed8ac Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 2 Dec 2013 16:25:59 +0100 Subject: [PATCH 356/572] satisfied 'issue' #14 --- widgets/yawn/init.lua | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 7ab76fe..a2f756e 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -46,8 +46,7 @@ yawn_notification_preset = {} local function fetch_weather() local url = api_url .. units_set .. city_id - local f = io.popen("curl --connect-timeout 1 -fsm 1 '" - .. url .. "'" ) + local f = io.popen("curl --connect-timeout 1 -fsm 1 '" .. url .. "'" ) local text = f:read("*all") f:close() @@ -58,12 +57,12 @@ local function fetch_weather() yawn.icon:set_image(icon_path .. "na.png") if text == "" then weather_data = "Service not available at the moment." - yawn.widget:set_text("N/A") + yawn.widget:set_text(" N/A") else weather_data = "City not found!\n" .. "Are you sure " .. city_id .. " is your Yahoo city ID?" - yawn.widget:set_text("?") + yawn.widget:set_text(" ?") end return end @@ -75,7 +74,7 @@ local function fetch_weather() -- may still happens in case of bad connectivity if weather_data == "" then yawn.icon:set_image(icon_path .. "na.png") - yawn.widget:set_text("?") + yawn.widget:set_text(" ?") return end @@ -149,7 +148,7 @@ function yawn.hide() end function yawn.show(t_out) - if yawn.widget._layout.text == "?" + if yawn.widget._layout.text:match("?") then fetch_weather(settings) end From c6d748757d263251137c8615dc0f2c11eee5cb9c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 3 Dec 2013 02:29:12 -0800 Subject: [PATCH 357/572] Updated Home (markdown) --- Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Home.md b/Home.md index 9ba8362..5581a9e 100644 --- a/Home.md +++ b/Home.md @@ -6,7 +6,7 @@ Dependencies Package | Requested by | Reason of choice --- | --- | --- alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) | / -curl | widgets accessing network resources | LuaSocket is not a core library. LuaSSL is out of date. +curl | widgets accessing network resources | LuaSocket is not a core library, and still not available for Lua 5.2+. LuaSSL is out of date. imagemagick | album arts in [mpd](https://github.com/copycat-killer/lain/wiki/mpd) notifications | Cairo doesn't do high quality filtering. Installation From 53c17b285e286cfae9870c0273aa0d896068b8aa Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 3 Dec 2013 02:29:29 -0800 Subject: [PATCH 358/572] Updated Home (markdown) --- Home.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Home.md b/Home.md index 5581a9e..be89e32 100644 --- a/Home.md +++ b/Home.md @@ -6,7 +6,8 @@ Dependencies Package | Requested by | Reason of choice --- | --- | --- alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) | / -curl | widgets accessing network resources | LuaSocket is not a core library, and still not available for Lua 5.2+. LuaSSL is out of date. +curl | widgets accessing network resources | LuaSocket is not a core library, and still not available for Lua 5.2+. +LuaSSL is out of date. imagemagick | album arts in [mpd](https://github.com/copycat-killer/lain/wiki/mpd) notifications | Cairo doesn't do high quality filtering. Installation From 9c916d5b05f729a3c71d74393d5e4ad8bddd8314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20G=C3=B6rlich?= Date: Wed, 4 Dec 2013 13:30:29 +0100 Subject: [PATCH 359/572] Count id tokens instead of every single diget --- widgets/imap.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/widgets/imap.lua b/widgets/imap.lua index b3f281d..87a9e61 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -61,9 +61,7 @@ local function worker(args) ws = f:read("*all") f:close() - t, mailcount = string.gsub(ws, "%d", "") - t = nil - mailcount = tonumber(mailcount) + _, mailcount = string.gsub(ws, "%d+", "") widget = imap.widget settings() From d4f59f292c3c499d997323f3c88b860775cad0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20G=C3=B6rlich?= Date: Wed, 4 Dec 2013 18:52:40 +0100 Subject: [PATCH 360/572] Fix unread count in imap widget --- widgets/imap.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/widgets/imap.lua b/widgets/imap.lua index 87a9e61..39518bd 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -62,6 +62,7 @@ local function worker(args) f:close() _, mailcount = string.gsub(ws, "%d+", "") + _ = nil widget = imap.widget settings() From 7b6d89cd4ff2b84fd333c8f6a5f0ef079b845f48 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 5 Dec 2013 01:18:49 -0800 Subject: [PATCH 361/572] Updated Home (markdown) --- Home.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Home.md b/Home.md index be89e32..5581a9e 100644 --- a/Home.md +++ b/Home.md @@ -6,8 +6,7 @@ Dependencies Package | Requested by | Reason of choice --- | --- | --- alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) | / -curl | widgets accessing network resources | LuaSocket is not a core library, and still not available for Lua 5.2+. -LuaSSL is out of date. +curl | widgets accessing network resources | LuaSocket is not a core library, and still not available for Lua 5.2+. LuaSSL is out of date. imagemagick | album arts in [mpd](https://github.com/copycat-killer/lain/wiki/mpd) notifications | Cairo doesn't do high quality filtering. Installation From f89991fe26dd904b05f4bac25f71e7d7d45c2206 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 5 Dec 2013 10:19:16 +0100 Subject: [PATCH 362/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index 65c1a3a..7b6d89c 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 65c1a3ab6e411aec30c3145178fac9f7fdbab87f +Subproject commit 7b6d89cd4ff2b84fd333c8f6a5f0ef079b845f48 From 66665bd8d33c016b06f41ff735b2d2ea0834647e Mon Sep 17 00:00:00 2001 From: yawnt Date: Mon, 23 Dec 2013 08:04:02 -0800 Subject: [PATCH 363/572] Created brightness (markdown) --- brightness.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 brightness.md diff --git a/brightness.md b/brightness.md new file mode 100644 index 0000000..590359a --- /dev/null +++ b/brightness.md @@ -0,0 +1,40 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + +Shows brightness level in a textbox. + + volumewidget = lain.widgets.contrib.brightness() + +### input table + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`timeout` | Refresh timeout seconds | int | 5 +`backlight` | Backlight Video | string | "acpi_video0" +`settings` | User settings | function | empty function + +`settings` can use the following variables: + +Variable | Meaning | Type | Values +--- | --- | --- | --- +`brightness_now` | Brightness level | int | 0-100 + +### output table + +Variable | Meaning | Type +--- | --- | --- +`widget` | The widget | `wibox.widget.textbox` +`update` | Update `widget` | function + +You can control the widget with key bindings like these: + + -- Volume control + awful.key({}, "XF86MonBrightnessUp", + function () + awful.util.spawn("xbacklight -inc 1") + brightnesswidget.update() + end), + awful.key({}, "XF86MonBrightnessDown", + function () + awful.util.spawn("xbacklight -dec 1") + brightnesswidget.update() + end), From 0bd5a1cdcb18e79b785469c0348a4c50d54864d4 Mon Sep 17 00:00:00 2001 From: yawnt Date: Mon, 23 Dec 2013 17:19:25 +0100 Subject: [PATCH 364/572] contrib-widget: brightness --- widgets/contrib/brightness.lua | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 widgets/contrib/brightness.lua diff --git a/widgets/contrib/brightness.lua b/widgets/contrib/brightness.lua new file mode 100644 index 0000000..bf14baf --- /dev/null +++ b/widgets/contrib/brightness.lua @@ -0,0 +1,46 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, yawnt + +--]] + +local newtimer = require("lain.helpers").newtimer + +local wibox = require("wibox") +local io = { popen = io.popen } +local string = { match = string.match } + +local setmetatable = setmetatable + +-- Brightness +-- lain.widgets.contrib.brightness +local brightness = {} + +local function worker(args) + local args = args or {} + local backlight = args.backlight or "acpi_video0" + local timeout = args.timeout or 5 + local settings = args.settings or function() end + + brightness.widget = wibox.widget.textbox('') + + function brightness.update() + local f = assert(io.popen('cat /sys/class/backlight/' .. backlight .. "/brightness")) + + brightness_now = { + level = f:read("*a") + } + f:close() + + widget = brightness.widget + settings() + end + + newtimer("brightness", timeout, brightness.update) + + return setmetatable(brightness, { __index = brightness.widget }) +end + +return setmetatable(brightness, { __call = function(_, ...) return worker(...) end }) From 0345cc3576955b37a981ee8f38d11e99c82dbb31 Mon Sep 17 00:00:00 2001 From: yawnt Date: Mon, 23 Dec 2013 18:04:06 +0100 Subject: [PATCH 365/572] fix: better code --- widgets/contrib/brightness.lua | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/widgets/contrib/brightness.lua b/widgets/contrib/brightness.lua index bf14baf..6967572 100644 --- a/widgets/contrib/brightness.lua +++ b/widgets/contrib/brightness.lua @@ -1,9 +1,9 @@ --[[ - - Licensed under GNU General Public License v2 + + Licensed under GNU General Public License v2 * (c) 2013, yawnt - + --]] local newtimer = require("lain.helpers").newtimer @@ -14,7 +14,7 @@ local string = { match = string.match } local setmetatable = setmetatable --- Brightness +-- Brightness -- lain.widgets.contrib.brightness local brightness = {} @@ -28,12 +28,9 @@ local function worker(args) function brightness.update() local f = assert(io.popen('cat /sys/class/backlight/' .. backlight .. "/brightness")) - - brightness_now = { - level = f:read("*a") - } + brightness_now = f:read("*a") f:close() - + widget = brightness.widget settings() end From ba7f3b15ec47e9293628e10565f55fca72dca05f Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 23 Dec 2013 09:10:31 -0800 Subject: [PATCH 366/572] Created brigthness (markdown) --- brigthness.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 brigthness.md diff --git a/brigthness.md b/brigthness.md new file mode 100644 index 0000000..b0dfe76 --- /dev/null +++ b/brigthness.md @@ -0,0 +1,24 @@ +[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) + +Shows the current level of screen brightness. + + mybrightness = lain.widgets.contrib.brightness() + +### input table + +Variable | Meaning | Type | Default +--- | --- | --- | --- +`backlight` | Card managing backlight | `acpi_video0` +`timeout` | Refresh timeout seconds | int | 5 +`settings` | User settings | function | empty function + +`settings` can use the string `brightness_now`, which indicates the current brightness level. + +### output table + +Variable | Meaning | Type +--- | --- | --- +`widget` | The textbox | `wibox.widget.textbox` +`update` | The notification | function + +You can control the widget with key bindings like these: [TODO] \ No newline at end of file From 09abc245c1190e6db675eccf232afff3af1cf4ac Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 23 Dec 2013 09:11:07 -0800 Subject: [PATCH 367/572] Updated Widgets (markdown) --- Widgets.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index 8a8945b..12178e2 100644 --- a/Widgets.md +++ b/Widgets.md @@ -49,4 +49,5 @@ Users contributed ---------------- - [task](https://github.com/copycat-killer/lain/wiki/task) -- [tpbat](https://github.com/copycat-killer/lain/wiki/tpbat) \ No newline at end of file +- [tpbat](https://github.com/copycat-killer/lain/wiki/tpbat) +- [brightness](https://github.com/copycat-killer/lain/wiki/brigthness) \ No newline at end of file From 346db7c907c29bbe01c238c70ef5e2a16060c44c Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 23 Dec 2013 09:14:39 -0800 Subject: [PATCH 369/572] Updated brightness (markdown) --- brightness.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/brightness.md b/brightness.md index 590359a..5a3a9db 100644 --- a/brightness.md +++ b/brightness.md @@ -1,15 +1,15 @@ [<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -Shows brightness level in a textbox. +Shows the current level of screen brightness in a textbox. - volumewidget = lain.widgets.contrib.brightness() + mybrightness = lain.widgets.contrib.brightness() ### input table Variable | Meaning | Type | Default --- | --- | --- | --- `timeout` | Refresh timeout seconds | int | 5 -`backlight` | Backlight Video | string | "acpi_video0" +`backlight` | Backlight video | string | "acpi_video0" `settings` | User settings | function | empty function `settings` can use the following variables: @@ -37,4 +37,4 @@ You can control the widget with key bindings like these: function () awful.util.spawn("xbacklight -dec 1") brightnesswidget.update() - end), + end), \ No newline at end of file From 507d34eec1cf963036d5f30ce8c960cc2b82bdf3 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 23 Dec 2013 09:15:04 -0800 Subject: [PATCH 370/572] Updated Widgets (markdown) --- Widgets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets.md b/Widgets.md index 12178e2..5917aac 100644 --- a/Widgets.md +++ b/Widgets.md @@ -50,4 +50,4 @@ Users contributed - [task](https://github.com/copycat-killer/lain/wiki/task) - [tpbat](https://github.com/copycat-killer/lain/wiki/tpbat) -- [brightness](https://github.com/copycat-killer/lain/wiki/brigthness) \ No newline at end of file +- [brightness](https://github.com/copycat-killer/lain/wiki/brightness) \ No newline at end of file From e379b9649b88e4e88a95731565e65d92c86b2824 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 23 Dec 2013 09:17:57 -0800 Subject: [PATCH 371/572] Destroyed brigthness (markdown) --- brigthness.md | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 brigthness.md diff --git a/brigthness.md b/brigthness.md deleted file mode 100644 index b0dfe76..0000000 --- a/brigthness.md +++ /dev/null @@ -1,24 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows the current level of screen brightness. - - mybrightness = lain.widgets.contrib.brightness() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`backlight` | Card managing backlight | `acpi_video0` -`timeout` | Refresh timeout seconds | int | 5 -`settings` | User settings | function | empty function - -`settings` can use the string `brightness_now`, which indicates the current brightness level. - -### output table - -Variable | Meaning | Type ---- | --- | --- -`widget` | The textbox | `wibox.widget.textbox` -`update` | The notification | function - -You can control the widget with key bindings like these: [TODO] \ No newline at end of file From f37929e6701328949d199d8c914480c179e2ee2d Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 23 Dec 2013 18:18:33 +0100 Subject: [PATCH 372/572] wiki: new commit --- README.rst | 6 +++--- widgets/contrib/brightness.lua | 10 +++++----- wiki | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.rst b/README.rst index 8eba2fb..07f4ee7 100644 --- a/README.rst +++ b/README.rst @@ -28,11 +28,11 @@ Just make sure that: - Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions or using ``lain.helpers``. If something is unclear, and you can't write it in such a way that it will be clear, explain it with a comment. -- You test your changes before submitting to make sure that not only your code works, but have not broken other parts of the module too! +- You test your changes before submitting to make sure that not only your code works, but did not break other parts of the module too! -- You update ``wiki`` submodule with a thorough section. +- You eventually update ``wiki`` submodule with a thorough section. -Contributed widgets have to be put it in ``lain/widget/contrib``. +Contributed widgets have to be put in ``lain/widget/contrib``. Screenshots ----------- diff --git a/widgets/contrib/brightness.lua b/widgets/contrib/brightness.lua index 6967572..0ba2f45 100644 --- a/widgets/contrib/brightness.lua +++ b/widgets/contrib/brightness.lua @@ -1,9 +1,9 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2013, yawnt - + + Licensed under GNU General Public License v2 + * (c) 2013, yawnt + --]] local newtimer = require("lain.helpers").newtimer @@ -14,7 +14,7 @@ local string = { match = string.match } local setmetatable = setmetatable --- Brightness +-- Brightness level -- lain.widgets.contrib.brightness local brightness = {} diff --git a/wiki b/wiki index 7b6d89c..e379b96 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 7b6d89cd4ff2b84fd333c8f6a5f0ef079b845f48 +Subproject commit e379b9649b88e4e88a95731565e65d92c86b2824 From 9f6ff057f4b99704d9396a66c4f2896954541d2e Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 24 Dec 2013 03:28:49 -0800 Subject: [PATCH 373/572] Updated brightness (markdown) --- brightness.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/brightness.md b/brightness.md index 5a3a9db..4cd4f8e 100644 --- a/brightness.md +++ b/brightness.md @@ -2,7 +2,7 @@ Shows the current level of screen brightness in a textbox. - mybrightness = lain.widgets.contrib.brightness() + brightnesswidget = lain.widgets.contrib.brightness() ### input table @@ -27,7 +27,7 @@ Variable | Meaning | Type You can control the widget with key bindings like these: - -- Volume control + -- Brightness control awful.key({}, "XF86MonBrightnessUp", function () awful.util.spawn("xbacklight -inc 1") From a8d6e9aa27ba2d8674c4d3ee6c6229469e30539f Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 24 Dec 2013 12:29:37 +0100 Subject: [PATCH 374/572] wiki: some typos fixed --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index e379b96..9f6ff05 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit e379b9649b88e4e88a95731565e65d92c86b2824 +Subproject commit 9f6ff057f4b99704d9396a66c4f2896954541d2e From 0f5d6dc4a543871c3ab7e3c36f6988b3a3ceffa4 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 24 Dec 2013 03:33:15 -0800 Subject: [PATCH 375/572] Updated tpbat (markdown) --- tpbat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tpbat.md b/tpbat.md index 3d0b0e8..e54f469 100644 --- a/tpbat.md +++ b/tpbat.md @@ -6,4 +6,4 @@ Includes hover notification with more details. tpbatwidget = lain.widgets.contrib.tpbat() -Configuration is identical to [main bat widget's](https://github.com/copycat-killer/lain/wiki/bat). \ No newline at end of file +Configuration is identical to [standard bat widget's](https://github.com/copycat-killer/lain/wiki/bat). \ No newline at end of file From 89807acfccfceb936b18e6e9ebf669bec7e01a16 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 24 Dec 2013 03:33:29 -0800 Subject: [PATCH 376/572] Updated tpbat (markdown) --- tpbat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tpbat.md b/tpbat.md index e54f469..5a7ba0c 100644 --- a/tpbat.md +++ b/tpbat.md @@ -6,4 +6,4 @@ Includes hover notification with more details. tpbatwidget = lain.widgets.contrib.tpbat() -Configuration is identical to [standard bat widget's](https://github.com/copycat-killer/lain/wiki/bat). \ No newline at end of file +Configuration is identical to [standard battery widget's](https://github.com/copycat-killer/lain/wiki/bat). \ No newline at end of file From c8e07d2ec34cfb12907e4ccb5f29908aa8c98f5a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 30 Dec 2013 06:57:45 -0800 Subject: [PATCH 377/572] Updated Layouts (markdown) --- Layouts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Layouts.md b/Layouts.md index 1ddca95..045c2c9 100644 --- a/Layouts.md +++ b/Layouts.md @@ -101,7 +101,7 @@ cascade Cascade all windows of a tag. -You can control the offsets by setting those two variables: +You can control the offsets by setting these two variables: lain.layout.cascade.cascade_offset_x = 64 lain.layout.cascade.cascade_offset_y = 16 From fddeeff66466ca8f8bd7d06099eabd1feda10675 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 30 Dec 2013 19:18:01 +0100 Subject: [PATCH 378/572] yawn: new localization word --- widgets/yawn/localizations/it_IT | 3 ++- widgets/yawn/localizations/localization_template | 3 ++- wiki | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/widgets/yawn/localizations/it_IT b/widgets/yawn/localizations/it_IT index f1bfbe2..70b0eef 100644 --- a/widgets/yawn/localizations/it_IT +++ b/widgets/yawn/localizations/it_IT @@ -50,7 +50,8 @@ Windy|Ventoso Wind|Ventoso Snow|Neve Sleet|Nevischio -Drizzle|Pioggerella +Light Drizzle|Pioggia Leggera +Drizzle|Pioggia Leggera Freezing Drizzle|Pioggerella Congelantesi Hail|Grandine Fog|Nebbia diff --git a/widgets/yawn/localizations/localization_template b/widgets/yawn/localizations/localization_template index e3a948f..453807e 100644 --- a/widgets/yawn/localizations/localization_template +++ b/widgets/yawn/localizations/localization_template @@ -50,8 +50,9 @@ Windy| Wind| Snow| Sleet| -Drizzle| Freezing Drizzle| +Light Drizzle| +Drizzle| Hail| Fog| Foggy| diff --git a/wiki b/wiki index 9f6ff05..c8e07d2 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 9f6ff057f4b99704d9396a66c4f2896954541d2e +Subproject commit c8e07d2ec34cfb12907e4ccb5f29908aa8c98f5a From 07a230fb1654cc6abc1bd1ea8b36d8dcb3c1ad62 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 2 Jan 2014 03:16:09 -0800 Subject: [PATCH 379/572] Updated calendar (markdown) --- calendar.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/calendar.md b/calendar.md index fa4e563..b06c453 100644 --- a/calendar.md +++ b/calendar.md @@ -26,4 +26,6 @@ You can call the notification with a key binding like this: awful.key({ altkey }, "c", function () lain.widgets.calendar:show(7) end), -where ``altkey = "Mod1"`` and ``show`` argument is an optional integer, meaning timeout seconds. \ No newline at end of file +where ``altkey = "Mod1"`` and ``show`` argument is an optional integer, meaning timeout seconds. + +**Note that** this widget exploits ``cal`` to do the alignment, in order to avoid more dozens of code lines, but this requires that your system font is monospaced. \ No newline at end of file From b7fbde4042a9275e9454acb6e586896319cf1455 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 4 Jan 2014 12:23:24 +0100 Subject: [PATCH 380/572] #18 fixed --- widgets/temp.lua | 10 ++++++++-- wiki | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/widgets/temp.lua b/widgets/temp.lua index b57c477..b55d52f 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -28,8 +28,14 @@ local function worker(args) function update() local f = io.open("/sys/class/thermal/thermal_zone0/temp") - coretemp_now = tonumber(f:read("*all")) / 1000 - f:close() + if f ~= nil + then + coretemp_now = tonumber(f:read("*all")) / 1000 + f:close() + else + coretemp_now = "N/A" + end + widget = temp.widget settings() end diff --git a/wiki b/wiki index c8e07d2..07a230f 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit c8e07d2ec34cfb12907e4ccb5f29908aa8c98f5a +Subproject commit 07a230fb1654cc6abc1bd1ea8b36d8dcb3c1ad62 From 8207714a8b362ecbae1a2a2a676ffb5922a419c2 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 4 Jan 2014 12:35:16 +0100 Subject: [PATCH 381/572] wiki updated --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 07f4ee7..f59c04d 100644 --- a/README.rst +++ b/README.rst @@ -6,7 +6,7 @@ Layouts, widgets and utilities for Awesome WM --------------------------------------------- :Author: Luke Bonham -:Version: 1.0-git +:Version: git :License: GNU-GPLv2_ :Source: https://github.com/copycat-killer/lain From 28b9a0b91312e080f352c6bde89bbc3718215b30 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 9 Jan 2014 14:33:18 +0100 Subject: [PATCH 382/572] brigthness: unused lib removed --- widgets/contrib/brightness.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/widgets/contrib/brightness.lua b/widgets/contrib/brightness.lua index 0ba2f45..04b8d2b 100644 --- a/widgets/contrib/brightness.lua +++ b/widgets/contrib/brightness.lua @@ -10,7 +10,6 @@ local newtimer = require("lain.helpers").newtimer local wibox = require("wibox") local io = { popen = io.popen } -local string = { match = string.match } local setmetatable = setmetatable From 780ce12033c8aa90c5060280cfbdfd6fddc7584f Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 13 Jan 2014 04:01:31 -0800 Subject: [PATCH 383/572] Updated bat (markdown) --- bat.md | 1 + 1 file changed, 1 insertion(+) diff --git a/bat.md b/bat.md index 50c14e8..82e7a8b 100644 --- a/bat.md +++ b/bat.md @@ -13,6 +13,7 @@ Variable | Meaning | Type | Default --- | --- | --- | --- `timeout` | Refresh timeout seconds | int | 30 `battery` | Identifier of the battery | string | "BAT0" +`notify` | Enable notifications | boolean | true `settings` | User settings | function | empty function `settings` can use the `bat_now` table, which contains the following strings: From b521dbdc8b305bc9580fe6a17d847fe5e1e22cd0 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 13 Jan 2014 13:03:21 +0100 Subject: [PATCH 384/572] pull #19 satisfaction --- widgets/bat.lua | 3 ++- wiki | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 2906de2..b3f91dd 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -27,6 +27,7 @@ local function worker(args) local args = args or {} local timeout = args.timeout or 30 local battery = args.battery or "BAT0" + local notify = args.notify or true local settings = args.settings or function() end bat.widget = wibox.widget.textbox('') @@ -96,7 +97,7 @@ local function worker(args) end -- notifications for low and critical states - if bat_now.status == "Discharging" + if bat_now.status == "Discharging" and notify then if tonumber(bat_now.perc) <= 5 then diff --git a/wiki b/wiki index 07a230f..780ce12 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 07a230fb1654cc6abc1bd1ea8b36d8dcb3c1ad62 +Subproject commit 780ce12033c8aa90c5060280cfbdfd6fddc7584f From 270c5fa6b12aeaa5cfb80716d119424d805e2465 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 14 Jan 2014 09:46:06 +0100 Subject: [PATCH 385/572] revert to original pull request #19 --- widgets/bat.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index b3f91dd..48a14fb 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -27,7 +27,7 @@ local function worker(args) local args = args or {} local timeout = args.timeout or 30 local battery = args.battery or "BAT0" - local notify = args.notify or true + local notify = args.notify or "on" local settings = args.settings or function() end bat.widget = wibox.widget.textbox('') @@ -97,7 +97,7 @@ local function worker(args) end -- notifications for low and critical states - if bat_now.status == "Discharging" and notify + if bat_now.status == "Discharging" and notify == "on" then if tonumber(bat_now.perc) <= 5 then From ac4b4d5d555c94015700c55ff294bf8e7d1645ef Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 14 Jan 2014 00:53:12 -0800 Subject: [PATCH 386/572] Updated bat (markdown) --- bat.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bat.md b/bat.md index 82e7a8b..c450dbe 100644 --- a/bat.md +++ b/bat.md @@ -13,7 +13,7 @@ Variable | Meaning | Type | Default --- | --- | --- | --- `timeout` | Refresh timeout seconds | int | 30 `battery` | Identifier of the battery | string | "BAT0" -`notify` | Enable notifications | boolean | true +`notify` | Enable notifications | string | "on" `settings` | User settings | function | empty function `settings` can use the `bat_now` table, which contains the following strings: @@ -23,6 +23,8 @@ Variable | Meaning | Type | Default - `time`; - `watt`. +To disable warning notifications, set `notify` to `off`. + ### output A textbox. \ No newline at end of file From b81da3a243ca8be6c778041e2f91cacb31470122 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 14 Jan 2014 00:53:56 -0800 Subject: [PATCH 387/572] Updated bat (markdown) --- bat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bat.md b/bat.md index c450dbe..6bbb21e 100644 --- a/bat.md +++ b/bat.md @@ -23,7 +23,7 @@ Variable | Meaning | Type | Default - `time`; - `watt`. -To disable warning notifications, set `notify` to `off`. +To disable warning notifications, set `notify` to `"off"`. ### output From 41d28b93ebbeb7e51584032e88c748426ea6cd82 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 14 Jan 2014 01:05:55 -0800 Subject: [PATCH 388/572] Updated alsabar (markdown) --- alsabar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alsabar.md b/alsabar.md index fa5f209..6138f2c 100644 --- a/alsabar.md +++ b/alsabar.md @@ -16,7 +16,7 @@ Variable | Meaning | Type | Default `settings` | User settings | function | empty function `width` | Bar width | int | 63 `height` | Bar height | int | 1 -`ticks` | Set bar ticks on | boolean | true +`ticks` | Set bar ticks on | boolean | false `ticks_size` | Ticks size | int | 7 `vertical` | Set the bar vertical | boolean | false `channel` | Mixer channel | string | "Master" From e0b6dd443ce1895e668313a93939f489fbd2ea05 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 14 Jan 2014 10:09:57 +0100 Subject: [PATCH 389/572] alsabar: fixed 'ticks' boolean issue; wiki updated --- widgets/alsabar.lua | 5 ++--- wiki | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 90d3a0d..365ac2d 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -95,7 +95,7 @@ local function worker(args) local settings = args.settings or function() end local width = args.width or 63 local height = args.heigth or 1 - local ticks = args.ticks or true + local ticks = args.ticks or false local ticks_size = args.ticks_size or 7 local vertical = args.vertical or false @@ -113,8 +113,7 @@ local function worker(args) alsabar.bar:set_height(height) alsabar.bar:set_ticks(ticks) alsabar.bar:set_ticks_size(ticks_size) - - if vertical then alsabar.bar:set_vertical(true) end + alsabar.bar:set_vertical(vertical) function alsabar.update() -- Get mixer control contents diff --git a/wiki b/wiki index 780ce12..41d28b9 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 780ce12033c8aa90c5060280cfbdfd6fddc7584f +Subproject commit 41d28b93ebbeb7e51584032e88c748426ea6cd82 From dd10cac1306530f46f0e8506156e1ef21b456fae Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 20 Jan 2014 09:52:35 -0800 Subject: [PATCH 390/572] Updated imap (markdown) --- imap.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/imap.md b/imap.md index ba92d0f..b0d5375 100644 --- a/imap.md +++ b/imap.md @@ -31,16 +31,26 @@ Variable | Meaning | Type | Default Let's focus better on `is_plain`. -You can just set your password like this: +The reason why it's false by default is to discourage the habit of storing passwords in plain files. - args.is_plain = false - args.password = "mypassword" +You can set your password in plain like this: + + myimapcheck = lain.widgets.imap({ + is_plain = true, + password = "myplainpassword", + [...] + }) and you'll have the same security provided by `~/.netrc`. **Or** you can use a keyring, like [python keyring](https://pypi.python.org/pypi/keyring): - args.password = "keyring get password" + myimapcheck = lain.widgets.imap({ + is_plain = true, + password = "myplainpassword", + server = "mail.autistici.org", + mail = "dada@anche.no", + }) When `is_plain == false`, it *executes* `password` before using it, so you can also use whatever password fetching solution you want. From a11f76cf00b430d3f7eec710879847cb654fe17f Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 20 Jan 2014 09:53:32 -0800 Subject: [PATCH 391/572] Updated imap (markdown) --- imap.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/imap.md b/imap.md index b0d5375..7952c81 100644 --- a/imap.md +++ b/imap.md @@ -46,10 +46,8 @@ and you'll have the same security provided by `~/.netrc`. **Or** you can use a keyring, like [python keyring](https://pypi.python.org/pypi/keyring): myimapcheck = lain.widgets.imap({ - is_plain = true, - password = "myplainpassword", - server = "mail.autistici.org", - mail = "dada@anche.no", + password = "keyring get mymail", + [...] }) When `is_plain == false`, it *executes* `password` before using it, so you can also use whatever password fetching solution you want. From 48fc17f8cd29d16c20b3bd5f482602dd70c891c5 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 20 Jan 2014 19:12:00 +0100 Subject: [PATCH 393/572] wiki: improved imap widget section --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index 41d28b9..ecf143b 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 41d28b93ebbeb7e51584032e88c748426ea6cd82 +Subproject commit ecf143be0d664ce754edeb1ed0ead3bd1104c7e6 From 60dc042b1f6fc1f9f3ce9e2b78e75af2f80bfe79 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 20 Jan 2014 10:14:22 -0800 Subject: [PATCH 394/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index 7952c81..f754348 100644 --- a/imap.md +++ b/imap.md @@ -31,7 +31,7 @@ Variable | Meaning | Type | Default Let's focus better on `is_plain`. -The reason why it's false by default is to discourage the habit of storing passwords in plain files. +The reason why it's false by default is to discourage the habit of storing passwords in plain. You can set your password in plain like this: From f996cdb74e7583534256d82706ef63d2b9811b42 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 20 Jan 2014 10:14:42 -0800 Subject: [PATCH 395/572] Updated imap (markdown) --- imap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.md b/imap.md index f754348..403a61a 100644 --- a/imap.md +++ b/imap.md @@ -33,7 +33,7 @@ Let's focus better on `is_plain`. The reason why it's false by default is to discourage the habit of storing passwords in plain. -You can set your password in plain like this: +So you can set your password in plain like this: myimapcheck = lain.widgets.imap({ is_plain = true, From cc739f08e74418d870df1389338cc5ccead57538 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 20 Jan 2014 19:15:19 +0100 Subject: [PATCH 396/572] wiki: improved imap widget section --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index ecf143b..f996cdb 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit ecf143be0d664ce754edeb1ed0ead3bd1104c7e6 +Subproject commit f996cdb74e7583534256d82706ef63d2b9811b42 From cbb144a79e8c4c243ac0b56d90945652a21e8db9 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 21 Jan 2014 15:42:33 +0100 Subject: [PATCH 397/572] revert #9; discouraging #21 and #22 situations --- widgets/mpd.lua | 16 ++-------------- widgets/yawn/init.lua | 2 +- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 36c3ed7..1749b57 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -38,19 +38,7 @@ local function worker(args) local mpdcover = helpers.scripts_dir .. "mpdcover" local mpdh = "telnet://" .. host .. ":" .. port - - local echo = nil - - if password == "" then - echo = "(echo -e 'status'; sleep 0.1;" .. - "echo -e 'currentsong'; sleep 0.1;" .. - "echo -e 'close')" - else - echo = "(echo -e 'password " .. password .. "'" .. - "echo -e 'status'; sleep 0.1;" .. - "echo -e 'currentsong'; sleep 0.1;" .. - "echo -e 'close')" - end + local echo = "echo 'password " .. password .. "\nstatus\ncurrentsong\nclose'" mpd.widget = wibox.widget.textbox('') @@ -71,7 +59,7 @@ local function worker(args) date = "N/A" } - local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 1 " .. mpdh) + local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh) for line in f:lines() do for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index a2f756e..36cdf54 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -46,7 +46,7 @@ yawn_notification_preset = {} local function fetch_weather() local url = api_url .. units_set .. city_id - local f = io.popen("curl --connect-timeout 1 -fsm 1 '" .. url .. "'" ) + local f = io.popen("curl --connect-timeout 1 -fsm 3 '" .. url .. "'" ) local text = f:read("*all") f:close() From 3a387e9f49b3b94c2907fe5e9730a6ae3f6662e1 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 21 Jan 2014 16:01:28 +0100 Subject: [PATCH 398/572] simple fix to #20 --- widgets/temp.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/widgets/temp.lua b/widgets/temp.lua index b55d52f..61a9aa5 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -22,12 +22,13 @@ local temp = {} local function worker(args) local args = args or {} local timeout = args.timeout or 5 + local tempfile = args.tempfile or "/sys/class/thermal/thermal_zone0/temp" local settings = args.settings or function() end temp.widget = wibox.widget.textbox('') function update() - local f = io.open("/sys/class/thermal/thermal_zone0/temp") + local f = io.open(tempfile) if f ~= nil then coretemp_now = tonumber(f:read("*all")) / 1000 From f87b80a92ce3a34c3f5843647be9c2189da53d99 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 21 Jan 2014 16:03:04 +0100 Subject: [PATCH 399/572] wiki updated --- Home.md | 34 ------ Layouts.md | 298 -------------------------------------------------- Utilities.md | 163 --------------------------- Widgets.md | 53 --------- alsa.md | 53 --------- alsabar.md | 85 -------------- bat.md | 30 ----- borderbox.md | 49 --------- brightness.md | 40 ------- calendar.md | 31 ------ cpu.md | 18 --- fs.md | 45 -------- imap.md | 68 ------------ maildir.md | 39 ------- mem.md | 18 --- mpd.md | 85 -------------- net.md | 26 ----- sysload.md | 18 --- task.md | 30 ----- temp.md | 20 ---- tpbat.md | 9 -- wiki | 2 +- yawn.md | 93 ---------------- 23 files changed, 1 insertion(+), 1306 deletions(-) delete mode 100644 Home.md delete mode 100644 Layouts.md delete mode 100644 Utilities.md delete mode 100644 Widgets.md delete mode 100644 alsa.md delete mode 100644 alsabar.md delete mode 100644 bat.md delete mode 100644 borderbox.md delete mode 100644 brightness.md delete mode 100644 calendar.md delete mode 100644 cpu.md delete mode 100644 fs.md delete mode 100644 imap.md delete mode 100644 maildir.md delete mode 100644 mem.md delete mode 100644 mpd.md delete mode 100644 net.md delete mode 100644 sysload.md delete mode 100644 task.md delete mode 100644 temp.md delete mode 100644 tpbat.md delete mode 100644 yawn.md diff --git a/Home.md b/Home.md deleted file mode 100644 index 5581a9e..0000000 --- a/Home.md +++ /dev/null @@ -1,34 +0,0 @@ -Welcome to the Lain wiki! - -Dependencies ------------------- - -Package | Requested by | Reason of choice ---- | --- | --- -alsa-utils | [alsa](https://github.com/copycat-killer/lain/wiki/alsa), [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) | / -curl | widgets accessing network resources | LuaSocket is not a core library, and still not available for Lua 5.2+. LuaSSL is out of date. -imagemagick | album arts in [mpd](https://github.com/copycat-killer/lain/wiki/mpd) notifications | Cairo doesn't do high quality filtering. - -Installation ---------------- - -### Arch Linux - -[AUR package](https://aur.archlinux.org/packages/lain/) - -### Other distributions - - git clone https://github.com/copycat-killer/lain.git ~/.config/awesome/lain - -Usage --------- - -First, include it into your `rc.lua`: - - local lain = require("lain") - -Then check out the submodules you want: - -- [Layouts](https://github.com/copycat-killer/lain/wiki/Layouts) -- [Widgets](https://github.com/copycat-killer/lain/wiki/Widgets) -- [Utilities](https://github.com/copycat-killer/lain/wiki/Utilities) \ No newline at end of file diff --git a/Layouts.md b/Layouts.md deleted file mode 100644 index 045c2c9..0000000 --- a/Layouts.md +++ /dev/null @@ -1,298 +0,0 @@ -Currently, there are **8** layouts. - - lain/layout - . - |-- termfair - |-- centerfair - |-- cascade - |-- cascadetile - |-- centerwork - |-- uselessfair - |-- uselesspiral - `-- uselesstile - -Just add your favourites to ``layouts`` table: - - layouts = - { - ... - lain.layout.termfair, - lain.layout.uselesstile, - ... - } - -Or set them on specific tags like this: - - awful.layout.set(lain.layout.uselessfair, tags[1][7]) - -How do layouts work? -========================= - -termfair --------- - -I do a lot of work on terminals. The common tiling algorithms usually -maximize windows, so you'll end up with a terminal that has about 200 -columns or more. That's way too much. Have you ever read a manpage in a -terminal of this size? - -This layout restricts the size of each window. Each window will have the -same width but is variable in height. Furthermore, windows are -left-aligned. The basic workflow is as follows (the number above the -screen is the number of open windows, the number in a cell is the fixed -number of a client): - - (1) (2) (3) - +---+---+---+ +---+---+---+ +---+---+---+ - | | | | | | | | | | | | - | 1 | | | -> | 2 | 1 | | -> | 3 | 2 | 1 | -> - | | | | | | | | | | | | - +---+---+---+ +---+---+---+ +---+---+---+ - - (4) (5) (6) - +---+---+---+ +---+---+---+ +---+---+---+ - | 4 | | | | 5 | 4 | | | 6 | 5 | 4 | - +---+---+---+ -> +---+---+---+ -> +---+---+---+ - | 3 | 2 | 1 | | 3 | 2 | 1 | | 3 | 2 | 1 | - +---+---+---+ +---+---+---+ +---+---+---+ - -The first client will be located in the left column. When opening -another window, this new window will be placed in the left column while -moving the first window into the middle column. Once a row is full, -another row above it will be created. - -Default number of columns and rows are respectively taken from `nmaster` -and `ncol` values in `awful.tag`, but you can set your own. - -For example, this sets `termfair` to 3 columns and at least 1 row: - - lain.layout.termfair.nmaster = 3 - lain.layout.termfair.ncol = 1 - -centerfair ----------- - -Similar to `termfair`, but with fixed number of vertical columns. Cols are centerded until there are `nmaster` columns, then windows are stacked as slaves, with possibly `ncol` clients per column at most. - - (1) (2) (3) - +---+---+---+ +-+---+---+-+ +---+---+---+ - | | | | | | | | | | | | | - | | 1 | | -> | | 1 | 2 | | -> | 1 | 2 | 3 | -> - | | | | | | | | | | | | | - +---+---+---+ +-+---+---+-+ +---+---+---+ - - (4) (5) - +---+---+---+ +---+---+---+ - | | | 3 | | | 2 | 4 | - + 1 + 2 +---+ -> + 1 +---+---+ - | | | 4 | | | 3 | 5 | - +---+---+---+ +---+---+---+ - -Like `termfair`, default number of columns and rows are respectively taken from `nmaster` -and `ncol` values in `awful.tag`, but you can set your own. - -For example: - - lain.layout.centerfair.nmaster = 3 - lain.layout.centerfair.ncol = 1 - -cascade -------- - -Cascade all windows of a tag. - -You can control the offsets by setting these two variables: - - lain.layout.cascade.cascade_offset_x = 64 - lain.layout.cascade.cascade_offset_y = 16 - -The following reserves space for 5 windows: - - lain.layout.cascade.nmaster = 5 - -That is, no window will get resized upon the creation of a new window, -unless there's more than 5 windows. - -cascadetile ------------ - -Similar to `awful.layout.suit.tile` layout, however, clients in the slave -column are cascaded instead of tiled. - -Left column size can be set, otherwise is controlled by `mwfact` of the -tag. Additional windows will be opened in another column on the right. -New windows are placed above old windows. - -Whether the slave column is placed on top of the master window or not is -controlled by the value of `ncol`. A value of 1 means "overlapping slave column" -and anything else means "don't overlap windows". - -Usage example: - - lain.layout.cascadetile.cascade_offset_x = 2 - lain.layout.cascadetile.cascade_offset_y = 32 - lain.layout.cascadetile.extra_padding = 5 - lain.layout.cascadetile.nmaster = 5 - lain.layout.ncol = 1 - -`extra_padding` reduces the size of the master window if "overlapping -slave column" is activated. This allows you to see if there are any -windows in your slave column. - -Setting `cascade_offset_x` to a very small value or even 0 is reccommended to avoid wasting space. - -centerwork ----------- - -You start with one window, centered horizontally: - - +--------------------------+ - | +----------+ | - | | | | - | | | | - | | | | - | | MAIN | | - | | | | - | | | | - | | | | - | | | | - | +----------+ | - +--------------------------+ - -This is your main working window. You do most of the work right here. -Sometimes, you may want to open up additional windows. They're put in -the following four slots: - - +--------------------------+ - | +---+ +----------+ +---+ | - | | | | | | | | - | | 0 | | | | 1 | | - | | | | | | | | - | +---+ | MAIN | +---+ | - | +---+ | | +---+ | - | | | | | | | | - | | 2 | | | | 3 | | - | | | | | | | | - | +---+ +----------+ +---+ | - +--------------------------+ - -Yes, the number "four" is fixed. In total, you can only have five open -windows with this layout. Additional windows are not managed and set to -floating mode. **This is intentional**. - -You can set the order of the four auxiliary windows. This is the default -configuration: - - lain.layout.centerwork.top_left = 0 - lain.layout.centerwork.top_right = 1 - lain.layout.centerwork.bottom_left = 2 - lain.layout.centerwork.bottom_right = 3 - -This means: The bottom left slot will be occupied by the third window -(not counting the main window). Suppose you want your windows to appear -in this order: - - +--------------------------+ - | +---+ +----------+ +---+ | - | | | | | | | | - | | 3 | | | | 0 | | - | | | | | | | | - | +---+ | MAIN | +---+ | - | +---+ | | +---+ | - | | | | | | | | - | | 2 | | | | 1 | | - | | | | | | | | - | +---+ +----------+ +---+ | - +--------------------------+ - -This would require you to use these settings: - - lain.layout.centerwork.top_left = 3 - lain.layout.centerwork.top_right = 0 - lain.layout.centerwork.bottom_left = 2 - lain.layout.centerwork.bottom_right = 1 - -*Please note:* If you use Awesome's default configuration, navigation in -this layout may be very confusing. How do you get from the main window -to satellite ones depends on the order in which the windows are opened. -Thus, use of `awful.client.focus.bydirection()` is suggested. -Here's an example: - - globalkeys = awful.util.table.join( - ... - awful.key({ modkey }, "j", - function() - awful.client.focus.bydirection("down") - if client.focus then client.focus:raise() end - end), - awful.key({ modkey }, "k", - function() - awful.client.focus.bydirection("up") - if client.focus then client.focus:raise() end - end), - awful.key({ modkey }, "h", - function() - awful.client.focus.bydirection("left") - if client.focus then client.focus:raise() end - end), - awful.key({ modkey }, "l", - function() - awful.client.focus.bydirection("right") - if client.focus then client.focus:raise() end - end), - ... - ) - -uselessfair, uselesspiral & uselesstile ---------------------------------------- -These are duplicates of the stock `fair`, `spiral` and `tile` layouts. - -However, "useless gaps" (see below) have been added. - -Useless gaps -============ - -Useless gaps are gaps between windows. They are "useless" because they -serve no special purpose despite increasing overview. I find it easier -to recognize window boundaries if windows are set apart a little bit. - -The `uselessfair` layout, for example, looks like this: - - +================+ - # # - # +---+ +---+ # - # | 1 | | | # - # +---+ | | # - # | 3 | # - # +---+ | | # - # | 2 | | | # - # +---+ +---+ # - # # - +================+ - -All of lain layouts provide useless gaps. To set the width of the gaps, -you have to add an item called `useless_gap_width` in your `theme.lua`. -If it doesn't exist, the width will default to 0. -Example: - - theme.useless_gap_width = 10 - -What about layout icons? -======================== - -They are located in ``lain/icons/layout``. - -To use them, add lines to your ``theme.lua`` like this: - - theme.lain_icons = os.getenv("HOME") .. "/.config/awesome/lain/icons/layout/default/" - theme.layout_termfair = theme.lain_icons .. "termfairw.png" - theme.layout_cascade = theme.lain_icons .. "cascadew.png" - theme.layout_cascadetile = theme.lain_icons .. "cascadetilew.png" - theme.layout_centerwork = theme.lain_icons .. "centerworkw.png" - -Credits goes to [Nicolas Estibals](https://github.com/nestibal) for creating -layout icons for default theme. - -You can use them as a template for your custom versions. - -[<- home](https://github.com/copycat-killer/lain/wiki) \ No newline at end of file diff --git a/Utilities.md b/Utilities.md deleted file mode 100644 index 99588b9..0000000 --- a/Utilities.md +++ /dev/null @@ -1,163 +0,0 @@ -markup ------- - -Made markup easier! - -First, require it like this: - - local markup = lain.util.markup - -then you can call its functions: - - +-- markup - | - |`-- bold() Set bold. - |`-- italic() Set italicized text. - |`-- strike() Set strikethrough text. - |`-- underline() Set underlined text. - |`-- monospace() Set monospaced text. - |`-- big() Set bigger text. - |`-- small() Set smaller text. - |`-- font() Set the font of the text. - | - |`--+ bg - | | - | |`-- color() Set background color. - | |`-- focus() Set focus background color. - | |`-- normal() Set normal background color. - | `-- urgent() Set urgent background color. - | - |`--+ fg - | | - | |`-- color() Set foreground color. - | |`-- focus() Set focus foreground color. - | |`-- normal() Set normal foreground color. - | `-- urgent() Set urgent foreground color. - | - |`-- focus() Set both foreground and background focus colors. - |`-- normal() Set both foreground and background normal colors. - `-- urgent() Set both foreground and background urgent colors. - -they all take one argument, which is the text to markup, except `fg.color` and `bg.color`: - - markup.fg.color(text, color) - markup.bg.color(text, color) - -dynamic tagging ---------------- - -That is: - -- add a new tag; -- rename current tag; -- move current tag; -- remove current tag. - -If you delete a tag, any rule set on it shall be broken, so be careful. - -Use it with key bindings like these: - - awful.key({ modkey, "Shift" }, "n", function () lain.util.add_tag(mypromptbox) end), - awful.key({ modkey, "Shift" }, "r", function () lain.util.rename_tag(mypromptbox) end), - awful.key({ modkey, "Shift" }, "Left", function () lain.util.move_tag(1) end), -- move to next tag - awful.key({ modkey, "Shift" }, "Right", function () lain.util.move_tag(-1) end), -- move to previous tag - awful.key({ modkey, "Shift" }, "d", function () lain.util.remove_tag() end), - -**Note** that these function won't work properly with [Copland theme](https://github.com/copycat-killer/awesome-copycats) or any other configuration that already uses a dynamic tagging module like [Eminent](https://github.com/copycat-killer/awesome-copycats/tree/master/eminent). - -useless\_gaps\_resize ---------------------- - -Changes `beautiful.useless_gaps_width` on the fly. - -The function takes an integer argument, being the amount of pixel to add/remove to gaps. - -You could use it with these keybindings: - - -- On the fly useless gaps change - awful.key({ altkey, "Control" }, "+", function () lain.util.useless_gaps_resize(1) end), - awful.key({ altkey, "Control" }, "-", function () lain.util.useless_gaps_resize(-1) end), - -where `altkey=Mod1`, or you could use it like this: - - mywidget:buttons(awful.util.table.join ( - awful.button({}, 4, function() lain.util.useless_gaps_resize(-1) end), - awful.button({}, 5, function() lain.util.useless_gaps_resize(1) end) - end) - )) - -so when hovering the mouse over `mywidget`, you can adjust useless gaps size by scrolling with the mouse wheel. - -tag\_view\_nonempty -------------------- - -This function lets you jump to the next/previous non-empty tag. -It takes two arguments: - -* `direction`: `1` for next non-empty tag, `-1` for previous. -* `sc`: Screen which the taglist is in. Default is `mouse.screen` or `1`. This - argument is optional. - -You can use it with key bindings like these: - - -- Non-empty tag browsing - awful.key({ altkey }, "Left", function () lain.util.tag_view_nonempty(-1) end), - awful.key({ altkey }, "Right", function () lain.util.tag_view_nonempty(1) end), - -where `altkey = "Mod1"`. - -menu\_clients\_current\_tags ----------------------------- - -Similar to `awful.menu.clients`, but this menu only shows the clients -of currently visible tags. Use it with a key binding like this: - - awful.key({ "Mod1" }, "Tab", - function() - awful.menu.menu_keys.down = { "Down", "Alt_L", "Tab", "j" } - awful.menu.menu_keys.up = { "Up", "k" } - lain.util.menu_clients_current_tags({ width = 350 }, { keygrabber = true }) - end), - -magnify\_client ---------------- - -Set a client to floating and resize it in the same way the "magnifier" -layout does it. Place it on the "current" screen (derived from the mouse -position). This allows you to magnify any client you wish, regardless of -the currently used layout. Use it with a client keybinding like this: - - clientkeys = awful.util.table.join( - ... - awful.key({ modkey, "Control" }, "m", lain.util.magnify_client), - ... - ) - -If you want to "de-magnify" it, just retype the keybinding. - -niceborder\_{focus, unfocus} ----------------------------- - -By default, your `rc.lua` contains something like this: - - client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end) - client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end) - -You can change it to this: - - client.connect_signal("focus", lain.util.niceborder_focus(c)) - client.connect_signal("unfocus", lain.util.niceborder_unfocus(c)) - -Now, when a client is focused or unfocused, Awesome will look up its -nice value in `/proc//stat`. If it's less than 0, the client is -classified as "high priority"; if it's greater than 0, the client is -classified as "low priority". If it's equal to 0, nothing special -happens. - -This requires to define additional colors in your `theme.lua`. For example: - - theme.border_focus_highprio = "#FF0000" - theme.border_normal_highprio = "#A03333" - - theme.border_focus_lowprio = "#3333FF" - theme.border_normal_lowprio = "#333366" \ No newline at end of file diff --git a/Widgets.md b/Widgets.md deleted file mode 100644 index 5917aac..0000000 --- a/Widgets.md +++ /dev/null @@ -1,53 +0,0 @@ -General usage -------------- - -Every widget is output by a `function`. - -For some widgets, `function` returns a `wibox.widget.textbox`, for others a table to be used for notification and update purposes. - -Every widget may take either a table or a list of variables as argument. - -If it takes a table, you have to define a function variable called `settings` in it, in order to make your customizations. - -To markup the textbox, call `widget:set_markup(...)` within `settings`. - -You can feed `set_markup` with predefined arguments, see the sections for all the details. - -`widget` is a textbox, so you can threat it like any other `wibox.widget.textbox`. - -Here follows an example: - - mycpu = lain.widgets.cpu({ - timeout = 4, - settings = function() - widget:set_markup("Cpu " .. cpu_now.usage) - end - }) - -If you want to see more complex applications, check [awesome-copycats](https://github.com/copycat-killer/awesome-copycats). - -Index ------ - -- [alsa](https://github.com/copycat-killer/lain/wiki/alsa) -- [alsabar](https://github.com/copycat-killer/lain/wiki/alsabar) -- [bat](https://github.com/copycat-killer/lain/wiki/bat) -- [borderbox](https://github.com/copycat-killer/lain/wiki/borderbox) -- [calendar](https://github.com/copycat-killer/lain/wiki/calendar) -- [cpu](https://github.com/copycat-killer/lain/wiki/cpu) -- [fs](https://github.com/copycat-killer/lain/wiki/fs) -- [imap](https://github.com/copycat-killer/lain/wiki/imap) -- [maildir](https://github.com/copycat-killer/lain/wiki/maildir) -- [mem](https://github.com/copycat-killer/lain/wiki/mem) -- [mpd](https://github.com/copycat-killer/lain/wiki/mpd) -- [net](https://github.com/copycat-killer/lain/wiki/net) -- [sysload](https://github.com/copycat-killer/lain/wiki/sysload) -- [temp](https://github.com/copycat-killer/lain/wiki/temp) -- [yawn](https://github.com/copycat-killer/lain/wiki/yawn) - -Users contributed ----------------- - -- [task](https://github.com/copycat-killer/lain/wiki/task) -- [tpbat](https://github.com/copycat-killer/lain/wiki/tpbat) -- [brightness](https://github.com/copycat-killer/lain/wiki/brightness) \ No newline at end of file diff --git a/alsa.md b/alsa.md deleted file mode 100644 index daf4016..0000000 --- a/alsa.md +++ /dev/null @@ -1,53 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows and controls alsa volume with a textbox. - - volumewidget = lain.widgets.alsa() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 5 -`channel` | Mixer channel | string | "Master" -`settings` | User settings | function | empty function - -`settings` can use the following variables: - -Variable | Meaning | Type | Values ---- | --- | --- | --- -`volume_now.level` | Self explained | int | 0-100 -`volume_now.status` | Device status | string | "on", "off" - -### output table - -Variable | Meaning | Type ---- | --- | --- -`widget` | The widget | `wibox.widget.textbox` -`update` | Update `widget` | function - -You can control the widget with key bindings like these: - - -- Volume control - awful.key({ altkey }, "Up", - function () - awful.util.spawn("amixer set Master 1%+") - volumewidget.update() - end), - awful.key({ altkey }, "Down", - function () - awful.util.spawn("amixer set Master 1%-") - volumewidget.update() - end), - awful.key({ altkey }, "m", - function () - awful.util.spawn("amixer set Master playback toggle") - volumewidget.update() - end), - awful.key({ altkey, "Control" }, "m", - function () - awful.util.spawn("amixer set Master playback 100%", false ) - volumewidget.update() - end), - -where `altkey = "Mod1"`. \ No newline at end of file diff --git a/alsabar.md b/alsabar.md deleted file mode 100644 index 6138f2c..0000000 --- a/alsabar.md +++ /dev/null @@ -1,85 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows and controls alsa volume with a progressbar; provides tooltips, notifications, and color changes at mute/unmute switch. - - volume = lain.widgets.alsabar() - -* Left click: Launch `alsamixer` in your `terminal`. -* Right click: Mute/unmute. -* Scroll wheel: Increase/decrase volume. - -The function takes a table as optional argument, which can contain: - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 4 -`settings` | User settings | function | empty function -`width` | Bar width | int | 63 -`height` | Bar height | int | 1 -`ticks` | Set bar ticks on | boolean | false -`ticks_size` | Ticks size | int | 7 -`vertical` | Set the bar vertical | boolean | false -`channel` | Mixer channel | string | "Master" -`step` | Step at which volume is increased/decreased | string | "5%" -`colors` | Bar colors | table | see **colors** -`notifications` | Notifications settings | table | see **notifications** - -### colors - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`background` | Bar backgrund color | string | `beautiful.bg_normal` -`mute` | Bar mute color | string | "#EB8F8F" -`unmute` | Bar unmute color | string | "#A4CE8A" - -### notifications - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`font` | Notifications font | string | The one defined in `beautiful.font` -`font_size` | Notifications font size | string | "11" -`color` | Notifications color | string | `beautiful.fg_normal` -`bar_size` | Wibox height | int | 18 - -It's **crucial** to set `notifications.bar_size` to your `mywibox[s]` height. - -`settings` can use the following variables: - -Variable | Meaning | Type | Values ---- | --- | --- | --- -`volume_now.level` | Self explained | int | 0-100 -`volume_now.status` | Device status | string | "on", "off" -### output table - -Variable | Meaning | Type ---- | --- | --- -`bar` | The widget | `awful.widget.progressbar` -`channel` | Alsa channel | string -`step` | Increase/decrease step | string -`notify` | The notification | function - -You can control the widget with key bindings like these: - - -- ALSA volume control - awful.key({ altkey }, "Up", - function () - awful.util.spawn("amixer -q set " .. volume.channel .. " " .. volume.step .. "+") - volume.notify() - end), - awful.key({ altkey }, "Down", - function () - awful.util.spawn("amixer -q set " .. volume.channel .. " " .. volume.step .. "-") - volume.notify() - end), - awful.key({ altkey }, "m", - function () - awful.util.spawn("amixer -q set " .. volume.channel .. " playback toggle") - volume.notify() - end), - awful.key({ altkey, "Control" }, "m", - function () - awful.util.spawn("amixer -q set " .. volume.channel .. " playback 100%") - volume.notify() - end), - -where `altkey = "Mod1"`. \ No newline at end of file diff --git a/bat.md b/bat.md deleted file mode 100644 index 6bbb21e..0000000 --- a/bat.md +++ /dev/null @@ -1,30 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows in a textbox the remaining time and percentage capacity of your laptop battery, as well as -the current wattage. - -Displays a notification when battery is low or critical. - - mybattery = lain.widgets.bat() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 30 -`battery` | Identifier of the battery | string | "BAT0" -`notify` | Enable notifications | string | "on" -`settings` | User settings | function | empty function - -`settings` can use the `bat_now` table, which contains the following strings: - -- `status` ("Not present", "Charging", "Discharging"); -- `perc`; -- `time`; -- `watt`. - -To disable warning notifications, set `notify` to `"off"`. - -### output - -A textbox. \ No newline at end of file diff --git a/borderbox.md b/borderbox.md deleted file mode 100644 index a56026a..0000000 --- a/borderbox.md +++ /dev/null @@ -1,49 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Creates a thin wibox at a position relative to another wibox. - -This allows to create "borders" for your wiboxes. - - lain.widget.borderbox(relbox, s, args) - -`relbox` and `s` (an integer being screen number) are required arguments, `args` is an optional table -which can contain: - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`position` | Position of the additional box | string | "above" -`color` | Color of the additional box | string | `#FFFFFF` -`size` | Size in pixels of the additional box | int | 1 - -Possible values for `.position`: `top`, `bottom`, `left` and `right`. - -### Example usage - -Think of this as a wibox: - - [======================] - -If `args.position = "above"`, then you'll get an additional wibox below -the existing one: - - ________________________ - [======================] - -It'll match position and size of the existing wibox. - -If your main wiboxes are stored in a table called `mywibox` (one wibox -for each screen) and are located at the bottom of your screen, then this -adds a borderbox on top of them: - - -- Layout section - for s = 1, screen.count() do - ... - - -- Most likely, you'll want to do this as well: - awful.screen.padding(screen[s], "bottom") - - -- Create the box and place it above the existing box. - lain.widgets.borderbox(mywibox[s], s ) - - ... - end \ No newline at end of file diff --git a/brightness.md b/brightness.md deleted file mode 100644 index 4cd4f8e..0000000 --- a/brightness.md +++ /dev/null @@ -1,40 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows the current level of screen brightness in a textbox. - - brightnesswidget = lain.widgets.contrib.brightness() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 5 -`backlight` | Backlight video | string | "acpi_video0" -`settings` | User settings | function | empty function - -`settings` can use the following variables: - -Variable | Meaning | Type | Values ---- | --- | --- | --- -`brightness_now` | Brightness level | int | 0-100 - -### output table - -Variable | Meaning | Type ---- | --- | --- -`widget` | The widget | `wibox.widget.textbox` -`update` | Update `widget` | function - -You can control the widget with key bindings like these: - - -- Brightness control - awful.key({}, "XF86MonBrightnessUp", - function () - awful.util.spawn("xbacklight -inc 1") - brightnesswidget.update() - end), - awful.key({}, "XF86MonBrightnessDown", - function () - awful.util.spawn("xbacklight -dec 1") - brightnesswidget.update() - end), \ No newline at end of file diff --git a/calendar.md b/calendar.md deleted file mode 100644 index b06c453..0000000 --- a/calendar.md +++ /dev/null @@ -1,31 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Attaches a calendar notification to a widget. - - lain.widgets.calendar:attach(widget, args) - -- Left click: switch to previous month. -- Right click: switch to next month. - -`args` is an optional table which can contain: - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`icons` | Path to calendar icons | string | [lain/icons/cal/white](https://github.com/copycat-killer/lain/tree/master/icons/cal/white) -`font_size` | Calendar font size | int | 12 -`fg` | Calendar foreground color | string | `beautiful.fg_normal` -`bg` | Calendar background color | string | `beautiful.bg_normal` -`position` | Calendar position | string | "top_right" - -`position` possible values are defined [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify). - -Notification will show an icon displaying current day, and formatted output -from ``cal`` with current day highlighted. - -You can call the notification with a key binding like this: - - awful.key({ altkey }, "c", function () lain.widgets.calendar:show(7) end), - -where ``altkey = "Mod1"`` and ``show`` argument is an optional integer, meaning timeout seconds. - -**Note that** this widget exploits ``cal`` to do the alignment, in order to avoid more dozens of code lines, but this requires that your system font is monospaced. \ No newline at end of file diff --git a/cpu.md b/cpu.md deleted file mode 100644 index e42180c..0000000 --- a/cpu.md +++ /dev/null @@ -1,18 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows in a textbox the average CPU usage percent for a given amount of time. - - mycpuusage = lain.widgets.cpu() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 5 -`settings` | User settings | function | empty function - -`settings` can use the string `cpu_now.usage`, which is the cpu use percentage. - -### output - -A textbox. \ No newline at end of file diff --git a/fs.md b/fs.md deleted file mode 100644 index 1e34f86..0000000 --- a/fs.md +++ /dev/null @@ -1,45 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows disk space usage for a set partition. - -Displays a notification when the partition is full or has low space. - - mypartition = lain.widgets.fs() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds -| int | 600 -`partition` | Partition to monitor | string | "/" -`settings` | User settings | function | empty function - -`settings` can use the following `partition` related float values: `fs_now.used`, `fs_now.available`, `fs_now.size_mb`, `fs_now.size_gb`. - -It can also use value strings in these formats: - - fs_info[p .. "used_p"] - fs_info[p .. "avail_p"] - fs_info[p .. "size_mb"] - fs_info[p .. "size_gb"] - -where `p` is the last column of `df` command ("/", "/home", "/boot", ...). - -This means you can set the widget for a certain partition, but you can look up at others too. - -Finally, `settings` can modify `fs_notification_preset` table too. This table will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: - - fs_notification_preset = { fg = beautiful.fg_normal } - -### output table - -Variable | Meaning | Type ---- | --- | --- -`widget` | The widget | `wibox.widget.textbox` -`show` | The notification | function - -You can display the notification with a key binding like this: - - awful.key({ altkey }, "h", function () mypartition.show(7) end), - -where ``altkey = "Mod1"`` and ``show`` argument is an optional integer, meaning timeout seconds. \ No newline at end of file diff --git a/imap.md b/imap.md deleted file mode 100644 index 403a61a..0000000 --- a/imap.md +++ /dev/null @@ -1,68 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows mail count in a textbox fetching over IMAP. - - myimapcheck = lain.widgets.imap(args) - -New mails are notified like this: - - +--------------------------------------------+ - | +---+ | - | |\ /| donald@disney.org has 3 new messages | - | +---+ | - +--------------------------------------------+ - -The function takes a table as argument. Required table parameters are: - -Variable | Meaning | Type ---- | --- | --- -`server` | Mail server | string -`mail` | User mail | string -`password` | User password | string - -while the optional are: - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`port` | IMAP port | int | 993 -`timeout` | Refresh timeout seconds | int | 60 -`is_plain` | Define whether `password` is a plain password (true) or a function that retrieves it (false) | boolean | false -`settings` | User settings | function - -Let's focus better on `is_plain`. - -The reason why it's false by default is to discourage the habit of storing passwords in plain. - -So you can set your password in plain like this: - - myimapcheck = lain.widgets.imap({ - is_plain = true, - password = "myplainpassword", - [...] - }) - -and you'll have the same security provided by `~/.netrc`. - -**Or** you can use a keyring, like [python keyring](https://pypi.python.org/pypi/keyring): - - myimapcheck = lain.widgets.imap({ - password = "keyring get mymail", - [...] - }) - -When `is_plain == false`, it *executes* `password` before using it, so you can also use whatever password fetching solution you want. - -`settings` can use the value `mailcount`, an integer greater or equal to zero, and can modify `mail_notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. - -Default definition: - - mail_notification _preset = { - icon = lain/icons/mail.png, - position = "top_left" - } - -Note that `mailcount` is 0 either if there are no new mails or credentials are invalid, so make sure you get the right settings. - -### output - -A textbox. \ No newline at end of file diff --git a/maildir.md b/maildir.md deleted file mode 100644 index 355ecdd..0000000 --- a/maildir.md +++ /dev/null @@ -1,39 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows maildirs status in a textbox. - -Maildirs are structured as follows: - - ~/Mail - . - |-- arch - | |-- cur - | |-- new - | `-- tmp - |-- gmail - | |-- cur - | |-- new - | `-- tmp - . - . - . - -therefore the widget checks whether there are files in the `new` directories. -If there's new mails, the textbox will say something like "mail: bugs(3), system(1)", otherwise it says -"no mail". - - mymaildir = lain.widgets.maildir("/path/to/my/maildir") - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 60 -`mailpath` | Path to your maildir | string | "~/Mail" -`settings` | User settings | function | empty function - -`settings` can use the string `newmail`, which format will be something like defined above, or "no mail". - -### output - -A textbox. \ No newline at end of file diff --git a/mem.md b/mem.md deleted file mode 100644 index 84b7ad2..0000000 --- a/mem.md +++ /dev/null @@ -1,18 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows memory status (in MiB) in a textbox. - - mymem = lain.widgets.mem() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 3 -`settings` | User settings | function | empty function - -`settings` can use the strings `mem_now.used` (memory used MB) and `mem_now.swapused` (swap used MB). - -### output - -A textbox. \ No newline at end of file diff --git a/mpd.md b/mpd.md deleted file mode 100644 index 646b690..0000000 --- a/mpd.md +++ /dev/null @@ -1,85 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows MPD status in a textbox. - - mpdwidget = lain.widgets.mpd() - -Now playing songs are notified like this: - - +--------------------------------------------------------+ - | +-------+ | - | |/^\_/^\| Now playing | - | |\ O O /| Cannibal Corpse (Hammer Smashed Face) - 1993 | - | | '.o.' | Hammer Smashed Face (Radio Disney Version) | - | +-------+ | - +--------------------------------------------------------+ - -You need a file like this - - (Front|front|Cover|cover|Art|art|Folder|folder)\.(jpg|jpeg|png|gif) - -in the album folder in order to show album art too. - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 1 -`password` | MPD password | string | "" -`host` | MPD server | string | "127.0.0.1" -`port` | MPD port | string | "6600" -`music_dir` | Music directory | string | "~/Music" -`cover_size` | Album art notification size | int | 100 -`default_art` | Default art | string | "" -`settings` | User settings | function | empty function - -`settings` can use `mpd_now` table, which contains the following string values: - -- state (possible values: "play", "pause", "stop") -- file -- artist -- title -- album -- date - -and can modify `mpd_notification_preset` table, which will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. Default definition: - - mpd_notification_preset = { - title = "Now playing", - timeout = 6, - text = string.format("%s (%s) - %s\n%s", mpd_now.artist, - mpd_now.album, mpd_now.date, mpd_now.title) - } - -### output table - -Variable | Meaning | Type ---- | --- | --- -`widget` | The textbox | `wibox.widget.textbox` -`update` | The notification | function - -You can control the widget with key bindings like these: - - -- MPD control - awful.key({ altkey, "Control" }, "Up", - function () - awful.util.spawn_with_shell("mpc toggle || ncmpcpp toggle || ncmpc toggle || pms toggle") - mpdwidget.update() - end), - awful.key({ altkey, "Control" }, "Down", - function () - awful.util.spawn_with_shell("mpc stop || ncmpcpp stop || ncmpc stop || pms stop") - mpdwidget.update() - end), - awful.key({ altkey, "Control" }, "Left", - function () - awful.util.spawn_with_shell("mpc prev || ncmpcpp prev || ncmpc prev || pms prev") - mpdwidget.update() - end), - awful.key({ altkey, "Control" }, "Right", - function () - awful.util.spawn_with_shell("mpc next || ncmpcpp next || ncmpc next || pms next") - mpdwidget.update() - end), - -where `altkey = "Mod1"`. \ No newline at end of file diff --git a/net.md b/net.md deleted file mode 100644 index f857239..0000000 --- a/net.md +++ /dev/null @@ -1,26 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Monitors network interfaces and shows current traffic in a textbox. - - mynet = lain.widgets.net() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 2 -`iface` | Network device | string | autodetected -`units` | Units | int | 1024 (kilobytes) -`settings` | User settings | function | empty function - -Possible other values for `units` are 1 (byte) or multiple of 1024: 1024^2 (mb), 1024^3 (gb), and so on. - -`settings` can use the following `iface` related strings: - -- `net_now.carrier` ("0", "1"); -- `net_now.state` ("up", "down"); -- `net_now.sent` and `net_now.received` (numbers). - -### output - -A textbox. \ No newline at end of file diff --git a/sysload.md b/sysload.md deleted file mode 100644 index 3e53881..0000000 --- a/sysload.md +++ /dev/null @@ -1,18 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows the current system load. - - mysysload = lain.widgets.sysload() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 5 -`settings` | User settings | function | empty function - -`settings` can use strings `load_1`, `load_5` and `load_15`, which are loadavg over 1, 5, and 15 minutes. - -### output - -A textbox. \ No newline at end of file diff --git a/task.md b/task.md deleted file mode 100644 index b4bc7f0..0000000 --- a/task.md +++ /dev/null @@ -1,30 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Attaches a [taskwarrior](http://taskwarrior.org/projects/show/taskwarrior) notification to a widget, and lets to add/search tasks from the promptbox. - - lain.widgets.contrib.task:attach(widget, args) - -`args` is an optional table which can contain: - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`font_size` | Calendar font size | int | 12 -`fg` | Calendar foreground color | string | `beautiful.fg_normal` -`bg` | Calendar background color | string | `beautiful.bg_normal` -`position` | Calendar position | string | "top_right" -`timeout` | Notification timeout seconds | int | 7 - -`position` possible values are defined [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify). - -Notification will show the output of `task` command. - -You can call the notification with a key binding like this: - - awful.key({ modkey, altkey }, "t", lain.widgets.contrib.task.show), - -where ``altkey = "Mod1"``. - -And you can prompt to add/search a task with key bindings like these: - - awful.key({ modkey, }, "t", lain.widgets.contrib.task.prompt_add), - awful.key({ modkey, "Shift" }, "t", lain.widgets.contrib.task.prompt_search), \ No newline at end of file diff --git a/temp.md b/temp.md deleted file mode 100644 index 91f3031..0000000 --- a/temp.md +++ /dev/null @@ -1,20 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -Shows the current core temperature in a textbox. - -Reads from `/sys/class/thermal`, so value is expressed in Celsius. - - mytemp = lain.widgets.temp() - -### input table - -Variable | Meaning | Type | Default ---- | --- | --- | --- -`timeout` | Refresh timeout seconds | int | 5 -`settings` | User settings | function | empty function - -`settings` can use the string `coretemp_now`, which means current core temperature, expressed in Celsius (linux standard). - -### output - -A textbox. \ No newline at end of file diff --git a/tpbat.md b/tpbat.md deleted file mode 100644 index 5a7ba0c..0000000 --- a/tpbat.md +++ /dev/null @@ -1,9 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -A battery widget that works with Lenovo ThinkPad laptops using [tp_smapi](http://www.thinkwiki.org/wiki/Tp_smapi). - -Includes hover notification with more details. - - tpbatwidget = lain.widgets.contrib.tpbat() - -Configuration is identical to [standard battery widget's](https://github.com/copycat-killer/lain/wiki/bat). \ No newline at end of file diff --git a/wiki b/wiki index f996cdb..2fe55cb 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit f996cdb74e7583534256d82706ef63d2b9811b42 +Subproject commit 2fe55cb50b4192866551d50dce563a52234961c7 diff --git a/yawn.md b/yawn.md deleted file mode 100644 index 30d160c..0000000 --- a/yawn.md +++ /dev/null @@ -1,93 +0,0 @@ -[<- widgets](https://github.com/copycat-killer/lain/wiki/Widgets) - -(YAhoo! Weather Notification) - -Yawn provides brief and compact Yahoo! Weather notification. - -Usage ------ - -You can ``register`` Yawn to get a set of widgets, or ``attach`` it to -an existent widget. - -### register - - yawn = lain.widgets.yawn(id, args) - -- ``id`` - - An integer that defines the WOEID code of your city. - To obtain it you can google 'yahoo weather %CITYNAME%' and follow the first link. - It will look like: - - http://weather.yahoo.com/united-states/california/san-diego-2487889/ - - and the last number in that link will be the ID you need. - -- ``args`` - - A required table which can contain: - - Variables | Meaning | Type | Possible values | Default value - --- | --- | --- | --- | --- - `u` | Units | string | "c" (Celsius), "f" (Fahrenheit) | "c" - `timeout` | Refresh timeout seconds | int | integers | 600 - `settings` | User settings | function | function | empty function - - `settings` can use strings `forecast`, `units`, and can modify `yawn_notification_preset` table, which - will be the preset for the naughty notifications. Check [here](http://awesome.naquadah.org/doc/api/modules/naughty.html#notify) for the list of variables it can contain. - -The function `register` creates an imagebox icon and a textbox widget. Add them to you wibox like this: - - right_layout:add(yawn.icon) - right_layout:add(yawn.widget) - -Hovering over ``yawn.icon`` will display the notification. - -### attach - - lain.widgets.yawn.attach(widget, id, args) - -Arguments: - -- ``widget`` - - The widget which you want to attach Yawn to. - -- ``id`` - - Same as in ``register``. - -- ``args`` - - Same as in ``register``. - -Hovering over ``widget`` will display the notification. - -Popup shortcut --------------- - -You can also create a keybinding for the weather popup like this: - - awful.key( { "Mod1" }, "w", function () yawn.show(5) end ) - -where ``show`` argument is an integer defining timeout seconds. - -Localization ------------- - -Default language is English, but Yawn can be localized. - -Move to `localizations` subdirectory and fill `localization_template`. - -Once you're done, rename it like your locale id. In my case: - - $ lua - Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio - > print(os.getenv("LANG"):match("(%S*$*)[.]")) - it_IT - > - -hence I named my file "it_IT" (Italian localization). - -**NOTE:** If you create a localization, feel free to send me! I will add it. \ No newline at end of file From 3fc0ed44dc2169d10a42f1c6f6ea39be7dc310dd Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 29 Jan 2014 11:56:32 +0100 Subject: [PATCH 400/572] new I/O file helper functions --- helpers.lua | 45 ++++++++++++++++++++++++++++++++----------- widgets/maildir.lua | 1 + widgets/yawn/init.lua | 1 + wiki | 2 +- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/helpers.lua b/helpers.lua index c42ce61..08aba0d 100644 --- a/helpers.lua +++ b/helpers.lua @@ -10,7 +10,8 @@ local debug = require("debug") local capi = { timer = timer } -local io = { open = io.open } +local io = { open = io.open, + lines = io.lines } local rawget = rawget -- Lain helper functions for internal use @@ -30,18 +31,40 @@ end -- }}} --- {{{ Read the first line of a file or return nil +-- {{{ File operations -function helpers.first_line(f) - local fp = io.open(f) - if not fp - then - return nil - end +-- see if the file exists +function helpers.file_exists(file) + local f = io.open(file, "rb") + if f then f:close() end + return f ~= nil +end - local content = fp:read("*l") - fp:close() - return content + +-- get all lines from a file, returns an empty +-- list/table if the file does not exist +function helpers.lines_from(file) + if not helpers.file_exists(file) then return {} end + lines = {} + for line in io.lines(file) do + lines[#lines + 1] = line + end + return lines +end + +-- get first line of a file, return nil if +-- the file does not exist +function helpers.first_line(file) + return helpers.lines_from(file)[1] +end + +-- get first non empty line from a file, +-- returns nil otherwise +function helpers.first_nonempty_line(file) + for k,v in pairs(lines_from(file)) do + if #v then return v end + end + return nil end -- }}} diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 5cb6840..d460881 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -1,3 +1,4 @@ + --[[ Licensed under GNU General Public License v2 diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 36cdf54..b4d9c05 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -1,3 +1,4 @@ + --[[ Licensed under GNU General Public License v2 diff --git a/wiki b/wiki index 2fe55cb..6825e84 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 2fe55cb50b4192866551d50dce563a52234961c7 +Subproject commit 6825e84bb73415c4cbf5fcd903ea4987976e4be3 From c73b41c6368deb9591b262d65515d4ff22f26fef Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 29 Jan 2014 20:08:16 +0100 Subject: [PATCH 401/572] fixed typo in helpers.lua --- helpers.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers.lua b/helpers.lua index 08aba0d..af6443f 100644 --- a/helpers.lua +++ b/helpers.lua @@ -61,7 +61,7 @@ end -- get first non empty line from a file, -- returns nil otherwise function helpers.first_nonempty_line(file) - for k,v in pairs(lines_from(file)) do + for k,v in pairs(helpers.lines_from(file)) do if #v then return v end end return nil From 13a6d1cf457e3c5ed813f74c03b01041115c29c4 Mon Sep 17 00:00:00 2001 From: Lukas Geis Date: Sun, 2 Feb 2014 14:29:44 +0100 Subject: [PATCH 402/572] Bat.lua: Adding naughty presets for customizable notifications --- widgets/bat.lua | 63 ++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 48a14fb..4a25d63 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -32,6 +32,22 @@ local function worker(args) bat.widget = wibox.widget.textbox('') + bat_notification_low_preset = { + title = "Battery low", + text = "Plug the cable!", + timeout = 15, + fg = "#202020", + bg = "#CDCDCD" + } + + bat_notification_critical_preset = { + title = "Battery exhausted", + text = "Shutdown imminent", + timeout = 15, + fg = "#000000", + bg = "#FFFFFF" + } + function update() bat_now = { status = "Not present", @@ -96,39 +112,28 @@ local function worker(args) bat_now.watt = "N/A" end - -- notifications for low and critical states - if bat_now.status == "Discharging" and notify == "on" - then - if tonumber(bat_now.perc) <= 5 - then - bat.id = naughty.notify({ - text = "shutdown imminent", - title = "battery nearly exhausted", - position = "top_right", - timeout = 15, - fg="#000000", - bg="#ffffff", - ontop = true, - replaces_id = bat.id - }).id - elseif tonumber(bat_now.perc) <= 15 - then - bat.id = naughty.notify({ - text = "plug the cable", - title = "battery low", - position = "top_right", - timeout = 15, - fg="#202020", - bg="#cdcdcd", - ontop = true, - replaces_id = bat.id - }).id - end - end end widget = bat.widget settings() + + -- notifications for low and critical states + if bat_now.status == "Discharging" and notify == "on" + then + if tonumber(bat_now.perc) <= 5 + then + bat.id = naughty.notify({ + preset = bat_notification_critical_preset, + replaces_id = bat.id + }).id + elseif tonumber(bat_now.perc) <= 15 + then + bat.id = naughty.notify({ + preset = bat_notification_low_preset, + replaces_id = bat.id + }).id + end + end end newtimer("bat", timeout, update) From 5c0ce12f8ec4999352ce4a27e996a4c14fea4ea9 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 4 Feb 2014 08:59:00 +0100 Subject: [PATCH 403/572] bat: little fixes --- widgets/bat.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 48a14fb..21b5c43 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -59,7 +59,7 @@ local function worker(args) bat_now.status = first_line(bstr .. "/status") or "N/A" - rate = tonumber(rate) + rate = tonumber(rate) or 1 ratev = tonumber(ratev) rem = tonumber(rem) tot = tonumber(tot) From 4114fc0e981e02f158db8a21e3aa43f4a78916fa Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 4 Feb 2014 09:22:22 +0100 Subject: [PATCH 404/572] calendar: font variable added --- widgets/calendar.lua | 29 +++++++++++++++-------------- wiki | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index f684fd7..c9e265a 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -38,9 +38,6 @@ function calendar:show(t_out, inc_offset) local f, c_text local today = tonumber(os.date('%d')) local init_t = '/usr/bin/cal | sed -r -e "s/(^| )( ' - -- let's take font only, font size is set in calendar table - local font = beautiful.font:sub(beautiful.font:find(""), - beautiful.font:find(" ")) if offs == 0 then -- current month showing, today highlighted @@ -86,7 +83,7 @@ function calendar:show(t_out, inc_offset) f = io.popen('/usr/bin/cal ' .. month .. ' ' .. year) end - c_text = "" .. f:read() .. "\n\n" .. f:read() .. "\n" @@ -94,21 +91,25 @@ function calendar:show(t_out, inc_offset) .. "" f:close() - cal_notification = naughty.notify({ text = c_text, - icon = calendar.notify_icon, - position = calendar.position, - fg = calendar.fg, - bg = calendar.bg, - timeout = tims }) + cal_notification = naughty.notify({ + text = c_text, + icon = calendar.notify_icon, + position = calendar.position, + fg = calendar.fg, + bg = calendar.bg, + timeout = tims + }) end function calendar:attach(widget, args) local args = args or {} - calendar.icons = args.icons or icons_dir .. "cal/white/" + calendar.icons = args.icons or icons_dir .. "cal/white/" + calendar.font = args.font or beautiful.font:sub(beautiful.font:find(""), + beautiful.font:find(" ")) calendar.font_size = tonumber(args.font_size) or 11 - calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF" - calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF" - calendar.position = args.position or "top_right" + calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF" + calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF" + calendar.position = args.position or "top_right" calendar.offset = 0 calendar.notify_icon = nil diff --git a/wiki b/wiki index 6825e84..d424887 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 6825e84bb73415c4cbf5fcd903ea4987976e4be3 +Subproject commit d4248875dcd12ceb300c8a876001ce68f5405758 From cec4a68c630b93315c43f53eef3f9a416726a3a3 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 7 Feb 2014 12:39:18 +0100 Subject: [PATCH 405/572] #25 fix attempt --- widgets/net.lua | 6 ++---- widgets/yawn/init.lua | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/widgets/net.lua b/widgets/net.lua index d79e117..af97201 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -35,7 +35,7 @@ function net.get_device() if ws ~= nil then return ws:gsub(": UP", "") else - return "" + return "network off" end end @@ -80,10 +80,8 @@ local function worker(args) then if helpers.get_map(iface) then - n_title = iface - if n_title == "" then n_title = "network" end naughty.notify({ - title = n_title, + title = iface, text = "no carrier", timeout = 7, position = "top_left", diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index b4d9c05..af7befc 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -58,12 +58,12 @@ local function fetch_weather() yawn.icon:set_image(icon_path .. "na.png") if text == "" then weather_data = "Service not available at the moment." - yawn.widget:set_text(" N/A") + yawn.widget:set_text(" N/A ") else weather_data = "City not found!\n" .. "Are you sure " .. city_id .. " is your Yahoo city ID?" - yawn.widget:set_text(" ?") + yawn.widget:set_text(" ? ") end return end From 3b724efc81f632e39ed630d25cf5bf63821dc98a Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 8 Feb 2014 11:44:09 +0100 Subject: [PATCH 406/572] 26# fix attempt --- widgets/bat.lua | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 4526c85..c2a6587 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -97,13 +97,17 @@ local function worker(args) bat_now.time = string.format("%02d:%02d", hrs, min) - local perc = (rem / tot) * 100 - if perc <= 100 then - bat_now.perc = string.format("%d", perc) - elseif perc > 100 then - bat_now.perc = "100" - elseif perc < 0 then - bat_now.perc = "0" + bat_now.perc = first_line(bstr .. "/capacity") + + if not bat_now.perc then + local perc = (rem / tot) * 100 + if perc <= 100 then + bat_now.perc = string.format("%d", perc) + elseif perc > 100 then + bat_now.perc = "100" + elseif perc < 0 then + bat_now.perc = "0" + end end if rate ~= nil and ratev ~= nil then @@ -118,7 +122,7 @@ local function worker(args) settings() -- notifications for low and critical states - if bat_now.status == "Discharging" and notify == "on" + if bat_now.status == "Discharging" and notify == "on" and bat_now.perc ~= nil then if tonumber(bat_now.perc) <= 5 then From 804a3b4084659a30586c6cdadf7b2b3de5019fd6 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 8 Feb 2014 12:10:13 +0100 Subject: [PATCH 407/572] #25 fix attempt 2 --- helpers.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/helpers.lua b/helpers.lua index af6443f..f2bd5e4 100644 --- a/helpers.lua +++ b/helpers.lua @@ -35,12 +35,11 @@ end -- see if the file exists function helpers.file_exists(file) - local f = io.open(file, "rb") + local f = io.open(file) if f then f:close() end return f ~= nil end - -- get all lines from a file, returns an empty -- list/table if the file does not exist function helpers.lines_from(file) From 82b3c95d4f89f0475d1c91163659ab339e661504 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 9 Feb 2014 10:36:40 +0100 Subject: [PATCH 408/572] #25 blueluke's fix attempt --- helpers.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/helpers.lua b/helpers.lua index f2bd5e4..863bb87 100644 --- a/helpers.lua +++ b/helpers.lua @@ -3,7 +3,6 @@ Licensed under GNU General Public License v2 * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann --]] @@ -33,10 +32,14 @@ end -- {{{ File operations --- see if the file exists +-- see if the file exists and is readable function helpers.file_exists(file) local f = io.open(file) - if f then f:close() end + if f then + local s = f:read() + f:close() + f = s + end return f ~= nil end From d352d807542aa221da7774d03a700cc596a09ba7 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 9 Feb 2014 17:44:28 +0100 Subject: [PATCH 409/572] #26 fix attempt 2 --- widgets/bat.lua | 5 +++-- widgets/yawn/init.lua | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index c2a6587..485fd57 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -122,15 +122,16 @@ local function worker(args) settings() -- notifications for low and critical states + bat_now.perc = tonumber(bat_now.perc) if bat_now.status == "Discharging" and notify == "on" and bat_now.perc ~= nil then - if tonumber(bat_now.perc) <= 5 + if bat_now.perc <= 5 then bat.id = naughty.notify({ preset = bat_notification_critical_preset, replaces_id = bat.id }).id - elseif tonumber(bat_now.perc) <= 15 + elseif bat_now.perc <= 15 then bat.id = naughty.notify({ preset = bat_notification_low_preset, diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index af7befc..3f08cd5 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -75,7 +75,7 @@ local function fetch_weather() -- may still happens in case of bad connectivity if weather_data == "" then yawn.icon:set_image(icon_path .. "na.png") - yawn.widget:set_text(" ?") + yawn.widget:set_text(" ? ") return end From cf1a6e745513eefdcff592d1b7ea43bb616bb18a Mon Sep 17 00:00:00 2001 From: aaron-lebo Date: Mon, 10 Feb 2014 03:02:14 -0600 Subject: [PATCH 410/572] Create acw.lua --- widgets/contrib/acw.lua | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 widgets/contrib/acw.lua diff --git a/widgets/contrib/acw.lua b/widgets/contrib/acw.lua new file mode 100644 index 0000000..0c3ae3f --- /dev/null +++ b/widgets/contrib/acw.lua @@ -0,0 +1,69 @@ +-[[ + + Licensed under GNU General Public License v2 + * (c) 2014, Aaron Lebo + +--]] + +local newtimer = require("lain.helpers").newtimer +local wibox = require("wibox") +local json = require("dkjson") + +-- acw (awesome crypto widget) +-- diplays BTC/USD and 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 +-- lain.widgets.contrib.acw + +acw = {widget=wibox.widget.textbox('')} + +local function get(url) + f = io.popen('curl -m 5 -s "' .. url .. '"') + if (not f) then return 0 end + return f:read("*all") +end + +local function parse(j) + local obj, pos, err = json.decode (j, 1, nil) + if err thenfunction worker(args) + return nil + else + return obj + end +end + +function worker(args) + local args = args or {} + local timeout = args.timeout or 600 + local settings = args.settings or function() end + + + local function update() + btc = parse(get("https://coinbase.com/api/v1/prices/buy")) + if btc then + btc = tonumber(btc["subtotal"]["amount"]) + btc_display = "$" .. btc + else + btc_display = "N/A" + end + doge = parse(get("http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=132")) + if doge and btc then + doge = tonumber(doge["return"]["markets"]["DOGE"]["lasttradeprice"]) + doge_display = string.format("$%.4f", btc * doge) + else + doge_display = "N/A" + end + prices = btc_display .. " " .. doge_display + prices_now = {} + prices_now.prices = prices + + widget = acw.widget + settings() + end + + newtimer("acw", timeout, update) + + return acw.widget +end + +return setmetatable(acw, { __call = function(_, ...) return worker(...) end }) From 700812653cc2b56d7b6f6c22d597f0c0064370dd Mon Sep 17 00:00:00 2001 From: aaron-lebo Date: Mon, 10 Feb 2014 03:06:50 -0600 Subject: [PATCH 411/572] Update acw.lua --- widgets/contrib/acw.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/widgets/contrib/acw.lua b/widgets/contrib/acw.lua index 0c3ae3f..c06de57 100644 --- a/widgets/contrib/acw.lua +++ b/widgets/contrib/acw.lua @@ -37,7 +37,6 @@ function worker(args) local timeout = args.timeout or 600 local settings = args.settings or function() end - local function update() btc = parse(get("https://coinbase.com/api/v1/prices/buy")) if btc then From 917bcb2135636c547ec987c5cdc57c212a4efaed Mon Sep 17 00:00:00 2001 From: Aaron Lebo Date: Mon, 10 Feb 2014 05:49:49 -0600 Subject: [PATCH 412/572] Moved acw from single file to folder. --- widgets/contrib/{acw.lua => acw/init.lua} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename widgets/contrib/{acw.lua => acw/init.lua} (100%) diff --git a/widgets/contrib/acw.lua b/widgets/contrib/acw/init.lua similarity index 100% rename from widgets/contrib/acw.lua rename to widgets/contrib/acw/init.lua From d79b8cd58c9f9a0088a1afec47e84e4f44c6e3c2 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 10 Feb 2014 19:17:47 +0100 Subject: [PATCH 413/572] moved acw/init to ccurr + code revision --- widgets/contrib/acw/init.lua | 68 ------------------------------- widgets/contrib/ccurr.lua | 78 ++++++++++++++++++++++++++++++++++++ wiki | 2 +- 3 files changed, 79 insertions(+), 69 deletions(-) delete mode 100644 widgets/contrib/acw/init.lua create mode 100644 widgets/contrib/ccurr.lua diff --git a/widgets/contrib/acw/init.lua b/widgets/contrib/acw/init.lua deleted file mode 100644 index c06de57..0000000 --- a/widgets/contrib/acw/init.lua +++ /dev/null @@ -1,68 +0,0 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2014, Aaron Lebo - ---]] - -local newtimer = require("lain.helpers").newtimer -local wibox = require("wibox") -local json = require("dkjson") - --- acw (awesome crypto widget) --- diplays BTC/USD and 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 --- lain.widgets.contrib.acw - -acw = {widget=wibox.widget.textbox('')} - -local function get(url) - f = io.popen('curl -m 5 -s "' .. url .. '"') - if (not f) then return 0 end - return f:read("*all") -end - -local function parse(j) - local obj, pos, err = json.decode (j, 1, nil) - if err thenfunction worker(args) - return nil - else - return obj - end -end - -function worker(args) - local args = args or {} - local timeout = args.timeout or 600 - local settings = args.settings or function() end - - local function update() - btc = parse(get("https://coinbase.com/api/v1/prices/buy")) - if btc then - btc = tonumber(btc["subtotal"]["amount"]) - btc_display = "$" .. btc - else - btc_display = "N/A" - end - doge = parse(get("http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=132")) - if doge and btc then - doge = tonumber(doge["return"]["markets"]["DOGE"]["lasttradeprice"]) - doge_display = string.format("$%.4f", btc * doge) - else - doge_display = "N/A" - end - prices = btc_display .. " " .. doge_display - prices_now = {} - prices_now.prices = prices - - widget = acw.widget - settings() - end - - newtimer("acw", timeout, update) - - return acw.widget -end - -return setmetatable(acw, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/contrib/ccurr.lua b/widgets/contrib/ccurr.lua new file mode 100644 index 0000000..b9a4f42 --- /dev/null +++ b/widgets/contrib/ccurr.lua @@ -0,0 +1,78 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2014, Aaron Lebo + +--]] + +local newtimer = require("lain.helpers").newtimer +local wibox = require("wibox") +local json = require("dkjson") + +-- 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 }) diff --git a/wiki b/wiki index d424887..72c82d4 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit d4248875dcd12ceb300c8a876001ce68f5405758 +Subproject commit 72c82d49aa961e15440db7dfefb749fe0d2cdd02 From 6f75cafe0c073c5062c8d45ccf1a3388e3e8ef69 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 10 Feb 2014 19:24:45 +0100 Subject: [PATCH 414/572] ccurr: final fixes + wiki updated --- widgets/contrib/ccurr.lua | 4 ++++ wiki | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/widgets/contrib/ccurr.lua b/widgets/contrib/ccurr.lua index b9a4f42..f696a35 100644 --- a/widgets/contrib/ccurr.lua +++ b/widgets/contrib/ccurr.lua @@ -7,9 +7,13 @@ --]] local newtimer = require("lain.helpers").newtimer + local wibox = require("wibox") local json = require("dkjson") +local string = { format = string.format } +local tonumber = tonumber + -- Crypto currencies widget -- lain.widgets.contrib.ccurr local ccurr = {} diff --git a/wiki b/wiki index 72c82d4..1f364a9 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 72c82d49aa961e15440db7dfefb749fe0d2cdd02 +Subproject commit 1f364a97ada361c479950cf8efa3f0b752f665fc From 72ed28967b4459a08c5c78f9a10d51b0174c20e6 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 10 Feb 2014 19:45:25 +0100 Subject: [PATCH 415/572] wiki updated --- widgets/contrib/tpbat/init.lua | 40 +++++++++++++++++----------------- wiki | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/widgets/contrib/tpbat/init.lua b/widgets/contrib/tpbat/init.lua index dbf90aa..72d6453 100644 --- a/widgets/contrib/tpbat/init.lua +++ b/widgets/contrib/tpbat/init.lua @@ -90,16 +90,28 @@ function tpbat.register(args) tpbat.widget = wibox.widget.textbox('') + bat_notification_low_preset = { + title = "Battery low", + text = "Plug the cable!", + timeout = 15, + fg = "#202020", + bg = "#CDCDCD" + } + + bat_notification_critical_preset = { + title = "Battery exhausted", + text = "Shutdown imminent", + timeout = 15, + fg = "#000000", + bg = "#FFFFFF" + } + if bat:get('state') == nil then local n = naughty.notify({ + preset = bat_notification_low_preset, title = "SMAPI Battery Warning: Unable to read battery state!", - text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths.", - position = "top_right", - timeout = 15, - fg="#202020", - bg="#cdcdcd", - ontop = true + text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths." }) end @@ -124,25 +136,13 @@ function tpbat.register(args) if bat_now.perc <= 5 then tpbat.id = naughty.notify({ - text = "shutdown imminent", - title = "battery nearly exhausted", - position = "top_right", - timeout = 15, - fg="#000000", - bg="#ffffff", - ontop = true, + preset = bat_notification_critical_preset, replaces_id = tpbat.id }).id elseif bat_now.perc <= 15 then tpbat.id = naughty.notify({ - text = "plug the cable", - title = "battery low", - position = "top_right", - timeout = 15, - fg="#202020", - bg="#cdcdcd", - ontop = true, + preset = bat_notification_low_preset, replaces_id = tpbat.id }).id end diff --git a/wiki b/wiki index 1f364a9..60ad9c7 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 1f364a97ada361c479950cf8efa3f0b752f665fc +Subproject commit 60ad9c7c6b9fa533f10cd4ce4b2912165b76c0d9 From 59d9cd21ca2aabf285a13b4835ffe9ca767d4604 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 12 Feb 2014 12:23:02 +0100 Subject: [PATCH 416/572] base widget template added --- scripts/dfs | 10 ++++++---- wiki | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/dfs b/scripts/dfs index 1730b6e..d78d2bb 100755 --- a/scripts/dfs +++ b/scripts/dfs @@ -6,6 +6,8 @@ # Integrated into Lain in september 2013 # https://github.com/copycat-killer/lain +# Requires gawk + # ------------------------------------------------------------------------- # Decoding options # ------------------------------------------------------------------------- @@ -183,7 +185,7 @@ echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v DEBUG=$DEBUG -v PATTERN=$PATT current_date = strftime ("%d-%m-%Y @ %H:%M:%S", localtime (systime ())); free_threshold = 10; # % - printf ("\n"); + printf ("\n"); printf ( \ "\n" \ @@ -197,9 +199,9 @@ echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v DEBUG=$DEBUG -v PATTERN=$PATT "Mount point\n" \ "%% Usato (*)" \ " - %% Free (*)\n" \ - "%% Usato\n" \ - "Spazio libero\n" \ - "Spazio totale\n" \ + "%% Used\n" \ + "Free\n" \ + "Total\n" \ "\n" ); } else diff --git a/wiki b/wiki index 60ad9c7..6075408 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 60ad9c7c6b9fa533f10cd4ce4b2912165b76c0d9 +Subproject commit 60754084cf7bb69d7387484e12fa686c73cfe1bc From e628b17d91e3f688be3d11fb39905f8f342dd543 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 13 Feb 2014 10:58:47 +0100 Subject: [PATCH 417/572] cal: --color=never added to discourage #29 --- widgets/calendar.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index c9e265a..d0df17c 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -37,7 +37,7 @@ function calendar:show(t_out, inc_offset) local tims = t_out or 0 local f, c_text local today = tonumber(os.date('%d')) - local init_t = '/usr/bin/cal | sed -r -e "s/(^| )( ' + local init_t = '/usr/bin/cal --color=never | sed -r -e "s/(^| )( ' if offs == 0 then -- current month showing, today highlighted From d3e9bd968c62d75b149f9eb4720454282eb3a18f Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 13 Feb 2014 17:35:55 +0100 Subject: [PATCH 418/572] base widget added (this time for real) --- widgets/base.lua | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 widgets/base.lua diff --git a/widgets/base.lua b/widgets/base.lua new file mode 100644 index 0000000..0431d03 --- /dev/null +++ b/widgets/base.lua @@ -0,0 +1,37 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2014, Luke Bonham + +--]] + +local newtimer = require("lain.helpers").newtimer +local wibox = require("wibox") + +local io = io +local setmetatable = setmetatable + +-- Basic template for simple widgets +-- lain.widgets.base +local base = {} + +local function worker(args) + local args = args or {} + local timeout = args.timeout or 5 + local cmd = args.cmd or "" + local settings = args.settings or function() end + + base.widget = wibox.widget.textbox('') + + function update() + output = io.popen(cmd):read("*all") + widget = base.widget + settings() + end + + newtimer(cmd, timeout, update) + return base.widget +end + +return setmetatable(base, { __call = function(_, ...) return worker(...) end }) From 342df3ab43dfe857195c3a5921781895718533b8 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 13 Feb 2014 18:17:48 +0100 Subject: [PATCH 419/572] base: update subfuction added; contrib/brightness removed because now redundant --- widgets/base.lua | 11 +++++---- widgets/contrib/brightness.lua | 42 ---------------------------------- wiki | 2 +- 3 files changed, 8 insertions(+), 47 deletions(-) delete mode 100644 widgets/contrib/brightness.lua diff --git a/widgets/base.lua b/widgets/base.lua index 0431d03..198b6f7 100644 --- a/widgets/base.lua +++ b/widgets/base.lua @@ -12,7 +12,7 @@ local wibox = require("wibox") local io = io local setmetatable = setmetatable --- Basic template for simple widgets +-- Basic template for custom widgets -- lain.widgets.base local base = {} @@ -24,14 +24,17 @@ local function worker(args) base.widget = wibox.widget.textbox('') - function update() - output = io.popen(cmd):read("*all") + function base.update() + local f = assert(io.popen(cmd)) + output = f:read("*all") + f:close() widget = base.widget settings() end newtimer(cmd, timeout, update) - return base.widget + + return setmetatable(base, { __index = base.widget }) end return setmetatable(base, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/contrib/brightness.lua b/widgets/contrib/brightness.lua deleted file mode 100644 index 04b8d2b..0000000 --- a/widgets/contrib/brightness.lua +++ /dev/null @@ -1,42 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, yawnt - ---]] - -local newtimer = require("lain.helpers").newtimer - -local wibox = require("wibox") -local io = { popen = io.popen } - -local setmetatable = setmetatable - --- Brightness level --- lain.widgets.contrib.brightness -local brightness = {} - -local function worker(args) - local args = args or {} - local backlight = args.backlight or "acpi_video0" - local timeout = args.timeout or 5 - local settings = args.settings or function() end - - brightness.widget = wibox.widget.textbox('') - - function brightness.update() - local f = assert(io.popen('cat /sys/class/backlight/' .. backlight .. "/brightness")) - brightness_now = f:read("*a") - f:close() - - widget = brightness.widget - settings() - end - - newtimer("brightness", timeout, brightness.update) - - return setmetatable(brightness, { __index = brightness.widget }) -end - -return setmetatable(brightness, { __call = function(_, ...) return worker(...) end }) diff --git a/wiki b/wiki index 6075408..b56a779 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 60754084cf7bb69d7387484e12fa686c73cfe1bc +Subproject commit b56a779e276987cb9f8f8d81785d35633db047d1 From cabd72a77557bc7d406b4a639e3abbd276003d91 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 14 Feb 2014 18:02:02 +0100 Subject: [PATCH 420/572] base: small fix --- widgets/base.lua | 2 +- widgets/calendar.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/base.lua b/widgets/base.lua index 198b6f7..3d4ce9e 100644 --- a/widgets/base.lua +++ b/widgets/base.lua @@ -32,7 +32,7 @@ local function worker(args) settings() end - newtimer(cmd, timeout, update) + newtimer(cmd, timeout, base.update) return setmetatable(base, { __index = base.widget }) end diff --git a/widgets/calendar.lua b/widgets/calendar.lua index d0df17c..c9e265a 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -37,7 +37,7 @@ function calendar:show(t_out, inc_offset) local tims = t_out or 0 local f, c_text local today = tonumber(os.date('%d')) - local init_t = '/usr/bin/cal --color=never | sed -r -e "s/(^| )( ' + local init_t = '/usr/bin/cal | sed -r -e "s/(^| )( ' if offs == 0 then -- current month showing, today highlighted From e4e2154c9bffa10f9bd3b68488f8e4ad8bd37d1b Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 16 Feb 2014 11:05:58 +0100 Subject: [PATCH 421/572] readme updated --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index f59c04d..23cfb9d 100644 --- a/README.rst +++ b/README.rst @@ -17,6 +17,8 @@ Successor of awesome-vain_, this module provides new layouts, a set of widgets a Read the wiki_ for all the info. +**Note that**: this module requires Awesome version 3.5 or higher. + Contributions ------------- From bd68259c512a9698495b71d5d02352c973336836 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 16 Feb 2014 11:08:21 +0100 Subject: [PATCH 422/572] readme updated --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 23cfb9d..1d15555 100644 --- a/README.rst +++ b/README.rst @@ -17,7 +17,7 @@ Successor of awesome-vain_, this module provides new layouts, a set of widgets a Read the wiki_ for all the info. -**Note that**: this module requires Awesome version 3.5 or higher. +**Note that** this module requires Awesome version 3.5 or higher. Contributions ------------- From 232f1aa2512cc7d82ddad6b03dcac8769c085a83 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 18 Feb 2014 10:47:19 +0100 Subject: [PATCH 423/572] readme updated --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 1d15555..ca6569b 100644 --- a/README.rst +++ b/README.rst @@ -34,7 +34,7 @@ Just make sure that: - You eventually update ``wiki`` submodule with a thorough section. -Contributed widgets have to be put in ``lain/widget/contrib``. +Contributed widgets have to be put in ``lain/widgets/contrib``. Screenshots ----------- From fd1ec3b943c348c811770c63c3b0ac7801088d05 Mon Sep 17 00:00:00 2001 From: Ayman Khamouma Date: Tue, 18 Feb 2014 13:42:16 +0200 Subject: [PATCH 424/572] use awful.tag.gettags in order to keep compatibility with custom configs such as tyrannical --- util/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/init.lua b/util/init.lua index 1dfff65..2f28b9a 100644 --- a/util/init.lua +++ b/util/init.lua @@ -146,7 +146,7 @@ function util.tag_view_nonempty(direction, sc) local s = sc or mouse.screen or 1 local scr = screen[s] - for i = 1, #tags[s] do + for i = 1, #awful.tag.gettags(s) do awful.tag.viewidx(direction,s) if #awful.client.visible(s) > 0 then return From 86b932b7c120c30e3ad2ce3838018f9e2942f729 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 22 Feb 2014 14:38:19 +0100 Subject: [PATCH 425/572] readme updated --- README.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index ca6569b..a06b64e 100644 --- a/README.rst +++ b/README.rst @@ -1,9 +1,9 @@ Lain ==== ---------------------------------------------- -Layouts, widgets and utilities for Awesome WM ---------------------------------------------- +-------------------------------------------------- +Layouts, widgets and utilities for Awesome WM 3.5+ +-------------------------------------------------- :Author: Luke Bonham :Version: git @@ -17,8 +17,6 @@ Successor of awesome-vain_, this module provides new layouts, a set of widgets a Read the wiki_ for all the info. -**Note that** this module requires Awesome version 3.5 or higher. - Contributions ------------- From efbe1c28ad42bf56c7ac2130b30ff687d9c05032 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 4 Mar 2014 09:54:43 +0100 Subject: [PATCH 426/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index b56a779..fc181b7 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit b56a779e276987cb9f8f8d81785d35633db047d1 +Subproject commit fc181b7e13ebd4b63b0e2bdc6e170101a022f783 From 880e0188ba8205c90db2c363893378dc0f341d77 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 11 Mar 2014 20:31:00 +0100 Subject: [PATCH 427/572] yawn: #31 fix + zh_CN added --- widgets/yawn/init.lua | 3 +- widgets/yawn/localizations/zh_CN | 60 ++++++++++++++++++++++++++++++++ wiki | 2 +- 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 widgets/yawn/localizations/zh_CN diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 3f08cd5..86a2d0f 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -135,7 +135,8 @@ local function fetch_weather() yawn.icon:set_image(sky) widget = yawn.widget - forecast = weather_data:match(": %S.-,"):gsub(": ", ""):gsub(",", "") + _data = weather_data:match(": %S.-,") or weather_data + forecast = _data:gsub(": ", ""):gsub(",", "") units = units:gsub(" ", "") settings() diff --git a/widgets/yawn/localizations/zh_CN b/widgets/yawn/localizations/zh_CN new file mode 100644 index 0000000..681bc60 --- /dev/null +++ b/widgets/yawn/localizations/zh_CN @@ -0,0 +1,60 @@ +Now:|当前: +Sun:|周日: +Mon:|周一: +Tue:|周二: +Wed:|周三: +Thu:|周四: +Fri:|周五: +Sat:|周六: +Mostly Sunny|晴时多云 +Sunny|阳光 +Sun|太阳 +Rain/Thunder|雨/雷 +Isolated Thunderstorms|局部雷雨 +Scattered Thunderstorms|零星雷雨 +Thundershowers|雷阵雨 +Thunderstorms|雷雨 +Thunder in the Vicinity|周围有雷雨 +Thunder|雷鸣 +AM|上午 +PM|下午 +Early|早 +Late|晚 +Few|短暂 +Severe|恶劣 +Clear|晴朗 +Fair|晴 +Partly|局部 +Mostly|大部 +Cloudy|多云 +Clouds|有云 +Scattered Showers|零星阵雨 +Light Snow Showers|小阵雪 +Snow Showers|阵雪 +Heavy Snow|大雪 +Scattered Snow Showers|零星阵雪 +Mixed Rain And Snow|雨夹雪 +Mixed Rain And Sleet|雨加雹 +Mixed Snow And Sleet|雪加雹 +Mixed Rain And Hail|雨加冰雹 +Snow Flurries|阵雪 +Blowing Snow|风吹雪 +Blowing Rain|风吹雨 +Heavy Rain|大雨 +Freezing Rain|冻雨 +Showers|阵雨 +Light Rain|小雨 +Heavy|大 +Rain|雨 +Windy|有风 +Wind|风 +Snow|雪 +Sleet|雹 +Freezing Drizzle|冻毛雨 +Light Drizzle|微雨 +Drizzle|毛毛雨 +Hail|冰雹 +Fog|雾 +Foggy|有雾 +Haze|薄雾 +Light|小 \ No newline at end of file diff --git a/wiki b/wiki index fc181b7..434d32a 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit fc181b7e13ebd4b63b0e2bdc6e170101a022f783 +Subproject commit 434d32a7dac5770ed7ddd1581967df7d7aeb76be From ad1c15b7c11d779eec233edc5df8a1e1f874fd63 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 11 Mar 2014 21:35:43 +0100 Subject: [PATCH 428/572] typos --- widgets/imap.lua | 2 +- widgets/yawn/localizations/zh_CN | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/imap.lua b/widgets/imap.lua index 39518bd..febff23 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -67,7 +67,7 @@ local function worker(args) widget = imap.widget settings() - if mailcount > helpers.get_map(mail) and mailcount >= 1 + if mailcount >= 1 and mailcount > helpers.get_map(mail) then if mailcount == 1 then nt = mail .. " has one new message" diff --git a/widgets/yawn/localizations/zh_CN b/widgets/yawn/localizations/zh_CN index 681bc60..20de61e 100644 --- a/widgets/yawn/localizations/zh_CN +++ b/widgets/yawn/localizations/zh_CN @@ -57,4 +57,4 @@ Hail|冰雹 Fog|雾 Foggy|有雾 Haze|薄雾 -Light|小 \ No newline at end of file +Light|小 From 39db2acd6928c85cf2d23240651af3be5a77b17c Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 11 Mar 2014 21:38:49 +0100 Subject: [PATCH 429/572] typos --- widgets/yawn/localizations/zh_CN | 2 ++ 1 file changed, 2 insertions(+) diff --git a/widgets/yawn/localizations/zh_CN b/widgets/yawn/localizations/zh_CN index 20de61e..ae8dfdf 100644 --- a/widgets/yawn/localizations/zh_CN +++ b/widgets/yawn/localizations/zh_CN @@ -58,3 +58,5 @@ Fog|雾 Foggy|有雾 Haze|薄雾 Light|小 + + From e411f4927620a3cfa7c72fd058701d82e0abee56 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 11 Mar 2014 21:44:22 +0100 Subject: [PATCH 430/572] #32 fix attempt --- widgets/bat.lua | 6 +++--- widgets/yawn/localizations/zh_CN | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 485fd57..cc0eac1 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -122,16 +122,16 @@ local function worker(args) settings() -- notifications for low and critical states - bat_now.perc = tonumber(bat_now.perc) + local nperc = tonumber(bat_now.perc) if bat_now.status == "Discharging" and notify == "on" and bat_now.perc ~= nil then - if bat_now.perc <= 5 + if nperc <= 5 then bat.id = naughty.notify({ preset = bat_notification_critical_preset, replaces_id = bat.id }).id - elseif bat_now.perc <= 15 + elseif nperc <= 15 then bat.id = naughty.notify({ preset = bat_notification_low_preset, diff --git a/widgets/yawn/localizations/zh_CN b/widgets/yawn/localizations/zh_CN index ae8dfdf..20de61e 100644 --- a/widgets/yawn/localizations/zh_CN +++ b/widgets/yawn/localizations/zh_CN @@ -58,5 +58,3 @@ Fog|雾 Foggy|有雾 Haze|薄雾 Light|小 - - From 15df52747e3ff10f61638fee7c85f6beb6bf28db Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 11 Mar 2014 21:50:44 +0100 Subject: [PATCH 431/572] #32 fix attempt --- widgets/bat.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index cc0eac1..c14e94c 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -122,9 +122,9 @@ local function worker(args) settings() -- notifications for low and critical states - local nperc = tonumber(bat_now.perc) if bat_now.status == "Discharging" and notify == "on" and bat_now.perc ~= nil then + local nperc = tonumber(bat_now.perc) if nperc <= 5 then bat.id = naughty.notify({ From a1032bea7bc9060ecac42623fb58977a17334000 Mon Sep 17 00:00:00 2001 From: zheng Date: Fri, 14 Mar 2014 21:59:40 +0800 Subject: [PATCH 432/572] modify localization for zh_CN --- widgets/yawn/localizations/zh_CN | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/widgets/yawn/localizations/zh_CN b/widgets/yawn/localizations/zh_CN index 20de61e..53b0219 100644 --- a/widgets/yawn/localizations/zh_CN +++ b/widgets/yawn/localizations/zh_CN @@ -7,7 +7,7 @@ Thu:|周四: Fri:|周五: Sat:|周六: Mostly Sunny|晴时多云 -Sunny|阳光 +Sunny|晴朗 Sun|太阳 Rain/Thunder|雨/雷 Isolated Thunderstorms|局部雷雨 @@ -34,9 +34,9 @@ Snow Showers|阵雪 Heavy Snow|大雪 Scattered Snow Showers|零星阵雪 Mixed Rain And Snow|雨夹雪 -Mixed Rain And Sleet|雨加雹 -Mixed Snow And Sleet|雪加雹 -Mixed Rain And Hail|雨加冰雹 +Mixed Rain And Sleet|雨转雨夹雪 +Mixed Snow And Sleet|雪转雨夹雪 +Mixed Rain And Hail|雨夹冰雹 Snow Flurries|阵雪 Blowing Snow|风吹雪 Blowing Rain|风吹雨 @@ -49,12 +49,12 @@ Rain|雨 Windy|有风 Wind|风 Snow|雪 -Sleet|雹 -Freezing Drizzle|冻毛雨 -Light Drizzle|微雨 +Sleet|冻雨 +Freezing Drizzle|冻毛毛雨 +Light Drizzle|细雨 Drizzle|毛毛雨 Hail|冰雹 Fog|雾 Foggy|有雾 -Haze|薄雾 +Haze|霾 Light|小 From 5c9ddf31ae45eee33586b6ec7bac7ccfaf9086fa Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 15 Mar 2014 11:13:26 +0100 Subject: [PATCH 433/572] #32 fix attempt 2 --- widgets/bat.lua | 2 +- wiki | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index c14e94c..1d8f8c3 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -124,7 +124,7 @@ local function worker(args) -- notifications for low and critical states if bat_now.status == "Discharging" and notify == "on" and bat_now.perc ~= nil then - local nperc = tonumber(bat_now.perc) + local nperc = tonumber(bat_now.perc) or 100 if nperc <= 5 then bat.id = naughty.notify({ diff --git a/wiki b/wiki index 434d32a..b35f693 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 434d32a7dac5770ed7ddd1581967df7d7aeb76be +Subproject commit b35f6931d9685d53e10a051c1d558151331b041f From a0bd2798accb561db079aebbdd3ee8d4d9c65465 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 30 Mar 2014 12:30:59 +0200 Subject: [PATCH 434/572] calendar: cal variable added --- widgets/calendar.lua | 7 ++++--- wiki | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index c9e265a..bd7f08c 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -37,13 +37,13 @@ function calendar:show(t_out, inc_offset) local tims = t_out or 0 local f, c_text local today = tonumber(os.date('%d')) - local init_t = '/usr/bin/cal | sed -r -e "s/(^| )( ' + local init_t = calendar.cal .. ' | sed -r -e "s/(^| )( ' if offs == 0 then -- current month showing, today highlighted if today >= 10 then - init_t = '/usr/bin/cal | sed -r -e "s/(^| )(' + init_t = calendar.cal .. ' | sed -r -e "s/(^| )(' end calendar.offset = 0 @@ -80,7 +80,7 @@ function calendar:show(t_out, inc_offset) calendar.notify_icon = nil - f = io.popen('/usr/bin/cal ' .. month .. ' ' .. year) + f = io.popen(calendar.cal .. ' ' .. month .. ' ' .. year) end c_text = "= 10 then @@ -61,7 +63,6 @@ function calendar:show(t_out, inc_offset) local month = tonumber(os.date('%m')) local year = tonumber(os.date('%Y')) - calendar.offset = calendar.offset + offs month = month + calendar.offset if month > 12 then From a8bbff7a6d224507d6212623cb1bdffea537e08d Mon Sep 17 00:00:00 2001 From: Brendan Almonte Date: Tue, 8 Apr 2014 21:36:35 -0400 Subject: [PATCH 437/572] Adding scrolling support to the calendar --- widgets/calendar.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index bd7f08c..f83b966 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -120,7 +120,11 @@ function calendar:attach(widget, args) widget:buttons(awful.util.table.join( awful.button({ }, 1, function () calendar:show(0, -1) end), awful.button({ }, 3, function () - calendar:show(0, 1) end) )) + calendar:show(0, 1) end), + awful.button({ }, 4, function () + calendar:show(0, -1) end), + awful.button({ }, 5, function () + calendar:show(0, 1) end))) end return setmetatable(calendar, { __call = function(_, ...) return create(...) end }) From 1bfc3bae68ac72ab3bf1754984cc8c6d7d5a247e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=20Kl=C3=A4rner?= Date: Thu, 10 Apr 2014 12:28:20 +0200 Subject: [PATCH 438/572] ask df for a specific filesystem POSIX df supports requesting a single filesystem, so doing so will ensure that df can only get stuck if the filesystem we requested is in a hung state. --- widgets/fs.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/fs.lua b/widgets/fs.lua index 7406e05..4d9d278 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -67,7 +67,7 @@ local function worker(args) fs_info = {} fs_now = {} - local f = io.popen("LC_ALL=C df -kP") + local f = io.popen("LC_ALL=C df -kP " .. partition) for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount) local s = string.match(line, "^.-[%s]([%d]+)") From 6f0c5a59f79fdb67941cee1461642d204d45c0a5 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 11 Apr 2014 09:36:22 +0200 Subject: [PATCH 439/572] wiki updated for pull #39 --- widgets/fs.lua | 4 +--- wiki | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/widgets/fs.lua b/widgets/fs.lua index 4d9d278..79f821e 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -50,7 +50,7 @@ function fs:show(t_out) }) end --- Units definitions +-- Unit definitions local unit = { ["mb"] = 1024, ["gb"] = 1024^2 } local function worker(args) @@ -84,8 +84,6 @@ local function worker(args) f:close() - -- chosen partition easy stuff - -- you can however check whatever partition else fs_now.used = tonumber(fs_info[partition .. " used_p"]) or 0 fs_now.available = tonumber(fs_info[partition .. " avail_p"]) or 0 fs_now.size_mb = tonumber(fs_info[partition .. " size_mb"]) or 0 diff --git a/wiki b/wiki index bff87f6..571b618 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit bff87f6bb0d1707d0f089a4449082ce43b121275 +Subproject commit 571b618dce199ba0e349c8c6498f08df45150329 From 6e2b1d3e43b77f9a5e72ed12754fefcc315f04d4 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 12 Apr 2014 15:01:43 +0200 Subject: [PATCH 440/572] revert #36; fix #41 --- widgets/mpd.lua | 3 +-- wiki | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index d8bcd78..1749b57 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -10,7 +10,6 @@ local helpers = require("lain.helpers") local escape_f = require("awful.util").escape -local surface = require("gears").surface local naughty = require("naughty") local wibox = require("wibox") @@ -92,7 +91,7 @@ local function worker(args) mpd.id = naughty.notify({ preset = mpd_notification_preset, - icon = surface.load_uncached("/tmp/mpdcover.png"), + icon = "/tmp/mpdcover.png", replaces_id = mpd.id }).id end diff --git a/wiki b/wiki index 571b618..54b3a71 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 571b618dce199ba0e349c8c6498f08df45150329 +Subproject commit 54b3a717b2f7069264ce5a20018ae4abf153e7b2 From f5eac3a48ed6de9b1fd6d58f97465a6a31654566 Mon Sep 17 00:00:00 2001 From: Andrea Scarpino Date: Sun, 13 Apr 2014 12:19:02 +0200 Subject: [PATCH 441/572] net: optional notifications --- widgets/net.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/widgets/net.lua b/widgets/net.lua index af97201..08c7366 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -44,6 +44,7 @@ local function worker(args) local timeout = args.timeout or 2 local iface = args.iface or net.get_device() local units = args.units or 1024 --kb + local notify = args.notify or "on" local settings = args.settings or function() end net.widget = wibox.widget.textbox('') @@ -76,7 +77,7 @@ local function worker(args) net.last_t = now_t net.last_r = now_r - if net_now.carrier ~= "1" + if net_now.carrier ~= "1" and notify == "on" then if helpers.get_map(iface) then From 74bbbc4e4d12c3c8efb2c92763f30e7d65fb885c Mon Sep 17 00:00:00 2001 From: Thomas Etcheverria Date: Sun, 20 Apr 2014 16:04:39 +0200 Subject: [PATCH 442/572] add yawn localization fr_FR --- widgets/yawn/localizations/fr_FR | 60 ++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 widgets/yawn/localizations/fr_FR diff --git a/widgets/yawn/localizations/fr_FR b/widgets/yawn/localizations/fr_FR new file mode 100644 index 0000000..b88f51d --- /dev/null +++ b/widgets/yawn/localizations/fr_FR @@ -0,0 +1,60 @@ +Now:|Auj: +Sun:|Dim: +Mon:|Lun: +Tue:|Mar: +Wed:|Mer: +Thu:|Jeu: +Fri:|Ven: +Sat:|Sam: +Mostly Sunny| +Sunny|Ensoleillé +Sun|Soleil +Rain/Thunder|Pluie/Orage +Isolated Thunderstorms|Orages localisés +Scattered Thunderstorms|Orages épars +Thundershowers| +Thunderstorms|Orages +Thunder in the Vicinity|Orage aux alentours +Thunder|Orages +AM|Matinée +PM|Après-midi +Early|Tôt +Late|Tard +Few|Quelques +Severe|Sévère +Clear|Clair +Fair|Clair +Partly|Partiellement +Mostly|Très +Cloudy|Nuageux +Clouds|Nuages +Scattered Showers|Nuages épars +Light Snow Showers|Légères averses de neige +Snow Showers|Averses de neige +Heavy Snow|Neige +Scattered Snow Showers|Averses de neige localisées +Mixed Rain And Snow|Alternance de neige et de pluie +Mixed Rain And Sleet|Alternance de pluie et de neige fondue +Mixed Snow And Sleet|Alternance de neige et de neige fondue +Mixed Rain And Hail|Alternance de pluie et de grêle +Snow Flurries|Averses de neige +Blowing Snow|Neige +Blowing Rain|Pluie +Heavy Rain|Pluie forte +Freezing Rain|Pluie verglaçante +Showers|Averses +Light Rain|Pluie légère +Heavy|Forte +Rain|Pluie +Windy|Venteux +Wind|Vent +Snow|Neige +Sleet|Neige fondue +Freezing Drizzle|Bruine verglaçante +Light Drizzle|Légère bruine +Drizzle|Bruine +Hail|Grêle +Fog|Brouillard +Foggy|Brumeux +Haze|Brume +Light|Clair \ No newline at end of file From d64e059ffb546edf4ac90ca05b0788382863bc30 Mon Sep 17 00:00:00 2001 From: Thomas Etcheverria Date: Mon, 21 Apr 2014 22:28:47 +0200 Subject: [PATCH 443/572] fix missing --- widgets/yawn/localizations/fr_FR | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/yawn/localizations/fr_FR b/widgets/yawn/localizations/fr_FR index b88f51d..444b02c 100644 --- a/widgets/yawn/localizations/fr_FR +++ b/widgets/yawn/localizations/fr_FR @@ -6,13 +6,13 @@ Wed:|Mer: Thu:|Jeu: Fri:|Ven: Sat:|Sam: -Mostly Sunny| +Mostly Sunny|Partiellement ensoleillé Sunny|Ensoleillé Sun|Soleil Rain/Thunder|Pluie/Orage Isolated Thunderstorms|Orages localisés Scattered Thunderstorms|Orages épars -Thundershowers| +Thundershowers|Tempête Thunderstorms|Orages Thunder in the Vicinity|Orage aux alentours Thunder|Orages From 1152e7e8a6c3c66a4a1631e3df8958a220f060a1 Mon Sep 17 00:00:00 2001 From: Zoltan Tombol Date: Sat, 26 Apr 2014 16:41:14 +0200 Subject: [PATCH 444/572] fix cpu load calculation --- widgets/cpu.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/cpu.lua b/widgets/cpu.lua index 0b21edc..7c1ecb0 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -43,9 +43,9 @@ local function worker(args) local total = 0 for field in string.gmatch(times, "[%s]+([^%s]+)") do - -- 3 = idle, 4 = ioWait. Essentially, the CPUs have done + -- 4 = idle, 5 = ioWait. Essentially, the CPUs have done -- nothing during these times. - if at == 3 or at == 4 + if at == 4 or at == 5 then idle = idle + field end From d65d0b6426ded28f6a5b4cd2cc0b65d34c4d4c6a Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Tue, 29 Apr 2014 12:58:25 +0200 Subject: [PATCH 445/572] cpu widget calc fix --- widgets/cpu.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/cpu.lua b/widgets/cpu.lua index 0b21edc..7c1ecb0 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -43,9 +43,9 @@ local function worker(args) local total = 0 for field in string.gmatch(times, "[%s]+([^%s]+)") do - -- 3 = idle, 4 = ioWait. Essentially, the CPUs have done + -- 4 = idle, 5 = ioWait. Essentially, the CPUs have done -- nothing during these times. - if at == 3 or at == 4 + if at == 4 or at == 5 then idle = idle + field end From b60b9b7c2d65a5c5f8e68fbec27665e9abb99f76 Mon Sep 17 00:00:00 2001 From: Thierry Ghelew Date: Wed, 7 May 2014 17:29:51 +0200 Subject: [PATCH 446/572] fix maildir and /util/init.lua which was not counting email properly and lacking function util.element_in_table function --- util/init.lua | 10 ++++++++++ widgets/maildir.lua | 9 ++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/util/init.lua b/util/init.lua index 2f28b9a..d99f007 100644 --- a/util/init.lua +++ b/util/init.lua @@ -210,4 +210,14 @@ function util.useless_gaps_resize(thatmuch) awful.layout.arrange(mouse.screen) end +-- Check if an element exist on a table +function util.element_in_table(element, tbl) + for _, i in pairs(tbl) do + if i == element then + return true + end + end + return false +end + return setmetatable(util, { __index = wrequire }) diff --git a/widgets/maildir.lua b/widgets/maildir.lua index d460881..8fe097e 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -11,6 +11,8 @@ local newtimer = require("lain.helpers").newtimer local wibox = require("wibox") +local util = require("lain.util") + local io = io local os = { getenv = os.getenv } local pairs = pairs @@ -66,15 +68,16 @@ local function worker(args) table.sort(boxes) newmail = "no mail" + --Count the total number of mails irrespective of where it was found + total = 0 - local count = 0 for box, number in pairs(boxes) do - count = count + 1 -- Add this box only if it's not to be ignored. if not util.element_in_table(box, ignore_boxes) then - if newmail == "" + total = total + number + if newmail == "no mail" then newmail = box .. "(" .. number .. ")" else From 90623d2e5d787909be18b494faa041a5fd8cb515 Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Thu, 8 May 2014 15:10:57 +0200 Subject: [PATCH 447/572] yawn: language failsafe --- widgets/yawn/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 86a2d0f..4109d6c 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -36,7 +36,7 @@ local localizations_path = project_path .. 'localizations/' local icon_path = project_path .. 'icons/' local api_url = 'http://weather.yahooapis.com/forecastrss' local units_set = '?u=c&w=' -- Default is Celsius -local language = string.match(os.getenv("LANG"), "(%S*$*)[.]") +local language = string.match(os.getenv("LANG"), "(%S*$*)[.]") or "en_US" -- if LANG is not set local weather_data = nil local notification = nil local city_id = nil From a8f64c8f087ac92e1d12d63d5b1cfea3d1d9132a Mon Sep 17 00:00:00 2001 From: Lukas Geis Date: Tue, 27 May 2014 15:54:37 +0200 Subject: [PATCH 448/572] Redshift widget and icons added --- icons/redshift/redshift_off.png | Bin 0 -> 267 bytes icons/redshift/redshift_on.png | Bin 0 -> 253 bytes widgets/contrib/redshift.lua | 79 ++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 icons/redshift/redshift_off.png create mode 100644 icons/redshift/redshift_on.png create mode 100644 widgets/contrib/redshift.lua diff --git a/icons/redshift/redshift_off.png b/icons/redshift/redshift_off.png new file mode 100644 index 0000000000000000000000000000000000000000..a92200fcde26a71dafbbc196264e9f3f7b720e93 GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|wj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&kwQRhpNT%Pxsc5-22_84^+AoS&PUnpXnkGB7w7r6!i7 zrYMwWmSiZnd-?{X=%um)#q&K~978NlCnrd3YY>cGkaV(skxAK+1zD*Fm+#o(BzpA9 zyT02!JFXZBW^?En?$K+?bSQVsY<>0r64%xLH)7f@yWSAFd^FqV$gZ{tGM*dT_%}?* zGQP+uB)Mm5pkv|050kBXRHR$9TNf{Xaq#t`gX|1Z0mk~9wjY%NxyjSj&t;ucLK6TD C<>&kwQRhpMg;@LNqNkAdl%#er@=ltB<)VvZPmw~~#C^fMp zHASI3vm`^o-P1Q9MK6^dD4yu);uvCaIypgNTZ3Tif~1r6i%iOnEXYbdxO~SJC()x< z-u2z?*>S~4Fq=cqa1YzV%MIRrol%Xx(aj%Nwe&1k?d)g`nce9(;lzWrJzQQqoc22p ndu(#t5oA%-CAUXUs)m8#$W~?T*MDd7fn4F~>gTe~DWM4fyunhR literal 0 HcmV?d00001 diff --git a/widgets/contrib/redshift.lua b/widgets/contrib/redshift.lua new file mode 100644 index 0000000..38f1d83 --- /dev/null +++ b/widgets/contrib/redshift.lua @@ -0,0 +1,79 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2014, blueluke + +--]] + +local os = os +local awful = require("awful") +local spawn = awful.util.spawn_with_shell + +local setmetatable = setmetatable + +-- redshift +-- 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 function init() + -- 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 + os.execute("pkill redshift") + -- Remove existing color adjustment + spawn("redshift -x") + -- (Re)start redshift + spawn("redshift") + running = true + active = true +end + +function redshift:toggle() + if running then + -- Sending -USR1 toggles redshift (See project website) + os.execute("pkill -USR1 redshift") + active = not active + else + init() + end + update_fnct() +end + +function redshift:off() + if running and active then + redshift:toggle() + end +end + +function redshift:on() + if not active then + redshift:toggle() + end +end + +function redshift:is_active() + return active +end + +-- Attach to a widget +-- Provides a button which toggles redshift on/off on click +-- @ param widget: widget to attach to +-- @ param fnct: function to be run each time redshift is toggled (optional). +-- Use it to update widget text or icons on status change. +function redshift:attach(widget, fnct) + update_fnct = fnct or function() end + if not attached then + init() + attached = true + update_fnct() + end + widget:buttons(awful.util.table.join( awful.button({}, 1, function () redshift:toggle() end) )) +end + +return setmetatable(redshift, { _call = function(_, ...) return create(...) end }) From 7acc7293fb5d2b2b4f1b0260de060c5d326fa406 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 2 Jun 2014 10:28:42 +0200 Subject: [PATCH 449/572] #49 fix --- widgets/calendar.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index f3d7b8a..61451fc 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -45,7 +45,7 @@ function calendar:show(t_out, inc_offset) then -- current month showing, today highlighted if today >= 10 then - init_t = calendar.cal .. ' | sed -r -e "s/(^| )(' + init_t = calendar.cal .. ' | sed -r -e "s/_\\x08//g" | sed -r -e "s/(^| )(' end calendar.offset = 0 From 0f5ce4dd76e96524ce7a534d228a212f51eb5c93 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 13 Jun 2014 09:44:36 +0200 Subject: [PATCH 450/572] #52 fix + multiple imap widgets feature added --- widgets/base.lua | 4 ++-- widgets/imap.lua | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/widgets/base.lua b/widgets/base.lua index 3d4ce9e..4f28e07 100644 --- a/widgets/base.lua +++ b/widgets/base.lua @@ -14,9 +14,9 @@ local setmetatable = setmetatable -- Basic template for custom widgets -- lain.widgets.base -local base = {} local function worker(args) + local base = {} local args = args or {} local timeout = args.timeout or 5 local cmd = args.cmd or "" @@ -37,4 +37,4 @@ local function worker(args) return setmetatable(base, { __index = base.widget }) end -return setmetatable(base, { __call = function(_, ...) return worker(...) end }) +return setmetatable({}, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/imap.lua b/widgets/imap.lua index febff23..6104388 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -20,9 +20,9 @@ local setmetatable = setmetatable -- Mail IMAP check -- lain.widgets.imap -local imap = {} local function worker(args) + local imap = {} local args = args or {} local server = args.server @@ -81,7 +81,7 @@ local function worker(args) end helpers.newtimer(mail, timeout, update, true) - return imap.widget + return setmetatable(imap, { __index = imap.widget }) end -return setmetatable(imap, { __call = function(_, ...) return worker(...) end }) +return setmetatable({}, { __call = function(_, ...) return worker(...) end }) From 4b634be781379140002b191b04e167a4460ae5f4 Mon Sep 17 00:00:00 2001 From: WooParadog Date: Sat, 19 Jul 2014 22:36:15 +0800 Subject: [PATCH 451/572] show notification window in focused screen --- widgets/alsabar.lua | 30 ++++++++++++++++-------------- widgets/bat.lua | 6 ++++-- widgets/calendar.lua | 3 ++- widgets/contrib/task.lua | 10 +++++++--- widgets/contrib/tpbat/init.lua | 12 ++++++++---- widgets/fs.lua | 7 ++++--- widgets/imap.lua | 6 +++++- widgets/mpd.lua | 3 ++- widgets/net.lua | 3 ++- widgets/yawn/init.lua | 3 ++- 10 files changed, 52 insertions(+), 31 deletions(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 365ac2d..4ae12e5 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -54,22 +54,22 @@ local alsabar = function alsabar.notify() alsabar.update() - local preset = - { + local preset = + { title = "", text = "", timeout = 4, font = alsabar.notifications.font .. " " .. alsabar.notifications.font_size, fg = alsabar.notifications.color - } + } - if alsabar._muted + if alsabar._muted then - preset.title = alsabar.channel .. " - Muted" - else - preset.title = alsabar.channel .. " - " .. alsabar._current_level * 100 .. "%" - end + preset.title = alsabar.channel .. " - Muted" + else + preset.title = alsabar.channel .. " - " .. alsabar._current_level * 100 .. "%" + end int = math.modf(alsabar._current_level * alsabar.notifications.bar_size) preset.text = "[" @@ -78,15 +78,17 @@ function alsabar.notify() .. "]" if alsabar._notify ~= nil then - alsabar._notify = naughty.notify ({ + alsabar._notify = naughty.notify ({ replaces_id = alsabar._notify.id, - preset = preset + preset = preset, + screen = client.focus and client.focus.screen or 1 }) - else - alsabar._notify = naughty.notify ({ - preset = preset + else + alsabar._notify = naughty.notify ({ + preset = preset, + screen = client.focus and client.focus.screen or 1 }) - end + end end local function worker(args) diff --git a/widgets/bat.lua b/widgets/bat.lua index 1d8f8c3..2ace758 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -129,13 +129,15 @@ local function worker(args) then bat.id = naughty.notify({ preset = bat_notification_critical_preset, - replaces_id = bat.id + replaces_id = bat.id, + screen = client.focus and client.focus.screen or 1 }).id elseif nperc <= 15 then bat.id = naughty.notify({ preset = bat_notification_low_preset, - replaces_id = bat.id + replaces_id = bat.id, + screen = client.focus and client.focus.screen or 1 }).id end end diff --git a/widgets/calendar.lua b/widgets/calendar.lua index 61451fc..4e6eda7 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -98,7 +98,8 @@ function calendar:show(t_out, inc_offset) position = calendar.position, fg = calendar.fg, bg = calendar.bg, - timeout = tims + timeout = tims, + screen = client.focus and client.focus.screen or 1 }) end diff --git a/widgets/contrib/task.lua b/widgets/contrib/task.lua index a6c9f31..6e6ebae 100644 --- a/widgets/contrib/task.lua +++ b/widgets/contrib/task.lua @@ -51,7 +51,9 @@ function task:show() position = task.position, fg = task.fg, bg = task.bg, - timeout = task.timeout }) + timeout = task.timeout, + screen = client.focus and client.focus.screen or 1 + }) end function task:prompt_add() @@ -72,7 +74,8 @@ function task:prompt_add() position = task.position, fg = task.fg, bg = task.bg, - timeout = task.timeout + timeout = task.timeout, + screen = client.focus and client.focus.screen or 1 }) end, nil, @@ -105,7 +108,8 @@ function task:prompt_search() position = task.position, fg = task.fg, bg = task.bg, - timeout = task.timeout + timeout = task.timeout, + screen = client.focus and client.focus.screen or 1 }) end, nil, diff --git a/widgets/contrib/tpbat/init.lua b/widgets/contrib/tpbat/init.lua index 72d6453..782bf35 100644 --- a/widgets/contrib/tpbat/init.lua +++ b/widgets/contrib/tpbat/init.lua @@ -75,7 +75,8 @@ function tpbat:show(t_out) tpbat_notification = naughty.notify({ preset = { fg = beautiful.fg_normal }, text = str, - timeout = t_out + timeout = t_out, + screen = client.focus and client.focus.screen or 1 }) end @@ -111,7 +112,8 @@ function tpbat.register(args) local n = naughty.notify({ preset = bat_notification_low_preset, title = "SMAPI Battery Warning: Unable to read battery state!", - text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths." + text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths.", + screen = client.focus and client.focus.screen or 1 }) end @@ -137,13 +139,15 @@ function tpbat.register(args) then tpbat.id = naughty.notify({ preset = bat_notification_critical_preset, - replaces_id = tpbat.id + replaces_id = tpbat.id, + screen = client.focus and client.focus.screen or 1 }).id elseif bat_now.perc <= 15 then tpbat.id = naughty.notify({ preset = bat_notification_low_preset, - replaces_id = tpbat.id + replaces_id = tpbat.id, + screen = client.focus and client.focus.screen or 1 }).id end end diff --git a/widgets/fs.lua b/widgets/fs.lua index 79f821e..867ce3f 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -46,7 +46,8 @@ function fs:show(t_out) notification = naughty.notify({ preset = fs_notification_preset, text = ws, - timeout = t_out + timeout = t_out, + screen = client.focus and client.focus.screen or 1 }) end @@ -66,7 +67,6 @@ local function worker(args) function update() fs_info = {} fs_now = {} - local f = io.popen("LC_ALL=C df -kP " .. partition) for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount) @@ -99,7 +99,8 @@ local function worker(args) text = partition .. " ran out!\nmake some room", timeout = 8, fg = "#000000", - bg = "#FFFFFF" + bg = "#FFFFFF", + screen = client.focus and client.focus.screen or 1 }) helpers.set_map("fs", true) else diff --git a/widgets/imap.lua b/widgets/imap.lua index 6104388..c404032 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -74,7 +74,11 @@ local function worker(args) else nt = mail .. " has " .. mailcount .. " new messages" end - naughty.notify({ preset = mail_notification_preset, text = nt }) + naughty.notify({ + preset = mail_notification_preset, + text = nt, + screen = client.focus and client.focus.screen or 1 + }) end helpers.set_map(mail, mailcount) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 1749b57..73efebb 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -92,7 +92,8 @@ local function worker(args) mpd.id = naughty.notify({ preset = mpd_notification_preset, icon = "/tmp/mpdcover.png", - replaces_id = mpd.id + replaces_id = mpd.id, + screen = client.focus and client.focus.screen or 1 }).id end elseif mpd_now.state ~= "pause" diff --git a/widgets/net.lua b/widgets/net.lua index 08c7366..1e59731 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -87,7 +87,8 @@ local function worker(args) timeout = 7, position = "top_left", icon = helpers.icons_dir .. "no_net.png", - fg = notify_fg or "#FFFFFF" + fg = notify_fg or "#FFFFFF", + screen = client.focus and client.focus.screen or 1 }) helpers.set_map(iface, false) end diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 4109d6c..da2b856 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -161,7 +161,8 @@ function yawn.show(t_out) preset = yawn_notification_preset, text = weather_data, icon = sky, - timeout = t_out + timeout = t_out, + screen = client.focus and client.focus.screen or 1 }) end From 57e595c656255e1093d261b255f789017c002bc0 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 21 Jul 2014 13:34:40 +0200 Subject: [PATCH 452/572] #54 fix attempt --- widgets/alsabar.lua | 84 +++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 4ae12e5..4430e76 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -24,70 +24,66 @@ local setmetatable = setmetatable -- ALSA volume bar -- lain.widgets.alsabar -local alsabar = -{ - channel = "Master", - step = "5%", +local alsabar = { + channel = "Master", + step = "5%", - colors = - { - background = beautiful.bg_normal, - mute = "#EB8F8F", - unmute = "#A4CE8A" - }, + colors = { + background = beautiful.bg_normal, + mute = "#EB8F8F", + unmute = "#A4CE8A" + }, - terminal = terminal or "xterm", - mixer = terminal .. " -e alsamixer", + terminal = terminal or "xterm", + mixer = terminal .. " -e alsamixer", - notifications = - { - font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), - font_size = "11", - color = beautiful.fg_normal, - bar_size = 18 - }, + notifications = { + font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), + font_size = "11", + color = beautiful.fg_normal, + bar_size = 18 + }, - _current_level = 0, - _muted = false + _current_level = 0, + _muted = false } function alsabar.notify() - alsabar.update() + alsabar.update() - local preset = - { - title = "", - text = "", - timeout = 4, - font = alsabar.notifications.font .. " " .. - alsabar.notifications.font_size, - fg = alsabar.notifications.color + local preset = { + title = "", + text = "", + timeout = 4, + font = alsabar.notifications.font .. " " .. + alsabar.notifications.font_size, + fg = alsabar.notifications.color } if alsabar._muted - then + then preset.title = alsabar.channel .. " - Muted" else - preset.title = alsabar.channel .. " - " .. alsabar._current_level * 100 .. "%" + preset.title = alsabar.channel .. " - " .. alsabar._current_level .. "%" end - int = math.modf(alsabar._current_level * alsabar.notifications.bar_size) - preset.text = "[" + int = math.modf((alsabar._current_level / 100) * alsabar.notifications.bar_size) + preset.text = "[" .. string.rep("|", int) .. string.rep(" ", alsabar.notifications.bar_size - int) .. "]" - if alsabar._notify ~= nil then + if alsabar._notify ~= nil then alsabar._notify = naughty.notify ({ - replaces_id = alsabar._notify.id, - preset = preset, - screen = client.focus and client.focus.screen or 1 - }) + replaces_id = alsabar._notify.id, + preset = preset, + screen = client.focus and client.focus.screen or 1 + }) else alsabar._notify = naughty.notify ({ - preset = preset, - screen = client.focus and client.focus.screen or 1 - }) + preset = preset, + screen = client.focus and client.focus.screen or 1 + }) end end @@ -131,8 +127,8 @@ local function worker(args) mute = "off" end - alsabar._current_level = tonumber(volu) / 100 - alsabar.bar:set_value(alsabar._current_level) + alsabar._current_level = tonumber(volu) + alsabar.bar:set_value(alsabar._current_level / 100) if not mute and tonumber(volu) == 0 or mute == "off" then From e2a279d9914ca92241d3f342cffbd47d3b8684a9 Mon Sep 17 00:00:00 2001 From: WooParadog Date: Sat, 26 Jul 2014 10:17:49 +0800 Subject: [PATCH 453/572] Add -M to amixer. -M Use the mapped volume for evaluating the percentage representation like alsamixer, to be more natural for human ear. --- widgets/alsa.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 28bb05c..4ed4f9c 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -29,7 +29,7 @@ local function worker(args) alsa.widget = wibox.widget.textbox('') function alsa.update() - local f = assert(io.popen('amixer get ' .. channel)) + local f = assert(io.popen('amixer -M get ' .. channel)) local mixer = f:read("*all") f:close() From 1862d1b139576794184ce07536897af9421d6c93 Mon Sep 17 00:00:00 2001 From: WooParadog Date: Sat, 26 Jul 2014 10:24:38 +0800 Subject: [PATCH 454/572] pass -M to amixer in alsabar --- widgets/alsabar.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 4430e76..e185c76 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -115,7 +115,7 @@ local function worker(args) function alsabar.update() -- Get mixer control contents - local f = io.popen("amixer get " .. alsabar.channel) + local f = io.popen("amixer -M get " .. alsabar.channel) local mixer = f:read("*all") f:close() From af3bcd29922f918780b42273d6d174e7d2b0a0d1 Mon Sep 17 00:00:00 2001 From: Axujen Date: Wed, 30 Jul 2014 14:37:20 +0000 Subject: [PATCH 455/572] Use the first client(master) as the central window --- layout/centerwork.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/centerwork.lua b/layout/centerwork.lua index b8175ea..939f18c 100644 --- a/layout/centerwork.lua +++ b/layout/centerwork.lua @@ -37,7 +37,7 @@ function centerwork.arrange(p) if #cls > 0 then -- Main column, fixed width and height. - local c = cls[#cls] + local c = cls[1] local g = {} local mainwid = math.floor(wa.width * mwfact) local slavewid = wa.width - mainwid @@ -57,7 +57,7 @@ function centerwork.arrange(p) if #cls > 1 then local at = 0 - for i = (#cls - 1),1,-1 + for i = (#cls),2,-1 do -- It's all fixed. If there are more than 5 clients, -- those additional clients will float. This is From f2fb4f6fdadc1b09877e5ef6bd75e06a668a4080 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 5 Aug 2014 12:59:19 +0200 Subject: [PATCH 456/572] IMAP wiget is now asynchronous --- asyncshell.lua | 80 ++++++++++++++++++++++++++++++++++++++++++++ widgets/alsa.lua | 2 +- widgets/alsabar.lua | 2 +- widgets/base.lua | 2 +- widgets/calendar.lua | 2 +- widgets/cpu.lua | 2 +- widgets/fs.lua | 2 +- widgets/imap.lua | 47 ++++++++++++++------------ widgets/maildir.lua | 2 +- widgets/net.lua | 2 +- widgets/sysload.lua | 2 +- widgets/temp.lua | 2 +- 12 files changed, 115 insertions(+), 32 deletions(-) create mode 100644 asyncshell.lua diff --git a/asyncshell.lua b/asyncshell.lua new file mode 100644 index 0000000..c05fb6b --- /dev/null +++ b/asyncshell.lua @@ -0,0 +1,80 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2013, Alexander Yakushev + +--]] + +-- Asynchronous io.popen for Awesome WM. +-- How to use... +-- ...asynchronously: +-- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end) +-- ...synchronously +-- wwidget.text = asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error" + +local spawn = require('awful.util').spawn + +asyncshell = {} +asyncshell.request_table = {} +asyncshell.id_counter = 0 +asyncshell.folder = "/tmp/asyncshell" +asyncshell.file_template = asyncshell.folder .. '/req' + +-- Create a directory for asynchell response files +os.execute("mkdir -p " .. asyncshell.folder) + +-- Returns next tag - unique identifier of the request +local function next_id() + asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000 + return asyncshell.id_counter +end + +-- Sends an asynchronous request for an output of the shell command. +-- @param command Command to be executed and taken output from +-- @param callback Function to be called when the command finishes +-- @return Request ID +function asyncshell.request(command, callback) + local id = next_id() + local tmpfname = asyncshell.file_template .. id + asyncshell.request_table[id] = {callback = callback} + local req = + string.format("bash -c '%s > %s; " .. + 'echo "asyncshell.deliver(%s)" | ' .. + "awesome-client' 2> /dev/null", + string.gsub(command, "'", "'\\''"), tmpfname, + id, tmpfname) + spawn(req, false) + return id +end + +-- Calls the remembered callback function on the output of the shell +-- command. +-- @param id Request ID +-- @param output The output file of the shell command to be delievered +function asyncshell.deliver(id) + if asyncshell.request_table[id] and + asyncshell.request_table[id].callback then + local output = io.open(asyncshell.file_template .. id, 'r') + asyncshell.request_table[id].callback(output) + end +end + +-- Sends a synchronous request for an output of the command. Waits for +-- the output, but if the given timeout expires returns nil. +-- @param command Command to be executed and taken output from +-- @param timeout Maximum amount of time to wait for the result +-- @return File handler on success, nil otherwise +function asyncshell.demand(command, timeout) + local id = next_id() + local tmpfname = asyncshell.file_template .. id + local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " .. + "(sleep %s; echo asynchell_timeout)", + command, tmpfname, timeout)) + local result = f:read("*line") + if result == "asyncshell_done" then + return io.open(tmpfname) + end +end + +return asyncshell diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 4ed4f9c..f62a150 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -30,7 +30,7 @@ local function worker(args) function alsa.update() local f = assert(io.popen('amixer -M get ' .. channel)) - local mixer = f:read("*all") + local mixer = f:read("*a") f:close() volume_now = {} diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index e185c76..8675cb5 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -116,7 +116,7 @@ local function worker(args) function alsabar.update() -- Get mixer control contents local f = io.popen("amixer -M get " .. alsabar.channel) - local mixer = f:read("*all") + local mixer = f:read("*a") f:close() -- Capture mixer control state: [5%] ... ... [on] diff --git a/widgets/base.lua b/widgets/base.lua index 4f28e07..6b808b7 100644 --- a/widgets/base.lua +++ b/widgets/base.lua @@ -26,7 +26,7 @@ local function worker(args) function base.update() local f = assert(io.popen(cmd)) - output = f:read("*all") + output = f:read("*a") f:close() widget = base.widget settings() diff --git a/widgets/calendar.lua b/widgets/calendar.lua index 4e6eda7..c690e3f 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -88,7 +88,7 @@ function calendar:show(t_out, inc_offset) .. calendar.font_size .. "'>" .. f:read() .. "\n\n" .. f:read() .. "\n" - .. f:read("*all"):gsub("\n*$", "") + .. f:read("*a"):gsub("\n*$", "") .. "" f:close() diff --git a/widgets/cpu.lua b/widgets/cpu.lua index 7c1ecb0..96e0d3b 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -58,7 +58,7 @@ local function worker(args) local dactive = active - cpu.last_active local dtotal = total - cpu.last_total - cpu_now = {} + cpu_noj = {} cpu_now.usage = tostring(math.ceil((dactive / dtotal) * 100)) widget = cpu.widget diff --git a/widgets/fs.lua b/widgets/fs.lua index 867ce3f..8127c28 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -40,7 +40,7 @@ function fs:show(t_out) fs:hide() local f = io.popen(helpers.scripts_dir .. "dfs") - ws = f:read("*all"):gsub("\n*$", "") + ws = f:read("*a"):gsub("\n*$", "") f:close() notification = naughty.notify({ diff --git a/widgets/imap.lua b/widgets/imap.lua index c404032..1dca87c 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -7,11 +7,11 @@ --]] local helpers = require("lain.helpers") +local async = require("lain.asyncshell") local naughty = require("naughty") local wibox = require("wibox") -local io = { popen = io.popen } local string = { format = string.format, gsub = string.gsub } local tonumber = tonumber @@ -42,7 +42,7 @@ local function worker(args) if not is_plain then local f = io.popen(password) - password = f:read("*all"):gsub("\n", "") + password = f:read("*a"):gsub("\n", "") f:close() end @@ -57,34 +57,37 @@ local function worker(args) curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%s %s -k", head_command, server, port, mail, password, request) - f = io.popen(curl) - ws = f:read("*all") - f:close() + async.request(curl, function(f) + ws = f:read("*a") + f:close() - _, mailcount = string.gsub(ws, "%d+", "") - _ = nil + _, mailcount = string.gsub(ws, "%d+", "") + _ = nil - widget = imap.widget - settings() + widget = imap.widget + settings() - if mailcount >= 1 and mailcount > helpers.get_map(mail) - then - if mailcount == 1 then - nt = mail .. " has one new message" - else - nt = mail .. " has " .. mailcount .. " new messages" + if mailcount >= 1 and mailcount > helpers.get_map(mail) + then + if mailcount == 1 then + nt = mail .. " has one new message" + else + nt = mail .. " has " .. mailcount .. " new messages" + end + naughty.notify({ + preset = mail_notification_preset, + text = nt, + screen = client.focus and client.focus.screen or 1 + }) end - naughty.notify({ - preset = mail_notification_preset, - text = nt, - screen = client.focus and client.focus.screen or 1 - }) - end - helpers.set_map(mail, mailcount) + helpers.set_map(mail, mailcount) + end) + end helpers.newtimer(mail, timeout, update, true) + return setmetatable(imap, { __index = imap.widget }) end diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 8fe097e..bd79221 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -53,7 +53,7 @@ local function worker(args) local np = io.popen("find " .. line .. "/new -mindepth 1 -type f " .. "-not -name '.*' -printf a") - local mailstring = np:read("*all") + local mailstring = np:read("*a") -- Strip off leading mailpath. local box = string.match(line, mailpath .. "/*([^/]+)") diff --git a/widgets/net.lua b/widgets/net.lua index 1e59731..7851d5a 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -29,7 +29,7 @@ local net = { function net.get_device() f = io.popen("ip link show | cut -d' ' -f2,9") - ws = f:read("*all") + ws = f:read("*a") f:close() ws = ws:match("%w+: UP") if ws ~= nil then diff --git a/widgets/sysload.lua b/widgets/sysload.lua index 2abac33..b15b1bf 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -30,7 +30,7 @@ local function worker(args) function update() local f = io.open("/proc/loadavg") - local ret = f:read("*all") + local ret = f:read("*a") f:close() load_1, load_5, load_15 = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") diff --git a/widgets/temp.lua b/widgets/temp.lua index 61a9aa5..4ae1c04 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -31,7 +31,7 @@ local function worker(args) local f = io.open(tempfile) if f ~= nil then - coretemp_now = tonumber(f:read("*all")) / 1000 + coretemp_now = tonumber(f:read("*a")) / 1000 f:close() else coretemp_now = "N/A" From 4903782e553dd8d16ae0ff5eab6c60886a52b673 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 7 Aug 2014 12:21:02 +0200 Subject: [PATCH 457/572] small fixes --- widgets/yawn/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index da2b856..148f547 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -48,7 +48,7 @@ yawn_notification_preset = {} local function fetch_weather() local url = api_url .. units_set .. city_id local f = io.popen("curl --connect-timeout 1 -fsm 3 '" .. url .. "'" ) - local text = f:read("*all") + local text = f:read("*a") f:close() -- In case of no connection or invalid city ID From 823659d83d1262bbd94821e8460822c0130fff56 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 7 Aug 2014 12:21:30 +0200 Subject: [PATCH 458/572] small fixes --- asyncshell.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asyncshell.lua b/asyncshell.lua index c05fb6b..4eb8d2e 100644 --- a/asyncshell.lua +++ b/asyncshell.lua @@ -39,7 +39,7 @@ function asyncshell.request(command, callback) local tmpfname = asyncshell.file_template .. id asyncshell.request_table[id] = {callback = callback} local req = - string.format("bash -c '%s > %s; " .. + string.format("sh -c '%s > %s; " .. 'echo "asyncshell.deliver(%s)" | ' .. "awesome-client' 2> /dev/null", string.gsub(command, "'", "'\\''"), tmpfname, From 6714db710a53b3c13d4526dcd922e1333ca6c1af Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 7 Aug 2014 13:37:24 +0200 Subject: [PATCH 459/572] mpd and yawn widget are now asynchronous --- asyncshell.lua | 2 + widgets/mpd.lua | 81 ++++++++++--------- widgets/yawn/init.lua | 178 +++++++++++++++++++++--------------------- 3 files changed, 133 insertions(+), 128 deletions(-) diff --git a/asyncshell.lua b/asyncshell.lua index 4eb8d2e..51885e8 100644 --- a/asyncshell.lua +++ b/asyncshell.lua @@ -13,6 +13,8 @@ -- ...synchronously -- wwidget.text = asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error" +-- This makes things faster, but puts weight on sysload and is more cpu demanding. + local spawn = require('awful.util').spawn asyncshell = {} diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 73efebb..385b5bb 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -8,6 +8,7 @@ --]] local helpers = require("lain.helpers") +local async = require("lain.asyncshell") local escape_f = require("awful.util").escape local naughty = require("naughty") @@ -50,56 +51,54 @@ local function worker(args) helpers.set_map("current mpd track", nil) function mpd.update() - mpd_now = { - state = "N/A", - file = "N/A", - artist = "N/A", - title = "N/A", - album = "N/A", - date = "N/A" - } + async.request(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh, function (f) + mpd_now = { + state = "N/A", + file = "N/A", + artist = "N/A", + title = "N/A", + album = "N/A", + date = "N/A" + } - local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh) - - for line in f:lines() 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 == "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) + for line in f:lines() 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 == "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) + end end end - end - f:close() + mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist, + mpd_now.album, mpd_now.date, mpd_now.title) + widget = mpd.widget + settings() - mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist, - mpd_now.album, mpd_now.date, mpd_now.title) - widget = mpd.widget - settings() - - if mpd_now.state == "play" - then - if mpd_now.title ~= helpers.get_map("current mpd track") + if mpd_now.state == "play" then - helpers.set_map("current mpd track", mpd_now.title) + if mpd_now.title ~= helpers.get_map("current mpd track") + then + helpers.set_map("current mpd track", mpd_now.title) - os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir, - mpd_now.file, cover_size, default_art)) + os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir, + mpd_now.file, cover_size, default_art)) - mpd.id = naughty.notify({ - preset = mpd_notification_preset, - icon = "/tmp/mpdcover.png", - replaces_id = mpd.id, - screen = client.focus and client.focus.screen or 1 - }).id + mpd.id = naughty.notify({ + preset = mpd_notification_preset, + icon = "/tmp/mpdcover.png", + replaces_id = mpd.id, + screen = client.focus and client.focus.screen or 1 + }).id + end + elseif mpd_now.state ~= "pause" + then + helpers.set_map("current mpd track", nil) end - elseif mpd_now.state ~= "pause" - then - helpers.set_map("current mpd track", nil) - end + end) end helpers.newtimer("mpd", timeout, mpd.update) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 148f547..033254e 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -7,6 +7,7 @@ --]] local newtimer = require("lain.helpers").newtimer +local async = require("lain.asyncshell") local naughty = require("naughty") local wibox = require("wibox") @@ -47,99 +48,102 @@ yawn_notification_preset = {} local function fetch_weather() local url = api_url .. units_set .. city_id - local f = io.popen("curl --connect-timeout 1 -fsm 3 '" .. url .. "'" ) - local text = f:read("*a") - f:close() + local cmd = "curl --connect-timeout 1 -fsm 3 '" .. url .. "'" - -- In case of no connection or invalid city ID - -- widgets won't display - if text == "" or text:match("City not found") - then - yawn.icon:set_image(icon_path .. "na.png") - if text == "" then - weather_data = "Service not available at the moment." - yawn.widget:set_text(" N/A ") - else - weather_data = "City not found!\n" .. - "Are you sure " .. city_id .. - " is your Yahoo city ID?" - yawn.widget:set_text(" ? ") - end - return - end - - -- Processing raw data - weather_data = text:gsub("<.->", "") - weather_data = weather_data:match("Current Conditions:.-Full") or "" - - -- may still happens in case of bad connectivity - if weather_data == "" then - yawn.icon:set_image(icon_path .. "na.png") - yawn.widget:set_text(" ? ") - return - end - - weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ") - weather_data = weather_data:gsub("Forecast:.-\n", "") - weather_data = weather_data:gsub("\nFull", "") - weather_data = weather_data:gsub("[\n]$", "") - weather_data = weather_data:gsub(" [-] " , ": ") - weather_data = weather_data:gsub("[.]", ",") - weather_data = weather_data:gsub("High: ", "") - weather_data = weather_data:gsub(" Low: ", " - ") - - -- Getting info for text widget - local now = weather_data:sub(weather_data:find("Now:")+5, - weather_data:find("\n")-1) - forecast = now:sub(1, now:find(",")-1) - units = now:sub(now:find(",")+2, -2) - - -- Day/Night icon change - local hour = tonumber(os.date("%H")) - sky = icon_path - - if forecast == "Clear" or - forecast == "Fair" or - forecast == "Partly Cloudy" or - forecast == "Mostly Cloudy" - then - if hour >= 6 and hour <= 18 - then - sky = sky .. "Day" - else - sky = sky .. "Night" - end - end - - sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png" - - -- In case there's no defined icon for current forecast - if io.open(sky) == nil then - sky = icon_path .. "na.png" - end - - -- Localization - local f = io.open(localizations_path .. language, "r") - if language:find("en_") == nil and f ~= nil - then + async.request(cmd, function(f) + local text = f:read("*a") f:close() - for line in io.lines(localizations_path .. language) - do - word = string.sub(line, 1, line:find("|")-1) - translation = string.sub(line, line:find("|")+1) - weather_data = string.gsub(weather_data, word, translation) + + -- In case of no connection or invalid city ID + -- widgets won't display + if text == "" or text:match("City not found") + then + yawn.icon:set_image(icon_path .. "na.png") + if text == "" then + weather_data = "Service not available at the moment." + yawn.widget:set_text(" N/A ") + else + weather_data = "City not found!\n" .. + "Are you sure " .. city_id .. + " is your Yahoo city ID?" + yawn.widget:set_text(" ? ") + end + return end - end - -- Finally setting infos - yawn.icon:set_image(sky) - widget = yawn.widget + -- Processing raw data + weather_data = text:gsub("<.->", "") + weather_data = weather_data:match("Current Conditions:.-Full") or "" - _data = weather_data:match(": %S.-,") or weather_data - forecast = _data:gsub(": ", ""):gsub(",", "") - units = units:gsub(" ", "") + -- may still happens in case of bad connectivity + if weather_data == "" then + yawn.icon:set_image(icon_path .. "na.png") + yawn.widget:set_text(" ? ") + return + end - settings() + weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ") + weather_data = weather_data:gsub("Forecast:.-\n", "") + weather_data = weather_data:gsub("\nFull", "") + weather_data = weather_data:gsub("[\n]$", "") + weather_data = weather_data:gsub(" [-] " , ": ") + weather_data = weather_data:gsub("[.]", ",") + weather_data = weather_data:gsub("High: ", "") + weather_data = weather_data:gsub(" Low: ", " - ") + + -- Getting info for text widget + local now = weather_data:sub(weather_data:find("Now:")+5, + weather_data:find("\n")-1) + forecast = now:sub(1, now:find(",")-1) + units = now:sub(now:find(",")+2, -2) + + -- Day/Night icon change + local hour = tonumber(os.date("%H")) + sky = icon_path + + if forecast == "Clear" or + forecast == "Fair" or + forecast == "Partly Cloudy" or + forecast == "Mostly Cloudy" + then + if hour >= 6 and hour <= 18 + then + sky = sky .. "Day" + else + sky = sky .. "Night" + end + end + + sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png" + + -- In case there's no defined icon for current forecast + if io.open(sky) == nil then + sky = icon_path .. "na.png" + end + + -- Localization + local f = io.open(localizations_path .. language, "r") + if language:find("en_") == nil and f ~= nil + then + f:close() + for line in io.lines(localizations_path .. language) + do + word = string.sub(line, 1, line:find("|")-1) + translation = string.sub(line, line:find("|")+1) + weather_data = string.gsub(weather_data, word, translation) + end + end + + -- Finally setting infos + yawn.icon:set_image(sky) + widget = yawn.widget + + _data = weather_data:match(": %S.-,") or weather_data + forecast = _data:gsub(": ", ""):gsub(",", "") + units = units:gsub(" ", "") + + settings() + end) end function yawn.hide() From bb7fbebf1f880683950bcd1f897951529775724f Mon Sep 17 00:00:00 2001 From: Chris Morin Date: Thu, 7 Aug 2014 17:13:32 -0400 Subject: [PATCH 460/572] fix typo --- widgets/cpu.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/cpu.lua b/widgets/cpu.lua index 96e0d3b..7c1ecb0 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -58,7 +58,7 @@ local function worker(args) local dactive = active - cpu.last_active local dtotal = total - cpu.last_total - cpu_noj = {} + cpu_now = {} cpu_now.usage = tostring(math.ceil((dactive / dtotal) * 100)) widget = cpu.widget From 0d5c25ffd4ed4d5c1a06b1f0b731b1cb6db79b8b Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 8 Aug 2014 14:10:25 +0200 Subject: [PATCH 461/572] abase widget added --- widgets/abase.lua | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 widgets/abase.lua diff --git a/widgets/abase.lua b/widgets/abase.lua new file mode 100644 index 0000000..20cc955 --- /dev/null +++ b/widgets/abase.lua @@ -0,0 +1,43 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2014, Luke Bonham + +--]] + +local newtimer = require("lain.helpers").newtimer +local async = require("lain.asyncshell") +local wibox = require("wibox") + +local io = io +local setmetatable = setmetatable + +-- Basic template for custom widgets +-- Asynchronous version +-- lain.widgets.abase + +local function worker(args) + local abase = {} + local args = args or {} + local timeout = args.timeout or 5 + local cmd = args.cmd or "" + local settings = args.settings or function() end + + abase.widget = wibox.widget.textbox('') + + function abase.update() + async.request(cmd, function(f) + output = f:read("*a") + f:close() + widget = abase.widget + settings() + end) + end + + newtimer(cmd, timeout, abase.update) + + return setmetatable(abase, { __index = abase.widget }) +end + +return setmetatable({}, { __call = function(_, ...) return worker(...) end }) From f37a31878edfb59d56c2b0fde04ae80c46a8809e Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 8 Aug 2014 14:25:21 +0200 Subject: [PATCH 462/572] widget module loads optimization --- helpers.lua | 2 +- widgets/abase.lua | 1 - widgets/base.lua | 4 ++-- widgets/borderbox.lua | 1 + widgets/calendar.lua | 2 +- widgets/fs.lua | 2 +- widgets/imap.lua | 2 +- widgets/maildir.lua | 2 +- widgets/net.lua | 2 +- widgets/temp.lua | 2 +- widgets/yawn/init.lua | 3 ++- 11 files changed, 12 insertions(+), 11 deletions(-) diff --git a/helpers.lua b/helpers.lua index 863bb87..1dfb09b 100644 --- a/helpers.lua +++ b/helpers.lua @@ -2,7 +2,7 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham + * (c) 2013, Luke Bonham --]] diff --git a/widgets/abase.lua b/widgets/abase.lua index 20cc955..075d615 100644 --- a/widgets/abase.lua +++ b/widgets/abase.lua @@ -10,7 +10,6 @@ local newtimer = require("lain.helpers").newtimer local async = require("lain.asyncshell") local wibox = require("wibox") -local io = io local setmetatable = setmetatable -- Basic template for custom widgets diff --git a/widgets/base.lua b/widgets/base.lua index 6b808b7..39b0863 100644 --- a/widgets/base.lua +++ b/widgets/base.lua @@ -9,10 +9,10 @@ local newtimer = require("lain.helpers").newtimer local wibox = require("wibox") -local io = io +local io = { popen = io.popen } local setmetatable = setmetatable --- Basic template for custom widgets +-- Basic template for custom widgets -- lain.widgets.base local function worker(args) diff --git a/widgets/borderbox.lua b/widgets/borderbox.lua index c251ea8..cce8517 100644 --- a/widgets/borderbox.lua +++ b/widgets/borderbox.lua @@ -8,6 +8,7 @@ --]] local wibox = require("awful.wibox") + local setmetatable = setmetatable -- Creates a thin wibox at a position relative to another wibox diff --git a/widgets/calendar.lua b/widgets/calendar.lua index c690e3f..d07a5b4 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -12,7 +12,7 @@ local awful = require("awful") local beautiful = require("beautiful") local naughty = require("naughty") -local io = io +local io = { popen = io.popen } local os = { date = os.date } local tonumber = tonumber diff --git a/widgets/fs.lua b/widgets/fs.lua index 8127c28..f78cfe0 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -14,7 +14,7 @@ local beautiful = require("beautiful") local wibox = require("wibox") local naughty = require("naughty") -local io = io +local io = { popen = io.popen } local pairs = pairs local string = { match = string.match, format = string.format } diff --git a/widgets/imap.lua b/widgets/imap.lua index 1dca87c..65c425e 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -57,7 +57,7 @@ local function worker(args) curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%s %s -k", head_command, server, port, mail, password, request) - async.request(curl, function(f) + async.request(curl, function(f) ws = f:read("*a") f:close() diff --git a/widgets/maildir.lua b/widgets/maildir.lua index bd79221..246341f 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -13,7 +13,7 @@ local wibox = require("wibox") local util = require("lain.util") -local io = io +local io = { popen = io.popen } local os = { getenv = os.getenv } local pairs = pairs local string = { len = string.len, diff --git a/widgets/net.lua b/widgets/net.lua index 7851d5a..9575000 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -13,7 +13,7 @@ local notify_fg = require("beautiful").fg_focus local naughty = require("naughty") local wibox = require("wibox") -local io = io +local io = { popen = io.popen } local tostring = tostring local string = { format = string.format, gsub = string.gsub } diff --git a/widgets/temp.lua b/widgets/temp.lua index 4ae1c04..5994f59 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -10,7 +10,7 @@ local newtimer = require("lain.helpers").newtimer local wibox = require("wibox") -local io = io +local io = { open = io.open } local tonumber = tonumber local setmetatable = setmetatable diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index 033254e..aa58ed1 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -13,7 +13,8 @@ local naughty = require("naughty") local wibox = require("wibox") local debug = { getinfo = debug.getinfo } -local io = io +local io = { lines = io.lines, + open = io.open } local os = { date = os.date, getenv = os.getenv } local string = { find = string.find, From 24ac1f98e6a5a92a61e5935b2ed4d03ed79ec6b0 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 8 Sep 2014 18:51:48 +0200 Subject: [PATCH 463/572] imap: increased curl connect-timeout --- widgets/imap.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/imap.lua b/widgets/imap.lua index 65c425e..3a6da8d 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -34,7 +34,7 @@ local function worker(args) local is_plain = args.is_plain or false local settings = args.settings or function() end - local head_command = "curl --connect-timeout 1 -fsm 3" + local head_command = "curl --connect-timeout 3 -fsm 3" local request = "-X 'SEARCH (UNSEEN)'" helpers.set_map(mail, 0) From 55e72b9aa480779b83129776658c41ccef28d599 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 11 Sep 2014 16:10:22 +0200 Subject: [PATCH 464/572] yawn: new words localized --- widgets/yawn/localizations/fr_FR | 3 ++- widgets/yawn/localizations/it_IT | 1 + widgets/yawn/localizations/localization_template | 1 + widgets/yawn/localizations/zh_CN | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/widgets/yawn/localizations/fr_FR b/widgets/yawn/localizations/fr_FR index 444b02c..18a35bb 100644 --- a/widgets/yawn/localizations/fr_FR +++ b/widgets/yawn/localizations/fr_FR @@ -57,4 +57,5 @@ Hail|Grêle Fog|Brouillard Foggy|Brumeux Haze|Brume -Light|Clair \ No newline at end of file +Light|Clair +With|Avec diff --git a/widgets/yawn/localizations/it_IT b/widgets/yawn/localizations/it_IT index 70b0eef..44d010e 100644 --- a/widgets/yawn/localizations/it_IT +++ b/widgets/yawn/localizations/it_IT @@ -58,3 +58,4 @@ Fog|Nebbia Foggy|Nebbioso Haze|Nebbia Light|Leggere +With|Con diff --git a/widgets/yawn/localizations/localization_template b/widgets/yawn/localizations/localization_template index 453807e..2fbf066 100644 --- a/widgets/yawn/localizations/localization_template +++ b/widgets/yawn/localizations/localization_template @@ -58,3 +58,4 @@ Fog| Foggy| Haze| Light| +With| diff --git a/widgets/yawn/localizations/zh_CN b/widgets/yawn/localizations/zh_CN index 53b0219..61e98a4 100644 --- a/widgets/yawn/localizations/zh_CN +++ b/widgets/yawn/localizations/zh_CN @@ -58,3 +58,4 @@ Fog|雾 Foggy|有雾 Haze|霾 Light|小 +With|與 From 0ffc8fe4e5f1ef79c4d22e5bcbcd1bf7234df539 Mon Sep 17 00:00:00 2001 From: projektile Date: Mon, 22 Sep 2014 11:25:27 -0400 Subject: [PATCH 465/572] save arezzo files --- layout/cascade.lua | 17 +++++++++++++- layout/cascadetile.lua | 38 +++++++++++++++++++++----------- layout/centerfair.lua | 46 +++++++++++++++++++++++++------------- layout/centerwork.lua | 37 +++++++++++++++++++++---------- layout/termfair.lua | 49 +++++++++++++++++++---------------------- layout/uselessfair.lua | 48 ++++++++++++++++++++-------------------- layout/uselesspiral.lua | 46 ++++++++++++++++++++++++-------------- layout/uselesstile.lua | 44 +++++++++++++++++++++++------------- 8 files changed, 203 insertions(+), 122 deletions(-) diff --git a/layout/cascade.lua b/layout/cascade.lua index cabacef..999c599 100644 --- a/layout/cascade.lua +++ b/layout/cascade.lua @@ -2,12 +2,14 @@ --[[ Licensed under GNU General Public License v2 + * (c) 2014, projektile * (c) 2013, Luke Bonham * (c) 2010-2012, Peter Hofmann --]] -local tag = require("awful.tag") +local tag = require("awful.tag") +local beautiful = require("beautiful") local cascade = { @@ -21,10 +23,23 @@ function cascade.arrange(p) -- Cascade windows. + -- A global border can be defined with + -- beautiful.global_border_width. + local global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + + -- Themes border width requires an offset. + local bw = tonumber(beautiful.border_width) or 0 + -- Screen. local wa = p.workarea local cls = p.clients + wa.height = wa.height - ((global_border * 2) + (bw * 2)) + wa.width = wa.width - ((global_border * 2) + (bw * 2)) + wa.x = wa.x + global_border + wa.y = wa.y + global_border + -- Opening a new window will usually force all existing windows to -- get resized. This wastes a lot of CPU time. So let's set a lower -- bound to "how_many": This wastes a little screen space but you'll diff --git a/layout/cascadetile.lua b/layout/cascadetile.lua index 98821e3..e9b9425 100644 --- a/layout/cascadetile.lua +++ b/layout/cascadetile.lua @@ -2,6 +2,7 @@ --[[ Licensed under GNU General Public License v2 + * (c) 2014, projektile * (c) 2013, Luke Bonham * (c) 2010-2012, Peter Hofmann @@ -30,25 +31,36 @@ function cascadetile.arrange(p) -- It's a bit hard to demonstrate the behaviour with ASCII-images... -- - -- (1) (2) (3) (4) - -- +-----+---+ +-----+---+ +-----+---+ +-----+---+ - -- | | | | | | | | | | | 4 | - -- | | | | | 2 | | | 3 | | | | - -- | 1 | | -> | 1 | | -> | 1 | | -> | 1 +---+ - -- | | | | +---+ | +---+ | | 3 | - -- | | | | | | | | 2 | | |---| - -- | | | | | | | |---| | | 2 | - -- | | | | | | | | | | |---| - -- +-----+---+ +-----+---+ +-----+---+ +-----+---+ + -- (1) (2) (3) (4) + -- +----------+---+ +----------+---+ +----------+---+ +----------+---+ + -- | | | | | 3 | | | 4 | | +---+| + -- | | | -> | | | -> | +---++ -> | +---+|+ + -- | 1 | 2 | | 1 +---++ | 1 | 3 || | 1 +---+|+| + -- | | | | | 2 || | +---++| | +---+|+ | + -- | | | | | || | | 2 | | | | 2 |+ | + -- +----------+---+ +---------+---++ +--------+---+-+ +------+---+---+ -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width. local useless_gap = tonumber(beautiful.useless_gap_width) or 0 + if useless_gap < 0 then useless_gap = 0 end + + -- A global border can be defined with + -- beautiful.global_border_width + local global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + + -- Themes border width requires an offset + local bw = tonumber(beautiful.border_width) or 0 -- Screen. local wa = p.workarea local cls = p.clients + -- Borders are factored in. + wa.height = wa.height - ((global_border * 2) + (bw * 2)) + wa.width = wa.width - ((global_border * 2) + (bw * 2)) + -- Width of main column? local t = tag.selected(p.screen) local mwfact @@ -108,8 +120,8 @@ function cascadetile.arrange(p) end g.height = wa.height - g.x = wa.x - g.y = wa.y + g.x = wa.x + global_border + g.y = wa.y + global_border if useless_gap > 0 then -- Reduce width once and move window to the right. Reduce @@ -138,7 +150,7 @@ function cascadetile.arrange(p) g.width = slavewid - current_offset_x g.height = wa.height - current_offset_y g.x = wa.x + mainwid + (how_many - i) * cascadetile.offset_x - g.y = wa.y + (i - 1) * cascadetile.offset_y + g.y = wa.y + (i - 1) * cascadetile.offset_y + global_border if useless_gap > 0 then g.width = g.width - 2 * useless_gap diff --git a/layout/centerfair.lua b/layout/centerfair.lua index 49b4a14..01a2fe0 100644 --- a/layout/centerfair.lua +++ b/layout/centerfair.lua @@ -1,11 +1,12 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010, Nicolas Estibals - * (c) 2010-2012, Peter Hofmann - + + Licensed under GNU General Public License v2 + * (c) 2014, projektile + * (c) 2013, Luke Bonham + * (c) 2010, Nicolas Estibals + * (c) 2010-2012, Peter Hofmann + --]] local tag = require("awful.tag") @@ -41,15 +42,30 @@ function centerfair.arrange(p) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width . local useless_gap = tonumber(beautiful.useless_gap_width) or 0 + if useless_gap < 0 then useless_gap = 0 end + + -- A global border can be defined with + -- beautiful.global_border_width + local global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + + -- Themes border width requires an offset + local bw = tonumber(beautiful.border_width) or 0 -- Screen. local wa = p.workarea local cls = p.clients + -- Borders are factored in. + wa.height = wa.height - ((global_border * 2) + (bw * 2)) + wa.width = wa.width - ((global_border * 2) + (bw * 2)) + -- How many vertical columns? Read from nmaster on the tag. local t = tag.selected(p.screen) local num_x = centerfair.nmaster or tag.getnmaster(t) local ncol = centerfair.ncol or tag.getncol(t) + if num_x <= 2 then num_x = 2 end + if num_x > #cls then num_x = #cls end local width = math.floor((wa.width-(num_x+1)*useless_gap) / num_x) @@ -61,24 +77,24 @@ function centerfair.arrange(p) local g = {} g.width = width g.height = wa.height - 2*useless_gap - 2 - g.y = offset_y + g.y = offset_y + global_border for i = 1, #cls do - g.x = offset_x + (i - 1) * (width + useless_gap + 2) + g.x = offset_x + (i - 1) * (width + useless_gap + 2) + global_border cls[i]:geometry(g) end else -- More clients than the number of columns, let's arrange it! - local offset_x = wa.x + local offset_x = wa.x if useless_gap > 0 then - offset_x = offset_x + offset_x = offset_x end -- Master client deserves a special treatement local g = {} - g.width = wa.width - (num_x-1)*width -num_x*useless_gap - 2 + g.width = wa.width - (num_x - 1) * width - num_x * useless_gap g.height = wa.height - 2*useless_gap - 2 - g.x = offset_x + useless_gap - g.y = offset_y + g.x = offset_x + useless_gap + global_border + g.y = offset_y + global_border cls[1]:geometry(g) -- Treat the other clients @@ -128,8 +144,8 @@ function centerfair.arrange(p) for i = 1, (num_x-1) do to_remove = 2 - g.height = math.floor((wa.height-useless_gap)/num_y[i]) - g.y = offset_y + g.height = math.floor((wa.height - (num_y[i] * useless_gap)) / num_y[i]) + g.y = offset_y + global_border for j = 0, (num_y[i]-2) do cls[nclient]:geometry(g) nclient = nclient + 1 diff --git a/layout/centerwork.lua b/layout/centerwork.lua index 939f18c..61f4907 100644 --- a/layout/centerwork.lua +++ b/layout/centerwork.lua @@ -2,6 +2,7 @@ --[[ Licensed under GNU General Public License v2 + * (c) 2014, projektile * (c) 2013, Luke Bonham * (c) 2010-2012, Peter Hofmann @@ -26,10 +27,22 @@ function centerwork.arrange(p) -- beautiful.useless_gap_width . local useless_gap = tonumber(beautiful.useless_gap_width) or 0 + -- A global border can be defined with + -- beautiful.global_border_width + local global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + + -- Themes border width requires an offset + local bw = tonumber(beautiful.border_width) or 0 + -- Screen. local wa = p.workarea local cls = p.clients + -- Borders are factored in. + wa.height = wa.height - ((global_border * 2) + (bw * 2)) + wa.width = wa.width - ((global_border * 2) + (bw * 2)) + -- Width of main column? local t = awful.tag.selected(p.screen) local mwfact = awful.tag.getmwfact(t) @@ -37,7 +50,7 @@ function centerwork.arrange(p) if #cls > 0 then -- Main column, fixed width and height. - local c = cls[1] + local c = cls[#cls] local g = {} local mainwid = math.floor(wa.width * mwfact) local slavewid = wa.width - mainwid @@ -48,8 +61,8 @@ function centerwork.arrange(p) g.height = wa.height - 2 * useless_gap g.width = mainwid - g.x = wa.x + slaveLwid - g.y = wa.y + useless_gap + g.x = wa.x + slaveLwid + global_border + g.y = wa.y + useless_gap + global_border c:geometry(g) @@ -57,7 +70,7 @@ function centerwork.arrange(p) if #cls > 1 then local at = 0 - for i = (#cls),2,-1 + for i = (#cls - 1),1,-1 do -- It's all fixed. If there are more than 5 clients, -- those additional clients will float. This is @@ -73,29 +86,29 @@ function centerwork.arrange(p) if at == centerwork.top_left then -- top left - g.x = wa.x + useless_gap - g.y = wa.y + useless_gap + g.x = wa.x + useless_gap + global_border + g.y = wa.y + useless_gap + global_border g.width = slaveLwid - 2 * useless_gap g.height = slaveThei - useless_gap elseif at == centerwork.top_right then -- top right - g.x = wa.x + slaveLwid + mainwid + useless_gap - g.y = wa.y + useless_gap + g.x = wa.x + slaveLwid + mainwid + useless_gap + global_border + g.y = wa.y + useless_gap + global_border g.width = slaveRwid - 2 * useless_gap g.height = slaveThei - useless_gap elseif at == centerwork.bottom_left then -- bottom left - g.x = wa.x + useless_gap - g.y = wa.y + slaveThei + useless_gap + g.x = wa.x + useless_gap + global_border + g.y = wa.y + slaveThei + useless_gap + global_border g.width = slaveLwid - 2 * useless_gap g.height = slaveBhei - 2 * useless_gap elseif at == centerwork.bottom_right then -- bottom right - g.x = wa.x + slaveLwid + mainwid + useless_gap - g.y = wa.y + slaveThei + useless_gap + g.x = wa.x + slaveLwid + mainwid + useless_gap + global_border + g.y = wa.y + slaveThei + useless_gap + global_border g.width = slaveRwid - 2 * useless_gap g.height = slaveBhei - 2 * useless_gap end diff --git a/layout/termfair.lua b/layout/termfair.lua index 89a44bb..4e45eec 100644 --- a/layout/termfair.lua +++ b/layout/termfair.lua @@ -2,6 +2,7 @@ --[[ Licensed under GNU General Public License v2 + * (c) 2014, projektile * (c) 2013, Luke Bonham * (c) 2010-2012, Peter Hofmann @@ -38,11 +39,24 @@ function termfair.arrange(p) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width. local useless_gap = tonumber(beautiful.useless_gap_width) or 0 + if useless_gap < 0 then useless_gap = 0 end + + -- A global border can be defined with + -- beautiful.global_border_width + local global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + + -- Themes border width requires an offset + local bw = tonumber(beautiful.border_width) or 0 -- Screen. local wa = p.workarea local cls = p.clients + -- Borders are factored in. + wa.height = wa.height - ((global_border * 2) + (bw * 2)) + wa.width = wa.width - ((global_border * 2) + (bw * 2)) + -- How many vertical columns? local t = tag.selected(p.screen) local num_x = termfair.nmaster or tag.getnmaster(t) @@ -79,43 +93,26 @@ function termfair.arrange(p) local g = {} if this_x == (num_x - 1) then - g.width = wa.width - (num_x - 1) * width + g.width = wa.width - (num_x - 1) * width - useless_gap else - g.width = width + g.width = width - useless_gap end if this_y == (num_y - 1) then - g.height = wa.height - (num_y - 1) * height + g.height = wa.height - (num_y - 1) * height - useless_gap else - g.height = height + g.height = height - useless_gap end - g.x = wa.x + this_x * width - g.y = wa.y + this_y * height + g.x = wa.x + this_x * width + global_border + g.y = wa.y + this_y * height + global_border if useless_gap > 0 then - -- Top and left clients are shrinked by two steps and - -- get moved away from the border. Other clients just - -- get shrinked in one direction. - - gap_factor = (useless_gap / 100) * 2 + -- All clients tile evenly. + g.x = g.x + (useless_gap / 2) + g.y = g.y + (useless_gap / 2) - if this_x == 0 - then - g.width = g.width - (2 + gap_factor) * useless_gap - g.x = g.x + useless_gap - else - g.width = g.width - (1 + gap_factor) * useless_gap - end - - if this_y == 0 - then - g.height = g.height - (2 + gap_factor) * useless_gap - g.y = g.y + useless_gap - else - g.height = g.height - (1 + gap_factor) * useless_gap - end end c:geometry(g) remaining_clients = remaining_clients - 1 diff --git a/layout/uselessfair.lua b/layout/uselessfair.lua index 6aa6666..6a386c3 100644 --- a/layout/uselessfair.lua +++ b/layout/uselessfair.lua @@ -2,6 +2,7 @@ --[[ Licensed under GNU General Public License v2 + * (c) 2014, projektile * (c) 2013, Luke Bonham * (c) 2012, Josh Komoroske * (c) 2010-2012, Peter Hofmann @@ -19,10 +20,23 @@ local function fair(p, orientation) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width. local useless_gap = tonumber(beautiful.useless_gap_width) or 0 + if useless_gap < 0 then useless_gap = 0 end + -- A global border can be defined with + -- beautiful.global_border_width. + local global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + + -- Themes border width requires an offset. + local bw = tonumber(beautiful.border_width) or 0 + + -- get our orientation right. local wa = p.workarea local cls = p.clients + wa.height = wa.height - ((global_border * 2) + (bw * 2)) + wa.width = wa.width - ((global_border * 2) + (bw * 2)) + if #cls > 0 then local cells = math.ceil(math.sqrt(#cls)) local strips = math.ceil(#cls / cells) @@ -47,8 +61,8 @@ local function fair(p, orientation) this_x = cell this_y = strip - g.x = wa.x + cell * g.width - g.y = wa.y + strip * g.height + g.x = wa.x + cell * g.width + global_border + g.y = wa.y + strip * g.height + global_border else if #cls < (strips * cells) and strip == strips - 1 then @@ -61,34 +75,20 @@ local function fair(p, orientation) this_x = strip this_y = cell - g.x = wa.x + strip * g.width - g.y = wa.y + cell * g.height + g.x = wa.x + strip * g.width + global_border + g.y = wa.y + cell * g.height + global_border + end -- Useless gap. if useless_gap > 0 then - -- Top and left clients are shrinked by two steps and - -- get moved away from the border. Other clients just - -- get shrinked in one direction. + -- All clients tile evenly. + g.width = g.width - useless_gap + g.x = g.x + (useless_gap / 2) + g.height = g.height - useless_gap + g.y = g.y + (useless_gap / 2) - gap_factor = (useless_gap / 100) * 2 - - if this_x == 0 - then - g.width = g.width - (2 + gap_factor) * useless_gap - g.x = g.x + useless_gap - else - g.width = g.width - (1 + gap_factor) * useless_gap - end - - if this_y == 0 - then - g.height = g.height - (2 + gap_factor) * useless_gap - g.y = g.y + useless_gap - else - g.height = g.height - (1 + gap_factor) * useless_gap - end end -- End of useless gap. diff --git a/layout/uselesspiral.lua b/layout/uselesspiral.lua index 3164c75..7c72912 100644 --- a/layout/uselesspiral.lua +++ b/layout/uselesspiral.lua @@ -2,7 +2,8 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham + * (c) 2014 projektile + * (c) 2013 Luke Bonham * (c) 2009 Uli Schlachter * (c) 2008 Julien Danjolu @@ -11,6 +12,8 @@ local beautiful = require("beautiful") local ipairs = ipairs local tonumber = tonumber +local math = require("math") +local naughty = require("naughty") local uselesspiral = {} @@ -18,19 +21,32 @@ local function spiral(p, spiral) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width. local useless_gap = tonumber(beautiful.useless_gap_width) or 0 + if useless_gap < 0 then useless_gap = 0 end + -- A global border can be defined with + -- beautiful.global_border_width + local global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + + -- Themes border width requires an offset + local bw = tonumber(beautiful.border_width) or 0 + + -- get our orientation right local wa = p.workarea local cls = p.clients - local n = #cls + local n = #cls -- number of windows total; k = which window number + + wa.height = wa.height - ((global_border * 2) + (bw * 2)) + wa.width = wa.width - ((global_border * 2) + (bw * 2)) local static_wa = wa for k, c in ipairs(cls) do if k < n then if k % 2 == 0 then - wa.height = wa.height / 2 + wa.height = (wa.height / 2) else - wa.width = wa.width / 2 + wa.width = (wa.width / 2) end end @@ -49,10 +65,10 @@ local function spiral(p, spiral) end local wa2 = {} - wa2.x = wa.x - wa2.y = wa.y - wa2.height = wa.height - wa2.width = wa.width + wa2.x = wa.x + (useless_gap / 2) + global_border + wa2.y = wa.y + (useless_gap / 2) + global_border + wa2.height = wa.height - (useless_gap / 2) + wa2.width = wa.width - (useless_gap / 2) -- Useless gap. if useless_gap > 0 @@ -64,8 +80,6 @@ local function spiral(p, spiral) top = false left = false - gap_factor = (useless_gap / 100) * 2 - if wa2.y == static_wa.y then top = true end @@ -75,17 +89,17 @@ local function spiral(p, spiral) end if top then - wa2.height = wa2.height - (2 + gap_factor) * useless_gap - wa2.y = wa2.y + useless_gap + wa2.height = wa2.height - useless_gap + wa2.y = wa2.y - (useless_gap / 2) else - wa2.height = wa2.height - (1 + gap_factor) * useless_gap + wa2.height = wa2.height - (useless_gap / 2) end if left then - wa2.width = wa2.width - (2 + gap_factor) * useless_gap - wa2.x = wa2.x + useless_gap + wa2.width = wa2.width - useless_gap + wa2.x = wa2.x - (useless_gap / 2) else - wa2.width = wa2.width - (1 + gap_factor) * useless_gap + wa2.width = wa2.width - (useless_gap / 2) end end -- End of useless gap. diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index e496500..47aa4a4 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -2,12 +2,14 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham + * (c) 2014 projektile + * (c) 2013 Luke Bonham * (c) 2009 Donald Ephraim Curtis * (c) 2008 Julien Danjolu --]] +local naughty = require("naughty") local tag = require("awful.tag") local beautiful = require("beautiful") local ipairs = ipairs @@ -22,6 +24,14 @@ local function tile_group(cls, wa, orientation, fact, group) -- A useless gap (like the dwm patch) can be defined with -- beautiful.useless_gap_width . local useless_gap = tonumber(beautiful.useless_gap_width) or 0 + if useless_gap < 0 then useless_gap = 0 end + + -- A global border can be defined with + -- beautiful.global_border_width + global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + + -- BW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 -- get our orientation right local height = "height" @@ -36,7 +46,8 @@ local function tile_group(cls, wa, orientation, fact, group) end -- make this more generic (not just width) - available = wa[width] - (group.coord - wa[x]) + --if for top + available = wa[width] - (group.coord - wa[x]) -- it's truly not here -- find our total values local total_fact = 0 @@ -58,20 +69,19 @@ local function tile_group(cls, wa, orientation, fact, group) end total_fact = total_fact + fact[i] end - size = math.min(size, available) - + size = math.min(size, (available - global_border)) local coord = wa[y] local geom = {} local used_size = 0 - local unused = wa[height] + local unused = wa[height] - (global_border * 2) local stat_coord = wa[x] --stat_coord = size for c = group.first,group.last do local i = c - group.first +1 - geom[width] = size + geom[width] = size - global_border geom[height] = math.floor(unused * fact[i] / total_fact) - geom[x] = group.coord - geom[y] = coord + geom[x] = group.coord + global_border + (useless_gap / 2) + geom[y] = coord + global_border + (useless_gap / 2) coord = coord + geom[height] unused = unused - geom[height] @@ -88,8 +98,6 @@ local function tile_group(cls, wa, orientation, fact, group) top = false left = false - gap_factor = (useless_gap / 100) * 2 - if geom[y] == wa[y] then top = true end @@ -99,17 +107,17 @@ local function tile_group(cls, wa, orientation, fact, group) end if top then - geom[height] = geom[height] - (2 + gap_factor) * useless_gap + geom[height] = geom[height] - (2 * useless_gap) geom[y] = geom[y] + useless_gap else - geom[height] = geom[height] - (1 + gap_factor) * useless_gap + geom[height] = geom[height] - useless_gap end if left then - geom[width] = geom[width] - (2 + gap_factor) * useless_gap + geom[width] = geom[width] - (2 * useless_gap) geom[x] = geom[x] + useless_gap else - geom[width] = geom[width] - (1 + gap_factor) * useless_gap + geom[width] = geom[width] - useless_gap end end -- End of useless gap. @@ -136,6 +144,11 @@ local function tile(param, orientation) y = "x" end + -- A global border can be defined with + -- beautiful.global_border_width + global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + local cls = param.clients local nmaster = math.min(tag.getnmaster(t), #cls) local nother = math.max(#cls - nmaster,0) @@ -181,7 +194,7 @@ local function tile(param, orientation) end for i = 1,ncol do -- Try to get equal width among remaining columns - local size = math.min( (wasize - (coord - wa[x])) / (ncol - i + 1) ) + local size = math.min((wasize - (coord - wa[x])) / (ncol - i + 1)) --+ (global_border/(ncol))/(ncol+i^2) local first = last + 1 last = last + math.floor((#cls - last)/(ncol - i + 1)) -- tile the column and update our current x coordinate @@ -228,3 +241,4 @@ uselesstile.arrange = uselesstile.right.arrange uselesstile.name = uselesstile.right.name return uselesstile + From 274a5f43c92b4b1285bebbc9f72b432fab1c19d4 Mon Sep 17 00:00:00 2001 From: projektile Date: Mon, 22 Sep 2014 11:29:46 -0400 Subject: [PATCH 466/572] set card --- widgets/alsa.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/widgets/alsa.lua b/widgets/alsa.lua index f62a150..114e2b2 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -23,14 +23,14 @@ local alsa = {} local function worker(args) local args = args or {} local timeout = args.timeout or 5 - local channel = args.channel or "Master" + local channel = args.channel or "Master -c 1" local settings = args.settings or function() end alsa.widget = wibox.widget.textbox('') function alsa.update() - local f = assert(io.popen('amixer -M get ' .. channel)) - local mixer = f:read("*a") + local f = assert(io.popen('amixer get ' .. channel)) + local mixer = f:read("*all") f:close() volume_now = {} From 4919f4ada59a938432d8a385a6ef29a704cea3da Mon Sep 17 00:00:00 2001 From: projektile Date: Mon, 22 Sep 2014 11:36:50 -0400 Subject: [PATCH 467/572] fix border offset --- layout/uselesstile.lua | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index 47aa4a4..dfbaf68 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -28,10 +28,11 @@ local function tile_group(cls, wa, orientation, fact, group) -- A global border can be defined with -- beautiful.global_border_width - global_border = tonumber(beautiful.global_border_width) or 0 + local global_border = tonumber(beautiful.global_border_width) or 0 if global_border < 0 then global_border = 0 end - -- BW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 + -- Themes border width requires an offset + local bw = tonumber(beautiful.border_width) or 0 -- get our orientation right local height = "height" @@ -78,8 +79,8 @@ local function tile_group(cls, wa, orientation, fact, group) --stat_coord = size for c = group.first,group.last do local i = c - group.first +1 - geom[width] = size - global_border - geom[height] = math.floor(unused * fact[i] / total_fact) + geom[width] = size - global_border - (bw * 2) + geom[height] = math.floor(unused * fact[i] / total_fact) - (bw * 2) geom[x] = group.coord + global_border + (useless_gap / 2) geom[y] = coord + global_border + (useless_gap / 2) @@ -144,11 +145,6 @@ local function tile(param, orientation) y = "x" end - -- A global border can be defined with - -- beautiful.global_border_width - global_border = tonumber(beautiful.global_border_width) or 0 - if global_border < 0 then global_border = 0 end - local cls = param.clients local nmaster = math.min(tag.getnmaster(t), #cls) local nother = math.max(#cls - nmaster,0) From 229d0d3860126bfbf190c54d8edad18174fe017a Mon Sep 17 00:00:00 2001 From: projektile Date: Mon, 22 Sep 2014 11:54:03 -0400 Subject: [PATCH 468/572] remove naughty --- layout/uselesspiral.lua | 1 - layout/uselesstile.lua | 1 - 2 files changed, 2 deletions(-) diff --git a/layout/uselesspiral.lua b/layout/uselesspiral.lua index 7c72912..ba63bca 100644 --- a/layout/uselesspiral.lua +++ b/layout/uselesspiral.lua @@ -13,7 +13,6 @@ local beautiful = require("beautiful") local ipairs = ipairs local tonumber = tonumber local math = require("math") -local naughty = require("naughty") local uselesspiral = {} diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index dfbaf68..eccfdad 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -9,7 +9,6 @@ --]] -local naughty = require("naughty") local tag = require("awful.tag") local beautiful = require("beautiful") local ipairs = ipairs From 96d23431f249efc4103b2a9d6e8e98775ce2d917 Mon Sep 17 00:00:00 2001 From: Dainese Hsiao Date: Thu, 25 Sep 2014 13:15:39 +0800 Subject: [PATCH 469/572] Add yawn localization zh_TW --- widgets/yawn/localizations/zh_TW | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 widgets/yawn/localizations/zh_TW diff --git a/widgets/yawn/localizations/zh_TW b/widgets/yawn/localizations/zh_TW new file mode 100644 index 0000000..03644c1 --- /dev/null +++ b/widgets/yawn/localizations/zh_TW @@ -0,0 +1,61 @@ +Now:|現在: +Sun:|週日: +Mon:|週一: +Tue:|週二: +Wed:|週三: +Thu:|週四: +Fri:|週五: +Sat:|週六: +Mostly Sunny|晴時多雲 +Sunny|大太陽 +Sun|太陽 +Rain/Thunder|雨時有雷 +Isolated Thunderstorms|局部雷雨 +Scattered Thunderstorms|零星雷雨 +Thundershowers|雷陣雨 +Thunderstorms|雷雨 +Thunder in the Vicinity|局部性雷雨 +Thunder|雷嗚 +AM|上午 +PM|下午 +Early|早 +Late|晚有 +Few|短暫 +Severe|惡劣 +Clear|晴朗 +Fair|晴 +Partly|局部 +Mostly|大部 +Cloudy|多雲 +Clouds|有雲 +Scattered Showers|零星陣雨 +Light Snow Showers|小陣雪 +Snow Showers|陣雪 +Heavy Snow|大雪 +Scattered Snow Showers|零星陣雪 +Mixed Rain And Snow|雨夾雪 +Mixed Rain And Sleet|雨時雨夾雪 +Mixed Snow And Sleet|雪時雨夾雪 +Mixed Rain And Hail|雨夾冰雹 +Snow Flurries|陣雪 +Blowing Snow|風吹雪 +Blowing Rain|風吹雨 +Heavy Rain|大雨 +Freezing Rain|凍雨 +Showers|陣雨 +Light Rain|小雨 +Heavy|大 +Rain|雨 +Windy|有風 +Wind|風 +Snow|雪 +Sleet|冰珠 +Freezing Drizzle|凍毛毛雨 +Light Drizzle|細雨 +Drizzle|毛毛雨 +Hail|冰雹 +Fog|霧 +Foggy|有霧 +Haze|霾 +Light|小 +With|與 From c4c149d2dfd5e9434dc357b66da6f9d1747258f2 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 26 Sep 2014 12:41:35 +0200 Subject: [PATCH 470/572] undo 'set card' from projektile/master --- widgets/alsa.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 114e2b2..f62a150 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -23,14 +23,14 @@ local alsa = {} local function worker(args) local args = args or {} local timeout = args.timeout or 5 - local channel = args.channel or "Master -c 1" + local channel = args.channel or "Master" local settings = args.settings or function() end alsa.widget = wibox.widget.textbox('') function alsa.update() - local f = assert(io.popen('amixer get ' .. channel)) - local mixer = f:read("*all") + local f = assert(io.popen('amixer -M get ' .. channel)) + local mixer = f:read("*a") f:close() volume_now = {} From ead527ecdb2c8be34211e440ea5fca09f56072c9 Mon Sep 17 00:00:00 2001 From: projektile Date: Sat, 27 Sep 2014 01:07:19 -0400 Subject: [PATCH 471/572] update dynamic border change --- util/init.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/util/init.lua b/util/init.lua index d99f007..ac3afec 100644 --- a/util/init.lua +++ b/util/init.lua @@ -210,6 +210,12 @@ function util.useless_gaps_resize(thatmuch) awful.layout.arrange(mouse.screen) end +-- On the fly global border change +function util.global_border_resize(thatmuch) + beautiful.global_border_width = tonumber(beautiful.global_border_width) + thatmuch + awful.layout.arrange(mouse.screen) +end + -- Check if an element exist on a table function util.element_in_table(element, tbl) for _, i in pairs(tbl) do From 99db3d7ac26154bc6a87f68cb5922010fce7aa04 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 11 Oct 2014 14:17:05 +0200 Subject: [PATCH 472/572] #66 removed hardcoded screen def in widgets notification --- widgets/alsabar.lua | 2 -- widgets/bat.lua | 2 -- widgets/calendar.lua | 1 - widgets/contrib/init.lua | 1 - widgets/contrib/task.lua | 6 +----- widgets/fs.lua | 2 -- widgets/imap.lua | 1 - widgets/mpd.lua | 1 - widgets/net.lua | 1 - widgets/yawn/init.lua | 1 - 10 files changed, 1 insertion(+), 17 deletions(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 8675cb5..96d57b0 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -77,12 +77,10 @@ function alsabar.notify() alsabar._notify = naughty.notify ({ replaces_id = alsabar._notify.id, preset = preset, - screen = client.focus and client.focus.screen or 1 }) else alsabar._notify = naughty.notify ({ preset = preset, - screen = client.focus and client.focus.screen or 1 }) end end diff --git a/widgets/bat.lua b/widgets/bat.lua index 2ace758..572d099 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -130,14 +130,12 @@ local function worker(args) bat.id = naughty.notify({ preset = bat_notification_critical_preset, replaces_id = bat.id, - screen = client.focus and client.focus.screen or 1 }).id elseif nperc <= 15 then bat.id = naughty.notify({ preset = bat_notification_low_preset, replaces_id = bat.id, - screen = client.focus and client.focus.screen or 1 }).id end end diff --git a/widgets/calendar.lua b/widgets/calendar.lua index d07a5b4..f9aed39 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -99,7 +99,6 @@ function calendar:show(t_out, inc_offset) fg = calendar.fg, bg = calendar.bg, timeout = tims, - screen = client.focus and client.focus.screen or 1 }) end diff --git a/widgets/contrib/init.lua b/widgets/contrib/init.lua index 9a9fa63..ccaed82 100644 --- a/widgets/contrib/init.lua +++ b/widgets/contrib/init.lua @@ -8,7 +8,6 @@ Licensed under GNU General Public License v2 * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann --]] diff --git a/widgets/contrib/task.lua b/widgets/contrib/task.lua index 6e6ebae..2e30cdc 100644 --- a/widgets/contrib/task.lua +++ b/widgets/contrib/task.lua @@ -2,7 +2,6 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham * (c) 2013, Jan Xie --]] @@ -20,7 +19,7 @@ local tonumber = tonumber local setmetatable = setmetatable -- Taskwarrior notification --- lain.widgets.task +-- lain.widgets.contrib.task local task = {} local task_notification = nil @@ -52,7 +51,6 @@ function task:show() fg = task.fg, bg = task.bg, timeout = task.timeout, - screen = client.focus and client.focus.screen or 1 }) end @@ -75,7 +73,6 @@ function task:prompt_add() fg = task.fg, bg = task.bg, timeout = task.timeout, - screen = client.focus and client.focus.screen or 1 }) end, nil, @@ -109,7 +106,6 @@ function task:prompt_search() fg = task.fg, bg = task.bg, timeout = task.timeout, - screen = client.focus and client.focus.screen or 1 }) end, nil, diff --git a/widgets/fs.lua b/widgets/fs.lua index f78cfe0..3b99cba 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -47,7 +47,6 @@ function fs:show(t_out) preset = fs_notification_preset, text = ws, timeout = t_out, - screen = client.focus and client.focus.screen or 1 }) end @@ -100,7 +99,6 @@ local function worker(args) timeout = 8, fg = "#000000", bg = "#FFFFFF", - screen = client.focus and client.focus.screen or 1 }) helpers.set_map("fs", true) else diff --git a/widgets/imap.lua b/widgets/imap.lua index 3a6da8d..d4b4cba 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -77,7 +77,6 @@ local function worker(args) naughty.notify({ preset = mail_notification_preset, text = nt, - screen = client.focus and client.focus.screen or 1 }) end diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 385b5bb..7fd611d 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -91,7 +91,6 @@ local function worker(args) preset = mpd_notification_preset, icon = "/tmp/mpdcover.png", replaces_id = mpd.id, - screen = client.focus and client.focus.screen or 1 }).id end elseif mpd_now.state ~= "pause" diff --git a/widgets/net.lua b/widgets/net.lua index 9575000..2bfd375 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -88,7 +88,6 @@ local function worker(args) position = "top_left", icon = helpers.icons_dir .. "no_net.png", fg = notify_fg or "#FFFFFF", - screen = client.focus and client.focus.screen or 1 }) helpers.set_map(iface, false) end diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index aa58ed1..b034395 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -167,7 +167,6 @@ function yawn.show(t_out) text = weather_data, icon = sky, timeout = t_out, - screen = client.focus and client.focus.screen or 1 }) end From 02a50839c84bed8920dd4c50971a82b3f4034658 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 11 Oct 2014 14:45:14 +0200 Subject: [PATCH 473/572] widgets: screen notification setting added --- widgets/alsabar.lua | 4 +++- widgets/calendar.lua | 3 ++- widgets/net.lua | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 96d57b0..65a2b33 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -41,7 +41,8 @@ local alsabar = { font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), font_size = "11", color = beautiful.fg_normal, - bar_size = 18 + bar_size = 18, + screen = 1 }, _current_level = 0, @@ -55,6 +56,7 @@ function alsabar.notify() title = "", text = "", timeout = 4, + screen = alsabar.notifications.screen, font = alsabar.notifications.font .. " " .. alsabar.notifications.font_size, fg = alsabar.notifications.color diff --git a/widgets/calendar.lua b/widgets/calendar.lua index f9aed39..bada79e 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -30,7 +30,7 @@ function calendar:hide() end end -function calendar:show(t_out, inc_offset) +function calendar:show(t_out, inc_offset, scr) calendar:hide() local offs = inc_offset or 0 @@ -99,6 +99,7 @@ function calendar:show(t_out, inc_offset) fg = calendar.fg, bg = calendar.bg, timeout = tims, + screen = scr or 1 }) end diff --git a/widgets/net.lua b/widgets/net.lua index 2bfd375..ed6a2ef 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -45,6 +45,7 @@ local function worker(args) local iface = args.iface or net.get_device() local units = args.units or 1024 --kb local notify = args.notify or "on" + local screen = args.screen or 1 local settings = args.settings or function() end net.widget = wibox.widget.textbox('') @@ -88,6 +89,7 @@ local function worker(args) position = "top_left", icon = helpers.icons_dir .. "no_net.png", fg = notify_fg or "#FFFFFF", + screen = screen }) helpers.set_map(iface, false) end From a250f4d3fcf483cdd7eb10254690a9a8feb4501a Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 11 Oct 2014 16:18:03 +0200 Subject: [PATCH 474/572] #66: screen position in calendar:attach --- widgets/calendar.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index bada79e..631b358 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -113,20 +113,21 @@ function calendar:attach(widget, args) calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF" calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF" calendar.position = args.position or "top_right" + calendar.scr_pos = args.scr_pos or 1 calendar.offset = 0 calendar.notify_icon = nil - widget:connect_signal("mouse::enter", function () calendar:show() end) + widget:connect_signal("mouse::enter", function () calendar:show(0, 0, 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) end), + calendar:show(0, -1, scr_pos) end), awful.button({ }, 3, function () - calendar:show(0, 1) end), + calendar:show(0, 1, scr_pos) end), awful.button({ }, 4, function () - calendar:show(0, -1) end), + calendar:show(0, -1, scr_pos) end), awful.button({ }, 5, function () - calendar:show(0, 1) end))) + calendar:show(0, 1, scr_pos) end))) end return setmetatable(calendar, { __call = function(_, ...) return create(...) end }) From 89bb71e154283db9edd656518073200821374100 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 20 Oct 2014 15:56:44 +0200 Subject: [PATCH 475/572] #68 solution attempt --- widgets/net.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/net.lua b/widgets/net.lua index ed6a2ef..84751b6 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -31,9 +31,9 @@ function net.get_device() f = io.popen("ip link show | cut -d' ' -f2,9") ws = f:read("*a") f:close() - ws = ws:match("%w+: UP") + ws = ws:match("%w+: UP") or ws:match("ppp%w+: UNKNOWN") if ws ~= nil then - return ws:gsub(": UP", "") + return ws:match("(%w+):") else return "network off" end From bfa2615942951cb2f9de04aba4742efef3ba7423 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Mon, 20 Oct 2014 18:05:47 +0200 Subject: [PATCH 476/572] #67 mpdcover lightened --- scripts/mpdcover | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mpdcover b/scripts/mpdcover index f6cf0d6..6f9062c 100755 --- a/scripts/mpdcover +++ b/scripts/mpdcover @@ -2,7 +2,7 @@ # # A simple cover fetcher script for current playing song on mpd. # -# Author : Wolfgang Mueller +# Original author: Wolfgang Mueller # # Adapted for Lain internal use. # https://github.com/copycat-killer/lain @@ -58,7 +58,7 @@ cover="${cover:=$DEFAULT_ART}" # check if art is available if [[ -n $cover ]]; then if [[ -n $COVER_RESIZE ]]; then - convert "$cover" -thumbnail $COVER_RESIZE -gravity "center" -background "$COVER_BACKGROUND" -extent $COVER_RESIZE "$TEMP_PATH" + convert "$cover" -scale $COVER_RESIZE -gravity "center" -background "$COVER_BACKGROUND" "$TEMP_PATH" cover="$TEMP_PATH" fi else From ada3be2c9a398b4a044e016eccf747be6a4fa718 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 8 Nov 2014 12:06:48 +0100 Subject: [PATCH 477/572] centerfair: added no cls[1] case --- layout/centerfair.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/layout/centerfair.lua b/layout/centerfair.lua index 01a2fe0..e2ecb33 100644 --- a/layout/centerfair.lua +++ b/layout/centerfair.lua @@ -95,7 +95,10 @@ function centerfair.arrange(p) g.height = wa.height - 2*useless_gap - 2 g.x = offset_x + useless_gap + global_border g.y = offset_y + global_border - cls[1]:geometry(g) + + if cls[1] then + cls[1]:geometry(g) + end -- Treat the other clients From b0eec6c5a8551f22e3c08c6aa0c0ad1b0b748250 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 8 Nov 2014 12:44:23 +0100 Subject: [PATCH 478/572] centerfair: ncol uselessgaps fixed --- layout/centerfair.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/centerfair.lua b/layout/centerfair.lua index e2ecb33..37507d3 100644 --- a/layout/centerfair.lua +++ b/layout/centerfair.lua @@ -91,7 +91,7 @@ function centerfair.arrange(p) -- Master client deserves a special treatement local g = {} - g.width = wa.width - (num_x - 1) * width - num_x * useless_gap + g.width = wa.width - (num_x - 1) * width - num_x * 2*useless_gap - 2 g.height = wa.height - 2*useless_gap - 2 g.x = offset_x + useless_gap + global_border g.y = offset_y + global_border @@ -142,7 +142,7 @@ function centerfair.arrange(p) g.width = width if useless_gap > 0 then - g.width = g.width - useless_gap/2 - 2 + g.width = g.width + useless_gap - 2 end for i = 1, (num_x-1) do From 5725cf2861fb9af395396afe168b9b911098da6d Mon Sep 17 00:00:00 2001 From: Moussab Date: Mon, 10 Nov 2014 23:46:57 +0100 Subject: [PATCH 479/572] Update centerfair.lua --- layout/centerfair.lua | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/layout/centerfair.lua b/layout/centerfair.lua index 37507d3..d3225b4 100644 --- a/layout/centerfair.lua +++ b/layout/centerfair.lua @@ -65,7 +65,6 @@ function centerfair.arrange(p) local num_x = centerfair.nmaster or tag.getnmaster(t) local ncol = centerfair.ncol or tag.getncol(t) if num_x <= 2 then num_x = 2 end - if num_x > #cls then num_x = #cls end local width = math.floor((wa.width-(num_x+1)*useless_gap) / num_x) @@ -79,7 +78,7 @@ function centerfair.arrange(p) g.height = wa.height - 2*useless_gap - 2 g.y = offset_y + global_border for i = 1, #cls do - g.x = offset_x + (i - 1) * (width + useless_gap + 2) + global_border + g.x = offset_x + (#cls - i) * (width + useless_gap + 2) + global_border cls[i]:geometry(g) end else @@ -96,9 +95,7 @@ function centerfair.arrange(p) g.x = offset_x + useless_gap + global_border g.y = offset_y + global_border - if cls[1] then - cls[1]:geometry(g) - end + cls[#cls]:geometry(g) -- Treat the other clients @@ -107,7 +104,7 @@ function centerfair.arrange(p) do local remaining_clients = #cls-1 local ncol_min = math.ceil(remaining_clients/(num_x-1)) - if ncol >= ncol_min + if ncol >= ncol_min then for i = (num_x-1), 1, -1 do if (remaining_clients-i+1) < ncol @@ -137,7 +134,7 @@ function centerfair.arrange(p) end -- Compute geometry of the other clients - local nclient = 2 + local nclient = #cls-1 -- we start with the 2nd client g.x = g.x + g.width+useless_gap + 2 g.width = width @@ -149,15 +146,15 @@ function centerfair.arrange(p) to_remove = 2 g.height = math.floor((wa.height - (num_y[i] * useless_gap)) / num_y[i]) g.y = offset_y + global_border - for j = 0, (num_y[i]-2) do + for j = 1, (num_y[i]-1) do cls[nclient]:geometry(g) - nclient = nclient + 1 + nclient = nclient - 1 g.y = g.y + g.height+useless_gap + 2 to_remove = to_remove + 2 end g.height = wa.height - num_y[i]*useless_gap - (num_y[i]-1)*g.height - useless_gap - to_remove cls[nclient]:geometry(g) - nclient = nclient + 1 + nclient = nclient - 1 g.x = g.x+g.width+useless_gap + 2 end end From 60febfc4dd6018ec8ead920f173b404412316473 Mon Sep 17 00:00:00 2001 From: Moussab Date: Mon, 10 Nov 2014 23:51:11 +0100 Subject: [PATCH 480/572] Update centerfair.lua --- layout/centerfair.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/centerfair.lua b/layout/centerfair.lua index d3225b4..383bf9e 100644 --- a/layout/centerfair.lua +++ b/layout/centerfair.lua @@ -104,7 +104,7 @@ function centerfair.arrange(p) do local remaining_clients = #cls-1 local ncol_min = math.ceil(remaining_clients/(num_x-1)) - if ncol >= ncol_min + if ncol >= ncol_min then for i = (num_x-1), 1, -1 do if (remaining_clients-i+1) < ncol From b73cb294e26db739f7d168f59c086c255807f667 Mon Sep 17 00:00:00 2001 From: Moussab Date: Mon, 10 Nov 2014 23:52:00 +0100 Subject: [PATCH 481/572] Update centerfair.lua --- layout/centerfair.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/centerfair.lua b/layout/centerfair.lua index 383bf9e..67462f7 100644 --- a/layout/centerfair.lua +++ b/layout/centerfair.lua @@ -146,7 +146,7 @@ function centerfair.arrange(p) to_remove = 2 g.height = math.floor((wa.height - (num_y[i] * useless_gap)) / num_y[i]) g.y = offset_y + global_border - for j = 1, (num_y[i]-1) do + for j = 0, (num_y[i]-2) do cls[nclient]:geometry(g) nclient = nclient - 1 g.y = g.y + g.height+useless_gap + 2 From 30658f602bff127945b0a5acee551fd58eb226fc Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 15 Nov 2014 13:21:22 +0100 Subject: [PATCH 482/572] yawn: fetch_weather local -> integrated; net: iface scope fixed --- asyncshell.lua | 6 +++--- widgets/net.lua | 3 ++- widgets/yawn/init.lua | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/asyncshell.lua b/asyncshell.lua index 51885e8..4a01caa 100644 --- a/asyncshell.lua +++ b/asyncshell.lua @@ -11,9 +11,9 @@ -- ...asynchronously: -- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end) -- ...synchronously --- wwidget.text = asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error" +-- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error") --- This makes things faster, but puts weight on sysload and is more cpu demanding. +-- This is more cpu demanding, but makes things faster. local spawn = require('awful.util').spawn @@ -39,7 +39,7 @@ end function asyncshell.request(command, callback) local id = next_id() local tmpfname = asyncshell.file_template .. id - asyncshell.request_table[id] = {callback = callback} + asyncshell.request_table[id] = { callback = callback } local req = string.format("sh -c '%s > %s; " .. 'echo "asyncshell.deliver(%s)" | ' .. diff --git a/widgets/net.lua b/widgets/net.lua index 84751b6..d1179a2 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -42,12 +42,13 @@ end local function worker(args) local args = args or {} local timeout = args.timeout or 2 - local iface = args.iface or net.get_device() local units = args.units or 1024 --kb local notify = args.notify or "on" local screen = args.screen or 1 local settings = args.settings or function() end + iface = args.iface or net.get_device() + net.widget = wibox.widget.textbox('') helpers.set_map(iface, true) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index b034395..be3e614 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -45,9 +45,9 @@ local city_id = nil local sky = nil local settings = function() end -yawn_notification_preset = {} +yawn_notification_preset = {} -local function fetch_weather() +function yawn.fetch_weather() local url = api_url .. units_set .. city_id local cmd = "curl --connect-timeout 1 -fsm 3 '" .. url .. "'" @@ -157,7 +157,7 @@ end function yawn.show(t_out) if yawn.widget._layout.text:match("?") then - fetch_weather(settings) + yawn.fetch_weather() end yawn.hide() @@ -179,7 +179,7 @@ function yawn.register(id, args) city_id = id - newtimer("yawn", timeout, fetch_weather) + newtimer("yawn", timeout, yawn.fetch_weather) yawn.icon:connect_signal("mouse::enter", function() yawn.show(0) From 0bfa28f7491904bebefeb02efe6e020da2ed8cf8 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sat, 15 Nov 2014 13:38:07 +0100 Subject: [PATCH 483/572] net: iface scope fixed 2 --- widgets/net.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/widgets/net.lua b/widgets/net.lua index d1179a2..2b06622 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -16,7 +16,8 @@ local wibox = require("wibox") local io = { popen = io.popen } local tostring = tostring local string = { format = string.format, - gsub = string.gsub } + gsub = string.gsub, + match = string.match } local setmetatable = setmetatable @@ -56,7 +57,10 @@ local function worker(args) function update() net_now = {} - if iface == "" then iface = net.get_device() end + if iface == "" or string.match(iface, "network off") + then + iface = net.get_device() + end net_now.carrier = helpers.first_line('/sys/class/net/' .. iface .. '/carrier') or "0" From 626328ed9a3726a113358d7491b84a7c326d8c9e Mon Sep 17 00:00:00 2001 From: alexey korobtsov Date: Mon, 17 Nov 2014 18:56:56 +0300 Subject: [PATCH 484/572] new file: widgets/yawn/localizations/ru_RU --- widgets/yawn/localizations/ru_RU | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 widgets/yawn/localizations/ru_RU diff --git a/widgets/yawn/localizations/ru_RU b/widgets/yawn/localizations/ru_RU new file mode 100644 index 0000000..0b9b9e9 --- /dev/null +++ b/widgets/yawn/localizations/ru_RU @@ -0,0 +1,61 @@ +Now:|Cейчас: +Sun:|Воскресенье: +Mon:|понедельник: +Tue:|Вторник: +Wed:|Среда: +Thu:|Четверг: +Fri:|Пятница: +Sat:|Суббота: +Mostly Sunny|Премушественно солнечно +Sunny|Солнечно +Sun|Солнце +Rain/Thunder|Дождь/Гром +Isolated Thunderstorms|Изолированные грозы +Scattered Thunderstorms|Рассеянные грозы +Thundershowers|Ливни +Thunderstorms|Грозы +Thunder in the Vicinity|Гром в окрестностях +Thunder|Гром +AM|Утро +PM|Вечер +Early|Рано +Late|Поздно +Few|Мало +Severe|Тяжелый +Clear|Ясно +Fair|Светлый +Partly|Частично +Mostly|По большй части +Cloudy|Облочно +Clouds|Облока +Scattered Showers|Рассеянные ливни +Light Snow Showers|Небольшой снег +Snow Showers|Ливневый Снег +Heavy Snow|Сильный снегопад +Scattered Snow Showers|Рассеянный ливневый снег +Mixed Rain And Snow|Снег с дождём +Mixed Rain And Sleet|Дождь и мокрый снег +Mixed Snow And Sleet|Снег и мокрый снег +Mixed Rain And Hail|Дождь с градом +Snow Flurries|Снежные порывы +Blowing Snow|Снег и ветер +Blowing Rain|Дождь и ветер +Heavy Rain|Сильный дождь +Freezing Rain|Ледяной дождь +Showers|Ливени +Light Rain|Небольшой дождь +Heavy|Сильный +Rain|Дождь +Windy|Ветреный +Wind|Ветер +Snow|Снег +Sleet|Мокрый снег +Freezing Drizzle|Изморозь +Light Drizzle|Лёгкая изморось +Drizzle|Моросящий дождь +Hail|Град +Fog|Туман +Foggy|Туманно +Haze|Дымка +Light|Лёгкий +With|С From 024e9bce6032d4f520600df2d345fe7f2ea6683d Mon Sep 17 00:00:00 2001 From: Alex Kir Date: Tue, 25 Nov 2014 23:14:56 +0200 Subject: [PATCH 485/572] Some might have spaces in passwords (Like I do) and then curl fails. * Changed string formatting of password to %q to always quote password --- widgets/imap.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/imap.lua b/widgets/imap.lua index d4b4cba..1ebbb76 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -54,7 +54,7 @@ local function worker(args) position = "top_left" } - curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%s %s -k", + curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%q %s -k", head_command, server, port, mail, password, request) async.request(curl, function(f) From 199213d8de04397f38cdea034c75a3af4bdcd0d6 Mon Sep 17 00:00:00 2001 From: loudcry Date: Mon, 1 Dec 2014 17:07:29 +0500 Subject: [PATCH 486/572] Some words' fixes I fixed some words. --- widgets/yawn/localizations/ru_RU | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/widgets/yawn/localizations/ru_RU b/widgets/yawn/localizations/ru_RU index 0b9b9e9..0b2ae23 100644 --- a/widgets/yawn/localizations/ru_RU +++ b/widgets/yawn/localizations/ru_RU @@ -1,12 +1,12 @@ Now:|Cейчас: Sun:|Воскресенье: -Mon:|понедельник: +Mon:|Понедельник: Tue:|Вторник: Wed:|Среда: Thu:|Четверг: Fri:|Пятница: Sat:|Суббота: -Mostly Sunny|Премушественно солнечно +Mostly Sunny|Преимущественно солнечно Sunny|Солнечно Sun|Солнце Rain/Thunder|Дождь/Гром @@ -25,9 +25,9 @@ Severe|Тяжелый Clear|Ясно Fair|Светлый Partly|Частично -Mostly|По большй части -Cloudy|Облочно -Clouds|Облока +Mostly|По большей части +Cloudy|Облачно +Clouds|Облака Scattered Showers|Рассеянные ливни Light Snow Showers|Небольшой снег Snow Showers|Ливневый Снег @@ -42,7 +42,7 @@ Blowing Snow|Снег и ветер Blowing Rain|Дождь и ветер Heavy Rain|Сильный дождь Freezing Rain|Ледяной дождь -Showers|Ливени +Showers|Ливни Light Rain|Небольшой дождь Heavy|Сильный Rain|Дождь From 82766de14737919c4d1eb3b27333a6ef0b80e6d2 Mon Sep 17 00:00:00 2001 From: themarcq Date: Mon, 8 Dec 2014 16:32:44 +0100 Subject: [PATCH 487/572] Now gaps between windows and screen borders and gaps vetween windows and windows are the same. --- layout/uselesstile.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index eccfdad..65ce9b5 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -80,8 +80,8 @@ local function tile_group(cls, wa, orientation, fact, group) local i = c - group.first +1 geom[width] = size - global_border - (bw * 2) geom[height] = math.floor(unused * fact[i] / total_fact) - (bw * 2) - geom[x] = group.coord + global_border + (useless_gap / 2) - geom[y] = coord + global_border + (useless_gap / 2) + geom[x] = group.coord + global_border + geom[y] = coord + global_border coord = coord + geom[height] unused = unused - geom[height] From b131bba91e213f8c28101ee33edc997d09750e1e Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 12 Dec 2014 19:26:43 +0100 Subject: [PATCH 488/572] yawn: de_DE added --- widgets/yawn/localizations/de_DE | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 widgets/yawn/localizations/de_DE diff --git a/widgets/yawn/localizations/de_DE b/widgets/yawn/localizations/de_DE new file mode 100644 index 0000000..82cef79 --- /dev/null +++ b/widgets/yawn/localizations/de_DE @@ -0,0 +1,61 @@ +Now:|Jetzt: +Sun:|So: +Mon:|Mo: +Tue:|Di: +Wed:|Mi: +Thu:|Do: +Fri:|Fr: +Sat:|Sa: +Mostly Sunny|Größtenteils Sonnig +Sunny|Sonnig +Sun|Sonne +Rain/Thunder|Regen/Donner +Isolated Thunderstorms|Vereinzelte Gewitter +Scattered Thunderstorms|Aufgelockertes Gewitter +Thundershowers|Gewitterschauer +Thunderstorms|Gewitter +Thunder in the Vicinity|Donner in der Umgebung +Thunder|Donner +AM|Vormittags +PM|Nachmittags +Early|Früh +Late|Spät +Few|einige +Severe|starker +Clear|Klar +Fair|Heiter +Partly|teilweise +Mostly|größtenteils +Cloudy|Wolkig +Clouds|Wolken +Scattered Showers|Vereinzelte Schauer +Light Snow Showers|Leichter Schneeregen +Snow Showers|Schneeregen +Heavy Snow|Starker Schneefall +Scattered Snow Showers|Vereinzelter Schneefall +Mixed Rain And Snow|Gemischter Regen und Schnee +Mixed Rain And Sleet|Gemischter Regen und Graupel +Mixed Snow And Sleet|Gemischter Schnee und Graupel +Mixed Rain And Hail|Gemischter Regen und Hagel +Snow Flurries|Schneegestöber +Blowing Snow|Schneetreiben +Blowing Rain|Treibender Regen +Heavy Rain|Starke Regenfälle +Freezing Rain|Eisregen +Showers|Schauer +Light Rain|Leichter Regen +Heavy|Starker +Rain|Regen +Windy|Windig +Wind|Wind +Snow|Schnee +Sleet|Graupel +Freezing Drizzle|Gefrierender Sprühregen +Light Drizzle|Leichter Sprühregen +Drizzle|Sprühregen +Hail|Hagel +Fog|Nebel +Foggy|Nebelig +Haze|Dunst +Light|leichter +With|mit \ No newline at end of file From 7d60073c29c91354038e0c0307ce4bf3537d84a1 Mon Sep 17 00:00:00 2001 From: Rongzhou Shen Date: Sat, 27 Dec 2014 12:14:13 -0800 Subject: [PATCH 489/572] Adding a moc widget to lain --- widgets/moc.lua | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 widgets/moc.lua diff --git a/widgets/moc.lua b/widgets/moc.lua new file mode 100644 index 0000000..9b1380a --- /dev/null +++ b/widgets/moc.lua @@ -0,0 +1,90 @@ +local helpers = require("lain.helpers") +local async = require("lain.asyncshell") + +local escape_f = require("awful.util").escape +local naughty = require("naughty") +local wibox = require("wibox") + +local io = { popen = io.popen } +local os = { execute = os.execute, + getenv = os.getenv } +local string = { format = string.format, + gmatch = string.gmatch } + +local setmetatable = setmetatable + +local moc = {} + +local function worker(args) + local args = args or {} + local timeout = args.timeout or 2 + 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 settings = args.settings or function() end + + local mpdcover = helpers.scripts_dir .. "mpdcover" + + moc.widget = wibox.widget.textbox('') + + moc_notification_preset = { + title = "Now playing", + timeout = 6 + } + + helpers.set_map("current moc track", nil) + + function moc.update() + async.request("mocp -i", function(f) + moc_now = { + state = "N/A", + file = "N/A", + artist = "N/A", + title = "N/A", + album = "N/A", + elapsed = "N/A", + total = "N/A" + } + + for line in f:lines() do + for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do + if k == "State" then moc_now.state = v + elseif k == "File" then moc_now.file = v + elseif k == "Artist" then moc_now.artist = escape_f(v) + elseif k == "SongTitle" then moc_now.title = escape_f(v) + elseif k == "Album" then moc_now.album = escape_f(v) + elseif k == "CurrentTime" then moc_now.elapsed = escape_f(v) + elseif k == "TotalTime" then moc_now.total = escape_f(v) + end + end + end + + moc_notification_preset.text = string.format("%s (%s) - %s\n%s", moc_now.artist, + moc_now.album, moc_now.total, moc_now.title) + widget = moc.widget + settings() + + if moc_now.state == "PLAY" then + if moc_now.title ~= helpers.get_map("current moc track") then + helpers.set_map("current moc track", moc_now.title) + os.execute(string.format("%s %q %q %d %q", mpdcover, "", + moc_now.file, cover_size, default_art)) + + moc.id = naughty.notify({ + preset = moc_notification_preset, + icon = "/tmp/mpdcover.png", + replaces_id = moc.id, + }).id + end + elseif moc_now.state ~= "PAUSE" then + helpers.set_map("current moc track", nil) + end + end) + end + + helpers.newtimer("moc", timeout, moc.update) + + return setmetatable(moc, { __index = moc.widget }) +end + +return setmetatable(moc, { __call = function(_, ...) return worker(...) end }) From 236d9e8a3d596da6648192080ba727cf2f699070 Mon Sep 17 00:00:00 2001 From: Rongzhou Shen Date: Sat, 27 Dec 2014 12:58:56 -0800 Subject: [PATCH 490/572] Moving moc to contrib and adding license information --- widgets/{ => contrib}/moc.lua | 36 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) rename widgets/{ => contrib}/moc.lua (76%) diff --git a/widgets/moc.lua b/widgets/contrib/moc.lua similarity index 76% rename from widgets/moc.lua rename to widgets/contrib/moc.lua index 9b1380a..84c618b 100644 --- a/widgets/moc.lua +++ b/widgets/contrib/moc.lua @@ -1,3 +1,11 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2014, anticlockwise + +--]] + local helpers = require("lain.helpers") local async = require("lain.asyncshell") @@ -16,34 +24,38 @@ local setmetatable = setmetatable local moc = {} local function worker(args) - local args = args or {} - local timeout = args.timeout or 2 - local music_dir = args.music_dir or os.getenv("HOME") .. "/Music" - local cover_size = args.cover_size or 100 + local args = args or {} + local timeout = args.timeout or 2 + 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 settings = args.settings or function() end + local settings = args.settings or function() end local mpdcover = helpers.scripts_dir .. "mpdcover" moc.widget = wibox.widget.textbox('') moc_notification_preset = { - title = "Now playing", + title = "Now playing", timeout = 6 } helpers.set_map("current moc track", nil) function moc.update() + -- mocp -i will produce output like: + -- Artist: Travis + -- Album: The Man Who + -- etc. async.request("mocp -i", function(f) moc_now = { - state = "N/A", - file = "N/A", - artist = "N/A", - title = "N/A", - album = "N/A", + state = "N/A", + file = "N/A", + artist = "N/A", + title = "N/A", + album = "N/A", elapsed = "N/A", - total = "N/A" + total = "N/A" } for line in f:lines() do From 10d2bbefe4cf3ef95b4240fb5dc11994c3224227 Mon Sep 17 00:00:00 2001 From: worron Date: Mon, 5 Jan 2015 23:31:52 +0300 Subject: [PATCH 491/572] Window border width issue fixes in uselessfair --- layout/uselessfair.lua | 55 ++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/layout/uselessfair.lua b/layout/uselessfair.lua index 6a386c3..058dae6 100644 --- a/layout/uselessfair.lua +++ b/layout/uselessfair.lua @@ -1,12 +1,12 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2014, projektile - * (c) 2013, Luke Bonham - * (c) 2012, Josh Komoroske - * (c) 2010-2012, Peter Hofmann - + + Licensed under GNU General Public License v2 + * (c) 2014, projektile + * (c) 2013, Luke Bonham + * (c) 2012, Josh Komoroske + * (c) 2010-2012, Peter Hofmann + --]] local beautiful = require("beautiful") @@ -30,12 +30,17 @@ local function fair(p, orientation) -- Themes border width requires an offset. local bw = tonumber(beautiful.border_width) or 0 + -- Total window size extend + local ext = 2 * bw + useless_gap + -- get our orientation right. local wa = p.workarea local cls = p.clients - wa.height = wa.height - ((global_border * 2) + (bw * 2)) - wa.width = wa.width - ((global_border * 2) + (bw * 2)) + wa.height = wa.height - 2 * global_border - useless_gap + wa.width = wa.width - 2 * global_border - useless_gap + wa.x = wa.x + useless_gap + global_border + wa.y = wa.y + useless_gap + global_border if #cls > 0 then local cells = math.ceil(math.sqrt(#cls)) @@ -45,10 +50,7 @@ local function fair(p, orientation) local strip = 0 for k, c in ipairs(cls) do local g = {} - -- Save actual grid index for use in the useless_gap - -- routine. - local this_x = 0 - local this_y = 0 + if ( orientation == "east" and #cls > 2 ) or ( orientation == "south" and #cls <= 2 ) then if #cls < (strips * cells) and strip == strips - 1 then @@ -58,11 +60,8 @@ local function fair(p, orientation) end g.height = wa.height / strips - this_x = cell - this_y = strip - - g.x = wa.x + cell * g.width + global_border - g.y = wa.y + strip * g.height + global_border + g.x = wa.x + cell * g.width + g.y = wa.y + strip * g.height else if #cls < (strips * cells) and strip == strips - 1 then @@ -72,25 +71,13 @@ local function fair(p, orientation) end g.width = wa.width / strips - this_x = strip - this_y = cell - - g.x = wa.x + strip * g.width + global_border - g.y = wa.y + cell * g.height + global_border + g.x = wa.x + strip * g.width + g.y = wa.y + cell * g.height end - -- Useless gap. - if useless_gap > 0 - then - -- All clients tile evenly. - g.width = g.width - useless_gap - g.x = g.x + (useless_gap / 2) - g.height = g.height - useless_gap - g.y = g.y + (useless_gap / 2) - - end - -- End of useless gap. + g.width = g.width - ext + g.height = g.height - ext c:geometry(g) From 2968bb25bdaa35c950ad112d682be16104df131e Mon Sep 17 00:00:00 2001 From: worron Date: Tue, 6 Jan 2015 01:53:09 +0300 Subject: [PATCH 492/572] Window border width issue fixes in uselesstile --- layout/uselesstile.lua | 97 ++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 60 deletions(-) diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index 65ce9b5..5bb0c05 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -1,12 +1,12 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2014 projektile - * (c) 2013 Luke Bonham - * (c) 2009 Donald Ephraim Curtis - * (c) 2008 Julien Danjolu - + + Licensed under GNU General Public License v2 + * (c) 2014 projektile + * (c) 2013 Luke Bonham + * (c) 2009 Donald Ephraim Curtis + * (c) 2008 Julien Danjolu + --]] local tag = require("awful.tag") @@ -19,16 +19,7 @@ local tonumber = tonumber local uselesstile = {} -local function tile_group(cls, wa, orientation, fact, group) - -- A useless gap (like the dwm patch) can be defined with - -- beautiful.useless_gap_width . - local useless_gap = tonumber(beautiful.useless_gap_width) or 0 - if useless_gap < 0 then useless_gap = 0 end - - -- A global border can be defined with - -- beautiful.global_border_width - local global_border = tonumber(beautiful.global_border_width) or 0 - if global_border < 0 then global_border = 0 end +local function tile_group(cls, wa, orientation, fact, group, gap) -- Themes border width requires an offset local bw = tonumber(beautiful.border_width) or 0 @@ -69,58 +60,28 @@ local function tile_group(cls, wa, orientation, fact, group) end total_fact = total_fact + fact[i] end - size = math.min(size, (available - global_border)) + size = math.min(size, available) local coord = wa[y] local geom = {} local used_size = 0 - local unused = wa[height] - (global_border * 2) + local unused = wa[height] local stat_coord = wa[x] --stat_coord = size for c = group.first,group.last do local i = c - group.first +1 - geom[width] = size - global_border - (bw * 2) + geom[width] = size - (bw * 2) geom[height] = math.floor(unused * fact[i] / total_fact) - (bw * 2) - geom[x] = group.coord + global_border - geom[y] = coord + global_border + geom[x] = group.coord + geom[y] = coord - coord = coord + geom[height] - unused = unused - geom[height] + coord = coord + geom[height] + 2 * bw + unused = unused - geom[height] - 2 * bw total_fact = total_fact - fact[i] - used_size = math.max(used_size, geom[width]) + used_size = math.max(used_size, geom[width] + 2 * bw) - -- Useless gap - if useless_gap > 0 - then - -- Top and left clients are shrinked by two steps and - -- get moved away from the border. Other clients just - -- get shrinked in one direction. - - top = false - left = false - - if geom[y] == wa[y] then - top = true - end - - if geom[x] == 0 or geom[x] == wa[x] then - left = true - end - - if top then - geom[height] = geom[height] - (2 * useless_gap) - geom[y] = geom[y] + useless_gap - else - geom[height] = geom[height] - useless_gap - end - - if left then - geom[width] = geom[width] - (2 * useless_gap) - geom[x] = geom[x] + useless_gap - else - geom[width] = geom[width] - useless_gap - end - end - -- End of useless gap. + -- Useless gap correction + geom.width = geom.width - gap + geom.height = geom.height - gap geom = cls[c]:geometry(geom) end @@ -132,6 +93,16 @@ local function tile(param, orientation) local t = tag.selected(param.screen) orientation = orientation or "right" + -- A useless gap (like the dwm patch) can be defined with + -- beautiful.useless_gap_width . + local useless_gap = tonumber(beautiful.useless_gap_width) or 0 + if useless_gap < 0 then useless_gap = 0 end + + -- A global border can be defined with + -- beautiful.global_border_width + local global_border = tonumber(beautiful.global_border_width) or 0 + if global_border < 0 then global_border = 0 end + -- this handles are different orientations local height = "height" local width = "width" @@ -152,6 +123,12 @@ local function tile(param, orientation) local wa = param.workarea local ncol = tag.getncol(t) + -- Workarea size correction + wa.height = wa.height - 2 * global_border - useless_gap + wa.width = wa.width - 2 * global_border - useless_gap + wa.x = wa.x + useless_gap + global_border + wa.y = wa.y + useless_gap + global_border + local data = tag.getdata(t).windowfact if not data then @@ -176,7 +153,7 @@ local function tile(param, orientation) if not data[0] then data[0] = {} end - coord = coord + tile_group(cls, wa, orientation, data[0], {first=1, last=nmaster, coord = coord, size = size}) + coord = coord + tile_group(cls, wa, orientation, data[0], {first=1, last=nmaster, coord = coord, size = size}, useless_gap) end if not place_master and nother > 0 then @@ -196,7 +173,7 @@ local function tile(param, orientation) if not data[i] then data[i] = {} end - coord = coord + tile_group(cls, wa, orientation, data[i], { first = first, last = last, coord = coord, size = size }) + coord = coord + tile_group(cls, wa, orientation, data[i], { first = first, last = last, coord = coord, size = size }, useless_gap) end end place_master = not place_master From 99b8b396798cd4ca08e1fa7c27af67f1afef1cf8 Mon Sep 17 00:00:00 2001 From: worron Date: Sat, 10 Jan 2015 19:51:12 +0300 Subject: [PATCH 493/572] Uselessfair code refactoring --- layout/uselessfair.lua | 142 ++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/layout/uselessfair.lua b/layout/uselessfair.lua index 058dae6..ee3aa40 100644 --- a/layout/uselessfair.lua +++ b/layout/uselessfair.lua @@ -2,7 +2,7 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2014, projektile + * (c) 2014, projektile, worron * (c) 2013, Luke Bonham * (c) 2012, Josh Komoroske * (c) 2010-2012, Peter Hofmann @@ -11,98 +11,98 @@ local beautiful = require("beautiful") local ipairs = ipairs -local math = { ceil = math.ceil, sqrt = math.sqrt } +local math = { ceil = math.ceil, sqrt = math.sqrt, floor = math.floor, max = math.max } local tonumber = tonumber local uselessfair = {} +-- Transformation functions +local function swap(geometry) + return { x = geometry.y, y = geometry.x, width = geometry.height, height = geometry.width } +end + +-- Client geometry correction depending on useless gap and window border +local function size_correction(c, geometry, useless_gap) + geometry.width = math.max(geometry.width - 2 * c.border_width - useless_gap, 1) + geometry.height = math.max(geometry.height - 2 * c.border_width - useless_gap, 1) + geometry.x = geometry.x + useless_gap / 2 + geometry.y = geometry.y + useless_gap / 2 +end + +-- Main tiling function local function fair(p, orientation) - -- A useless gap (like the dwm patch) can be defined with - -- beautiful.useless_gap_width. - local useless_gap = tonumber(beautiful.useless_gap_width) or 0 - if useless_gap < 0 then useless_gap = 0 end - -- A global border can be defined with - -- beautiful.global_border_width. - local global_border = tonumber(beautiful.global_border_width) or 0 - if global_border < 0 then global_border = 0 end + -- Theme vars + local useless_gap = beautiful.useless_gap_width or 0 + local global_border = beautiful.global_border_width or 0 - -- Themes border width requires an offset. - local bw = tonumber(beautiful.border_width) or 0 - - -- Total window size extend - local ext = 2 * bw + useless_gap - - -- get our orientation right. + -- Aliases local wa = p.workarea local cls = p.clients + -- Nothing to tile here + if #cls == 0 then return end + + -- Workarea size correction depending on useless gap and global border wa.height = wa.height - 2 * global_border - useless_gap wa.width = wa.width - 2 * global_border - useless_gap - wa.x = wa.x + useless_gap + global_border - wa.y = wa.y + useless_gap + global_border + wa.x = wa.x + useless_gap / 2 + global_border + wa.y = wa.y + useless_gap / 2 + global_border - if #cls > 0 then - local cells = math.ceil(math.sqrt(#cls)) - local strips = math.ceil(#cls / cells) + -- Geometry calculation + local row, col = 0, 0 - local cell = 0 - local strip = 0 - for k, c in ipairs(cls) do - local g = {} + local rows = math.ceil(math.sqrt(#cls)) + local cols = math.ceil(#cls / rows) - if ( orientation == "east" and #cls > 2 ) - or ( orientation == "south" and #cls <= 2 ) then - if #cls < (strips * cells) and strip == strips - 1 then - g.width = wa.width / (cells - ((strips * cells) - #cls)) - else - g.width = wa.width / cells - end - g.height = wa.height / strips + for i, c in ipairs(cls) do + local g = {} - g.x = wa.x + cell * g.width - g.y = wa.y + strip * g.height + -- find tile orientation for current client and swap geometry if need + local need_swap = (orientation == "east" and #cls <= 2) or (orientation == "south" and #cls > 2) + local area = need_swap and swap(wa) or wa - else - if #cls < (strips * cells) and strip == strips - 1 then - g.height = wa.height / (cells - ((strips * cells) - #cls)) - else - g.height = wa.height / cells - end - g.width = wa.width / strips - - g.x = wa.x + strip * g.width - g.y = wa.y + cell * g.height - - end - - g.width = g.width - ext - g.height = g.height - ext - - c:geometry(g) - - cell = cell + 1 - if cell == cells then - cell = 0 - strip = strip + 1 - end + -- calculate geometry + if #cls < (cols * rows) and row == cols - 1 then + g.width = area.width / (rows - ((cols * rows) - #cls)) + else + g.width = area.width / rows end + + g.height = area.height / cols + g.x = area.x + col * g.width + g.y = area.y + row * g.height + + -- turn back to real if geometry was swapped + if need_swap then g = swap(g) end + + -- window size correction depending on useless gap and window border + size_correction(c, g, useless_gap) + + -- set geometry + c:geometry(g) + + -- update tile grid coordinates + col = i % rows + row = math.floor(i / rows) end end ---- Horizontal fair layout. --- @param screen The screen to arrange. -uselessfair.horizontal = {} -uselessfair.horizontal.name = "uselessfairh" -function uselessfair.horizontal.arrange(p) - return fair(p, "east") +-- Layout constructor +local function construct_layout(name, direction) + return { + name = name, + -- @p screen The screen number to tile + arrange = function(p) return fair(p, direction) end + } end --- Vertical fair layout. --- @param screen The screen to arrange. -uselessfair.name = "uselessfair" -function uselessfair.arrange(p) - return fair(p, "south") -end +-- Build layouts with different tile direction +uselessfair.vertical = construct_layout("uselessfair", "south") +uselessfair.horizontal = construct_layout("uselessfairh", "east") + +-- Module aliase +uselessfair.arrange = uselessfair.vertical.arrange +uselessfair.name = uselessfair.vertical.name return uselessfair From 192543618537de4a4dab3adc14ad4bd6d696304e Mon Sep 17 00:00:00 2001 From: worron Date: Sat, 10 Jan 2015 19:52:08 +0300 Subject: [PATCH 494/572] Uselesstile code refactoring --- layout/uselesstile.lua | 316 +++++++++++++++++++---------------------- 1 file changed, 146 insertions(+), 170 deletions(-) diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index 5bb0c05..d244f43 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -2,7 +2,7 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2014 projektile + * (c) 2014 projektile, worron * (c) 2013 Luke Bonham * (c) 2009 Donald Ephraim Curtis * (c) 2008 Julien Danjolu @@ -13,204 +13,180 @@ local tag = require("awful.tag") local beautiful = require("beautiful") local ipairs = ipairs local math = { floor = math.floor, + ceil = math.ceil, max = math.max, min = math.min } local tonumber = tonumber local uselesstile = {} -local function tile_group(cls, wa, orientation, fact, group, gap) - - -- Themes border width requires an offset - local bw = tonumber(beautiful.border_width) or 0 - - -- get our orientation right - local height = "height" - local width = "width" - local x = "x" - local y = "y" - if orientation == "top" or orientation == "bottom" then - height = "width" - width = "height" - x = "y" - y = "x" - end - - -- make this more generic (not just width) - --if for top - available = wa[width] - (group.coord - wa[x]) -- it's truly not here - - -- find our total values - local total_fact = 0 - local min_fact = 1 - local size = group.size - for c = group.first,group.last do - -- determine the width/height based on the size_hint - local i = c - group.first +1 - local size_hints = cls[c].size_hints - local size_hint = size_hints["min_"..width] or size_hints["base_"..width] or 0 - size_hint = size_hint + cls[c].border_width*2 - size = math.max(size_hint, size) - - -- calculate the height - if not fact[i] then - fact[i] = min_fact - else - min_fact = math.min(fact[i],min_fact) - end - total_fact = total_fact + fact[i] - end - size = math.min(size, available) - local coord = wa[y] - local geom = {} - local used_size = 0 - local unused = wa[height] - local stat_coord = wa[x] - --stat_coord = size - for c = group.first,group.last do - local i = c - group.first +1 - geom[width] = size - (bw * 2) - geom[height] = math.floor(unused * fact[i] / total_fact) - (bw * 2) - geom[x] = group.coord - geom[y] = coord - - coord = coord + geom[height] + 2 * bw - unused = unused - geom[height] - 2 * bw - total_fact = total_fact - fact[i] - used_size = math.max(used_size, geom[width] + 2 * bw) - - -- Useless gap correction - geom.width = geom.width - gap - geom.height = geom.height - gap - - geom = cls[c]:geometry(geom) - end - - return used_size +-- Transformation functions +local function flip(canvas, geometry) + return { + -- vertical only + x = 2 * canvas.x + canvas.width - geometry.x - geometry.width, + y = geometry.y, + width = geometry.width, + height = geometry.height + } end -local function tile(param, orientation) - local t = tag.selected(param.screen) - orientation = orientation or "right" +local function swap(geometry) + return { x = geometry.y, y = geometry.x, width = geometry.height, height = geometry.width } +end - -- A useless gap (like the dwm patch) can be defined with - -- beautiful.useless_gap_width . - local useless_gap = tonumber(beautiful.useless_gap_width) or 0 - if useless_gap < 0 then useless_gap = 0 end +-- Find geometry for column/row tiling +local function cut_area(wa, total, index, is_horizontal) + local wa = is_horizontal and swap(wa) or wa + local height = wa.height / total - -- A global border can be defined with - -- beautiful.global_border_width - local global_border = tonumber(beautiful.global_border_width) or 0 - if global_border < 0 then global_border = 0 end + local area = { + x = wa.x, + y = wa.y + (index - 1) * height, + width = wa.width, + height = height + } - -- this handles are different orientations - local height = "height" - local width = "width" - local x = "x" - local y = "y" - if orientation == "top" or orientation == "bottom" then - height = "width" - width = "height" - x = "y" - y = "x" + if is_horizontal then area = swap(area) end + + return area +end + +-- Client geometry correction depending on useless gap and window border +local function size_correction(c, geometry, useless_gap) + geometry.width = math.max(geometry.width - 2 * c.border_width - useless_gap, 1) + geometry.height = math.max(geometry.height - 2 * c.border_width - useless_gap, 1) + geometry.x = geometry.x + useless_gap / 2 + geometry.y = geometry.y + useless_gap / 2 +end + +-- Tile group of clients in given area +-- @canvas need for proper transformation only +local function tile_column(canvas, area, list, useless_gap, transformation) + for i, c in ipairs(list) do + local g = cut_area(area, #list, i) + + -- swap workarea dimensions + if transformation.flip then g = flip(canvas, g) end + if transformation.swap then g = swap(g) end + + -- useless gap and border correction + size_correction(c, g, useless_gap) + + c:geometry(g) + end +end + +--Main tile function +local function tile(p, orientation) + + -- Theme vars + local useless_gap = beautiful.useless_gap_width or 0 + local global_border = beautiful.global_border_width or 0 + + -- Aliases + local wa = p.workarea + local cls = p.clients + local t = tag.selected(p.screen) + + -- Nothing to tile here + if #cls == 0 then return end + + -- Get tag prop + local nmaster = math.min(tag.getnmaster(t), #cls) + local mwfact = tag.getmwfact(t) + + if nmaster == 0 then + mwfact = 0 + elseif nmaster == #cls then + mwfact = 1 end - local cls = param.clients - local nmaster = math.min(tag.getnmaster(t), #cls) - local nother = math.max(#cls - nmaster,0) - - local mwfact = tag.getmwfact(t) - local wa = param.workarea - local ncol = tag.getncol(t) - - -- Workarea size correction + -- Workarea size correction depending on useless gap and global border wa.height = wa.height - 2 * global_border - useless_gap wa.width = wa.width - 2 * global_border - useless_gap - wa.x = wa.x + useless_gap + global_border - wa.y = wa.y + useless_gap + global_border + wa.x = wa.x + useless_gap / 2 + global_border + wa.y = wa.y + useless_gap / 2 + global_border - local data = tag.getdata(t).windowfact + -- Find which transformation we need for given orientation + local transformation = { + swap = orientation == 'top' or orientation == 'bottom', + flip = orientation == 'left' or orientation == 'top' + } - if not data then - data = {} - tag.getdata(t).windowfact = data + -- Swap workarea dimensions if orientation vertical + if transformation.swap then wa = swap(wa) end + + -- Split master and other windows + local cls_master, cls_other = {}, {} + + for i, c in ipairs(cls) do + if i <= nmaster then + table.insert(cls_master, c) + else + table.insert(cls_other, c) + end end - local coord = wa[x] - local place_master = true - if orientation == "left" or orientation == "top" then - -- if we are on the left or top we need to render the other windows first - place_master = false - end + -- Tile master windows + local master_area = { + x = wa.x, + y = wa.y, + width = nmaster > 0 and wa.width * mwfact or 0, + height = wa.height + } - -- this was easier than writing functions because there is a lot of data we need - for d = 1,2 do - if place_master and nmaster > 0 then - local size = wa[width] - if nother > 0 then - size = math.min(wa[width] * mwfact, wa[width] - (coord - wa[x])) - end - if not data[0] then - data[0] = {} - end - coord = coord + tile_group(cls, wa, orientation, data[0], {first=1, last=nmaster, coord = coord, size = size}, useless_gap) + tile_column(wa, master_area, cls_master, useless_gap, transformation) + + -- Tile other windows + local other_area = { + x = wa.x + master_area.width, + y = wa.y, + width = wa.width - master_area.width, + height = wa.height + } + + -- get column number for other windows + local ncol = math.min(tag.getncol(t), #cls_other) + + -- split other windows to column groups + local last_small_column = ncol - #cls_other % ncol + local rows_min = math.floor(#cls_other / ncol) + + local client_index = 1 + for i = 1, ncol do + local position = transformation.flip and ncol - i + 1 or i + local rows = i <= last_small_column and rows_min or rows_min + 1 + local column = {} + + for j = 1, rows do + table.insert(column, cls_other[client_index]) + client_index = client_index + 1 end - if not place_master and nother > 0 then - local last = nmaster - - -- we have to modify the work area size to consider left and top views - local wasize = wa[width] - if nmaster > 0 and (orientation == "left" or orientation == "top") then - wasize = wa[width] - wa[width]*mwfact - end - for i = 1,ncol do - -- Try to get equal width among remaining columns - local size = math.min((wasize - (coord - wa[x])) / (ncol - i + 1)) --+ (global_border/(ncol))/(ncol+i^2) - local first = last + 1 - last = last + math.floor((#cls - last)/(ncol - i + 1)) - -- tile the column and update our current x coordinate - if not data[i] then - data[i] = {} - end - coord = coord + tile_group(cls, wa, orientation, data[i], { first = first, last = last, coord = coord, size = size }, useless_gap) - end - end - place_master = not place_master + -- and tile + local column_area = cut_area(other_area, ncol, position, true) + tile_column(wa, column_area, column, useless_gap, transformation) end - end -uselesstile.right = {} -uselesstile.right.name = "uselesstile" -uselesstile.right.arrange = tile - ---- The main tile algo, on left. --- @param screen The screen number to tile. -uselesstile.left = {} -uselesstile.left.name = "uselesstileleft" -function uselesstile.left.arrange(p) - return tile(p, "left") +-- Layout constructor +local function construct_layout(name, orientation) + return { + name = name, + -- @p screen number to tile + arrange = function(p) return tile(p, orientation) end + } end ---- The main tile algo, on bottom. --- @param screen The screen number to tile. -uselesstile.bottom = {} -uselesstile.bottom.name = "uselesstilebottom" -function uselesstile.bottom.arrange(p) - return tile(p, "bottom") -end - ---- The main tile algo, on top. --- @param screen The screen number to tile. -uselesstile.top = {} -uselesstile.top.name = "uselesstiletop" -function uselesstile.top.arrange(p) - return tile(p, "top") -end +-- Build layouts with different tile direction +uselesstile.right = construct_layout("uselesstile", "right") +uselesstile.left = construct_layout("uselesstileleft", "left") +uselesstile.bottom = construct_layout("uselesstilebottom", "bottom") +uselesstile.top = construct_layout("uselesstiletop", "top") +-- Module aliase uselesstile.arrange = uselesstile.right.arrange uselesstile.name = uselesstile.right.name return uselesstile - From cba1548e922af2580a28132cfb90d92007ec9ba3 Mon Sep 17 00:00:00 2001 From: Yuexiao Guo Date: Mon, 12 Jan 2015 18:27:39 -0500 Subject: [PATCH 495/572] fixed mount point length calculation and misalignment of 4-digit size numbers --- scripts/dfs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/dfs b/scripts/dfs index d78d2bb..f04b051 100755 --- a/scripts/dfs +++ b/scripts/dfs @@ -107,7 +107,7 @@ fi # Computing mount point max length # ------------------------------------------------------------------------- MOUNT_POINT_MAX_LENGTH=` \ - echo $SORTED_FILE_SYSTEMS_INFO | $AWK_COMMAND -v PATTERN=$PATTERN \ + echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v PATTERN=$PATTERN \ ' BEGIN { mount_point_length_max = 15; @@ -364,22 +364,22 @@ $0 ~ PATTERN { if (total_size > 1 * t_bytes) printf ( \ - "| %3d%% %5.1f %5.1f Tb\n", \ + "| %3d%% %6.1f %6.1f Tb\n", \ percentage_occupied, free_size / t_bytes, total_size / t_bytes \ ); else if (total_size > 1 * g_bytes) printf ( \ - "| %3d%% %5.1f %5.1f Gb\n", \ + "| %3d%% %6.1f %6.1f Gb\n", \ percentage_occupied, free_size / g_bytes, total_size / g_bytes \ ); else if (total_size > 1 * m_byptes) printf ( \ - "| %3d%% %5.1f %5.1f Mb\n", \ + "| %3d%% %6.1f %6.1f Mb\n", \ percentage_occupied, free_size / m_bytes, total_size / m_bytes \ ); else printf ( \ - "| %3d%% %5.1f %5.1f Kb\n", \ + "| %3d%% %6.1f %6.1f Kb\n", \ percentage_occupied, free_size / k_bytes, total_size / k_bytes \ ); } From 02dba8b36a555276f40761bcc8c8e8a388b027c6 Mon Sep 17 00:00:00 2001 From: Jack Pugmire Date: Thu, 15 Jan 2015 23:44:22 -0500 Subject: [PATCH 496/572] Added keys to mpd_now for querying the length of a song and the current time (both in seconds). --- widgets/mpd.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 7fd611d..99624a2 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -58,7 +58,9 @@ local function worker(args) artist = "N/A", title = "N/A", album = "N/A", - date = "N/A" + date = "N/A", + time = "N/A", + elapsed= "N/A" } for line in f:lines() do @@ -69,6 +71,8 @@ local function worker(args) 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= math.floor(v) end end end From 4bc0f2927df80247d3762c0909683776fea0b978 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 20 Jan 2015 10:16:06 +0100 Subject: [PATCH 497/572] pull #90: fixed tabs --- widgets/mpd.lua | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 99624a2..9054c22 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -53,26 +53,26 @@ 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", - artist = "N/A", - title = "N/A", - album = "N/A", - date = "N/A", - time = "N/A", - elapsed= "N/A" + state = "N/A", + file = "N/A", + artist = "N/A", + title = "N/A", + album = "N/A", + date = "N/A", + time = "N/A", + elapsed = "N/A" } for line in f:lines() 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 == "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= math.floor(v) + if k = = "state" then mpd_now.state = v + elseif k = = "file" then mpd_now.file = 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 = math.floor(v) end end end From 6796803a40fd31c05566dad437a54f4e995a4c8f Mon Sep 17 00:00:00 2001 From: luke bonham Date: Tue, 20 Jan 2015 10:18:15 +0100 Subject: [PATCH 498/572] mpd: fixed bad auto-fixed scope --- widgets/mpd.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 9054c22..0d43e34 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -65,14 +65,14 @@ local function worker(args) for line in f:lines() 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 = = "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 = math.floor(v) + if k == "state" then mpd_now.state = v + elseif k == "file" then mpd_now.file = 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 = math.floor(v) end end end From c37514124a09ecd9532ca15a86e31aa4c15e46e2 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 30 Jan 2015 14:12:13 +0100 Subject: [PATCH 499/572] mpd: mpd_now.elapsed seconds fixed --- widgets/mpd.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 0d43e34..c10eb78 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -14,10 +14,11 @@ local escape_f = require("awful.util").escape local naughty = require("naughty") local wibox = require("wibox") -local io = { popen = io.popen } local os = { execute = os.execute, getenv = os.getenv } +local math = { floor = math.floor } local string = { format = string.format, + match = string.match, gmatch = string.gmatch } local setmetatable = setmetatable @@ -72,7 +73,7 @@ local function worker(args) 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 = math.floor(v) + elseif k == "elapsed" then mpd_now.elapsed = string.match(v, "%d+") end end end From 75db05552172584c57624b853384fa1a79acfcfb Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 30 Jan 2015 14:26:37 +0100 Subject: [PATCH 500/572] new submodule: lain.util.separators --- util/separators.lua | 102 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 util/separators.lua diff --git a/util/separators.lua b/util/separators.lua new file mode 100644 index 0000000..0eb0658 --- /dev/null +++ b/util/separators.lua @@ -0,0 +1,102 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2015, luke bonham + * (c) 2015, plotnikovanton + +--]] + +local wibox = require("wibox") +local beautiful = require("beautiful") +local gears = require("gears") + +-- Lain cairo separators util submodule +-- lain.util.separators +local separators = {} + +local height = beautiful.awful_widget_height or 0 +local width = beautiful.separators_width or 9 + +-- [[ Arrow + +-- Right +function separators.arrow_right(col1, col2) + local widget = wibox.widget.base.make_widget() + + widget.fit = function(m, w, h) return width, height end + + widget.draw = function(mycross, wibox, cr, width, height) + if col2 ~= "alpha" then + cr:set_source_rgb(gears.color.parse_color(col2)) + cr:new_path() + cr:move_to(0, 0) + cr:line_to(width, height/2) + cr:line_to(width, 0) + cr:close_path() + cr:fill() + + cr:new_path() + cr:move_to(0, height) + cr:line_to(width, height/2) + cr:line_to(width, height) + cr:close_path() + cr:fill() + end + + if col1 ~= "alpha" then + cr:set_source_rgb(gears.color.parse_color(col1)) + cr:new_path() + cr:move_to(0, 0) + cr:line_to(width, height/2) + cr:line_to(0, height) + cr:close_path() + cr:fill() + end + end + + return widget +end + +-- Left +function separators.arrow_left(col1, col2) + local widget = wibox.widget.base.make_widget() + + widget.fit = function(m, w, h) return width, height end + + widget.draw = function(mycross, wibox, cr, width, height) + if col1 ~= "alpha" then + cr:set_source_rgb(gears.color.parse_color(col1)) + cr:new_path() + cr:move_to(width, 0) + cr:line_to(0, height/2) + cr:line_to(0, 0) + cr:close_path() + cr:fill() + + cr:new_path() + cr:move_to(width, height) + cr:line_to(0, height/2) + cr:line_to(0, height) + cr:close_path() + cr:fill() + end + + if col2 ~= "alpha" then + cr:new_path() + cr:move_to(width, 0) + cr:line_to(0, height/2) + cr:line_to(width, height) + cr:close_path() + + cr:set_source_rgb(gears.color.parse_color(col2)) + cr:fill() + end + end + + return widget +end + +-- ]] + +return separators From 925c0276a567c35bb3cf140aedc368b9a6e152db Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 1 Feb 2015 11:39:26 +0100 Subject: [PATCH 501/572] asyncshell.request: removed unused argument --- asyncshell.lua | 3 +-- helpers.lua | 2 +- util/separators.lua | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/asyncshell.lua b/asyncshell.lua index 4a01caa..36ccc47 100644 --- a/asyncshell.lua +++ b/asyncshell.lua @@ -44,8 +44,7 @@ function asyncshell.request(command, callback) string.format("sh -c '%s > %s; " .. 'echo "asyncshell.deliver(%s)" | ' .. "awesome-client' 2> /dev/null", - string.gsub(command, "'", "'\\''"), tmpfname, - id, tmpfname) + string.gsub(command, "'", "'\\''"), tmpfname, id) spawn(req, false) return id end diff --git a/helpers.lua b/helpers.lua index 1dfb09b..9c4a83f 100644 --- a/helpers.lua +++ b/helpers.lua @@ -9,7 +9,7 @@ local debug = require("debug") local capi = { timer = timer } -local io = { open = io.open, +local io = { open = io.open, lines = io.lines } local rawget = rawget diff --git a/util/separators.lua b/util/separators.lua index 0eb0658..d2a3891 100644 --- a/util/separators.lua +++ b/util/separators.lua @@ -2,7 +2,7 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2015, luke bonham + * (c) 2015, Luke Bonham * (c) 2015, plotnikovanton --]] @@ -11,7 +11,7 @@ local wibox = require("wibox") local beautiful = require("beautiful") local gears = require("gears") --- Lain cairo separators util submodule +-- Lain Cairo separators util submodule -- lain.util.separators local separators = {} From 0049a18e8ff1a5bbb91132c6ed58a7712af0ad07 Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Thu, 5 Feb 2015 09:07:28 +0100 Subject: [PATCH 502/572] #91 pull + clean useless lines --- widgets/calendar.lua | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index 631b358..cbba676 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -37,17 +37,12 @@ function calendar:show(t_out, inc_offset, scr) local tims = t_out or 0 local f, c_text local today = tonumber(os.date('%d')) - local init_t = calendar.cal .. ' | sed -r -e "s/(^| )( ' + local init_t = calendar.cal .. ' | sed -r -e "s/_\\x08//g" | sed -r -e "s/(^| )(' calendar.offset = calendar.offset + offs if offs == 0 or calendar.offset == 0 then -- current month showing, today highlighted - if today >= 10 - then - init_t = calendar.cal .. ' | sed -r -e "s/_\\x08//g" | sed -r -e "s/(^| )(' - end - calendar.offset = 0 calendar.notify_icon = calendar.icons .. today .. ".png" From 16925f3f26b8e74516de9b6f25c5e207eea0a91e Mon Sep 17 00:00:00 2001 From: worron Date: Thu, 12 Feb 2015 20:16:14 +0300 Subject: [PATCH 503/572] Vertical client resizing fix --- layout/uselesstile.lua | 66 +++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index d244f43..bd365a8 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -35,19 +35,18 @@ local function swap(geometry) return { x = geometry.y, y = geometry.x, width = geometry.height, height = geometry.width } end --- Find geometry for column/row tiling -local function cut_area(wa, total, index, is_horizontal) - local wa = is_horizontal and swap(wa) or wa - local height = wa.height / total +-- Find geometry for secondary windows column +local function cut_column(wa, n, index) + local width = wa.width / n + local area = { x = wa.x + (index - 1) * width, y = wa.y, width = width, height = wa.height } - local area = { - x = wa.x, - y = wa.y + (index - 1) * height, - width = wa.width, - height = height - } + return area +end - if is_horizontal then area = swap(area) end +-- Find geometry for certain window in column +local function cut_row(wa, factor, index, used) + local height = wa.height * factor.window[index] / factor.total + local area = { x = wa.x, y = wa.y + used, width = wa.width, height = height } return area end @@ -60,11 +59,33 @@ local function size_correction(c, geometry, useless_gap) geometry.y = geometry.y + useless_gap / 2 end +-- Check size factor for group of clients and calculate total +local function calc_factor(n, winfactors) + local factor = { window = winfactors, total = 0, min = 1 } + + for i = 1, n do + if not factor.window[i] then + factor.window[i] = factor.min + else + factor.min = math.min(factor.window[i], factor.min) + if factor.window[i] < 0.05 then factor.window[i] = 0.05 end + end + factor.total = factor.total + factor.window[i] + end + + return factor +end + -- Tile group of clients in given area -- @canvas need for proper transformation only -local function tile_column(canvas, area, list, useless_gap, transformation) +-- @winfactors table with clients size factors +local function tile_column(canvas, area, list, useless_gap, transformation, winfactors) + local used = 0 + local factor = calc_factor(#list, winfactors) + for i, c in ipairs(list) do - local g = cut_area(area, #list, i) + local g = cut_row(area, factor, i, used) + used = used + g.height -- swap workarea dimensions if transformation.flip then g = flip(canvas, g) end @@ -102,6 +123,14 @@ local function tile(p, orientation) mwfact = 1 end + -- clients size factor + local data = tag.getdata(t).windowfact + + if not data then + data = {} + tag.getdata(t).windowfact = data + end + -- Workarea size correction depending on useless gap and global border wa.height = wa.height - 2 * global_border - useless_gap wa.width = wa.width - 2 * global_border - useless_gap @@ -136,7 +165,8 @@ local function tile(p, orientation) height = wa.height } - tile_column(wa, master_area, cls_master, useless_gap, transformation) + if not data[0] then data[0] = {} end + tile_column(wa, master_area, cls_master, useless_gap, transformation, data[0]) -- Tile other windows local other_area = { @@ -164,9 +194,11 @@ local function tile(p, orientation) client_index = client_index + 1 end - -- and tile - local column_area = cut_area(other_area, ncol, position, true) - tile_column(wa, column_area, column, useless_gap, transformation) + -- and tile + local column_area = cut_column(other_area, ncol, position) + + if not data[i] then data[i] = {} end + tile_column(wa, column_area, column, useless_gap, transformation, data[i]) end end From 5a1a02a63dc9e203f1df9a39ca657fd62677a258 Mon Sep 17 00:00:00 2001 From: emikkva Date: Mon, 16 Feb 2015 23:43:06 +0200 Subject: [PATCH 504/572] Add a card attribute for alsa and alsabar Currently alsa.lua and alsabar.lua do not support the amixer command line option "-c" which allows defining which card to use. For at least new Dell E-series laptops, the card is not the default (0) and therefore this functionality is required for these widgets to work. --- widgets/alsa.lua | 6 ++++-- widgets/alsabar.lua | 11 ++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/widgets/alsa.lua b/widgets/alsa.lua index f62a150..5a4335e 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -12,7 +12,8 @@ local newtimer = require("lain.helpers").newtimer local wibox = require("wibox") local io = { popen = io.popen } -local string = { match = string.match } +local string = { match = string.match, + format = string.format } local setmetatable = setmetatable @@ -22,6 +23,7 @@ local alsa = {} local function worker(args) local args = args or {} + local card = args.card or "0" local timeout = args.timeout or 5 local channel = args.channel or "Master" local settings = args.settings or function() end @@ -29,7 +31,7 @@ local function worker(args) alsa.widget = wibox.widget.textbox('') function alsa.update() - local f = assert(io.popen('amixer -M get ' .. channel)) + local f = assert(io.popen(string.format("amixer -c %s -M get %s", card, channel))) local mixer = f:read("*a") f:close() diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 65a2b33..fa10bc2 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -25,6 +25,7 @@ local setmetatable = setmetatable -- ALSA volume bar -- lain.widgets.alsabar local alsabar = { + card = "0", channel = "Master", step = "5%", @@ -97,6 +98,7 @@ local function worker(args) local ticks_size = args.ticks_size or 7 local vertical = args.vertical or false + alsabar.card = args.card or alsabar.card alsabar.channel = args.channel or alsabar.channel alsabar.step = args.step or alsabar.step alsabar.colors = args.colors or alsabar.colors @@ -115,7 +117,7 @@ local function worker(args) function alsabar.update() -- Get mixer control contents - local f = io.popen("amixer -M get " .. alsabar.channel) + local f = assert(io.popen(string.format("amixer -c %s -M get %s", alsabar.card, alsabar.channel))) local mixer = f:read("*a") f:close() @@ -129,7 +131,6 @@ local function worker(args) alsabar._current_level = tonumber(volu) alsabar.bar:set_value(alsabar._current_level / 100) - if not mute and tonumber(volu) == 0 or mute == "off" then alsabar._muted = true @@ -154,15 +155,15 @@ local function worker(args) awful.util.spawn(alsabar.mixer) end), awful.button ({}, 3, function() - awful.util.spawn(string.format("amixer set %s toggle", alsabar.channel)) + awful.util.spawn(string.format("amixer -c %s set %s toggle", alsabar.card, alsabar.channel)) alsabar.update() end), awful.button ({}, 4, function() - awful.util.spawn(string.format("amixer set %s %s+", alsabar.channel, alsabar.step)) + awful.util.spawn(string.format("amixer -c %s set %s %s+", alsabar.card, alsabar.channel, alsabar.step)) alsabar.update() end), awful.button ({}, 5, function() - awful.util.spawn(string.format("amixer set %s %s-", alsabar.channel, alsabar.step)) + awful.util.spawn(string.format("amixer -c %s set %s %s-", alsabar.card, alsabar.channel, alsabar.step)) alsabar.update() end) )) From a535b86435d83bac68be5f2ca76680d37b3ac07d Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Mon, 9 Mar 2015 21:33:11 +0100 Subject: [PATCH 505/572] alsa: added card, channel to widget table --- widgets/alsa.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 5a4335e..7d25096 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -23,15 +23,16 @@ local alsa = {} local function worker(args) local args = args or {} - local card = args.card or "0" local timeout = args.timeout or 5 - local channel = args.channel or "Master" local settings = args.settings or function() end + alsa.card = args.card or "0" + alsa.channel = args.channel or "Master" + alsa.widget = wibox.widget.textbox('') function alsa.update() - local f = assert(io.popen(string.format("amixer -c %s -M get %s", card, channel))) + local f = assert(io.popen(string.format("amixer -c %s -M get %s", alsa.card, alsa.channel))) local mixer = f:read("*a") f:close() From adc899ba1f81db76258b265e1309c43288ad57e7 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 25 Mar 2015 19:41:08 +0100 Subject: [PATCH 506/572] #103: revert to original fs implementation --- widgets/alsabar.lua | 2 +- widgets/fs.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index fa10bc2..b12e55c 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -27,7 +27,7 @@ local setmetatable = setmetatable local alsabar = { card = "0", channel = "Master", - step = "5%", + step = "2%", colors = { background = beautiful.bg_normal, diff --git a/widgets/fs.lua b/widgets/fs.lua index 3b99cba..8b51178 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -66,7 +66,7 @@ local function worker(args) function update() fs_info = {} fs_now = {} - local f = io.popen("LC_ALL=C df -kP " .. partition) + local f = assert(io.popen("LC_ALL=C df -kP")) for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount) local s = string.match(line, "^.-[%s]([%d]+)") From 91c1b804b92653b3c0c6d65e676033e84527014d Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Sat, 28 Mar 2015 11:39:45 +0100 Subject: [PATCH 507/572] alsabar: string.format use for preset.text in alsabar._notify --- widgets/alsabar.lua | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index b12e55c..d233b28 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -70,11 +70,9 @@ function alsabar.notify() preset.title = alsabar.channel .. " - " .. alsabar._current_level .. "%" end - int = math.modf((alsabar._current_level / 100) * alsabar.notifications.bar_size) - preset.text = "[" - .. string.rep("|", int) - .. string.rep(" ", alsabar.notifications.bar_size - int) - .. "]" + local int = math.modf((alsabar._current_level / 100) * alsabar.notifications.bar_size) + preset.text = string.format("[%s%s]", string.rep("|", int), + string.rep(" ", alsabar.notifications.bar_size - int)) if alsabar._notify ~= nil then alsabar._notify = naughty.notify ({ From c9b11c5962f5a2c491f85755dff72a36829149df Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Sat, 28 Mar 2015 11:40:06 +0100 Subject: [PATCH 508/572] alsabar: string.format use for preset.text in alsabar._notify --- widgets/alsabar.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index d233b28..b2cba9e 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -71,7 +71,7 @@ function alsabar.notify() end local int = math.modf((alsabar._current_level / 100) * alsabar.notifications.bar_size) - preset.text = string.format("[%s%s]", string.rep("|", int), + preset.text = string.format("[%s%s]", string.rep("|", int), string.rep(" ", alsabar.notifications.bar_size - int)) if alsabar._notify ~= nil then From 422c9387f197669900f46e5469918747169350b8 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 13 Apr 2015 11:38:44 +0200 Subject: [PATCH 509/572] yawn: fair/windy icon added --- widgets/yawn/icons/DayFairWindy.png | 1 + widgets/yawn/icons/NightFairWindy.png | 1 + 2 files changed, 2 insertions(+) create mode 120000 widgets/yawn/icons/DayFairWindy.png create mode 120000 widgets/yawn/icons/NightFairWindy.png diff --git a/widgets/yawn/icons/DayFairWindy.png b/widgets/yawn/icons/DayFairWindy.png new file mode 120000 index 0000000..8ee94d1 --- /dev/null +++ b/widgets/yawn/icons/DayFairWindy.png @@ -0,0 +1 @@ +DayClear.png \ No newline at end of file diff --git a/widgets/yawn/icons/NightFairWindy.png b/widgets/yawn/icons/NightFairWindy.png new file mode 120000 index 0000000..23df45a --- /dev/null +++ b/widgets/yawn/icons/NightFairWindy.png @@ -0,0 +1 @@ +NightClear.png \ No newline at end of file From 161abc46abf98a9a28ee4ee4f4b8c10ac57eabbc Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 13 Apr 2015 11:49:13 +0200 Subject: [PATCH 510/572] yawn: fair/windy icon added --- widgets/yawn/init.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua index be3e614..1f6b0f4 100644 --- a/widgets/yawn/init.lua +++ b/widgets/yawn/init.lua @@ -102,10 +102,10 @@ function yawn.fetch_weather() local hour = tonumber(os.date("%H")) sky = icon_path - if forecast == "Clear" or - forecast == "Fair" or - forecast == "Partly Cloudy" or - forecast == "Mostly Cloudy" + if string.find(forecast, "Clear") or + string.find(forecast, "Fair") or + string.find(forecast, "Partly Cloudy") or + string.find(forecast, "Mostly Cloudy") then if hour >= 6 and hour <= 18 then From f78d4517069ee277be97bf908df48fbead4fc127 Mon Sep 17 00:00:00 2001 From: Oleg Hahm Date: Sun, 17 May 2015 22:58:52 +0200 Subject: [PATCH 511/572] smapi: round remaining hour estimation --- widgets/contrib/tpbat/smapi.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/contrib/tpbat/smapi.lua b/widgets/contrib/tpbat/smapi.lua index 862d4cd..c7f093e 100644 --- a/widgets/contrib/tpbat/smapi.lua +++ b/widgets/contrib/tpbat/smapi.lua @@ -87,7 +87,7 @@ function smapi:battery(name) return "N/A" end - local hrs = mins_left / 60 + local hrs = math.floor(mins_left / 60) local min = mins_left % 60 return string.format("%02d:%02d", hrs, min) end From aaf1142688933bc5673d4b8309886db2a178ce90 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 19 May 2015 14:11:36 +0200 Subject: [PATCH 512/572] #109: catch n%0 --- layout/uselesstile.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index bd365a8..877fad1 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -179,6 +179,8 @@ local function tile(p, orientation) -- get column number for other windows local ncol = math.min(tag.getncol(t), #cls_other) + if ncol == 0 then ncol = 1 end + -- split other windows to column groups local last_small_column = ncol - #cls_other % ncol local rows_min = math.floor(#cls_other / ncol) From c3ddefb68d7020b125335f30355abd7aa21b0820 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 19 May 2015 15:41:33 +0200 Subject: [PATCH 513/572] net: removed 'tostring' for numbers --- widgets/mem.lua | 4 +--- widgets/net.lua | 5 ++--- widgets/sysload.lua | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/widgets/mem.lua b/widgets/mem.lua index 986fa76..46bb5f9 100644 --- a/widgets/mem.lua +++ b/widgets/mem.lua @@ -13,9 +13,7 @@ local wibox = require("wibox") local io = { lines = io.lines } local math = { floor = math.floor } -local string = { format = string.format, - gmatch = string.gmatch, - len = string.len } +local string = { gmatch = string.gmatch } local setmetatable = setmetatable diff --git a/widgets/net.lua b/widgets/net.lua index 2b06622..2585ad4 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -14,7 +14,6 @@ local naughty = require("naughty") local wibox = require("wibox") local io = { popen = io.popen } -local tostring = tostring local string = { format = string.format, gsub = string.gsub, match = string.match } @@ -71,10 +70,10 @@ local function worker(args) local now_r = helpers.first_line('/sys/class/net/' .. iface .. '/statistics/rx_bytes') or 0 - net_now.sent = tostring((now_t - net.last_t) / timeout / units) + net_now.sent = (now_t - net.last_t) / timeout / units net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ",", ".") - net_now.received = tostring((now_r - net.last_r) / timeout / units) + net_now.received = (now_r - net.last_r) / timeout / units net_now.received = string.gsub(string.format('%.1f', net_now.received), ",", ".") widget = net.widget diff --git a/widgets/sysload.lua b/widgets/sysload.lua index b15b1bf..144ad0c 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -12,8 +12,7 @@ local newtimer = require("lain.helpers").newtimer local wibox = require("wibox") local io = { open = io.open } -local string = { format = string.format, - match = string.match } +local string = { match = string.match } local setmetatable = setmetatable From f48afb841e25768fac7e9c971dc6acf8e40e6f65 Mon Sep 17 00:00:00 2001 From: Dmitry Nedbaylo Date: Sun, 31 May 2015 15:44:45 +0300 Subject: [PATCH 514/572] Calendar: added post calendar command for extra processing --- widgets/calendar.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/widgets/calendar.lua b/widgets/calendar.lua index cbba676..cc0ebe7 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -37,7 +37,8 @@ function calendar:show(t_out, inc_offset, scr) local tims = t_out or 0 local f, c_text local today = tonumber(os.date('%d')) - local init_t = calendar.cal .. ' | sed -r -e "s/_\\x08//g" | sed -r -e "s/(^| )(' + local init_t = calendar.cal .. ' ' .. calendar.post_cal .. ' ' .. + ' | sed -r -e "s/_\\x08//g" | sed -r -e "s/(^| )(' calendar.offset = calendar.offset + offs @@ -76,7 +77,8 @@ function calendar:show(t_out, inc_offset, scr) calendar.notify_icon = nil - f = io.popen(calendar.cal .. ' ' .. month .. ' ' .. year) + f = io.popen(calendar.cal .. ' ' .. month .. ' ' .. year .. ' ' .. + calendar.post_cal) end c_text = " Date: Wed, 24 Jun 2015 14:05:37 +0200 Subject: [PATCH 516/572] wiki updated --- .gitmodules | 4 ++-- lain.wiki | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 160000 lain.wiki diff --git a/.gitmodules b/.gitmodules index 350c0f8..a66da18 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "wiki"] - path = wiki +[submodule "lain.wiki"] + path = lain.wiki url = https://github.com/copycat-killer/lain.wiki.git diff --git a/lain.wiki b/lain.wiki new file mode 160000 index 0000000..b011c03 --- /dev/null +++ b/lain.wiki @@ -0,0 +1 @@ +Subproject commit b011c0339e805ee1596d0b6778d6c497dab41109 From eba28656f08e1a496abc194718cc1191d83fac9e Mon Sep 17 00:00:00 2001 From: luke bonham Date: Wed, 24 Jun 2015 14:07:51 +0200 Subject: [PATCH 517/572] wiki submodule updated --- .gitmodules | 2 +- lain.wiki | 1 - wiki | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) delete mode 160000 lain.wiki diff --git a/.gitmodules b/.gitmodules index a66da18..a50818f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "lain.wiki"] - path = lain.wiki + path = wiki url = https://github.com/copycat-killer/lain.wiki.git diff --git a/lain.wiki b/lain.wiki deleted file mode 160000 index b011c03..0000000 --- a/lain.wiki +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b011c0339e805ee1596d0b6778d6c497dab41109 diff --git a/wiki b/wiki index 54b3a71..b011c03 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 54b3a717b2f7069264ce5a20018ae4abf153e7b2 +Subproject commit b011c0339e805ee1596d0b6778d6c497dab41109 From 8c5b64675dfbf196871ee31cf22920627019bd84 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 2 Jul 2015 12:06:07 +0200 Subject: [PATCH 518/572] better weather module: OpenWeatherMap; #105 --- asyncshell.lua | 4 +- .../openweathermap/01d.png | Bin .../openweathermap/01n.png | Bin .../openweathermap/02d.png | Bin .../openweathermap/02n.png | Bin .../openweathermap/03d.png | Bin .../openweathermap/03n.png | Bin .../openweathermap/04d.png | Bin icons/openweathermap/04n.png | 1 + .../Rain.png => icons/openweathermap/09d.png | Bin icons/openweathermap/09n.png | 1 + .../openweathermap/10d.png | Bin icons/openweathermap/10n.png | 1 + .../openweathermap/11d.png | Bin icons/openweathermap/11n.png | 1 + .../openweathermap/13d.png | Bin icons/openweathermap/13n.png | 1 + .../Foggy.png => icons/openweathermap/50d.png | Bin icons/openweathermap/50n.png | 1 + icons/openweathermap/README.md | 3 + .../icons => icons/openweathermap}/na.png | Bin util/dkjson.lua | 713 ++++++++++++++++++ widgets/contrib/ccurr.lua | 2 +- widgets/weather.lua | 125 +++ widgets/yawn/icons/BlowingSnow.png | Bin 11454 -> 0 bytes widgets/yawn/icons/DayFair.png | 1 - widgets/yawn/icons/DayFairWindy.png | 1 - widgets/yawn/icons/Drizzle.png | 1 - widgets/yawn/icons/Fog.png | 1 - widgets/yawn/icons/FreezingDrizzle.png | Bin 13166 -> 0 bytes widgets/yawn/icons/FreezingRain.png | Bin 13979 -> 0 bytes widgets/yawn/icons/Hail.png | Bin 7325 -> 0 bytes widgets/yawn/icons/Haze.png | 1 - widgets/yawn/icons/HeavyRain.png | 1 - widgets/yawn/icons/LightRain.png | 1 - widgets/yawn/icons/LightSnow.png | 1 - widgets/yawn/icons/LightSnowShowers.png | Bin 8779 -> 0 bytes widgets/yawn/icons/Mist.png | 1 - widgets/yawn/icons/MixedRainAndHail.png | Bin 9060 -> 0 bytes widgets/yawn/icons/MixedRainAndSleet.png | Bin 10978 -> 0 bytes widgets/yawn/icons/MixedRainAndSnow.png | Bin 10808 -> 0 bytes widgets/yawn/icons/NightFair.png | 1 - widgets/yawn/icons/NightFairWindy.png | 1 - widgets/yawn/icons/README.md | 6 - widgets/yawn/icons/Sleet.png | 1 - widgets/yawn/icons/Snow.png | 1 - widgets/yawn/icons/SnowFlurries.png | 1 - widgets/yawn/icons/SnowShowers.png | Bin 9961 -> 0 bytes widgets/yawn/icons/Sunny.png | Bin 14018 -> 0 bytes widgets/yawn/icons/ThunderintheVicinity.png | 1 - widgets/yawn/icons/Wind.png | Bin 8726 -> 0 bytes widgets/yawn/init.lua | 206 ----- widgets/yawn/localizations/de_DE | 61 -- widgets/yawn/localizations/fr_FR | 61 -- widgets/yawn/localizations/it_IT | 61 -- .../yawn/localizations/localization_template | 61 -- widgets/yawn/localizations/ru_RU | 61 -- widgets/yawn/localizations/zh_CN | 61 -- widgets/yawn/localizations/zh_TW | 61 -- wiki | 2 +- 60 files changed, 850 insertions(+), 659 deletions(-) rename widgets/yawn/icons/DayClear.png => icons/openweathermap/01d.png (100%) rename widgets/yawn/icons/NightClear.png => icons/openweathermap/01n.png (100%) rename widgets/yawn/icons/DayPartlyCloudy.png => icons/openweathermap/02d.png (100%) rename widgets/yawn/icons/NightPartlyCloudy.png => icons/openweathermap/02n.png (100%) rename widgets/yawn/icons/DayMostlyCloudy.png => icons/openweathermap/03d.png (100%) rename widgets/yawn/icons/NightMostlyCloudy.png => icons/openweathermap/03n.png (100%) rename widgets/yawn/icons/Cloudy.png => icons/openweathermap/04d.png (100%) create mode 120000 icons/openweathermap/04n.png rename widgets/yawn/icons/Rain.png => icons/openweathermap/09d.png (100%) create mode 120000 icons/openweathermap/09n.png rename widgets/yawn/icons/Showers.png => icons/openweathermap/10d.png (100%) create mode 120000 icons/openweathermap/10n.png rename widgets/yawn/icons/RainThunder.png => icons/openweathermap/11d.png (100%) create mode 120000 icons/openweathermap/11n.png rename widgets/yawn/icons/HeavySnow.png => icons/openweathermap/13d.png (100%) create mode 120000 icons/openweathermap/13n.png rename widgets/yawn/icons/Foggy.png => icons/openweathermap/50d.png (100%) create mode 120000 icons/openweathermap/50n.png create mode 100644 icons/openweathermap/README.md rename {widgets/yawn/icons => icons/openweathermap}/na.png (100%) create mode 100644 util/dkjson.lua create mode 100644 widgets/weather.lua delete mode 100755 widgets/yawn/icons/BlowingSnow.png delete mode 120000 widgets/yawn/icons/DayFair.png delete mode 120000 widgets/yawn/icons/DayFairWindy.png delete mode 120000 widgets/yawn/icons/Drizzle.png delete mode 120000 widgets/yawn/icons/Fog.png delete mode 100755 widgets/yawn/icons/FreezingDrizzle.png delete mode 100755 widgets/yawn/icons/FreezingRain.png delete mode 100755 widgets/yawn/icons/Hail.png delete mode 120000 widgets/yawn/icons/Haze.png delete mode 120000 widgets/yawn/icons/HeavyRain.png delete mode 120000 widgets/yawn/icons/LightRain.png delete mode 120000 widgets/yawn/icons/LightSnow.png delete mode 100755 widgets/yawn/icons/LightSnowShowers.png delete mode 120000 widgets/yawn/icons/Mist.png delete mode 100755 widgets/yawn/icons/MixedRainAndHail.png delete mode 100755 widgets/yawn/icons/MixedRainAndSleet.png delete mode 100755 widgets/yawn/icons/MixedRainAndSnow.png delete mode 120000 widgets/yawn/icons/NightFair.png delete mode 120000 widgets/yawn/icons/NightFairWindy.png delete mode 100644 widgets/yawn/icons/README.md delete mode 120000 widgets/yawn/icons/Sleet.png delete mode 120000 widgets/yawn/icons/Snow.png delete mode 120000 widgets/yawn/icons/SnowFlurries.png delete mode 100755 widgets/yawn/icons/SnowShowers.png delete mode 100755 widgets/yawn/icons/Sunny.png delete mode 120000 widgets/yawn/icons/ThunderintheVicinity.png delete mode 100755 widgets/yawn/icons/Wind.png delete mode 100644 widgets/yawn/init.lua delete mode 100644 widgets/yawn/localizations/de_DE delete mode 100644 widgets/yawn/localizations/fr_FR delete mode 100644 widgets/yawn/localizations/it_IT delete mode 100644 widgets/yawn/localizations/localization_template delete mode 100644 widgets/yawn/localizations/ru_RU delete mode 100644 widgets/yawn/localizations/zh_CN delete mode 100644 widgets/yawn/localizations/zh_TW diff --git a/asyncshell.lua b/asyncshell.lua index 36ccc47..0aafa17 100644 --- a/asyncshell.lua +++ b/asyncshell.lua @@ -10,11 +10,9 @@ -- How to use... -- ...asynchronously: -- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end) --- ...synchronously +-- ...synchronously: -- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error") --- This is more cpu demanding, but makes things faster. - local spawn = require('awful.util').spawn asyncshell = {} diff --git a/widgets/yawn/icons/DayClear.png b/icons/openweathermap/01d.png similarity index 100% rename from widgets/yawn/icons/DayClear.png rename to icons/openweathermap/01d.png diff --git a/widgets/yawn/icons/NightClear.png b/icons/openweathermap/01n.png similarity index 100% rename from widgets/yawn/icons/NightClear.png rename to icons/openweathermap/01n.png diff --git a/widgets/yawn/icons/DayPartlyCloudy.png b/icons/openweathermap/02d.png similarity index 100% rename from widgets/yawn/icons/DayPartlyCloudy.png rename to icons/openweathermap/02d.png diff --git a/widgets/yawn/icons/NightPartlyCloudy.png b/icons/openweathermap/02n.png similarity index 100% rename from widgets/yawn/icons/NightPartlyCloudy.png rename to icons/openweathermap/02n.png diff --git a/widgets/yawn/icons/DayMostlyCloudy.png b/icons/openweathermap/03d.png similarity index 100% rename from widgets/yawn/icons/DayMostlyCloudy.png rename to icons/openweathermap/03d.png diff --git a/widgets/yawn/icons/NightMostlyCloudy.png b/icons/openweathermap/03n.png similarity index 100% rename from widgets/yawn/icons/NightMostlyCloudy.png rename to icons/openweathermap/03n.png diff --git a/widgets/yawn/icons/Cloudy.png b/icons/openweathermap/04d.png similarity index 100% rename from widgets/yawn/icons/Cloudy.png rename to icons/openweathermap/04d.png diff --git a/icons/openweathermap/04n.png b/icons/openweathermap/04n.png new file mode 120000 index 0000000..b9a83df --- /dev/null +++ b/icons/openweathermap/04n.png @@ -0,0 +1 @@ +04d.png \ No newline at end of file diff --git a/widgets/yawn/icons/Rain.png b/icons/openweathermap/09d.png similarity index 100% rename from widgets/yawn/icons/Rain.png rename to icons/openweathermap/09d.png diff --git a/icons/openweathermap/09n.png b/icons/openweathermap/09n.png new file mode 120000 index 0000000..cca1f5d --- /dev/null +++ b/icons/openweathermap/09n.png @@ -0,0 +1 @@ +09d.png \ No newline at end of file diff --git a/widgets/yawn/icons/Showers.png b/icons/openweathermap/10d.png similarity index 100% rename from widgets/yawn/icons/Showers.png rename to icons/openweathermap/10d.png diff --git a/icons/openweathermap/10n.png b/icons/openweathermap/10n.png new file mode 120000 index 0000000..6e01227 --- /dev/null +++ b/icons/openweathermap/10n.png @@ -0,0 +1 @@ +10d.png \ No newline at end of file diff --git a/widgets/yawn/icons/RainThunder.png b/icons/openweathermap/11d.png similarity index 100% rename from widgets/yawn/icons/RainThunder.png rename to icons/openweathermap/11d.png diff --git a/icons/openweathermap/11n.png b/icons/openweathermap/11n.png new file mode 120000 index 0000000..b227917 --- /dev/null +++ b/icons/openweathermap/11n.png @@ -0,0 +1 @@ +11d.png \ No newline at end of file diff --git a/widgets/yawn/icons/HeavySnow.png b/icons/openweathermap/13d.png similarity index 100% rename from widgets/yawn/icons/HeavySnow.png rename to icons/openweathermap/13d.png diff --git a/icons/openweathermap/13n.png b/icons/openweathermap/13n.png new file mode 120000 index 0000000..94e5a52 --- /dev/null +++ b/icons/openweathermap/13n.png @@ -0,0 +1 @@ +13d.png \ No newline at end of file diff --git a/widgets/yawn/icons/Foggy.png b/icons/openweathermap/50d.png similarity index 100% rename from widgets/yawn/icons/Foggy.png rename to icons/openweathermap/50d.png diff --git a/icons/openweathermap/50n.png b/icons/openweathermap/50n.png new file mode 120000 index 0000000..e3ba961 --- /dev/null +++ b/icons/openweathermap/50n.png @@ -0,0 +1 @@ +50d.png \ No newline at end of file diff --git a/icons/openweathermap/README.md b/icons/openweathermap/README.md new file mode 100644 index 0000000..f908fbd --- /dev/null +++ b/icons/openweathermap/README.md @@ -0,0 +1,3 @@ +[Plain Weather Icons](http://merlinthered.deviantart.com/art/plain-weather-icons-157162192), created by [MerlinTheRed](http://merlinthered.deviantart.com/). + + diff --git a/widgets/yawn/icons/na.png b/icons/openweathermap/na.png similarity index 100% rename from widgets/yawn/icons/na.png rename to icons/openweathermap/na.png diff --git a/util/dkjson.lua b/util/dkjson.lua new file mode 100644 index 0000000..89aa2e1 --- /dev/null +++ b/util/dkjson.lua @@ -0,0 +1,713 @@ +-- Module options: +local always_try_using_lpeg = true +local register_global_module_table = false +local global_module_name = 'json' + +--[==[ + +David Kolf's JSON module for Lua 5.1/5.2 + +Version 2.5 + + +For the documentation see the corresponding readme.txt or visit +. + +You can contact the author by sending an e-mail to 'david' at the +domain 'dkolf.de'. + + +Copyright (C) 2010-2013 David Heiko Kolf + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--]==] + +-- global dependencies: +local pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset = + pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset +local error, require, pcall, select = error, require, pcall, select +local floor, huge = math.floor, math.huge +local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat = + string.rep, string.gsub, string.sub, string.byte, string.char, + string.find, string.len, string.format +local strmatch = string.match +local concat = table.concat + +local json = { version = "dkjson 2.5" } + +if register_global_module_table then + _G[global_module_name] = json +end + +local _ENV = nil -- blocking globals in Lua 5.2 + +pcall (function() + -- Enable access to blocked metatables. + -- Don't worry, this module doesn't change anything in them. + local debmeta = require "debug".getmetatable + if debmeta then getmetatable = debmeta end +end) + +json.null = setmetatable ({}, { + __tojson = function () return "null" end +}) + +local function isarray (tbl) + local max, n, arraylen = 0, 0, 0 + for k,v in pairs (tbl) do + if k == 'n' and type(v) == 'number' then + arraylen = v + if v > max then + max = v + end + else + if type(k) ~= 'number' or k < 1 or floor(k) ~= k then + return false + end + if k > max then + max = k + end + n = n + 1 + end + end + if max > 10 and max > arraylen and max > n * 2 then + return false -- don't create an array with too many holes + end + return true, max +end + +local escapecodes = { + ["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f", + ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t" +} + +local function escapeutf8 (uchar) + local value = escapecodes[uchar] + if value then + return value + end + local a, b, c, d = strbyte (uchar, 1, 4) + a, b, c, d = a or 0, b or 0, c or 0, d or 0 + if a <= 0x7f then + value = a + elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then + value = (a - 0xc0) * 0x40 + b - 0x80 + elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then + value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80 + elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then + value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80 + else + return "" + end + if value <= 0xffff then + return strformat ("\\u%.4x", value) + elseif value <= 0x10ffff then + -- encode as UTF-16 surrogate pair + value = value - 0x10000 + local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400) + return strformat ("\\u%.4x\\u%.4x", highsur, lowsur) + else + return "" + end +end + +local function fsub (str, pattern, repl) + -- gsub always builds a new string in a buffer, even when no match + -- exists. First using find should be more efficient when most strings + -- don't contain the pattern. + if strfind (str, pattern) then + return gsub (str, pattern, repl) + else + return str + end +end + +local function quotestring (value) + -- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js + value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8) + if strfind (value, "[\194\216\220\225\226\239]") then + value = fsub (value, "\194[\128-\159\173]", escapeutf8) + value = fsub (value, "\216[\128-\132]", escapeutf8) + value = fsub (value, "\220\143", escapeutf8) + value = fsub (value, "\225\158[\180\181]", escapeutf8) + value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8) + value = fsub (value, "\226\129[\160-\175]", escapeutf8) + value = fsub (value, "\239\187\191", escapeutf8) + value = fsub (value, "\239\191[\176-\191]", escapeutf8) + end + return "\"" .. value .. "\"" +end +json.quotestring = quotestring + +local function replace(str, o, n) + local i, j = strfind (str, o, 1, true) + if i then + return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1) + else + return str + end +end + +-- locale independent num2str and str2num functions +local decpoint, numfilter + +local function updatedecpoint () + decpoint = strmatch(tostring(0.5), "([^05+])") + -- build a filter that can be used to remove group separators + numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+" +end + +updatedecpoint() + +local function num2str (num) + return replace(fsub(tostring(num), numfilter, ""), decpoint, ".") +end + +local function str2num (str) + local num = tonumber(replace(str, ".", decpoint)) + if not num then + updatedecpoint() + num = tonumber(replace(str, ".", decpoint)) + end + return num +end + +local function addnewline2 (level, buffer, buflen) + buffer[buflen+1] = "\n" + buffer[buflen+2] = strrep (" ", level) + buflen = buflen + 2 + return buflen +end + +function json.addnewline (state) + if state.indent then + state.bufferlen = addnewline2 (state.level or 0, + state.buffer, state.bufferlen or #(state.buffer)) + end +end + +local encode2 -- forward declaration + +local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state) + local kt = type (key) + if kt ~= 'string' and kt ~= 'number' then + return nil, "type '" .. kt .. "' is not supported as a key by JSON." + end + if prev then + buflen = buflen + 1 + buffer[buflen] = "," + end + if indent then + buflen = addnewline2 (level, buffer, buflen) + end + buffer[buflen+1] = quotestring (key) + buffer[buflen+2] = ":" + return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state) +end + +local function appendcustom(res, buffer, state) + local buflen = state.bufferlen + if type (res) == 'string' then + buflen = buflen + 1 + buffer[buflen] = res + end + return buflen +end + +local function exception(reason, value, state, buffer, buflen, defaultmessage) + defaultmessage = defaultmessage or reason + local handler = state.exception + if not handler then + return nil, defaultmessage + else + state.bufferlen = buflen + local ret, msg = handler (reason, value, state, defaultmessage) + if not ret then return nil, msg or defaultmessage end + return appendcustom(ret, buffer, state) + end +end + +function json.encodeexception(reason, value, state, defaultmessage) + return quotestring("<" .. defaultmessage .. ">") +end + +encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state) + local valtype = type (value) + local valmeta = getmetatable (value) + valmeta = type (valmeta) == 'table' and valmeta -- only tables + local valtojson = valmeta and valmeta.__tojson + if valtojson then + if tables[value] then + return exception('reference cycle', value, state, buffer, buflen) + end + tables[value] = true + state.bufferlen = buflen + local ret, msg = valtojson (value, state) + if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end + tables[value] = nil + buflen = appendcustom(ret, buffer, state) + elseif value == nil then + buflen = buflen + 1 + buffer[buflen] = "null" + elseif valtype == 'number' then + local s + if value ~= value or value >= huge or -value >= huge then + -- This is the behaviour of the original JSON implementation. + s = "null" + else + s = num2str (value) + end + buflen = buflen + 1 + buffer[buflen] = s + elseif valtype == 'boolean' then + buflen = buflen + 1 + buffer[buflen] = value and "true" or "false" + elseif valtype == 'string' then + buflen = buflen + 1 + buffer[buflen] = quotestring (value) + elseif valtype == 'table' then + if tables[value] then + return exception('reference cycle', value, state, buffer, buflen) + end + tables[value] = true + level = level + 1 + local isa, n = isarray (value) + if n == 0 and valmeta and valmeta.__jsontype == 'object' then + isa = false + end + local msg + if isa then -- JSON array + buflen = buflen + 1 + buffer[buflen] = "[" + for i = 1, n do + buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state) + if not buflen then return nil, msg end + if i < n then + buflen = buflen + 1 + buffer[buflen] = "," + end + end + buflen = buflen + 1 + buffer[buflen] = "]" + else -- JSON object + local prev = false + buflen = buflen + 1 + buffer[buflen] = "{" + local order = valmeta and valmeta.__jsonorder or globalorder + if order then + local used = {} + n = #order + for i = 1, n do + local k = order[i] + local v = value[k] + if v then + used[k] = true + buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) + prev = true -- add a seperator before the next element + end + end + for k,v in pairs (value) do + if not used[k] then + buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) + if not buflen then return nil, msg end + prev = true -- add a seperator before the next element + end + end + else -- unordered + for k,v in pairs (value) do + buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state) + if not buflen then return nil, msg end + prev = true -- add a seperator before the next element + end + end + if indent then + buflen = addnewline2 (level - 1, buffer, buflen) + end + buflen = buflen + 1 + buffer[buflen] = "}" + end + tables[value] = nil + else + return exception ('unsupported type', value, state, buffer, buflen, + "type '" .. valtype .. "' is not supported by JSON.") + end + return buflen +end + +function json.encode (value, state) + state = state or {} + local oldbuffer = state.buffer + local buffer = oldbuffer or {} + state.buffer = buffer + updatedecpoint() + local ret, msg = encode2 (value, state.indent, state.level or 0, + buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state) + if not ret then + error (msg, 2) + elseif oldbuffer == buffer then + state.bufferlen = ret + return true + else + state.bufferlen = nil + state.buffer = nil + return concat (buffer) + end +end + +local function loc (str, where) + local line, pos, linepos = 1, 1, 0 + while true do + pos = strfind (str, "\n", pos, true) + if pos and pos < where then + line = line + 1 + linepos = pos + pos = pos + 1 + else + break + end + end + return "line " .. line .. ", column " .. (where - linepos) +end + +local function unterminated (str, what, where) + return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where) +end + +local function scanwhite (str, pos) + while true do + pos = strfind (str, "%S", pos) + if not pos then return nil end + local sub2 = strsub (str, pos, pos + 1) + if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then + -- UTF-8 Byte Order Mark + pos = pos + 3 + elseif sub2 == "//" then + pos = strfind (str, "[\n\r]", pos + 2) + if not pos then return nil end + elseif sub2 == "/*" then + pos = strfind (str, "*/", pos + 2) + if not pos then return nil end + pos = pos + 2 + else + return pos + end + end +end + +local escapechars = { + ["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f", + ["n"] = "\n", ["r"] = "\r", ["t"] = "\t" +} + +local function unichar (value) + if value < 0 then + return nil + elseif value <= 0x007f then + return strchar (value) + elseif value <= 0x07ff then + return strchar (0xc0 + floor(value/0x40), + 0x80 + (floor(value) % 0x40)) + elseif value <= 0xffff then + return strchar (0xe0 + floor(value/0x1000), + 0x80 + (floor(value/0x40) % 0x40), + 0x80 + (floor(value) % 0x40)) + elseif value <= 0x10ffff then + return strchar (0xf0 + floor(value/0x40000), + 0x80 + (floor(value/0x1000) % 0x40), + 0x80 + (floor(value/0x40) % 0x40), + 0x80 + (floor(value) % 0x40)) + else + return nil + end +end + +local function scanstring (str, pos) + local lastpos = pos + 1 + local buffer, n = {}, 0 + while true do + local nextpos = strfind (str, "[\"\\]", lastpos) + if not nextpos then + return unterminated (str, "string", pos) + end + if nextpos > lastpos then + n = n + 1 + buffer[n] = strsub (str, lastpos, nextpos - 1) + end + if strsub (str, nextpos, nextpos) == "\"" then + lastpos = nextpos + 1 + break + else + local escchar = strsub (str, nextpos + 1, nextpos + 1) + local value + if escchar == "u" then + value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16) + if value then + local value2 + if 0xD800 <= value and value <= 0xDBff then + -- we have the high surrogate of UTF-16. Check if there is a + -- low surrogate escaped nearby to combine them. + if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then + value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16) + if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then + value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000 + else + value2 = nil -- in case it was out of range for a low surrogate + end + end + end + value = value and unichar (value) + if value then + if value2 then + lastpos = nextpos + 12 + else + lastpos = nextpos + 6 + end + end + end + end + if not value then + value = escapechars[escchar] or escchar + lastpos = nextpos + 2 + end + n = n + 1 + buffer[n] = value + end + end + if n == 1 then + return buffer[1], lastpos + elseif n > 1 then + return concat (buffer), lastpos + else + return "", lastpos + end +end + +local scanvalue -- forward declaration + +local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta) + local len = strlen (str) + local tbl, n = {}, 0 + local pos = startpos + 1 + if what == 'object' then + setmetatable (tbl, objectmeta) + else + setmetatable (tbl, arraymeta) + end + while true do + pos = scanwhite (str, pos) + if not pos then return unterminated (str, what, startpos) end + local char = strsub (str, pos, pos) + if char == closechar then + return tbl, pos + 1 + end + local val1, err + val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta) + if err then return nil, pos, err end + pos = scanwhite (str, pos) + if not pos then return unterminated (str, what, startpos) end + char = strsub (str, pos, pos) + if char == ":" then + if val1 == nil then + return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")" + end + pos = scanwhite (str, pos + 1) + if not pos then return unterminated (str, what, startpos) end + local val2 + val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta) + if err then return nil, pos, err end + tbl[val1] = val2 + pos = scanwhite (str, pos) + if not pos then return unterminated (str, what, startpos) end + char = strsub (str, pos, pos) + else + n = n + 1 + tbl[n] = val1 + end + if char == "," then + pos = pos + 1 + end + end +end + +scanvalue = function (str, pos, nullval, objectmeta, arraymeta) + pos = pos or 1 + pos = scanwhite (str, pos) + if not pos then + return nil, strlen (str) + 1, "no valid JSON value (reached the end)" + end + local char = strsub (str, pos, pos) + if char == "{" then + return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta) + elseif char == "[" then + return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta) + elseif char == "\"" then + return scanstring (str, pos) + else + local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos) + if pstart then + local number = str2num (strsub (str, pstart, pend)) + if number then + return number, pend + 1 + end + end + pstart, pend = strfind (str, "^%a%w*", pos) + if pstart then + local name = strsub (str, pstart, pend) + if name == "true" then + return true, pend + 1 + elseif name == "false" then + return false, pend + 1 + elseif name == "null" then + return nullval, pend + 1 + end + end + return nil, pos, "no valid JSON value at " .. loc (str, pos) + end +end + +local function optionalmetatables(...) + if select("#", ...) > 0 then + return ... + else + return {__jsontype = 'object'}, {__jsontype = 'array'} + end +end + +function json.decode (str, pos, nullval, ...) + local objectmeta, arraymeta = optionalmetatables(...) + return scanvalue (str, pos, nullval, objectmeta, arraymeta) +end + +function json.use_lpeg () + local g = require ("lpeg") + + if g.version() == "0.11" then + error "due to a bug in LPeg 0.11, it cannot be used for JSON matching" + end + + local pegmatch = g.match + local P, S, R = g.P, g.S, g.R + + local function ErrorCall (str, pos, msg, state) + if not state.msg then + state.msg = msg .. " at " .. loc (str, pos) + state.pos = pos + end + return false + end + + local function Err (msg) + return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall) + end + + local SingleLineComment = P"//" * (1 - S"\n\r")^0 + local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/" + local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0 + + local PlainChar = 1 - S"\"\\\n\r" + local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars + local HexDigit = R("09", "af", "AF") + local function UTF16Surrogate (match, pos, high, low) + high, low = tonumber (high, 16), tonumber (low, 16) + if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then + return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000) + else + return false + end + end + local function UTF16BMP (hex) + return unichar (tonumber (hex, 16)) + end + local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit)) + local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP + local Char = UnicodeEscape + EscapeSequence + PlainChar + local String = P"\"" * g.Cs (Char ^ 0) * (P"\"" + Err "unterminated string") + local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0)) + local Fractal = P"." * R"09"^0 + local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1 + local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num + local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1) + local SimpleValue = Number + String + Constant + local ArrayContent, ObjectContent + + -- The functions parsearray and parseobject parse only a single value/pair + -- at a time and store them directly to avoid hitting the LPeg limits. + local function parsearray (str, pos, nullval, state) + local obj, cont + local npos + local t, nt = {}, 0 + repeat + obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state) + if not npos then break end + pos = npos + nt = nt + 1 + t[nt] = obj + until cont == 'last' + return pos, setmetatable (t, state.arraymeta) + end + + local function parseobject (str, pos, nullval, state) + local obj, key, cont + local npos + local t = {} + repeat + key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state) + if not npos then break end + pos = npos + t[key] = obj + until cont == 'last' + return pos, setmetatable (t, state.objectmeta) + end + + local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) * Space * (P"]" + Err "']' expected") + local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) * Space * (P"}" + Err "'}' expected") + local Value = Space * (Array + Object + SimpleValue) + local ExpectedValue = Value + Space * Err "value expected" + ArrayContent = Value * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp() + local Pair = g.Cg (Space * String * Space * (P":" + Err "colon expected") * ExpectedValue) + ObjectContent = Pair * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp() + local DecodeValue = ExpectedValue * g.Cp () + + function json.decode (str, pos, nullval, ...) + local state = {} + state.objectmeta, state.arraymeta = optionalmetatables(...) + local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state) + if state.msg then + return nil, state.pos, state.msg + else + return obj, retpos + end + end + + -- use this function only once: + json.use_lpeg = function () return json end + + json.using_lpeg = true + + return json -- so you can get the module using json = require "dkjson".use_lpeg() +end + +if always_try_using_lpeg then + pcall (json.use_lpeg) +end + +return json diff --git a/widgets/contrib/ccurr.lua b/widgets/contrib/ccurr.lua index f696a35..980e19b 100644 --- a/widgets/contrib/ccurr.lua +++ b/widgets/contrib/ccurr.lua @@ -7,9 +7,9 @@ --]] local newtimer = require("lain.helpers").newtimer +local json = require("lain.util").dkjson local wibox = require("wibox") -local json = require("dkjson") local string = { format = string.format } local tonumber = tonumber diff --git a/widgets/weather.lua b/widgets/weather.lua new file mode 100644 index 0000000..d8dfd3f --- /dev/null +++ b/widgets/weather.lua @@ -0,0 +1,125 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2015, Luke Bonham + +--]] + +local newtimer = require("lain.helpers").newtimer +local async = require("lain.asyncshell") +local json = require("lain.util").dkjson +local lain_icons = require("lain.helpers").icons_dir +local naughty = require("naughty") +local wibox = require("wibox") + +local math = { floor = math.floor } +local string = { format = string.format, + gsub = string.gsub } + +local setmetatable = setmetatable + +-- OpenWeatherMap +-- current weather and X-days forecast +-- lain.widgets.weather + +local function worker(args) + local weather = {} + local args = args or {} + local timeout = args.timeout or 900 -- 15 min + local timeout_forecast = args.timeout or 86400 -- 24 hrs + local current_call = "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s'" + local forecast_call = "curl -s 'http://api.openweathermap.org/data/2.5/forecast/daily?id=%s&units=%s&lang=%s&cnt=%s'" + local city_id = args.city_id + local units = args.units or "metric" + local lang = args.lang or "en" + local cnt = args.cnt or 7 + local date_cmd = args.date_cmd or "date -u -d @%d +'%%a %%d'" + local icons_path = args.icons_path or lain_icons .. "openweathermap/" + local w_notification_preset = args.w_notification_preset or {} + local settings = args.settings or function() end + + weather.widget = wibox.widget.textbox('') + weather.icon = wibox.widget.imagebox() + + function weather.show(t_out) + weather.hide() + weather.notification = naughty.notify({ + text = weather.notification_text, + icon = weather.icon_path, + timeout = t_out, + preset = w_notification_preset + }) + end + + function weather.hide() + if weather.notification ~= nil then + naughty.destroy(weather.notification) + weather.notification = nil + end + end + + function weather.attach(obj) + obj:connect_signal("mouse::enter", function() + weather.show(0) + end) + obj:connect_signal("mouse::leave", function() + weather.hide() + end) + end + + function weather.forecast_update() + local cmd = string.format(forecast_call, city_id, units, lang, cnt) + async.request(cmd, function(f) + j = f:read("*a") + f:close() + weather_now, pos, err = json.decode(j, 1, nil) + + if tonumber(weather_now["cod"]) == 200 then + weather.notification_text = '' + for i = 1, weather_now["cnt"] do + local f = assert(io.popen(string.format(date_cmd, weather_now["list"][i]["dt"]))) + day = string.gsub(f:read("a"), "\n", "") + f:close() + + tmin = math.floor(weather_now["list"][i]["temp"]["min"]) + tmax = math.floor(weather_now["list"][i]["temp"]["max"]) + desc = weather_now["list"][i]["weather"][1]["description"] + + weather.notification_text = weather.notification_text .. + string.format("%s: %s, %d - %d ", day, desc, tmin, tmax) + + if i < weather_now["cnt"] then + weather.notification_text = weather.notification_text .. "\n" + end + end + end + end) + end + + function weather.update() + local cmd = string.format(current_call, city_id, units, lang) + async.request(cmd, function(f) + j = f:read("*a") + f:close() + weather_now, pos, err = json.decode(j, 1, nil) + + if err then + weather.widget.set_text("N/A") + weather.icon:set_image(icons_path .. "na.png") + elseif tonumber(weather_now["cod"]) == 200 then + weather.icon_path = icons_path .. weather_now["weather"][1]["icon"] .. ".png" + weather.icon:set_image(weather.icon_path) + widget = weather.widget + settings() + end + end) + end + + newtimer("weather", timeout, weather.update) + newtimer("weather_forecast", timeout, weather.forecast_update) + + return setmetatable(weather, { __index = weather.widget }) +end + +return setmetatable({}, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/yawn/icons/BlowingSnow.png b/widgets/yawn/icons/BlowingSnow.png deleted file mode 100755 index 6223f8f7d2c1be89dbb216537dbfe0e97e4edd28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11454 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 diff --git a/widgets/yawn/icons/DayFair.png b/widgets/yawn/icons/DayFair.png deleted file mode 120000 index 8ee94d1..0000000 --- a/widgets/yawn/icons/DayFair.png +++ /dev/null @@ -1 +0,0 @@ -DayClear.png \ No newline at end of file diff --git a/widgets/yawn/icons/DayFairWindy.png b/widgets/yawn/icons/DayFairWindy.png deleted file mode 120000 index 8ee94d1..0000000 --- a/widgets/yawn/icons/DayFairWindy.png +++ /dev/null @@ -1 +0,0 @@ -DayClear.png \ No newline at end of file diff --git a/widgets/yawn/icons/Drizzle.png b/widgets/yawn/icons/Drizzle.png deleted file mode 120000 index df34463..0000000 --- a/widgets/yawn/icons/Drizzle.png +++ /dev/null @@ -1 +0,0 @@ -Rain.png \ No newline at end of file diff --git a/widgets/yawn/icons/Fog.png b/widgets/yawn/icons/Fog.png deleted file mode 120000 index b615645..0000000 --- a/widgets/yawn/icons/Fog.png +++ /dev/null @@ -1 +0,0 @@ -Foggy.png \ No newline at end of file diff --git a/widgets/yawn/icons/FreezingDrizzle.png b/widgets/yawn/icons/FreezingDrizzle.png deleted file mode 100755 index 6a661408b9638977477cb5ba28c918f4e9e766c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13166 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
  • S236D+`KjrhMq5Ij+iT7#d>q&))}ssJ4g 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 SkrO_Njs%wG47yPXH|NC%vv9yM4-Q193JUov7 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 diff --git a/widgets/yawn/icons/Mist.png b/widgets/yawn/icons/Mist.png deleted file mode 120000 index b615645..0000000 --- a/widgets/yawn/icons/Mist.png +++ /dev/null @@ -1 +0,0 @@ -Foggy.png \ No newline at end of file diff --git a/widgets/yawn/icons/MixedRainAndHail.png b/widgets/yawn/icons/MixedRainAndHail.png deleted file mode 100755 index 758b01e48eaa6ad27d8b0d692e285a92e90a4ee1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9060 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 F{s-1-Kk5Jg diff --git a/widgets/yawn/icons/MixedRainAndSleet.png b/widgets/yawn/icons/MixedRainAndSleet.png deleted file mode 100755 index 7f0d252565ba1e256fc4fb281eab2ba2fbd1be12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10978 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 IvXbTf?`dGNzKt4V`T=vcm9#$5vHe4?5 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 b@c`k>S|VAx$A*JPDIsNfb-5}T^U(hTcXN<$ diff --git a/widgets/yawn/icons/NightFair.png b/widgets/yawn/icons/NightFair.png deleted file mode 120000 index 23df45a..0000000 --- a/widgets/yawn/icons/NightFair.png +++ /dev/null @@ -1 +0,0 @@ -NightClear.png \ No newline at end of file diff --git a/widgets/yawn/icons/NightFairWindy.png b/widgets/yawn/icons/NightFairWindy.png deleted file mode 120000 index 23df45a..0000000 --- a/widgets/yawn/icons/NightFairWindy.png +++ /dev/null @@ -1 +0,0 @@ -NightClear.png \ No newline at end of file diff --git a/widgets/yawn/icons/README.md b/widgets/yawn/icons/README.md deleted file mode 100644 index e4dc111..0000000 --- a/widgets/yawn/icons/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Yawn icons -========== - -These are [Plain Weather Icons](http://merlinthered.deviantart.com/art/plain-weather-icons-157162192), created by [MerlinTheRed](http://merlinthered.deviantart.com/). - - diff --git a/widgets/yawn/icons/Sleet.png b/widgets/yawn/icons/Sleet.png deleted file mode 120000 index f8f9693..0000000 --- a/widgets/yawn/icons/Sleet.png +++ /dev/null @@ -1 +0,0 @@ -SnowShowers.png \ No newline at end of file diff --git a/widgets/yawn/icons/Snow.png b/widgets/yawn/icons/Snow.png deleted file mode 120000 index f8f9693..0000000 --- a/widgets/yawn/icons/Snow.png +++ /dev/null @@ -1 +0,0 @@ -SnowShowers.png \ No newline at end of file diff --git a/widgets/yawn/icons/SnowFlurries.png b/widgets/yawn/icons/SnowFlurries.png deleted file mode 120000 index 2e090cd..0000000 --- a/widgets/yawn/icons/SnowFlurries.png +++ /dev/null @@ -1 +0,0 @@ -BlowingSnow.png \ No newline at end of file diff --git a/widgets/yawn/icons/SnowShowers.png b/widgets/yawn/icons/SnowShowers.png deleted file mode 100755 index 30534a20d052bbc9c6353dd9eb950f3ea5956954..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9961 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 diff --git a/widgets/yawn/init.lua b/widgets/yawn/init.lua deleted file mode 100644 index 1f6b0f4..0000000 --- a/widgets/yawn/init.lua +++ /dev/null @@ -1,206 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - ---]] - -local newtimer = require("lain.helpers").newtimer -local async = require("lain.asyncshell") - -local naughty = require("naughty") -local wibox = require("wibox") - -local debug = { getinfo = debug.getinfo } -local io = { lines = io.lines, - open = io.open } -local os = { date = os.date, - getenv = os.getenv } -local string = { find = string.find, - match = string.match, - gsub = string.gsub, - sub = string.sub } -local tonumber = tonumber - -local setmetatable = setmetatable - --- YAhoo! Weather Notification --- lain.widgets.yawn -local yawn = -{ - icon = wibox.widget.imagebox(), - widget = wibox.widget.textbox('') -} - -local project_path = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]] -local localizations_path = project_path .. 'localizations/' -local icon_path = project_path .. 'icons/' -local api_url = 'http://weather.yahooapis.com/forecastrss' -local units_set = '?u=c&w=' -- Default is Celsius -local language = string.match(os.getenv("LANG"), "(%S*$*)[.]") or "en_US" -- if LANG is not set -local weather_data = nil -local notification = nil -local city_id = nil -local sky = nil -local settings = function() end - -yawn_notification_preset = {} - -function yawn.fetch_weather() - local url = api_url .. units_set .. city_id - local cmd = "curl --connect-timeout 1 -fsm 3 '" .. url .. "'" - - async.request(cmd, function(f) - local text = f:read("*a") - f:close() - - -- In case of no connection or invalid city ID - -- widgets won't display - if text == "" or text:match("City not found") - then - yawn.icon:set_image(icon_path .. "na.png") - if text == "" then - weather_data = "Service not available at the moment." - yawn.widget:set_text(" N/A ") - else - weather_data = "City not found!\n" .. - "Are you sure " .. city_id .. - " is your Yahoo city ID?" - yawn.widget:set_text(" ? ") - end - return - end - - -- Processing raw data - weather_data = text:gsub("<.->", "") - weather_data = weather_data:match("Current Conditions:.-Full") or "" - - -- may still happens in case of bad connectivity - if weather_data == "" then - yawn.icon:set_image(icon_path .. "na.png") - yawn.widget:set_text(" ? ") - return - end - - weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ") - weather_data = weather_data:gsub("Forecast:.-\n", "") - weather_data = weather_data:gsub("\nFull", "") - weather_data = weather_data:gsub("[\n]$", "") - weather_data = weather_data:gsub(" [-] " , ": ") - weather_data = weather_data:gsub("[.]", ",") - weather_data = weather_data:gsub("High: ", "") - weather_data = weather_data:gsub(" Low: ", " - ") - - -- Getting info for text widget - local now = weather_data:sub(weather_data:find("Now:")+5, - weather_data:find("\n")-1) - forecast = now:sub(1, now:find(",")-1) - units = now:sub(now:find(",")+2, -2) - - -- Day/Night icon change - local hour = tonumber(os.date("%H")) - sky = icon_path - - if string.find(forecast, "Clear") or - string.find(forecast, "Fair") or - string.find(forecast, "Partly Cloudy") or - string.find(forecast, "Mostly Cloudy") - then - if hour >= 6 and hour <= 18 - then - sky = sky .. "Day" - else - sky = sky .. "Night" - end - end - - sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png" - - -- In case there's no defined icon for current forecast - if io.open(sky) == nil then - sky = icon_path .. "na.png" - end - - -- Localization - local f = io.open(localizations_path .. language, "r") - if language:find("en_") == nil and f ~= nil - then - f:close() - for line in io.lines(localizations_path .. language) - do - word = string.sub(line, 1, line:find("|")-1) - translation = string.sub(line, line:find("|")+1) - weather_data = string.gsub(weather_data, word, translation) - end - end - - -- Finally setting infos - yawn.icon:set_image(sky) - widget = yawn.widget - - _data = weather_data:match(": %S.-,") or weather_data - forecast = _data:gsub(": ", ""):gsub(",", "") - units = units:gsub(" ", "") - - settings() - end) -end - -function yawn.hide() - if notification ~= nil then - naughty.destroy(notification) - notification = nil - end -end - -function yawn.show(t_out) - if yawn.widget._layout.text:match("?") - then - yawn.fetch_weather() - end - - yawn.hide() - - notification = naughty.notify({ - preset = yawn_notification_preset, - text = weather_data, - icon = sky, - timeout = t_out, - }) -end - -function yawn.register(id, args) - local args = args or {} - local timeout = args.timeout or 600 - settings = args.settings or function() end - - if args.u == "f" then units_set = '?u=f&w=' end - - city_id = id - - newtimer("yawn", timeout, yawn.fetch_weather) - - yawn.icon:connect_signal("mouse::enter", function() - yawn.show(0) - end) - yawn.icon:connect_signal("mouse::leave", function() - yawn.hide() - end) - - return yawn -end - -function yawn.attach(widget, id, args) - yawn.register(id, args) - - widget:connect_signal("mouse::enter", function() - yawn.show(0) - end) - - widget:connect_signal("mouse::leave", function() - yawn.hide() - end) -end - -return setmetatable(yawn, { __call = function(_, ...) return yawn.register(...) end }) diff --git a/widgets/yawn/localizations/de_DE b/widgets/yawn/localizations/de_DE deleted file mode 100644 index 82cef79..0000000 --- a/widgets/yawn/localizations/de_DE +++ /dev/null @@ -1,61 +0,0 @@ -Now:|Jetzt: -Sun:|So: -Mon:|Mo: -Tue:|Di: -Wed:|Mi: -Thu:|Do: -Fri:|Fr: -Sat:|Sa: -Mostly Sunny|Größtenteils Sonnig -Sunny|Sonnig -Sun|Sonne -Rain/Thunder|Regen/Donner -Isolated Thunderstorms|Vereinzelte Gewitter -Scattered Thunderstorms|Aufgelockertes Gewitter -Thundershowers|Gewitterschauer -Thunderstorms|Gewitter -Thunder in the Vicinity|Donner in der Umgebung -Thunder|Donner -AM|Vormittags -PM|Nachmittags -Early|Früh -Late|Spät -Few|einige -Severe|starker -Clear|Klar -Fair|Heiter -Partly|teilweise -Mostly|größtenteils -Cloudy|Wolkig -Clouds|Wolken -Scattered Showers|Vereinzelte Schauer -Light Snow Showers|Leichter Schneeregen -Snow Showers|Schneeregen -Heavy Snow|Starker Schneefall -Scattered Snow Showers|Vereinzelter Schneefall -Mixed Rain And Snow|Gemischter Regen und Schnee -Mixed Rain And Sleet|Gemischter Regen und Graupel -Mixed Snow And Sleet|Gemischter Schnee und Graupel -Mixed Rain And Hail|Gemischter Regen und Hagel -Snow Flurries|Schneegestöber -Blowing Snow|Schneetreiben -Blowing Rain|Treibender Regen -Heavy Rain|Starke Regenfälle -Freezing Rain|Eisregen -Showers|Schauer -Light Rain|Leichter Regen -Heavy|Starker -Rain|Regen -Windy|Windig -Wind|Wind -Snow|Schnee -Sleet|Graupel -Freezing Drizzle|Gefrierender Sprühregen -Light Drizzle|Leichter Sprühregen -Drizzle|Sprühregen -Hail|Hagel -Fog|Nebel -Foggy|Nebelig -Haze|Dunst -Light|leichter -With|mit \ No newline at end of file diff --git a/widgets/yawn/localizations/fr_FR b/widgets/yawn/localizations/fr_FR deleted file mode 100644 index 18a35bb..0000000 --- a/widgets/yawn/localizations/fr_FR +++ /dev/null @@ -1,61 +0,0 @@ -Now:|Auj: -Sun:|Dim: -Mon:|Lun: -Tue:|Mar: -Wed:|Mer: -Thu:|Jeu: -Fri:|Ven: -Sat:|Sam: -Mostly Sunny|Partiellement ensoleillé -Sunny|Ensoleillé -Sun|Soleil -Rain/Thunder|Pluie/Orage -Isolated Thunderstorms|Orages localisés -Scattered Thunderstorms|Orages épars -Thundershowers|Tempête -Thunderstorms|Orages -Thunder in the Vicinity|Orage aux alentours -Thunder|Orages -AM|Matinée -PM|Après-midi -Early|Tôt -Late|Tard -Few|Quelques -Severe|Sévère -Clear|Clair -Fair|Clair -Partly|Partiellement -Mostly|Très -Cloudy|Nuageux -Clouds|Nuages -Scattered Showers|Nuages épars -Light Snow Showers|Légères averses de neige -Snow Showers|Averses de neige -Heavy Snow|Neige -Scattered Snow Showers|Averses de neige localisées -Mixed Rain And Snow|Alternance de neige et de pluie -Mixed Rain And Sleet|Alternance de pluie et de neige fondue -Mixed Snow And Sleet|Alternance de neige et de neige fondue -Mixed Rain And Hail|Alternance de pluie et de grêle -Snow Flurries|Averses de neige -Blowing Snow|Neige -Blowing Rain|Pluie -Heavy Rain|Pluie forte -Freezing Rain|Pluie verglaçante -Showers|Averses -Light Rain|Pluie légère -Heavy|Forte -Rain|Pluie -Windy|Venteux -Wind|Vent -Snow|Neige -Sleet|Neige fondue -Freezing Drizzle|Bruine verglaçante -Light Drizzle|Légère bruine -Drizzle|Bruine -Hail|Grêle -Fog|Brouillard -Foggy|Brumeux -Haze|Brume -Light|Clair -With|Avec diff --git a/widgets/yawn/localizations/it_IT b/widgets/yawn/localizations/it_IT deleted file mode 100644 index 44d010e..0000000 --- a/widgets/yawn/localizations/it_IT +++ /dev/null @@ -1,61 +0,0 @@ -Now:|Ora: -Sun:|Dom: -Mon:|Lun: -Tue:|Mar: -Wed:|Mer: -Thu:|Gio: -Fri:|Ven: -Sat:|Sab: -Mostly Sunny|Abbastanza Soleggiato -Sunny|Soleggiato -Sun|Soleggiato -Rain/Thunder|Temporali -Isolated Thunderstorms|Temporali Isolati -Scattered Thunderstorms|Temporali Sparsi -Thundershowers|Rovesci Temporaleschi -Thunderstorms|Temporali -Thunder in the Vicinity|Tuoni in prossimità -Thunder|Temporale -AM|In Mattinata -PM|Nel Pomeriggio -Early|In Mattinata -Late|In Serata -Few|Sporadiche -Severe|Forti -Clear|Sereno -Fair|Sereno -Partly|Parzialmente -Mostly|Molto -Cloudy|Nuvoloso -Clouds|Nuvoloso -Scattered Showers|Temporali Sparsi -Light Snow Showers|Nevicate Leggere -Snow Showers|Nevicate -aeavy Snow|Forti Nevicate -Scattered Snow Showers|Nevicate Sparse -Mixed Rain And Snow|Pioggia E Neve -Mixed Rain And Sleet|Pioggia E Nevischio -Mixed Snow And Sleet|Neve E Nevischio -Mixed Rain And Hail|Pioggia E Grandine -Snow Flurries|Folate Di Neve -Blowing Snow|Neve Battente -Blowing Rain|Pioggia Battente -Heavy Rain|Forti Piogge -Freezing Rain|Pioggia Congelantesi -Showers|Piogge -Light Rain|Pioggia Leggera -Heavy|Forti -Rain|Piovoso -Windy|Ventoso -Wind|Ventoso -Snow|Neve -Sleet|Nevischio -Light Drizzle|Pioggia Leggera -Drizzle|Pioggia Leggera -Freezing Drizzle|Pioggerella Congelantesi -Hail|Grandine -Fog|Nebbia -Foggy|Nebbioso -Haze|Nebbia -Light|Leggere -With|Con diff --git a/widgets/yawn/localizations/localization_template b/widgets/yawn/localizations/localization_template deleted file mode 100644 index 2fbf066..0000000 --- a/widgets/yawn/localizations/localization_template +++ /dev/null @@ -1,61 +0,0 @@ -Now:| -Sun:| -Mon:| -Tue:| -Wed:| -Thu:| -Fri:| -Sat:| -Mostly Sunny| -Sunny| -Sun| -Rain/Thunder| -Isolated Thunderstorms| -Scattered Thunderstorms| -Thundershowers| -Thunderstorms| -Thunder in the Vicinity| -Thunder| -AM| -PM| -Early| -Late| -Few| -Severe| -Clear| -Fair| -Partly| -Mostly| -Cloudy| -Clouds| -Scattered Showers| -Light Snow Showers| -Snow Showers| -Heavy Snow| -Scattered Snow Showers| -Mixed Rain And Snow| -Mixed Rain And Sleet| -Mixed Snow And Sleet| -Mixed Rain And Hail| -Snow Flurries| -Blowing Snow| -Blowing Rain| -Heavy Rain| -Freezing Rain| -Showers| -Light Rain| -Heavy| -Rain| -Windy| -Wind| -Snow| -Sleet| -Freezing Drizzle| -Light Drizzle| -Drizzle| -Hail| -Fog| -Foggy| -Haze| -Light| -With| diff --git a/widgets/yawn/localizations/ru_RU b/widgets/yawn/localizations/ru_RU deleted file mode 100644 index 0b2ae23..0000000 --- a/widgets/yawn/localizations/ru_RU +++ /dev/null @@ -1,61 +0,0 @@ -Now:|Cейчас: -Sun:|Воскресенье: -Mon:|Понедельник: -Tue:|Вторник: -Wed:|Среда: -Thu:|Четверг: -Fri:|Пятница: -Sat:|Суббота: -Mostly Sunny|Преимущественно солнечно -Sunny|Солнечно -Sun|Солнце -Rain/Thunder|Дождь/Гром -Isolated Thunderstorms|Изолированные грозы -Scattered Thunderstorms|Рассеянные грозы -Thundershowers|Ливни -Thunderstorms|Грозы -Thunder in the Vicinity|Гром в окрестностях -Thunder|Гром -AM|Утро -PM|Вечер -Early|Рано -Late|Поздно -Few|Мало -Severe|Тяжелый -Clear|Ясно -Fair|Светлый -Partly|Частично -Mostly|По большей части -Cloudy|Облачно -Clouds|Облака -Scattered Showers|Рассеянные ливни -Light Snow Showers|Небольшой снег -Snow Showers|Ливневый Снег -Heavy Snow|Сильный снегопад -Scattered Snow Showers|Рассеянный ливневый снег -Mixed Rain And Snow|Снег с дождём -Mixed Rain And Sleet|Дождь и мокрый снег -Mixed Snow And Sleet|Снег и мокрый снег -Mixed Rain And Hail|Дождь с градом -Snow Flurries|Снежные порывы -Blowing Snow|Снег и ветер -Blowing Rain|Дождь и ветер -Heavy Rain|Сильный дождь -Freezing Rain|Ледяной дождь -Showers|Ливни -Light Rain|Небольшой дождь -Heavy|Сильный -Rain|Дождь -Windy|Ветреный -Wind|Ветер -Snow|Снег -Sleet|Мокрый снег -Freezing Drizzle|Изморозь -Light Drizzle|Лёгкая изморось -Drizzle|Моросящий дождь -Hail|Град -Fog|Туман -Foggy|Туманно -Haze|Дымка -Light|Лёгкий -With|С diff --git a/widgets/yawn/localizations/zh_CN b/widgets/yawn/localizations/zh_CN deleted file mode 100644 index 61e98a4..0000000 --- a/widgets/yawn/localizations/zh_CN +++ /dev/null @@ -1,61 +0,0 @@ -Now:|当前: -Sun:|周日: -Mon:|周一: -Tue:|周二: -Wed:|周三: -Thu:|周四: -Fri:|周五: -Sat:|周六: -Mostly Sunny|晴时多云 -Sunny|晴朗 -Sun|太阳 -Rain/Thunder|雨/雷 -Isolated Thunderstorms|局部雷雨 -Scattered Thunderstorms|零星雷雨 -Thundershowers|雷阵雨 -Thunderstorms|雷雨 -Thunder in the Vicinity|周围有雷雨 -Thunder|雷鸣 -AM|上午 -PM|下午 -Early|早 -Late|晚 -Few|短暂 -Severe|恶劣 -Clear|晴朗 -Fair|晴 -Partly|局部 -Mostly|大部 -Cloudy|多云 -Clouds|有云 -Scattered Showers|零星阵雨 -Light Snow Showers|小阵雪 -Snow Showers|阵雪 -Heavy Snow|大雪 -Scattered Snow Showers|零星阵雪 -Mixed Rain And Snow|雨夹雪 -Mixed Rain And Sleet|雨转雨夹雪 -Mixed Snow And Sleet|雪转雨夹雪 -Mixed Rain And Hail|雨夹冰雹 -Snow Flurries|阵雪 -Blowing Snow|风吹雪 -Blowing Rain|风吹雨 -Heavy Rain|大雨 -Freezing Rain|冻雨 -Showers|阵雨 -Light Rain|小雨 -Heavy|大 -Rain|雨 -Windy|有风 -Wind|风 -Snow|雪 -Sleet|冻雨 -Freezing Drizzle|冻毛毛雨 -Light Drizzle|细雨 -Drizzle|毛毛雨 -Hail|冰雹 -Fog|雾 -Foggy|有雾 -Haze|霾 -Light|小 -With|與 diff --git a/widgets/yawn/localizations/zh_TW b/widgets/yawn/localizations/zh_TW deleted file mode 100644 index 03644c1..0000000 --- a/widgets/yawn/localizations/zh_TW +++ /dev/null @@ -1,61 +0,0 @@ -Now:|現在: -Sun:|週日: -Mon:|週一: -Tue:|週二: -Wed:|週三: -Thu:|週四: -Fri:|週五: -Sat:|週六: -Mostly Sunny|晴時多雲 -Sunny|大太陽 -Sun|太陽 -Rain/Thunder|雨時有雷 -Isolated Thunderstorms|局部雷雨 -Scattered Thunderstorms|零星雷雨 -Thundershowers|雷陣雨 -Thunderstorms|雷雨 -Thunder in the Vicinity|局部性雷雨 -Thunder|雷嗚 -AM|上午 -PM|下午 -Early|早 -Late|晚有 -Few|短暫 -Severe|惡劣 -Clear|晴朗 -Fair|晴 -Partly|局部 -Mostly|大部 -Cloudy|多雲 -Clouds|有雲 -Scattered Showers|零星陣雨 -Light Snow Showers|小陣雪 -Snow Showers|陣雪 -Heavy Snow|大雪 -Scattered Snow Showers|零星陣雪 -Mixed Rain And Snow|雨夾雪 -Mixed Rain And Sleet|雨時雨夾雪 -Mixed Snow And Sleet|雪時雨夾雪 -Mixed Rain And Hail|雨夾冰雹 -Snow Flurries|陣雪 -Blowing Snow|風吹雪 -Blowing Rain|風吹雨 -Heavy Rain|大雨 -Freezing Rain|凍雨 -Showers|陣雨 -Light Rain|小雨 -Heavy|大 -Rain|雨 -Windy|有風 -Wind|風 -Snow|雪 -Sleet|冰珠 -Freezing Drizzle|凍毛毛雨 -Light Drizzle|細雨 -Drizzle|毛毛雨 -Hail|冰雹 -Fog|霧 -Foggy|有霧 -Haze|霾 -Light|小 -With|與 diff --git a/wiki b/wiki index b011c03..75c796a 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit b011c0339e805ee1596d0b6778d6c497dab41109 +Subproject commit 75c796a9a7a0f0f468bd36f77c7b918a2ff9a4d5 From 072ac2e973bb0a289ee608f9adc5a304dcfeb828 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Thu, 2 Jul 2015 12:09:45 +0200 Subject: [PATCH 519/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index 75c796a..6cf15f9 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 75c796a9a7a0f0f468bd36f77c7b918a2ff9a4d5 +Subproject commit 6cf15f990457d3bfa9ac61ee3d57099143d1200d From 95c019cb253f824014a55c48a82b13d8f280bdb5 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 3 Jul 2015 11:56:38 +0200 Subject: [PATCH 520/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index 6cf15f9..b260e93 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 6cf15f990457d3bfa9ac61ee3d57099143d1200d +Subproject commit b260e938c83f1339b0b4b3b003f33f302f9a47b1 From e1450f8828c1be4e290cec0a34538ebe6cb86b50 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 3 Jul 2015 12:17:31 +0200 Subject: [PATCH 521/572] whitespaces cleaning --- helpers.lua | 6 +++--- layout/centerfair.lua | 2 +- layout/uselessfair.lua | 14 +++++++------- layout/uselesspiral.lua | 8 ++++---- layout/uselesstile.lua | 14 +++++++------- util/separators.lua | 4 ++-- widgets/abase.lua | 2 +- widgets/calendar.lua | 4 ++-- widgets/contrib/moc.lua | 8 ++++---- widgets/contrib/redshift.lua | 34 +++++++++++++++++----------------- widgets/contrib/task.lua | 4 ++-- 11 files changed, 50 insertions(+), 50 deletions(-) diff --git a/helpers.lua b/helpers.lua index 9c4a83f..dbee617 100644 --- a/helpers.lua +++ b/helpers.lua @@ -43,12 +43,12 @@ function helpers.file_exists(file) return f ~= nil end --- get all lines from a file, returns an empty +-- get all lines from a file, returns an empty -- list/table if the file does not exist function helpers.lines_from(file) if not helpers.file_exists(file) then return {} end lines = {} - for line in io.lines(file) do + for line in io.lines(file) do lines[#lines + 1] = line end return lines @@ -64,7 +64,7 @@ end -- returns nil otherwise function helpers.first_nonempty_line(file) for k,v in pairs(helpers.lines_from(file)) do - if #v then return v end + if #v then return v end end return nil end diff --git a/layout/centerfair.lua b/layout/centerfair.lua index 67462f7..1e8915d 100644 --- a/layout/centerfair.lua +++ b/layout/centerfair.lua @@ -90,7 +90,7 @@ function centerfair.arrange(p) -- Master client deserves a special treatement local g = {} - g.width = wa.width - (num_x - 1) * width - num_x * 2*useless_gap - 2 + g.width = wa.width - (num_x - 1) * width - num_x * 2*useless_gap - 2 g.height = wa.height - 2*useless_gap - 2 g.x = offset_x + useless_gap + global_border g.y = offset_y + global_border diff --git a/layout/uselessfair.lua b/layout/uselessfair.lua index ee3aa40..e1284e0 100644 --- a/layout/uselessfair.lua +++ b/layout/uselessfair.lua @@ -1,12 +1,12 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2014, projektile, worron - * (c) 2013, Luke Bonham - * (c) 2012, Josh Komoroske - * (c) 2010-2012, Peter Hofmann - + + Licensed under GNU General Public License v2 + * (c) 2014, projektile, worron + * (c) 2013, Luke Bonham + * (c) 2012, Josh Komoroske + * (c) 2010-2012, Peter Hofmann + --]] local beautiful = require("beautiful") diff --git a/layout/uselesspiral.lua b/layout/uselesspiral.lua index ba63bca..c388961 100644 --- a/layout/uselesspiral.lua +++ b/layout/uselesspiral.lua @@ -2,10 +2,10 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2014 projektile - * (c) 2013 Luke Bonham - * (c) 2009 Uli Schlachter - * (c) 2008 Julien Danjolu + * (c) 2014, projektile + * (c) 2013, Luke Bonham + * (c) 2009, Uli Schlachter + * (c) 2008, Julien Danjolu --]] diff --git a/layout/uselesstile.lua b/layout/uselesstile.lua index 877fad1..e48c85d 100644 --- a/layout/uselesstile.lua +++ b/layout/uselesstile.lua @@ -1,12 +1,12 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2014 projektile, worron - * (c) 2013 Luke Bonham - * (c) 2009 Donald Ephraim Curtis - * (c) 2008 Julien Danjolu - + + Licensed under GNU General Public License v2 + * (c) 2014, projektile, worron + * (c) 2013, Luke Bonham + * (c) 2009, Donald Ephraim Curtis + * (c) 2008, Julien Danjolu + --]] local tag = require("awful.tag") diff --git a/util/separators.lua b/util/separators.lua index d2a3891..6e5ef96 100644 --- a/util/separators.lua +++ b/util/separators.lua @@ -2,8 +2,8 @@ --[[ Licensed under GNU General Public License v2 - * (c) 2015, Luke Bonham - * (c) 2015, plotnikovanton + * (c) 2015, Luke Bonham + * (c) 2015, plotnikovanton --]] diff --git a/widgets/abase.lua b/widgets/abase.lua index 075d615..8ffdf0e 100644 --- a/widgets/abase.lua +++ b/widgets/abase.lua @@ -12,7 +12,7 @@ local wibox = require("wibox") local setmetatable = setmetatable --- Basic template for custom widgets +-- Basic template for custom widgets -- Asynchronous version -- lain.widgets.abase diff --git a/widgets/calendar.lua b/widgets/calendar.lua index cc0ebe7..3e65f38 100644 --- a/widgets/calendar.lua +++ b/widgets/calendar.lua @@ -37,7 +37,7 @@ function calendar:show(t_out, inc_offset, scr) local tims = t_out or 0 local f, c_text local today = tonumber(os.date('%d')) - local init_t = calendar.cal .. ' ' .. calendar.post_cal .. ' ' .. + local init_t = calendar.cal .. ' ' .. calendar.post_cal .. ' ' .. ' | sed -r -e "s/_\\x08//g" | sed -r -e "s/(^| )(' calendar.offset = calendar.offset + offs @@ -77,7 +77,7 @@ function calendar:show(t_out, inc_offset, scr) calendar.notify_icon = nil - f = io.popen(calendar.cal .. ' ' .. month .. ' ' .. year .. ' ' .. + f = io.popen(calendar.cal .. ' ' .. month .. ' ' .. year .. ' ' .. calendar.post_cal) end diff --git a/widgets/contrib/moc.lua b/widgets/contrib/moc.lua index 84c618b..cfdbec7 100644 --- a/widgets/contrib/moc.lua +++ b/widgets/contrib/moc.lua @@ -1,9 +1,9 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2014, anticlockwise - + + Licensed under GNU General Public License v2 + * (c) 2014, anticlockwise + --]] local helpers = require("lain.helpers") diff --git a/widgets/contrib/redshift.lua b/widgets/contrib/redshift.lua index 38f1d83..5ed9300 100644 --- a/widgets/contrib/redshift.lua +++ b/widgets/contrib/redshift.lua @@ -1,25 +1,25 @@ --[[ - - Licensed under GNU General Public License v2 - * (c) 2014, blueluke - + + Licensed under GNU General Public License v2 + * (c) 2014, blueluke + --]] -local os = os -local awful = require("awful") -local spawn = awful.util.spawn_with_shell +local awful = require("awful") +local os = os +local spawn = awful.util.spawn_with_shell local setmetatable = setmetatable --- redshift +-- Redshift -- 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() @@ -35,11 +35,11 @@ local function init() end function redshift:toggle() - if running then + if running then -- Sending -USR1 toggles redshift (See project website) os.execute("pkill -USR1 redshift") active = not active - else + else init() end update_fnct() @@ -63,9 +63,9 @@ end -- Attach to a widget -- Provides a button which toggles redshift on/off on click --- @ param widget: widget to attach to --- @ param fnct: function to be run each time redshift is toggled (optional). --- Use it to update widget text or icons on status change. +-- @param widget: Widget to attach to. +-- @param fnct: Function to be run each time redshift is toggled (optional). +-- Use it to update widget text or icons on status change. function redshift:attach(widget, fnct) update_fnct = fnct or function() end if not attached then diff --git a/widgets/contrib/task.lua b/widgets/contrib/task.lua index 2e30cdc..6425926 100644 --- a/widgets/contrib/task.lua +++ b/widgets/contrib/task.lua @@ -59,7 +59,7 @@ function task:prompt_add() mypromptbox[mouse.screen].widget, function (...) local f = io.popen("task add " .. ...) - c_text = "\n" .. f:read("*all") @@ -94,7 +94,7 @@ function task:prompt_search() c_text = "" - .. c_text + .. c_text .. "" end From 8468b88f4a6fd21042253d463c500f6da6f6d2fc Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 3 Jul 2015 18:05:22 +0200 Subject: [PATCH 522/572] weather.forecast_update: forgot to add check on err --- widgets/weather.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/weather.lua b/widgets/weather.lua index d8dfd3f..c69d02b 100644 --- a/widgets/weather.lua +++ b/widgets/weather.lua @@ -75,7 +75,7 @@ local function worker(args) f:close() weather_now, pos, err = json.decode(j, 1, nil) - if tonumber(weather_now["cod"]) == 200 then + if not err and tonumber(weather_now["cod"]) == 200 then weather.notification_text = '' for i = 1, weather_now["cnt"] do local f = assert(io.popen(string.format(date_cmd, weather_now["list"][i]["dt"]))) From 538269c108c4060e4c97cf5bc188299f4db9f4be Mon Sep 17 00:00:00 2001 From: luke bonham Date: Fri, 3 Jul 2015 18:10:03 +0200 Subject: [PATCH 523/572] weather.forecast_update: forgot to add check on err --- widgets/weather.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/weather.lua b/widgets/weather.lua index c69d02b..7223c29 100644 --- a/widgets/weather.lua +++ b/widgets/weather.lua @@ -75,7 +75,7 @@ local function worker(args) f:close() weather_now, pos, err = json.decode(j, 1, nil) - if not err and tonumber(weather_now["cod"]) == 200 then + if not err and weather_now ~= nil and tonumber(weather_now["cod"]) == 200 then weather.notification_text = '' for i = 1, weather_now["cnt"] do local f = assert(io.popen(string.format(date_cmd, weather_now["list"][i]["dt"]))) From fdf8132242195669ee6eeff5e4c91da1c372ee47 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 5 Jul 2015 11:12:41 +0200 Subject: [PATCH 524/572] weather: add back default hover notification; #113 --- widgets/weather.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/widgets/weather.lua b/widgets/weather.lua index 7223c29..7673284 100644 --- a/widgets/weather.lua +++ b/widgets/weather.lua @@ -116,6 +116,8 @@ local function worker(args) end) end + weather.attach(weather.widget) + newtimer("weather", timeout, weather.update) newtimer("weather_forecast", timeout, weather.forecast_update) From e165a3c28990a642f2f8e69d7985752ad60d6de6 Mon Sep 17 00:00:00 2001 From: luke bonham Date: Sun, 5 Jul 2015 11:30:24 +0200 Subject: [PATCH 525/572] weather: added failsafe check; #105 --- widgets/weather.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/widgets/weather.lua b/widgets/weather.lua index 7673284..d1624fa 100644 --- a/widgets/weather.lua +++ b/widgets/weather.lua @@ -30,7 +30,7 @@ local function worker(args) local timeout_forecast = args.timeout or 86400 -- 24 hrs local current_call = "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s'" local forecast_call = "curl -s 'http://api.openweathermap.org/data/2.5/forecast/daily?id=%s&units=%s&lang=%s&cnt=%s'" - local city_id = args.city_id + local city_id = args.city_id or 0 -- placeholder local units = args.units or "metric" local lang = args.lang or "en" local cnt = args.cnt or 7 @@ -93,6 +93,9 @@ local function worker(args) weather.notification_text = weather.notification_text .. "\n" end end + else + weather.icon_path = icons_path .. "na.png" + weather.notification_text = "API/connection error or bad/not set city ID" end end) end @@ -104,14 +107,14 @@ local function worker(args) f:close() weather_now, pos, err = json.decode(j, 1, nil) - if err then - weather.widget.set_text("N/A") - weather.icon:set_image(icons_path .. "na.png") - elseif tonumber(weather_now["cod"]) == 200 then + if not err and weather_now ~= nil and tonumber(weather_now["cod"]) == 200 then weather.icon_path = icons_path .. weather_now["weather"][1]["icon"] .. ".png" weather.icon:set_image(weather.icon_path) widget = weather.widget settings() + else + weather.widget._layout.text = " N/A " -- tries to avoid textbox bugs + weather.icon:set_image(icons_path .. "na.png") end end) end From b9bca04108ebed74c3eb0a2cbee6cfee6263e39a Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 9 Jul 2015 12:52:18 +0200 Subject: [PATCH 526/572] enhancement: unique timers for widgets; #114 --- widgets/alsa.lua | 4 +++- widgets/alsabar.lua | 6 ++++-- widgets/bat.lua | 2 +- widgets/contrib/tpbat/init.lua | 2 +- widgets/fs.lua | 12 ++++++------ widgets/weather.lua | 4 ++-- wiki | 2 +- 7 files changed, 18 insertions(+), 14 deletions(-) diff --git a/widgets/alsa.lua b/widgets/alsa.lua index a356892..979d9fd 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -60,7 +60,9 @@ local function worker(args) settings() end - newtimer("alsa", timeout, alsa.update) + timer_id = string.format("alsa-%s-%s", alsa.cmd, alsa.channel) + + newtimer(timer_id, timeout, alsa.update) return setmetatable(alsa, { __index = alsa.widget }) end diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 1421975..2639aa4 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -148,8 +148,6 @@ local function worker(args) settings() end - newtimer("alsabar", timeout, alsabar.update) - alsabar.bar:buttons (awful.util.table.join ( awful.button ({}, 1, function() awful.util.spawn(alsabar.mixer) @@ -168,6 +166,10 @@ local function worker(args) end) )) + timer_id = string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel) + + newtimer(timer_id, timeout, alsa.update) + return alsabar end diff --git a/widgets/bat.lua b/widgets/bat.lua index 572d099..626239b 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -141,7 +141,7 @@ local function worker(args) end end - newtimer("bat", timeout, update) + newtimer(battery, timeout, update) return bat.widget end diff --git a/widgets/contrib/tpbat/init.lua b/widgets/contrib/tpbat/init.lua index 782bf35..0a22526 100644 --- a/widgets/contrib/tpbat/init.lua +++ b/widgets/contrib/tpbat/init.lua @@ -159,7 +159,7 @@ function tpbat.register(args) settings() end - newtimer("tpbat", timeout, update) + newtimer("tpbat-" .. bat.name, timeout, update) widget:connect_signal('mouse::enter', function () tpbat:show() end) widget:connect_signal('mouse::leave', function () tpbat:hide() end) diff --git a/widgets/fs.lua b/widgets/fs.lua index 8b51178..fab61bd 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -61,7 +61,7 @@ local function worker(args) fs.widget = wibox.widget.textbox('') - helpers.set_map("fs", false) + helpers.set_map(partition, false) function update() fs_info = {} @@ -91,7 +91,7 @@ local function worker(args) widget = fs.widget settings() - if fs_now.used >= 99 and not helpers.get_map("fs") + if fs_now.used >= 99 and not helpers.get_map(partition) then naughty.notify({ title = "warning", @@ -100,17 +100,17 @@ local function worker(args) fg = "#000000", bg = "#FFFFFF", }) - helpers.set_map("fs", true) + helpers.set_map(partition, true) else - helpers.set_map("fs", false) + helpers.set_map(partition, false) end end - helpers.newtimer(partition, timeout, update) - widget:connect_signal('mouse::enter', function () fs:show(0) end) widget:connect_signal('mouse::leave', function () fs:hide() end) + helpers.newtimer(partition, timeout, update) + return setmetatable(fs, { __index = fs.widget }) end diff --git a/widgets/weather.lua b/widgets/weather.lua index d1624fa..77d9b9b 100644 --- a/widgets/weather.lua +++ b/widgets/weather.lua @@ -121,8 +121,8 @@ local function worker(args) weather.attach(weather.widget) - newtimer("weather", timeout, weather.update) - newtimer("weather_forecast", timeout, weather.forecast_update) + newtimer("weather-" .. city_id, timeout, weather.update) + newtimer("weather_forecast" .. city_id, timeout, weather.forecast_update) return setmetatable(weather, { __index = weather.widget }) end diff --git a/wiki b/wiki index b260e93..54b3a71 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit b260e938c83f1339b0b4b3b003f33f302f9a47b1 +Subproject commit 54b3a717b2f7069264ce5a20018ae4abf153e7b2 From 6457c4d2c3aebf318a53489189cb638c00d291be Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Thu, 9 Jul 2015 12:53:08 +0200 Subject: [PATCH 527/572] enhancement: unique timers for widgets; #114 --- widgets/alsabar.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 2639aa4..8ec5a00 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -168,7 +168,7 @@ local function worker(args) timer_id = string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel) - newtimer(timer_id, timeout, alsa.update) + newtimer(timer_id, timeout, alsabar.update) return alsabar end From 7af06fff37b5da6ff625e7c1f39306fe7cc04a91 Mon Sep 17 00:00:00 2001 From: aajjbb Date: Sat, 11 Jul 2015 14:19:12 -0300 Subject: [PATCH 528/572] fixing small typo in fs widget which lead to nil reference --- widgets/fs.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/fs.lua b/widgets/fs.lua index fab61bd..951f0cc 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -106,8 +106,8 @@ local function worker(args) end end - widget:connect_signal('mouse::enter', function () fs:show(0) end) - widget:connect_signal('mouse::leave', function () fs:hide() end) + fs.widget:connect_signal('mouse::enter', function () fs:show(0) end) + fs.widget:connect_signal('mouse::leave', function () fs:hide() end) helpers.newtimer(partition, timeout, update) From e815650ecceedc5e6b68d8e5571ed8839d1c8d3d Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 12 Jul 2015 11:22:10 +0200 Subject: [PATCH 529/572] uniform timers for single-instance widgets; #114 --- widgets/alsabar.lua | 4 ++-- widgets/cpu.lua | 2 +- widgets/mem.lua | 2 +- widgets/sysload.lua | 2 +- widgets/temp.lua | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index 8ec5a00..c957dbb 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -56,7 +56,7 @@ function alsabar.notify() local preset = { title = "", text = "", - timeout = 4, + timeout = 5, screen = alsabar.notifications.screen, font = alsabar.notifications.font .. " " .. alsabar.notifications.font_size, @@ -90,7 +90,7 @@ end local function worker(args) local args = args or {} - local timeout = args.timeout or 4 + local timeout = args.timeout or 5 local settings = args.settings or function() end local width = args.width or 63 local height = args.heigth or 1 diff --git a/widgets/cpu.lua b/widgets/cpu.lua index 7c1ecb0..ec84101 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -28,7 +28,7 @@ local cpu = { local function worker(args) local args = args or {} - local timeout = args.timeout or 5 + local timeout = args.timeout or 2 local settings = args.settings or function() end cpu.widget = wibox.widget.textbox('') diff --git a/widgets/mem.lua b/widgets/mem.lua index 46bb5f9..f6213b2 100644 --- a/widgets/mem.lua +++ b/widgets/mem.lua @@ -23,7 +23,7 @@ local mem = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 3 + local timeout = args.timeout or 2 local settings = args.settings or function() end mem.widget = wibox.widget.textbox('') diff --git a/widgets/sysload.lua b/widgets/sysload.lua index 144ad0c..b10c5e2 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -22,7 +22,7 @@ local sysload = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 5 + local timeout = args.timeout or 2 local settings = args.settings or function() end sysload.widget = wibox.widget.textbox('') diff --git a/widgets/temp.lua b/widgets/temp.lua index 5994f59..1e93848 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -21,7 +21,7 @@ local temp = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 5 + local timeout = args.timeout or 2 local tempfile = args.tempfile or "/sys/class/thermal/thermal_zone0/temp" local settings = args.settings or function() end From f6cc2aedd67c1b63f14b8975ccb9a815d04117f6 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 12 Jul 2015 11:51:58 +0200 Subject: [PATCH 530/572] mpd: added http streams check; #115 --- widgets/mpd.lua | 12 +++++++++--- wiki | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index c10eb78..6b66f81 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -89,12 +89,18 @@ local function worker(args) then helpers.set_map("current mpd track", mpd_now.title) - os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir, - mpd_now.file, cover_size, default_art)) + if string.match(mpd_now.file, "http://") == nil + then -- local file + os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir, + mpd_now.file, cover_size, default_art)) + current_icon = "/tmp/mpdcover.png" + else -- http stream + current_icon = default_art + end mpd.id = naughty.notify({ preset = mpd_notification_preset, - icon = "/tmp/mpdcover.png", + icon = current_icon, replaces_id = mpd.id, }).id end diff --git a/wiki b/wiki index 54b3a71..4021f24 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 54b3a717b2f7069264ce5a20018ae4abf153e7b2 +Subproject commit 4021f24b33be60d2e6b4050098bd8da131648a7e From 0d5ac3cb2c730821c609c93caf446c5e58a3a7d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:44:40 -0300 Subject: [PATCH 531/572] Delete asyncshell_REMOTE_32072.lua --- asyncshell_REMOTE_32072.lua | 72 ------------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 asyncshell_REMOTE_32072.lua diff --git a/asyncshell_REMOTE_32072.lua b/asyncshell_REMOTE_32072.lua deleted file mode 100644 index 827cf4b..0000000 --- a/asyncshell_REMOTE_32072.lua +++ /dev/null @@ -1,72 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2015, worron - * (c) 2013, Alexander Yakushev - ---]] - --- Asynchronous io.popen for Awesome WM. --- How to use: --- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end) - --- Grab environment -local awful = require('awful') - --- Initialize tables for module -asyncshell = { request_table = {}, id_counter = 0 } - --- Request counter -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 10000 - return asyncshell.id_counter -end - --- Remove given request -function asyncshell.clear(id) - if asyncshell.request_table[id] then - if asyncshell.request_table[id].timer then - asyncshell.request_table[id].timer:stop() - asyncshell.request_table[id].timer = nil - end - asyncshell.request_table[id] = nil - end -end - --- Sends an asynchronous request for an output of the shell command --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @param timeout Maximum amount of time to wait for the result (optional) -function asyncshell.request(command, callback, timeout) - local id = next_id() - asyncshell.request_table[id] = { callback = callback } - - local formatted_command = string.gsub(command, '"','\"') - - local req = string.format( - "echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &", - id, formatted_command - ) - - awful.util.spawn_with_shell(req) - - if timeout then - asyncshell.request_table[id].timer = timer({ timeout = timeout }) - asyncshell.request_table[id].timer:connect_signal("timeout", function() asyncshell.clear(id) end) - asyncshell.request_table[id].timer:start() - end -end - --- Calls the remembered callback function on the output of the shell command --- @param id Request ID --- @param output Shell command output to be delievered -function asyncshell.deliver(id, output) - local output = string.sub(output, 2, -2) - if asyncshell.request_table[id] then - asyncshell.request_table[id].callback(output) - asyncshell.clear(id) - end -end - -return asyncshell From becc25c5888a21377e1757aa7ba3e016795cdd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:44:49 -0300 Subject: [PATCH 532/572] Delete asyncshell_REMOTE_1080.lua --- asyncshell_REMOTE_1080.lua | 72 -------------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 asyncshell_REMOTE_1080.lua diff --git a/asyncshell_REMOTE_1080.lua b/asyncshell_REMOTE_1080.lua deleted file mode 100644 index 827cf4b..0000000 --- a/asyncshell_REMOTE_1080.lua +++ /dev/null @@ -1,72 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2015, worron - * (c) 2013, Alexander Yakushev - ---]] - --- Asynchronous io.popen for Awesome WM. --- How to use: --- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end) - --- Grab environment -local awful = require('awful') - --- Initialize tables for module -asyncshell = { request_table = {}, id_counter = 0 } - --- Request counter -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 10000 - return asyncshell.id_counter -end - --- Remove given request -function asyncshell.clear(id) - if asyncshell.request_table[id] then - if asyncshell.request_table[id].timer then - asyncshell.request_table[id].timer:stop() - asyncshell.request_table[id].timer = nil - end - asyncshell.request_table[id] = nil - end -end - --- Sends an asynchronous request for an output of the shell command --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @param timeout Maximum amount of time to wait for the result (optional) -function asyncshell.request(command, callback, timeout) - local id = next_id() - asyncshell.request_table[id] = { callback = callback } - - local formatted_command = string.gsub(command, '"','\"') - - local req = string.format( - "echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &", - id, formatted_command - ) - - awful.util.spawn_with_shell(req) - - if timeout then - asyncshell.request_table[id].timer = timer({ timeout = timeout }) - asyncshell.request_table[id].timer:connect_signal("timeout", function() asyncshell.clear(id) end) - asyncshell.request_table[id].timer:start() - end -end - --- Calls the remembered callback function on the output of the shell command --- @param id Request ID --- @param output Shell command output to be delievered -function asyncshell.deliver(id, output) - local output = string.sub(output, 2, -2) - if asyncshell.request_table[id] then - asyncshell.request_table[id].callback(output) - asyncshell.clear(id) - end -end - -return asyncshell From 2c6bec4ae463f4ca2ef60f8efe30509f75cbdcb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:44:57 -0300 Subject: [PATCH 533/572] Delete asyncshell_LOCAL_32072.lua --- asyncshell_LOCAL_32072.lua | 79 -------------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 asyncshell_LOCAL_32072.lua diff --git a/asyncshell_LOCAL_32072.lua b/asyncshell_LOCAL_32072.lua deleted file mode 100644 index 0aafa17..0000000 --- a/asyncshell_LOCAL_32072.lua +++ /dev/null @@ -1,79 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Alexander Yakushev - ---]] - --- Asynchronous io.popen for Awesome WM. --- How to use... --- ...asynchronously: --- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end) --- ...synchronously: --- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error") - -local spawn = require('awful.util').spawn - -asyncshell = {} -asyncshell.request_table = {} -asyncshell.id_counter = 0 -asyncshell.folder = "/tmp/asyncshell" -asyncshell.file_template = asyncshell.folder .. '/req' - --- Create a directory for asynchell response files -os.execute("mkdir -p " .. asyncshell.folder) - --- Returns next tag - unique identifier of the request -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000 - return asyncshell.id_counter -end - --- Sends an asynchronous request for an output of the shell command. --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @return Request ID -function asyncshell.request(command, callback) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - asyncshell.request_table[id] = { callback = callback } - local req = - string.format("sh -c '%s > %s; " .. - 'echo "asyncshell.deliver(%s)" | ' .. - "awesome-client' 2> /dev/null", - string.gsub(command, "'", "'\\''"), tmpfname, id) - spawn(req, false) - return id -end - --- Calls the remembered callback function on the output of the shell --- command. --- @param id Request ID --- @param output The output file of the shell command to be delievered -function asyncshell.deliver(id) - if asyncshell.request_table[id] and - asyncshell.request_table[id].callback then - local output = io.open(asyncshell.file_template .. id, 'r') - asyncshell.request_table[id].callback(output) - end -end - --- Sends a synchronous request for an output of the command. Waits for --- the output, but if the given timeout expires returns nil. --- @param command Command to be executed and taken output from --- @param timeout Maximum amount of time to wait for the result --- @return File handler on success, nil otherwise -function asyncshell.demand(command, timeout) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " .. - "(sleep %s; echo asynchell_timeout)", - command, tmpfname, timeout)) - local result = f:read("*line") - if result == "asyncshell_done" then - return io.open(tmpfname) - end -end - -return asyncshell From 6f7dae29dc64fb5adc5677d24eaba90ea54510f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:45:06 -0300 Subject: [PATCH 534/572] Delete asyncshell_BACKUP_1080.lua --- asyncshell_BACKUP_1080.lua | 145 ------------------------------------- 1 file changed, 145 deletions(-) delete mode 100644 asyncshell_BACKUP_1080.lua diff --git a/asyncshell_BACKUP_1080.lua b/asyncshell_BACKUP_1080.lua deleted file mode 100644 index 5c6e7e8..0000000 --- a/asyncshell_BACKUP_1080.lua +++ /dev/null @@ -1,145 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 -<<<<<<< HEAD -======= - * (c) 2015, worron ->>>>>>> upstream/master - * (c) 2013, Alexander Yakushev - ---]] - --- Asynchronous io.popen for Awesome WM. -<<<<<<< HEAD --- How to use... --- ...asynchronously: --- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end) --- ...synchronously: --- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error") - -local spawn = require('awful.util').spawn - -asyncshell = {} -asyncshell.request_table = {} -asyncshell.id_counter = 0 -asyncshell.folder = "/tmp/asyncshell" -asyncshell.file_template = asyncshell.folder .. '/req' - --- Create a directory for asynchell response files -os.execute("mkdir -p " .. asyncshell.folder) - --- Returns next tag - unique identifier of the request -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000 - return asyncshell.id_counter -end - --- Sends an asynchronous request for an output of the shell command. --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @return Request ID -function asyncshell.request(command, callback) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - asyncshell.request_table[id] = { callback = callback } - local req = - string.format("sh -c '%s > %s; " .. - 'echo "asyncshell.deliver(%s)" | ' .. - "awesome-client' 2> /dev/null", - string.gsub(command, "'", "'\\''"), tmpfname, id) - spawn(req, false) - return id -end - --- Calls the remembered callback function on the output of the shell --- command. --- @param id Request ID --- @param output The output file of the shell command to be delievered -function asyncshell.deliver(id) - if asyncshell.request_table[id] and - asyncshell.request_table[id].callback then - local output = io.open(asyncshell.file_template .. id, 'r') - asyncshell.request_table[id].callback(output) - end -end - --- Sends a synchronous request for an output of the command. Waits for --- the output, but if the given timeout expires returns nil. --- @param command Command to be executed and taken output from --- @param timeout Maximum amount of time to wait for the result --- @return File handler on success, nil otherwise -function asyncshell.demand(command, timeout) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " .. - "(sleep %s; echo asynchell_timeout)", - command, tmpfname, timeout)) - local result = f:read("*line") - if result == "asyncshell_done" then - return io.open(tmpfname) - end -======= --- How to use: --- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end) - --- Grab environment -local awful = require('awful') - --- Initialize tables for module -asyncshell = { request_table = {}, id_counter = 0 } - --- Request counter -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 10000 - return asyncshell.id_counter -end - --- Remove given request -function asyncshell.clear(id) - if asyncshell.request_table[id] then - if asyncshell.request_table[id].timer then - asyncshell.request_table[id].timer:stop() - asyncshell.request_table[id].timer = nil - end - asyncshell.request_table[id] = nil - end -end - --- Sends an asynchronous request for an output of the shell command --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @param timeout Maximum amount of time to wait for the result (optional) -function asyncshell.request(command, callback, timeout) - local id = next_id() - asyncshell.request_table[id] = { callback = callback } - - local formatted_command = string.gsub(command, '"','\"') - - local req = string.format( - "echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &", - id, formatted_command - ) - - awful.util.spawn_with_shell(req) - - if timeout then - asyncshell.request_table[id].timer = timer({ timeout = timeout }) - asyncshell.request_table[id].timer:connect_signal("timeout", function() asyncshell.clear(id) end) - asyncshell.request_table[id].timer:start() - end -end - --- Calls the remembered callback function on the output of the shell command --- @param id Request ID --- @param output Shell command output to be delievered -function asyncshell.deliver(id, output) - local output = string.sub(output, 2, -2) - if asyncshell.request_table[id] then - asyncshell.request_table[id].callback(output) - asyncshell.clear(id) - end ->>>>>>> upstream/master -end - -return asyncshell From 51cdffaf5ef8afddf92effb9fde6d67c77f0e43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:45:14 -0300 Subject: [PATCH 535/572] Delete asyncshell_BACKUP_32072.lua --- asyncshell_BACKUP_32072.lua | 145 ------------------------------------ 1 file changed, 145 deletions(-) delete mode 100644 asyncshell_BACKUP_32072.lua diff --git a/asyncshell_BACKUP_32072.lua b/asyncshell_BACKUP_32072.lua deleted file mode 100644 index 5c6e7e8..0000000 --- a/asyncshell_BACKUP_32072.lua +++ /dev/null @@ -1,145 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 -<<<<<<< HEAD -======= - * (c) 2015, worron ->>>>>>> upstream/master - * (c) 2013, Alexander Yakushev - ---]] - --- Asynchronous io.popen for Awesome WM. -<<<<<<< HEAD --- How to use... --- ...asynchronously: --- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end) --- ...synchronously: --- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error") - -local spawn = require('awful.util').spawn - -asyncshell = {} -asyncshell.request_table = {} -asyncshell.id_counter = 0 -asyncshell.folder = "/tmp/asyncshell" -asyncshell.file_template = asyncshell.folder .. '/req' - --- Create a directory for asynchell response files -os.execute("mkdir -p " .. asyncshell.folder) - --- Returns next tag - unique identifier of the request -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000 - return asyncshell.id_counter -end - --- Sends an asynchronous request for an output of the shell command. --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @return Request ID -function asyncshell.request(command, callback) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - asyncshell.request_table[id] = { callback = callback } - local req = - string.format("sh -c '%s > %s; " .. - 'echo "asyncshell.deliver(%s)" | ' .. - "awesome-client' 2> /dev/null", - string.gsub(command, "'", "'\\''"), tmpfname, id) - spawn(req, false) - return id -end - --- Calls the remembered callback function on the output of the shell --- command. --- @param id Request ID --- @param output The output file of the shell command to be delievered -function asyncshell.deliver(id) - if asyncshell.request_table[id] and - asyncshell.request_table[id].callback then - local output = io.open(asyncshell.file_template .. id, 'r') - asyncshell.request_table[id].callback(output) - end -end - --- Sends a synchronous request for an output of the command. Waits for --- the output, but if the given timeout expires returns nil. --- @param command Command to be executed and taken output from --- @param timeout Maximum amount of time to wait for the result --- @return File handler on success, nil otherwise -function asyncshell.demand(command, timeout) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " .. - "(sleep %s; echo asynchell_timeout)", - command, tmpfname, timeout)) - local result = f:read("*line") - if result == "asyncshell_done" then - return io.open(tmpfname) - end -======= --- How to use: --- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end) - --- Grab environment -local awful = require('awful') - --- Initialize tables for module -asyncshell = { request_table = {}, id_counter = 0 } - --- Request counter -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 10000 - return asyncshell.id_counter -end - --- Remove given request -function asyncshell.clear(id) - if asyncshell.request_table[id] then - if asyncshell.request_table[id].timer then - asyncshell.request_table[id].timer:stop() - asyncshell.request_table[id].timer = nil - end - asyncshell.request_table[id] = nil - end -end - --- Sends an asynchronous request for an output of the shell command --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @param timeout Maximum amount of time to wait for the result (optional) -function asyncshell.request(command, callback, timeout) - local id = next_id() - asyncshell.request_table[id] = { callback = callback } - - local formatted_command = string.gsub(command, '"','\"') - - local req = string.format( - "echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &", - id, formatted_command - ) - - awful.util.spawn_with_shell(req) - - if timeout then - asyncshell.request_table[id].timer = timer({ timeout = timeout }) - asyncshell.request_table[id].timer:connect_signal("timeout", function() asyncshell.clear(id) end) - asyncshell.request_table[id].timer:start() - end -end - --- Calls the remembered callback function on the output of the shell command --- @param id Request ID --- @param output Shell command output to be delievered -function asyncshell.deliver(id, output) - local output = string.sub(output, 2, -2) - if asyncshell.request_table[id] then - asyncshell.request_table[id].callback(output) - asyncshell.clear(id) - end ->>>>>>> upstream/master -end - -return asyncshell From 0a23f7826f0a9fd027f2ac7b49bb95389426c116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:45:23 -0300 Subject: [PATCH 536/572] Delete asyncshell_BASE_32072.lua --- asyncshell_BASE_32072.lua | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 asyncshell_BASE_32072.lua diff --git a/asyncshell_BASE_32072.lua b/asyncshell_BASE_32072.lua deleted file mode 100644 index e69de29..0000000 From fd82b1dabac8a156142d303b5042ba6ed23e906a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:45:30 -0300 Subject: [PATCH 537/572] Delete asyncshell_LOCAL_1080.lua --- asyncshell_LOCAL_1080.lua | 79 --------------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 asyncshell_LOCAL_1080.lua diff --git a/asyncshell_LOCAL_1080.lua b/asyncshell_LOCAL_1080.lua deleted file mode 100644 index 0aafa17..0000000 --- a/asyncshell_LOCAL_1080.lua +++ /dev/null @@ -1,79 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Alexander Yakushev - ---]] - --- Asynchronous io.popen for Awesome WM. --- How to use... --- ...asynchronously: --- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end) --- ...synchronously: --- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error") - -local spawn = require('awful.util').spawn - -asyncshell = {} -asyncshell.request_table = {} -asyncshell.id_counter = 0 -asyncshell.folder = "/tmp/asyncshell" -asyncshell.file_template = asyncshell.folder .. '/req' - --- Create a directory for asynchell response files -os.execute("mkdir -p " .. asyncshell.folder) - --- Returns next tag - unique identifier of the request -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000 - return asyncshell.id_counter -end - --- Sends an asynchronous request for an output of the shell command. --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @return Request ID -function asyncshell.request(command, callback) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - asyncshell.request_table[id] = { callback = callback } - local req = - string.format("sh -c '%s > %s; " .. - 'echo "asyncshell.deliver(%s)" | ' .. - "awesome-client' 2> /dev/null", - string.gsub(command, "'", "'\\''"), tmpfname, id) - spawn(req, false) - return id -end - --- Calls the remembered callback function on the output of the shell --- command. --- @param id Request ID --- @param output The output file of the shell command to be delievered -function asyncshell.deliver(id) - if asyncshell.request_table[id] and - asyncshell.request_table[id].callback then - local output = io.open(asyncshell.file_template .. id, 'r') - asyncshell.request_table[id].callback(output) - end -end - --- Sends a synchronous request for an output of the command. Waits for --- the output, but if the given timeout expires returns nil. --- @param command Command to be executed and taken output from --- @param timeout Maximum amount of time to wait for the result --- @return File handler on success, nil otherwise -function asyncshell.demand(command, timeout) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " .. - "(sleep %s; echo asynchell_timeout)", - command, tmpfname, timeout)) - local result = f:read("*line") - if result == "asyncshell_done" then - return io.open(tmpfname) - end -end - -return asyncshell From f91084371eb3559824a512bb6a7821a5c315ed3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:45:37 -0300 Subject: [PATCH 538/572] Delete asyncshell_BASE_1080.lua --- asyncshell_BASE_1080.lua | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 asyncshell_BASE_1080.lua diff --git a/asyncshell_BASE_1080.lua b/asyncshell_BASE_1080.lua deleted file mode 100644 index e69de29..0000000 From fe3e3afc0597aa7344e97109f883a2ae351e493d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:45:44 -0300 Subject: [PATCH 539/572] Delete asyncshell.lua.orig --- asyncshell.lua.orig | 145 -------------------------------------------- 1 file changed, 145 deletions(-) delete mode 100644 asyncshell.lua.orig diff --git a/asyncshell.lua.orig b/asyncshell.lua.orig deleted file mode 100644 index 5c6e7e8..0000000 --- a/asyncshell.lua.orig +++ /dev/null @@ -1,145 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 -<<<<<<< HEAD -======= - * (c) 2015, worron ->>>>>>> upstream/master - * (c) 2013, Alexander Yakushev - ---]] - --- Asynchronous io.popen for Awesome WM. -<<<<<<< HEAD --- How to use... --- ...asynchronously: --- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end) --- ...synchronously: --- widget:set_text(asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error") - -local spawn = require('awful.util').spawn - -asyncshell = {} -asyncshell.request_table = {} -asyncshell.id_counter = 0 -asyncshell.folder = "/tmp/asyncshell" -asyncshell.file_template = asyncshell.folder .. '/req' - --- Create a directory for asynchell response files -os.execute("mkdir -p " .. asyncshell.folder) - --- Returns next tag - unique identifier of the request -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000 - return asyncshell.id_counter -end - --- Sends an asynchronous request for an output of the shell command. --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @return Request ID -function asyncshell.request(command, callback) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - asyncshell.request_table[id] = { callback = callback } - local req = - string.format("sh -c '%s > %s; " .. - 'echo "asyncshell.deliver(%s)" | ' .. - "awesome-client' 2> /dev/null", - string.gsub(command, "'", "'\\''"), tmpfname, id) - spawn(req, false) - return id -end - --- Calls the remembered callback function on the output of the shell --- command. --- @param id Request ID --- @param output The output file of the shell command to be delievered -function asyncshell.deliver(id) - if asyncshell.request_table[id] and - asyncshell.request_table[id].callback then - local output = io.open(asyncshell.file_template .. id, 'r') - asyncshell.request_table[id].callback(output) - end -end - --- Sends a synchronous request for an output of the command. Waits for --- the output, but if the given timeout expires returns nil. --- @param command Command to be executed and taken output from --- @param timeout Maximum amount of time to wait for the result --- @return File handler on success, nil otherwise -function asyncshell.demand(command, timeout) - local id = next_id() - local tmpfname = asyncshell.file_template .. id - local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " .. - "(sleep %s; echo asynchell_timeout)", - command, tmpfname, timeout)) - local result = f:read("*line") - if result == "asyncshell_done" then - return io.open(tmpfname) - end -======= --- How to use: --- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end) - --- Grab environment -local awful = require('awful') - --- Initialize tables for module -asyncshell = { request_table = {}, id_counter = 0 } - --- Request counter -local function next_id() - asyncshell.id_counter = (asyncshell.id_counter + 1) % 10000 - return asyncshell.id_counter -end - --- Remove given request -function asyncshell.clear(id) - if asyncshell.request_table[id] then - if asyncshell.request_table[id].timer then - asyncshell.request_table[id].timer:stop() - asyncshell.request_table[id].timer = nil - end - asyncshell.request_table[id] = nil - end -end - --- Sends an asynchronous request for an output of the shell command --- @param command Command to be executed and taken output from --- @param callback Function to be called when the command finishes --- @param timeout Maximum amount of time to wait for the result (optional) -function asyncshell.request(command, callback, timeout) - local id = next_id() - asyncshell.request_table[id] = { callback = callback } - - local formatted_command = string.gsub(command, '"','\"') - - local req = string.format( - "echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &", - id, formatted_command - ) - - awful.util.spawn_with_shell(req) - - if timeout then - asyncshell.request_table[id].timer = timer({ timeout = timeout }) - asyncshell.request_table[id].timer:connect_signal("timeout", function() asyncshell.clear(id) end) - asyncshell.request_table[id].timer:start() - end -end - --- Calls the remembered callback function on the output of the shell command --- @param id Request ID --- @param output Shell command output to be delievered -function asyncshell.deliver(id, output) - local output = string.sub(output, 2, -2) - if asyncshell.request_table[id] then - asyncshell.request_table[id].callback(output) - asyncshell.clear(id) - end ->>>>>>> upstream/master -end - -return asyncshell From 57490f19d69f7686b59fb17b19b3cb4967be0653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeferson=20Lesb=C3=A3o=20de=20Siqueira?= Date: Mon, 24 Aug 2015 17:45:53 -0300 Subject: [PATCH 540/572] Delete README.rst.orig --- README.rst.orig | 55 ------------------------------------------------- 1 file changed, 55 deletions(-) delete mode 100644 README.rst.orig diff --git a/README.rst.orig b/README.rst.orig deleted file mode 100644 index 7c6d786..0000000 --- a/README.rst.orig +++ /dev/null @@ -1,55 +0,0 @@ -Lain -==== - --------------------------------------------------- -Layouts, widgets and utilities for Awesome WM 3.5+ --------------------------------------------------- - -:Author: Luke Bonham -:Version: git -<<<<<<< HEAD -:License: GNU-GPLv2_ -======= -:License: GNU-GPL2_ ->>>>>>> upstream/master -:Source: https://github.com/copycat-killer/lain - -Description ------------ - -Successor of awesome-vain_, this module provides new layouts, a set of widgets and utility functions, in order to improve Awesome_ usability and configurability. - -Read the wiki_ for all the info. - -Contributions -------------- - -Any contribution is welcome! Feel free to make a pull request. - -Just make sure that: - -- Your code fits with the general style of the module. In particular, you should use the same indentation pattern that the code uses, and also avoid adding space at the ends of lines. - -- Your code its easy to understand, maintainable, and modularized. You should also avoid code duplication wherever possible by adding functions or using ``lain.helpers``. If something is unclear, and you can't write it in such a way that it will be clear, explain it with a comment. - -- You test your changes before submitting to make sure that not only your code works, but did not break other parts of the module too! - -- You eventually update ``wiki`` submodule with a thorough section. - -Contributed widgets have to be put in ``lain/widgets/contrib``. - -Screenshots ------------ - -.. image:: http://i.imgur.com/8D9A7lW.png -.. image:: http://i.imgur.com/9Iv3OR3.png -.. image:: http://i.imgur.com/STCPcaJ.png - -<<<<<<< HEAD -.. _GNU-GPLv2: http://www.gnu.org/licenses/gpl-2.0.html -======= -.. _GNU-GPL2: http://www.gnu.org/licenses/gpl-2.0.html ->>>>>>> upstream/master -.. _awesome-vain: https://github.com/vain/awesome-vain -.. _Awesome: http://awesome.naquadah.org/ -.. _wiki: https://github.com/copycat-killer/lain/wiki From 010e60a8cd421ef6e0f15b5fda882e9e15939b71 Mon Sep 17 00:00:00 2001 From: aajjbb Date: Sat, 29 Aug 2015 16:32:38 -0300 Subject: [PATCH 541/572] merging with upstream --- widgets/abase.lua.orig | 41 -------- widgets/alsa.lua.orig | 81 -------------- widgets/alsabar.lua.orig | 215 -------------------------------------- widgets/base.lua.orig | 51 --------- widgets/calendar.lua.orig | 181 -------------------------------- widgets/fs.lua.orig | 153 --------------------------- widgets/imap.lua.orig | 131 ----------------------- widgets/maildir.lua.orig | 116 -------------------- widgets/mpd.lua.orig | 147 -------------------------- widgets/net.lua.orig | 116 -------------------- widgets/sysload.lua.orig | 49 --------- widgets/temp.lua.orig | 52 --------- widgets/weather.lua.orig | 185 -------------------------------- 13 files changed, 1518 deletions(-) delete mode 100644 widgets/abase.lua.orig delete mode 100644 widgets/alsa.lua.orig delete mode 100644 widgets/alsabar.lua.orig delete mode 100644 widgets/base.lua.orig delete mode 100644 widgets/calendar.lua.orig delete mode 100644 widgets/fs.lua.orig delete mode 100644 widgets/imap.lua.orig delete mode 100644 widgets/maildir.lua.orig delete mode 100644 widgets/mpd.lua.orig delete mode 100644 widgets/net.lua.orig delete mode 100644 widgets/sysload.lua.orig delete mode 100644 widgets/temp.lua.orig delete mode 100644 widgets/weather.lua.orig diff --git a/widgets/abase.lua.orig b/widgets/abase.lua.orig deleted file mode 100644 index 98f7818..0000000 --- a/widgets/abase.lua.orig +++ /dev/null @@ -1,41 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2014, Luke Bonham - ---]] - -local newtimer = require("lain.helpers").newtimer -local async = require("lain.asyncshell") -local wibox = require("wibox") - -local setmetatable = setmetatable - --- Basic template for custom widgets --- Asynchronous version --- lain.widgets.abase - -local function worker(args) - local abase = {} - local args = args or {} - local timeout = args.timeout or 5 - local cmd = args.cmd or "" - local settings = args.settings or function() end - - abase.widget = wibox.widget.textbox('') - - function abase.update() - async.request(cmd, function(f) - output = f - widget = abase.widget - settings() - end) - end - - newtimer(cmd, timeout, abase.update) - - return setmetatable(abase, { __index = abase.widget }) -end - -return setmetatable({}, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/alsa.lua.orig b/widgets/alsa.lua.orig deleted file mode 100644 index 0ed11c7..0000000 --- a/widgets/alsa.lua.orig +++ /dev/null @@ -1,81 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010, Adrian C. - ---]] - -local newtimer = require("lain.helpers").newtimer -<<<<<<< HEAD - -local wibox = require("wibox") - -local io = { popen = io.popen } -======= -local read_pipe = require("lain.helpers").read_pipe - -local wibox = require("wibox") - ->>>>>>> upstream/master -local string = { match = string.match, - format = string.format } - -local setmetatable = setmetatable - --- ALSA volume --- lain.widgets.alsa -local alsa = {} - -local function worker(args) - local args = args or {} - local timeout = args.timeout or 5 - local settings = args.settings or function() end - - alsa.cmd = args.cmd or "amixer" - alsa.channel = args.channel or "Master" - - alsa.widget = wibox.widget.textbox('') - - function alsa.update() -<<<<<<< HEAD - local f = assert(io.popen(string.format("%s get %s", alsa.cmd, alsa.channel))) - local mixer = f:read("*a") - f:close() -======= - local mixer = read_pipe(string.format("%s get %s", alsa.cmd, alsa.channel)) ->>>>>>> upstream/master - - volume_now = {} - - volume_now.level, volume_now.status = string.match(mixer, "([%d]+)%%.*%[([%l]*)") - - if volume_now.level == nil - then - volume_now.level = "0" - volume_now.status = "off" - end - - if volume_now.status == "" - then - if volume_now.level == "0" - then - volume_now.status = "off" - else - volume_now.status = "on" - end - end - - widget = alsa.widget - settings() - end - - timer_id = string.format("alsa-%s-%s", alsa.cmd, alsa.channel) - - newtimer(timer_id, timeout, alsa.update) - - return setmetatable(alsa, { __index = alsa.widget }) -end - -return setmetatable(alsa, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/alsabar.lua.orig b/widgets/alsabar.lua.orig deleted file mode 100644 index 3cda639..0000000 --- a/widgets/alsabar.lua.orig +++ /dev/null @@ -1,215 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2013, Rman - ---]] - -local newtimer = require("lain.helpers").newtimer -<<<<<<< HEAD -======= -local read_pipe = require("lain.helpers").read_pipe ->>>>>>> upstream/master - -local awful = require("awful") -local beautiful = require("beautiful") -local naughty = require("naughty") - -<<<<<<< HEAD -local io = { popen = io.popen } -local math = { modf = math.modf } -======= -local math = { modf = math.modf } -local mouse = mouse ->>>>>>> upstream/master -local string = { format = string.format, - match = string.match, - rep = string.rep } -local tonumber = tonumber - -local setmetatable = setmetatable - --- ALSA volume bar --- lain.widgets.alsabar -local alsabar = { -<<<<<<< HEAD - card = "0", -======= ->>>>>>> upstream/master - channel = "Master", - step = "2%", - - colors = { - background = beautiful.bg_normal, - mute = "#EB8F8F", - unmute = "#A4CE8A" - }, - - terminal = terminal or "xterm", - mixer = terminal .. " -e alsamixer", - - notifications = { - font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")), - font_size = "11", - color = beautiful.fg_normal, - bar_size = 18, - screen = 1 - }, - - _current_level = 0, - _muted = false -} - -function alsabar.notify() - alsabar.update() - - local preset = { - title = "", - text = "", - timeout = 5, - screen = alsabar.notifications.screen, - font = alsabar.notifications.font .. " " .. - alsabar.notifications.font_size, - fg = alsabar.notifications.color - } - - if alsabar._muted - then - preset.title = alsabar.channel .. " - Muted" - else - preset.title = alsabar.channel .. " - " .. alsabar._current_level .. "%" - end - - int = math.modf((alsabar._current_level / 100) * alsabar.notifications.bar_size) - preset.text = "[" - .. string.rep("|", int) - .. string.rep(" ", alsabar.notifications.bar_size - int) - .. "]" - -<<<<<<< HEAD -======= - if alsabar.followmouse then - preset.screen = mouse.screen - end - ->>>>>>> upstream/master - if alsabar._notify ~= nil then - alsabar._notify = naughty.notify ({ - replaces_id = alsabar._notify.id, - preset = preset, - }) - else - alsabar._notify = naughty.notify ({ - preset = preset, - }) - end -end - -local function worker(args) - local args = args or {} - local timeout = args.timeout or 5 - local settings = args.settings or function() end - local width = args.width or 63 - local height = args.heigth or 1 - local ticks = args.ticks or false - local ticks_size = args.ticks_size or 7 - local vertical = args.vertical or false - - alsabar.cmd = args.cmd or "amixer" - alsabar.channel = args.channel or alsabar.channel - alsabar.step = args.step or alsabar.step - alsabar.colors = args.colors or alsabar.colors - alsabar.notifications = args.notifications or alsabar.notifications -<<<<<<< HEAD -======= - alsabar.followmouse = args.followmouse or false ->>>>>>> upstream/master - - alsabar.bar = awful.widget.progressbar() - - alsabar.bar:set_background_color(alsabar.colors.background) - alsabar.bar:set_color(alsabar.colors.unmute) - alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } }) - alsabar.bar:set_width(width) - alsabar.bar:set_height(height) - alsabar.bar:set_ticks(ticks) - alsabar.bar:set_ticks_size(ticks_size) - alsabar.bar:set_vertical(vertical) - - function alsabar.update() - -- Get mixer control contents -<<<<<<< HEAD - local f = assert(io.popen(string.format("%s get %s", alsabar.cmd, alsabar.channel))) - local mixer = f:read("*a") - f:close() -======= - local mixer = read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.channel)) ->>>>>>> upstream/master - - -- Capture mixer control state: [5%] ... ... [on] - local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") - - if volu == nil then - volu = 0 - mute = "off" - end - - alsabar._current_level = tonumber(volu) - alsabar.bar:set_value(alsabar._current_level / 100) - if not mute and tonumber(volu) == 0 or mute == "off" - then - alsabar._muted = true - alsabar.tooltip:set_text (" [Muted] ") - alsabar.bar:set_color(alsabar.colors.mute) - else - alsabar._muted = false - alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu)) - alsabar.bar:set_color(alsabar.colors.unmute) - end - - volume_now = {} - volume_now.level = tonumber(volu) - volume_now.status = mute - settings() - end - - alsabar.bar:buttons (awful.util.table.join ( - awful.button ({}, 1, function() - awful.util.spawn(alsabar.mixer) - end), - awful.button ({}, 3, function() -<<<<<<< HEAD - awful.util.spawn(string.format("amixer -c %s set %s toggle", alsabar.card, alsabar.channel)) - alsabar.update() - end), - awful.button ({}, 4, function() - awful.util.spawn(string.format("amixer -c %s set %s %s+", alsabar.card, alsabar.channel, alsabar.step)) - alsabar.update() - end), - awful.button ({}, 5, function() - awful.util.spawn(string.format("amixer -c %s set %s %s-", alsabar.card, alsabar.channel, alsabar.step)) -======= - awful.util.spawn(string.format("%s set %s toggle", alsabar.cmd, alsabar.channel)) - alsabar.update() - end), - awful.button ({}, 4, function() - awful.util.spawn(string.format("%s set %s %s+", alsabar.cmd, alsabar.channel, alsabar.step)) - alsabar.update() - end), - awful.button ({}, 5, function() - awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step)) ->>>>>>> upstream/master - alsabar.update() - end) - )) - - timer_id = string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel) - - newtimer(timer_id, timeout, alsabar.update) - - return alsabar -end - -return setmetatable(alsabar, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/base.lua.orig b/widgets/base.lua.orig deleted file mode 100644 index ae9dd10..0000000 --- a/widgets/base.lua.orig +++ /dev/null @@ -1,51 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2014, Luke Bonham - ---]] - -local newtimer = require("lain.helpers").newtimer -<<<<<<< HEAD -local wibox = require("wibox") - -local io = { popen = io.popen } -======= -local read_pipe = require("lain.helpers").read_pipe - -local wibox = require("wibox") - ->>>>>>> upstream/master -local setmetatable = setmetatable - --- Basic template for custom widgets --- lain.widgets.base - -local function worker(args) - local base = {} - local args = args or {} - local timeout = args.timeout or 5 - local cmd = args.cmd or "" - local settings = args.settings or function() end - - base.widget = wibox.widget.textbox('') - - function base.update() -<<<<<<< HEAD - local f = assert(io.popen(cmd)) - output = f:read("*a") - f:close() -======= - output = read_pipe(cmd) ->>>>>>> upstream/master - widget = base.widget - settings() - end - - newtimer(cmd, timeout, base.update) - - return setmetatable(base, { __index = base.widget }) -end - -return setmetatable({}, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/calendar.lua.orig b/widgets/calendar.lua.orig deleted file mode 100644 index 187fdc0..0000000 --- a/widgets/calendar.lua.orig +++ /dev/null @@ -1,181 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - ---]] - -local icons_dir = require("lain.helpers").icons_dir - -local awful = require("awful") -local beautiful = require("beautiful") -local naughty = require("naughty") - -local io = { popen = io.popen } -local os = { date = os.date } -<<<<<<< HEAD -======= -local mouse = mouse ->>>>>>> upstream/master -local tonumber = tonumber - -local setmetatable = setmetatable - --- Calendar notification --- lain.widgets.calendar -local calendar = {} -local cal_notification = nil - -function calendar:hide() - if cal_notification ~= nil then - naughty.destroy(cal_notification) - cal_notification = nil - end -end - -function calendar:show(t_out, inc_offset, scr) - calendar:hide() - - local offs = inc_offset or 0 - local tims = t_out or 0 - local f, c_text - local today = tonumber(os.date('%d')) - local init_t = calendar.cal .. ' ' .. calendar.post_cal .. ' ' .. - ' | sed -r -e "s/_\\x08//g" | sed -r -e "s/(^| )(' - - calendar.offset = calendar.offset + offs - - if offs == 0 or calendar.offset == 0 - then -- current month showing, today highlighted - calendar.offset = 0 - calendar.notify_icon = calendar.icons .. today .. ".png" - - -- bg and fg inverted to highlight today - f = io.popen( init_t .. today .. - ')($| )/\\1\\2<\\/span><\\/b>\\3/"' ) - - else -- no current month showing, no day to highlight - local month = tonumber(os.date('%m')) - local year = tonumber(os.date('%Y')) - - month = month + calendar.offset - - if month > 12 then - month = month % 12 - year = year + 1 - if month <= 0 then - month = 12 - end - elseif month < 1 then - month = month + 12 - year = year - 1 - if month <= 0 then - month = 1 - end - end - - calendar.notify_icon = nil - - f = io.popen(calendar.cal .. ' ' .. month .. ' ' .. year .. ' ' .. - calendar.post_cal) - end - - c_text = "" - .. f:read() .. "\n\n" - .. f:read() .. "\n" -<<<<<<< HEAD - .. f:read("*a"):gsub("\n*$", "") - .. "" - f:close() - -======= - .. f:read("*all"):gsub("\n*$", "") - .. "" - f:close() - - if calendar.followmouse then - scrp = mouse.screen - else - scrp = scr or calendar.scr_pos - end - ->>>>>>> upstream/master - cal_notification = naughty.notify({ - text = c_text, - icon = calendar.notify_icon, - position = calendar.position, - fg = calendar.fg, - bg = calendar.bg, - timeout = tims, -<<<<<<< HEAD - screen = scr or 1 -======= - screen = scrp ->>>>>>> upstream/master - }) -end - -function calendar:attach(widget, args) - local args = args or {} -<<<<<<< HEAD - calendar.cal = args.cal or "/usr/bin/cal" - calendar.post_cal = args.post_cal or "" - calendar.icons = args.icons or icons_dir .. "cal/white/" - calendar.font = args.font or beautiful.font:sub(beautiful.font:find(""), - beautiful.font:find(" ")) - calendar.font_size = tonumber(args.font_size) or 11 - calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF" - calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF" - calendar.position = args.position or "top_right" - calendar.scr_pos = args.scr_pos or 1 - - calendar.offset = 0 - calendar.notify_icon = nil - - widget:connect_signal("mouse::enter", function () calendar:show(0, 0, 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, scr_pos) end), - awful.button({ }, 3, function () - calendar:show(0, 1, scr_pos) end), - awful.button({ }, 4, function () - calendar:show(0, -1, scr_pos) end), - awful.button({ }, 5, function () - calendar:show(0, 1, scr_pos) end))) -======= - - calendar.cal = args.cal or "/usr/bin/cal" - calendar.post_cal = args.post_cal or "" - calendar.icons = args.icons or icons_dir .. "cal/white/" - calendar.font = args.font or beautiful.font:sub(beautiful.font:find(""), - beautiful.font:find(" ")) - calendar.font_size = tonumber(args.font_size) or 11 - calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF" - calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF" - calendar.position = args.position or "top_right" - calendar.scr_pos = args.scr_pos or 1 - calendar.followmouse = args.followmouse or false - - calendar.offset = 0 - calendar.notify_icon = nil - - widget:connect_signal("mouse::enter", function () calendar:show(0, 0, calendar.scr_pos) end) - widget:connect_signal("mouse::leave", function () calendar:hide() end) - widget:buttons(awful.util.table.join(awful.button({ }, 1, function () - calendar:show(0, -1, calendar.scr_pos) end), - awful.button({ }, 3, function () - calendar:show(0, 1, calendar.scr_pos) end), - awful.button({ }, 4, function () - calendar:show(0, -1, calendar.scr_pos) end), - awful.button({ }, 5, function () - calendar:show(0, 1, calendar.scr_pos) end))) ->>>>>>> upstream/master -end - -return setmetatable(calendar, { __call = function(_, ...) return create(...) end }) diff --git a/widgets/fs.lua.orig b/widgets/fs.lua.orig deleted file mode 100644 index c1a3ab7..0000000 --- a/widgets/fs.lua.orig +++ /dev/null @@ -1,153 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010, Adrian C. - * (c) 2009, Lucas de Vries - ---]] - -local helpers = require("lain.helpers") - -local beautiful = require("beautiful") -local wibox = require("wibox") -local naughty = require("naughty") - -local io = { popen = io.popen } -local pairs = pairs -<<<<<<< HEAD -======= -local mouse = mouse ->>>>>>> upstream/master -local string = { match = string.match, - format = string.format } -local tonumber = tonumber - -local setmetatable = setmetatable - --- File system disk space usage --- lain.widgets.fs -local fs = {} -<<<<<<< HEAD - -local notification = nil -fs_notification_preset = { fg = beautiful.fg_normal } - -function fs:hide() - if notification ~= nil then - naughty.destroy(notification) - notification = nil -======= -local fs_notification = nil - -function fs:hide() - if fs_notification ~= nil then - naughty.destroy(fs_notification) - fs_notification = nil ->>>>>>> upstream/master - end -end - -function fs:show(t_out) - fs:hide() - -<<<<<<< HEAD - local f = io.popen(helpers.scripts_dir .. "dfs") - ws = f:read("*a"):gsub("\n*$", "") - f:close() - - notification = naughty.notify({ - preset = fs_notification_preset, - text = ws, - timeout = t_out, -======= - local ws = helpers.read_pipe(helpers.scripts_dir .. "dfs"):gsub("\n*$", "") - - if fs.followmouse then - fs.notification_preset.screen = mouse.screen - end - - fs_notification = naughty.notify({ - preset = fs.notification_preset, - text = ws, - timeout = t_out ->>>>>>> upstream/master - }) -end - --- Unit definitions -local unit = { ["mb"] = 1024, ["gb"] = 1024^2 } - -local function worker(args) -<<<<<<< HEAD - local args = args or {} - local timeout = args.timeout or 600 - local partition = args.partition or "/" - local settings = args.settings or function() end -======= - local args = args or {} - local timeout = args.timeout or 600 - local partition = args.partition or "/" - local settings = args.settings or function() end - - fs.followmouse = args.followmouse or false - fs.notification_preset = args.notification_preset or { fg = beautiful.fg_normal } ->>>>>>> upstream/master - - fs.widget = wibox.widget.textbox('') - - helpers.set_map(partition, false) - - function update() - fs_info = {} - fs_now = {} - local f = assert(io.popen("LC_ALL=C df -kP")) - - for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount) - local s = string.match(line, "^.-[%s]([%d]+)") - local u,a,p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%") - local m = string.match(line, "%%[%s]([%p%w]+)") - - if u and m then -- Handle 1st line and broken regexp - fs_info[m .. " size_mb"] = string.format("%.1f", tonumber(s) / unit["mb"]) - fs_info[m .. " size_gb"] = string.format("%.1f", tonumber(s) / unit["gb"]) - fs_info[m .. " used_p"] = tonumber(p) - fs_info[m .. " avail_p"] = 100 - tonumber(p) - end - end - - f:close() - - fs_now.used = tonumber(fs_info[partition .. " used_p"]) or 0 - fs_now.available = tonumber(fs_info[partition .. " avail_p"]) 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 - - widget = fs.widget - settings() - - if fs_now.used >= 99 and not helpers.get_map(partition) - then - naughty.notify({ - title = "warning", - text = partition .. " ran out!\nmake some room", - timeout = 8, - fg = "#000000", - bg = "#FFFFFF", - }) - helpers.set_map(partition, true) - else - helpers.set_map(partition, false) - end - end - - fs.widget:connect_signal('mouse::enter', function () fs:show(0) end) - fs.widget:connect_signal('mouse::leave', function () fs:hide() end) - - helpers.newtimer(partition, timeout, update) - - return setmetatable(fs, { __index = fs.widget }) -end - -return setmetatable(fs, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/imap.lua.orig b/widgets/imap.lua.orig deleted file mode 100644 index 1121f1a..0000000 --- a/widgets/imap.lua.orig +++ /dev/null @@ -1,131 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - ---]] - -local helpers = require("lain.helpers") -local async = require("lain.asyncshell") - -local naughty = require("naughty") -local wibox = require("wibox") - -<<<<<<< HEAD -======= -local mouse = mouse ->>>>>>> upstream/master -local string = { format = string.format, - gsub = string.gsub } -local tonumber = tonumber - -local setmetatable = setmetatable - --- Mail IMAP check --- lain.widgets.imap - -local function worker(args) -<<<<<<< HEAD - local imap = {} - local args = args or {} - - local server = args.server - local mail = args.mail - local password = args.password - - local port = args.port or 993 - local timeout = args.timeout or 60 - local is_plain = args.is_plain or false - local settings = args.settings or function() end -======= - local imap = {} - local args = args or {} - - local server = args.server - local mail = args.mail - local password = args.password - - local port = args.port or 993 - local timeout = args.timeout or 60 - local is_plain = args.is_plain or false - local followmouse = args.followmouse or false - local settings = args.settings or function() end ->>>>>>> upstream/master - - local head_command = "curl --connect-timeout 3 -fsm 3" - local request = "-X 'SEARCH (UNSEEN)'" - - helpers.set_map(mail, 0) - - if not is_plain - then -<<<<<<< HEAD - local f = io.popen(password) - password = f:read("*a"):gsub("\n", "") - f:close() -======= - password = helpers.read_pipe(password):gsub("\n", "") ->>>>>>> upstream/master - end - - imap.widget = wibox.widget.textbox('') - - function update() - mail_notification_preset = { - icon = helpers.icons_dir .. "mail.png", - position = "top_left" - } - -<<<<<<< HEAD -======= - if followmouse then - mail_notification_preset.screen = mouse.screen - end - ->>>>>>> upstream/master - curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%q %s -k", - head_command, server, port, mail, password, request) - - async.request(curl, function(f) -<<<<<<< HEAD - ws = f:read("*a") - f:close() - - _, mailcount = string.gsub(ws, "%d+", "") -======= - _, mailcount = string.gsub(f, "%d+", "") ->>>>>>> upstream/master - _ = nil - - widget = imap.widget - settings() - - if mailcount >= 1 and mailcount > helpers.get_map(mail) - then - if mailcount == 1 then - nt = mail .. " has one new message" - else - nt = mail .. " has " .. mailcount .. " new messages" - end - naughty.notify({ - preset = mail_notification_preset, -<<<<<<< HEAD - text = nt, -======= - text = nt ->>>>>>> upstream/master - }) - end - - helpers.set_map(mail, mailcount) - end) - - end - - helpers.newtimer(mail, timeout, update, true) - - return setmetatable(imap, { __index = imap.widget }) -end - -return setmetatable({}, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/maildir.lua.orig b/widgets/maildir.lua.orig deleted file mode 100644 index a0d5e8c..0000000 --- a/widgets/maildir.lua.orig +++ /dev/null @@ -1,116 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann - ---]] - -local newtimer = require("lain.helpers").newtimer -<<<<<<< HEAD -======= -local read_pipe = require("lain.helpers").read_pipe ->>>>>>> upstream/master - -local wibox = require("wibox") - -local util = require("lain.util") - -local io = { popen = io.popen } -local os = { getenv = os.getenv } -local pairs = pairs -local string = { len = string.len, - match = string.match } -local table = { sort = table.sort } - -local setmetatable = setmetatable - --- Maildir check --- lain.widgets.maildir -local maildir = {} - -local function worker(args) - local args = args or {} - local timeout = args.timeout or 60 - local mailpath = args.mailpath or os.getenv("HOME") .. "/Mail" - local ignore_boxes = args.ignore_boxes or {} - local settings = args.settings or function() end - - maildir.widget = wibox.widget.textbox('') - - function update() - -- Find pathes to mailboxes. - local p = io.popen("find " .. mailpath .. - " -mindepth 1 -maxdepth 1 -type d" .. - " -not -name .git") - local boxes = {} - repeat - line = p:read("*l") - if line ~= nil - then - -- Find all files in the "new" subdirectory. For each - -- file, print a single character (no newline). Don't - -- match files that begin with a dot. - -- Afterwards the length of this string is the number of - -- new mails in that box. -<<<<<<< HEAD - local np = io.popen("find " .. line .. - "/new -mindepth 1 -type f " .. - "-not -name '.*' -printf a") - local mailstring = np:read("*a") -======= - local mailstring = read_pipe("find " .. line .. - "/new -mindepth 1 -type f " .. - "-not -name '.*' -printf a") ->>>>>>> upstream/master - - -- Strip off leading mailpath. - local box = string.match(line, mailpath .. "/*([^/]+)") - local nummails = string.len(mailstring) - if nummails > 0 - then - boxes[box] = nummails - end - end - until line == nil - -<<<<<<< HEAD - table.sort(boxes) - - newmail = "no mail" - --Count the total number of mails irrespective of where it was found -======= - p:close() - table.sort(boxes) - - newmail = "no mail" - -- Count the total number of mails irrespective of where it was found ->>>>>>> upstream/master - total = 0 - - for box, number in pairs(boxes) - do - -- Add this box only if it's not to be ignored. - if not util.element_in_table(box, ignore_boxes) - then - total = total + number - if newmail == "no mail" - then - newmail = box .. "(" .. number .. ")" - else - newmail = newmail .. ", " .. - box .. "(" .. number .. ")" - end - end - end - - widget = maildir.widget - settings() - end - - newtimer(mailpath, timeout, update, true) - return maildir.widget -end - -return setmetatable(maildir, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/mpd.lua.orig b/widgets/mpd.lua.orig deleted file mode 100644 index 9207b15..0000000 --- a/widgets/mpd.lua.orig +++ /dev/null @@ -1,147 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010, Adrian C. - ---]] - -local helpers = require("lain.helpers") -local async = require("lain.asyncshell") - -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 } -<<<<<<< HEAD -======= -local mouse = mouse ->>>>>>> upstream/master -local string = { format = string.format, - match = string.match, - gmatch = string.gmatch } - -local setmetatable = setmetatable - --- MPD infos --- lain.widgets.mpd -local mpd = {} - -local function worker(args) - local args = args or {} - local timeout = args.timeout or 2 - local password = args.password or "" - local host = args.host or "127.0.0.1" - local port = args.port or "6600" - 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 "" -<<<<<<< HEAD -======= - local followmouse = args.followmouse or false - local echo_cmd = args.echo_cmd or "echo" ->>>>>>> upstream/master - local settings = args.settings or function() end - - local mpdcover = helpers.scripts_dir .. "mpdcover" - local mpdh = "telnet://" .. host .. ":" .. port -<<<<<<< HEAD - local echo = "echo 'password " .. password .. "\nstatus\ncurrentsong\nclose'" -======= - local echo = echo_cmd .. " 'password " .. password .. "\nstatus\ncurrentsong\nclose'" ->>>>>>> upstream/master - - mpd.widget = wibox.widget.textbox('') - - mpd_notification_preset = { - title = "Now playing", - timeout = 6 - } - - helpers.set_map("current mpd track", nil) - - function mpd.update() - async.request(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh, function (f) - mpd_now = { - state = "N/A", - file = "N/A", - artist = "N/A", - title = "N/A", - album = "N/A", - date = "N/A", - time = "N/A", - elapsed = "N/A" - } - -<<<<<<< HEAD - for line in f:lines() do -======= - for line in string.gmatch(f, "[^\n]+") do ->>>>>>> upstream/master - 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 == "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+") - end - end - end - - mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist, - mpd_now.album, mpd_now.date, mpd_now.title) - widget = mpd.widget - settings() - - if mpd_now.state == "play" - then - if mpd_now.title ~= helpers.get_map("current mpd track") - then - helpers.set_map("current mpd track", mpd_now.title) - -<<<<<<< HEAD - if string.match(mpd_now.file, "http://") == nil -======= - if string.match(mpd_now.file, "http.*://") == nil ->>>>>>> upstream/master - then -- local file - os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir, - mpd_now.file, cover_size, default_art)) - current_icon = "/tmp/mpdcover.png" - else -- http stream - current_icon = default_art - end - -<<<<<<< HEAD -======= - if followmouse then - mpd_notification_preset.screen = mouse.screen - end - ->>>>>>> upstream/master - mpd.id = naughty.notify({ - preset = mpd_notification_preset, - icon = current_icon, - replaces_id = mpd.id, - }).id - end - elseif mpd_now.state ~= "pause" - then - helpers.set_map("current mpd track", nil) - end - end) - end - - helpers.newtimer("mpd", timeout, mpd.update) - - return setmetatable(mpd, { __index = mpd.widget }) -end - -return setmetatable(mpd, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/net.lua.orig b/widgets/net.lua.orig deleted file mode 100644 index efd1386..0000000 --- a/widgets/net.lua.orig +++ /dev/null @@ -1,116 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann - ---]] - -local helpers = require("lain.helpers") - -local notify_fg = require("beautiful").fg_focus -local naughty = require("naughty") -local wibox = require("wibox") - -<<<<<<< HEAD -local io = { popen = io.popen } -======= ->>>>>>> upstream/master -local string = { format = string.format, - gsub = string.gsub, - match = string.match } - -local setmetatable = setmetatable - --- Network infos --- lain.widgets.net -local net = { - last_t = 0, - last_r = 0 -} - -function net.get_device() -<<<<<<< HEAD - f = io.popen("ip link show | cut -d' ' -f2,9") - ws = f:read("*a") - f:close() -======= - local ws = helpers.read_pipe("ip link show | cut -d' ' -f2,9") ->>>>>>> upstream/master - ws = ws:match("%w+: UP") or ws:match("ppp%w+: UNKNOWN") - if ws ~= nil then - return ws:match("(%w+):") - else - return "network off" - end -end - -local function worker(args) - local args = args or {} - local timeout = args.timeout or 2 - local units = args.units or 1024 --kb - local notify = args.notify or "on" - local screen = args.screen or 1 - local settings = args.settings or function() end - - iface = args.iface or net.get_device() - - net.widget = wibox.widget.textbox('') - - helpers.set_map(iface, true) - - function update() - net_now = {} - - if iface == "" or string.match(iface, "network off") - then - iface = net.get_device() - end - - net_now.carrier = helpers.first_line('/sys/class/net/' .. iface .. - '/carrier') or "0" - net_now.state = helpers.first_line('/sys/class/net/' .. iface .. - '/operstate') or "down" - local now_t = helpers.first_line('/sys/class/net/' .. iface .. - '/statistics/tx_bytes') or 0 - local now_r = helpers.first_line('/sys/class/net/' .. iface .. - '/statistics/rx_bytes') or 0 - - net_now.sent = (now_t - net.last_t) / timeout / units - net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ",", ".") - - net_now.received = (now_r - net.last_r) / timeout / units - net_now.received = string.gsub(string.format('%.1f', net_now.received), ",", ".") - - widget = net.widget - settings() - - net.last_t = now_t - net.last_r = now_r - - if net_now.carrier ~= "1" and notify == "on" - then - if helpers.get_map(iface) - then - naughty.notify({ - title = iface, - text = "no carrier", - timeout = 7, - position = "top_left", - icon = helpers.icons_dir .. "no_net.png", - fg = notify_fg or "#FFFFFF", - screen = screen - }) - helpers.set_map(iface, false) - end - else - helpers.set_map(iface, true) - end - end - - helpers.newtimer(iface, timeout, update) - return net.widget -end - -return setmetatable(net, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/sysload.lua.orig b/widgets/sysload.lua.orig deleted file mode 100644 index 64ddd00..0000000 --- a/widgets/sysload.lua.orig +++ /dev/null @@ -1,49 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - * (c) 2010-2012, Peter Hofmann - ---]] - -local newtimer = require("lain.helpers").newtimer - -local wibox = require("wibox") - -local io = { open = io.open } -local string = { match = string.match } - -local setmetatable = setmetatable - --- System load --- lain.widgets.sysload -local sysload = {} - -local function worker(args) - local args = args or {} - local timeout = args.timeout or 2 - local settings = args.settings or function() end - - sysload.widget = wibox.widget.textbox('') - - function update() - local f = io.open("/proc/loadavg") -<<<<<<< HEAD - local ret = f:read("*a") -======= - local ret = f:read("*all") ->>>>>>> upstream/master - f:close() - - load_1, load_5, load_15 = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") - - widget = sysload.widget - settings() - end - - newtimer("sysload", timeout, update) - return sysload.widget -end - -return setmetatable(sysload, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/temp.lua.orig b/widgets/temp.lua.orig deleted file mode 100644 index 93f72af..0000000 --- a/widgets/temp.lua.orig +++ /dev/null @@ -1,52 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - ---]] - -local newtimer = require("lain.helpers").newtimer - -local wibox = require("wibox") - -local io = { open = io.open } -local tonumber = tonumber - -local setmetatable = setmetatable - --- coretemp --- lain.widgets.temp -local temp = {} - -local function worker(args) - local args = args or {} - local timeout = args.timeout or 2 - local tempfile = args.tempfile or "/sys/class/thermal/thermal_zone0/temp" - local settings = args.settings or function() end - - temp.widget = wibox.widget.textbox('') - - function update() - local f = io.open(tempfile) - if f ~= nil - then -<<<<<<< HEAD - coretemp_now = tonumber(f:read("*a")) / 1000 -======= - coretemp_now = tonumber(f:read("*all")) / 1000 ->>>>>>> upstream/master - f:close() - else - coretemp_now = "N/A" - end - - widget = temp.widget - settings() - end - - newtimer("coretemp", timeout, update) - return temp.widget -end - -return setmetatable(temp, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/weather.lua.orig b/widgets/weather.lua.orig deleted file mode 100644 index ce67156..0000000 --- a/widgets/weather.lua.orig +++ /dev/null @@ -1,185 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2015, Luke Bonham - ---]] - -local newtimer = require("lain.helpers").newtimer -<<<<<<< HEAD -local async = require("lain.asyncshell") -local json = require("lain.util").dkjson -local lain_icons = require("lain.helpers").icons_dir -======= -local read_pipe = require("lain.helpers").read_pipe - -local async = require("lain.asyncshell") -local json = require("lain.util").dkjson -local lain_icons = require("lain.helpers").icons_dir - ->>>>>>> upstream/master -local naughty = require("naughty") -local wibox = require("wibox") - -local math = { floor = math.floor } -<<<<<<< HEAD -======= -local mouse = mouse ->>>>>>> upstream/master -local string = { format = string.format, - gsub = string.gsub } - -local setmetatable = setmetatable - --- OpenWeatherMap --- current weather and X-days forecast --- lain.widgets.weather - -local function worker(args) -<<<<<<< HEAD - local weather = {} - local args = args or {} - local timeout = args.timeout or 900 -- 15 min - local timeout_forecast = args.timeout or 86400 -- 24 hrs - local current_call = "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s'" - local forecast_call = "curl -s 'http://api.openweathermap.org/data/2.5/forecast/daily?id=%s&units=%s&lang=%s&cnt=%s'" - local city_id = args.city_id or 0 -- placeholder - local units = args.units or "metric" - local lang = args.lang or "en" - local cnt = args.cnt or 7 - local date_cmd = args.date_cmd or "date -u -d @%d +'%%a %%d'" - local icons_path = args.icons_path or lain_icons .. "openweathermap/" - local w_notification_preset = args.w_notification_preset or {} - local settings = args.settings or function() end -======= - local weather = {} - local args = args or {} - local timeout = args.timeout or 900 -- 15 min - local timeout_forecast = args.timeout or 86400 -- 24 hrs - local current_call = "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s'" - local forecast_call = "curl -s 'http://api.openweathermap.org/data/2.5/forecast/daily?id=%s&units=%s&lang=%s&cnt=%s'" - local city_id = args.city_id or 0 -- placeholder - local units = args.units or "metric" - local lang = args.lang or "en" - local cnt = args.cnt or 7 - local date_cmd = args.date_cmd or "date -u -d @%d +'%%a %%d'" - local icons_path = args.icons_path or lain_icons .. "openweathermap/" - local notification_preset = args.notification_preset or {} - local followmouse = args.followmouse or false - local settings = args.settings or function() end ->>>>>>> upstream/master - - weather.widget = wibox.widget.textbox('') - weather.icon = wibox.widget.imagebox() - - function weather.show(t_out) - weather.hide() -<<<<<<< HEAD -======= - - if followmouse then - notification_preset.screen = mouse.screen - end - ->>>>>>> upstream/master - weather.notification = naughty.notify({ - text = weather.notification_text, - icon = weather.icon_path, - timeout = t_out, -<<<<<<< HEAD - preset = w_notification_preset -======= - preset = notification_preset ->>>>>>> upstream/master - }) - end - - function weather.hide() - if weather.notification ~= nil then - naughty.destroy(weather.notification) - weather.notification = nil - end - end - - function weather.attach(obj) - obj:connect_signal("mouse::enter", function() - weather.show(0) - end) - obj:connect_signal("mouse::leave", function() - weather.hide() - end) - end - - function weather.forecast_update() - local cmd = string.format(forecast_call, city_id, units, lang, cnt) - async.request(cmd, function(f) -<<<<<<< HEAD - j = f:read("*a") - f:close() - weather_now, pos, err = json.decode(j, 1, nil) -======= - weather_now, pos, err = json.decode(f, 1, nil) ->>>>>>> upstream/master - - if not err and weather_now ~= nil and tonumber(weather_now["cod"]) == 200 then - weather.notification_text = '' - for i = 1, weather_now["cnt"] do -<<<<<<< HEAD - local f = assert(io.popen(string.format(date_cmd, weather_now["list"][i]["dt"]))) - day = string.gsub(f:read("a"), "\n", "") - f:close() -======= - day = string.gsub(read_pipe(string.format(date_cmd, weather_now["list"][i]["dt"])), "\n", "") ->>>>>>> upstream/master - - tmin = math.floor(weather_now["list"][i]["temp"]["min"]) - tmax = math.floor(weather_now["list"][i]["temp"]["max"]) - desc = weather_now["list"][i]["weather"][1]["description"] - - weather.notification_text = weather.notification_text .. - string.format("%s: %s, %d - %d ", day, desc, tmin, tmax) - - if i < weather_now["cnt"] then - weather.notification_text = weather.notification_text .. "\n" - end - end - else - weather.icon_path = icons_path .. "na.png" - weather.notification_text = "API/connection error or bad/not set city ID" - end - end) - end - - function weather.update() - local cmd = string.format(current_call, city_id, units, lang) - async.request(cmd, function(f) -<<<<<<< HEAD - j = f:read("*a") - f:close() - weather_now, pos, err = json.decode(j, 1, nil) -======= - weather_now, pos, err = json.decode(f, 1, nil) ->>>>>>> upstream/master - - if not err and weather_now ~= nil and tonumber(weather_now["cod"]) == 200 then - weather.icon_path = icons_path .. weather_now["weather"][1]["icon"] .. ".png" - weather.icon:set_image(weather.icon_path) - widget = weather.widget - settings() - else - weather.widget._layout.text = " N/A " -- tries to avoid textbox bugs - weather.icon:set_image(icons_path .. "na.png") - end - end) - end - - weather.attach(weather.widget) - - newtimer("weather-" .. city_id, timeout, weather.update) - newtimer("weather_forecast" .. city_id, timeout, weather.forecast_update) - - return setmetatable(weather, { __index = weather.widget }) -end - -return setmetatable({}, { __call = function(_, ...) return worker(...) end }) From 69572f3574dafbae68e7c03d279e51e23752b814 Mon Sep 17 00:00:00 2001 From: aajjbb Date: Tue, 15 Sep 2015 10:15:44 -0300 Subject: [PATCH 542/572] merging with upstream --- helpers.lua.orig | 123 ----------------------------------------------- 1 file changed, 123 deletions(-) delete mode 100644 helpers.lua.orig diff --git a/helpers.lua.orig b/helpers.lua.orig deleted file mode 100644 index f88c042..0000000 --- a/helpers.lua.orig +++ /dev/null @@ -1,123 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Luke Bonham - ---]] - -local debug = require("debug") - -local capi = { timer = timer } -local io = { open = io.open, -<<<<<<< HEAD - lines = io.lines } -======= - lines = io.lines, - popen = io.popen } ->>>>>>> upstream/master -local rawget = rawget - --- Lain helper functions for internal use --- lain.helpers -local helpers = {} - -helpers.lain_dir = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]] -helpers.icons_dir = helpers.lain_dir .. 'icons/' -helpers.scripts_dir = helpers.lain_dir .. 'scripts/' - --- {{{ Modules loader - -function helpers.wrequire(table, key) - local module = rawget(table, key) - return module or require(table._NAME .. '.' .. key) -end - --- }}} - --- {{{ File operations - --- see if the file exists and is readable -function helpers.file_exists(file) - local f = io.open(file) - if f then - local s = f:read() - f:close() - f = s - end - return f ~= nil -end - --- get all lines from a file, returns an empty --- list/table if the file does not exist -function helpers.lines_from(file) - if not helpers.file_exists(file) then return {} end - lines = {} - for line in io.lines(file) do - lines[#lines + 1] = line - end - return lines -end - --- get first line of a file, return nil if --- the file does not exist -function helpers.first_line(file) - return helpers.lines_from(file)[1] -end - --- get first non empty line from a file, --- returns nil otherwise -function helpers.first_nonempty_line(file) - for k,v in pairs(helpers.lines_from(file)) do - if #v then return v end - end - return nil -end - --- }}} - --- {{{ Timer maker - -helpers.timer_table = {} - -function helpers.newtimer(name, timeout, fun, nostart) - helpers.timer_table[name] = capi.timer({ timeout = timeout }) - helpers.timer_table[name]:connect_signal("timeout", fun) - helpers.timer_table[name]:start() - if not nostart then - helpers.timer_table[name]:emit_signal("timeout") - end -end - --- }}} - -<<<<<<< HEAD -======= --- {{{ Pipe operations - --- read the full output of a pipe (command) -function helpers.read_pipe(cmd) - local f = assert(io.popen(cmd)) - local output = f:read("*all") - f:close() - return output -end - --- }}} - ->>>>>>> upstream/master --- {{{ A map utility - -helpers.map_table = {} - -function helpers.set_map(element, value) - helpers.map_table[element] = value -end - -function helpers.get_map(element) - return helpers.map_table[element] -end - --- }}} - -return helpers From ad71a6bc497a258cbdbb0821484f3d47bb2f19f6 Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Sat, 10 Oct 2015 10:20:45 +0200 Subject: [PATCH 543/572] dfs: fix misalignments; widgets/weather: added APPID argument --- scripts/dfs | 4 ++-- widgets/weather.lua | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/dfs b/scripts/dfs index f04b051..bc27b81 100755 --- a/scripts/dfs +++ b/scripts/dfs @@ -212,7 +212,7 @@ echo "$SORTED_FILE_SYSTEMS_INFO" | $AWK_COMMAND -v DEBUG=$DEBUG -v PATTERN=$PATT printf ("\n%s", narrow_margin); else printf ("%-*s", LEFT_COLUMN + 2, ""); - print " Used Free Total "; + print " Used Free Total "; if (! NARROW_MODE) print ""; } @@ -352,7 +352,7 @@ $0 ~ PATTERN { # printf ("stars_number = %d\n", stars_number); printf ("|"); - for (i = 1; i <= stars_number; i++) + for (i = 1; i <= stars_number && i <= 49; i++) { printf ("%s", "*"); } diff --git a/widgets/weather.lua b/widgets/weather.lua index de3163c..68abae9 100644 --- a/widgets/weather.lua +++ b/widgets/weather.lua @@ -30,10 +30,11 @@ local setmetatable = setmetatable local function worker(args) local weather = {} local args = args or {} + local APPID = args.APPID or 1 -- mandatory local timeout = args.timeout or 900 -- 15 min local timeout_forecast = args.timeout or 86400 -- 24 hrs - local current_call = "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s'" - local forecast_call = "curl -s 'http://api.openweathermap.org/data/2.5/forecast/daily?id=%s&units=%s&lang=%s&cnt=%s'" + local current_call = "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s&APPID=%s'" + local forecast_call = "curl -s 'http://api.openweathermap.org/data/2.5/forecast/daily?id=%s&units=%s&lang=%s&cnt=%s&APPID=%s'" local city_id = args.city_id or 0 -- placeholder local units = args.units or "metric" local lang = args.lang or "en" @@ -83,7 +84,7 @@ local function worker(args) end function weather.forecast_update() - local cmd = string.format(forecast_call, city_id, units, lang, cnt) + local cmd = string.format(forecast_call, city_id, units, lang, cnt, APPID) async.request(cmd, function(f) local pos, err weather_now, pos, err = json.decode(f, 1, nil) @@ -112,7 +113,7 @@ local function worker(args) end function weather.update() - local cmd = string.format(current_call, city_id, units, lang) + local cmd = string.format(current_call, city_id, units, lang, APPID) async.request(cmd, function(f) local pos, err weather_now, pos, err = json.decode(f, 1, nil) From 69ddbc74a59ead7b3c140d42d94cb39d574284fa Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Sat, 10 Oct 2015 10:33:08 +0200 Subject: [PATCH 544/572] asyncshell: assert compatibility across multiple shells; #145 fix --- asyncshell.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/asyncshell.lua b/asyncshell.lua index 827cf4b..2d6b7e3 100644 --- a/asyncshell.lua +++ b/asyncshell.lua @@ -14,6 +14,9 @@ -- Grab environment local awful = require('awful') +-- Avoid discrepancies across multiple shells +awful.util.shell = '/bin/sh' + -- Initialize tables for module asyncshell = { request_table = {}, id_counter = 0 } From 912bd26ede8901c98fd8d7a35f8493ee448109ad Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Mon, 12 Oct 2015 12:09:44 +0200 Subject: [PATCH 545/572] merge and resolve conflicts from #134; #114 --- helpers.lua | 12 ++++++++--- widgets/abase.lua | 19 +++++++++++------ widgets/alsa.lua | 17 +++++++++++---- widgets/alsabar.lua | 52 +++++++++++++++++++++++++-------------------- widgets/base.lua | 19 ++++++++++------- widgets/bat.lua | 51 +++++++++++++++++++++++++++----------------- widgets/cpu.lua | 37 +++++++++++++++++--------------- widgets/fs.lua | 15 ++++++++----- widgets/imap.lua | 6 ++++-- widgets/maildir.lua | 10 +++++---- widgets/mem.lua | 49 ++++++++++++++++++++++++++++++------------ widgets/mpd.lua | 16 +++++++++----- widgets/net.lua | 45 ++++++++++++++++++++++----------------- widgets/sysload.lua | 24 +++++++++++++++------ widgets/temp.lua | 16 ++++++++------ wiki | 2 +- 16 files changed, 247 insertions(+), 143 deletions(-) diff --git a/helpers.lua b/helpers.lua index 4e90e16..503c40e 100644 --- a/helpers.lua +++ b/helpers.lua @@ -76,10 +76,16 @@ end helpers.timer_table = {} -function helpers.newtimer(name, timeout, fun, nostart) - helpers.timer_table[name] = capi.timer({ timeout = timeout }) +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 diff --git a/widgets/abase.lua b/widgets/abase.lua index 98f7818..87af872 100644 --- a/widgets/abase.lua +++ b/widgets/abase.lua @@ -6,9 +6,9 @@ --]] -local newtimer = require("lain.helpers").newtimer -local async = require("lain.asyncshell") -local wibox = require("wibox") +local helpers = require("lain.helpers") +local async = require("lain.asyncshell") +local wibox = require("wibox") local setmetatable = setmetatable @@ -19,21 +19,26 @@ local setmetatable = setmetatable local function worker(args) local abase = {} local args = args or {} - local timeout = args.timeout or 5 + local timeout = args.timeout or 1 local cmd = args.cmd or "" local settings = args.settings or function() end abase.widget = wibox.widget.textbox('') + helpers.set_map(cmd, '') function abase.update() async.request(cmd, function(f) output = f - widget = abase.widget - settings() + + if helpers.get_map(cmd) ~= output then + widget = abase.widget + settings() + helpers.set_map(cmd, output) + end end) end - newtimer(cmd, timeout, abase.update) + helpers.newtimer(cmd, timeout, abase.update) return setmetatable(abase, { __index = abase.widget }) end diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 85d5311..0bb2059 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -19,11 +19,14 @@ local setmetatable = setmetatable -- ALSA volume -- lain.widgets.alsa -local alsa = {} +local alsa = { + level = "0", + status = "off", +} local function worker(args) local args = args or {} - local timeout = args.timeout or 5 + local timeout = args.timeout or 1 local settings = args.settings or function() end alsa.cmd = args.cmd or "amixer" @@ -54,8 +57,14 @@ local function worker(args) end end - widget = alsa.widget - settings() + if alsa.level ~= volume_now.level or alsa.status ~= volume_now.status + then + widget = alsa.widget + settings() + + alsa.level = volume_now.level + alsa.status = volume_now.status + end end timer_id = string.format("alsa-%s-%s", alsa.cmd, alsa.channel) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index c7498d2..fc45c72 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -47,7 +47,8 @@ local alsabar = { }, _current_level = 0, - _muted = false + _muted = false, + _status = "off" } function alsabar.notify() @@ -56,7 +57,7 @@ function alsabar.notify() local preset = { title = "", text = "", - timeout = 5, + timeout = 1, screen = alsabar.notifications.screen, font = alsabar.notifications.font .. " " .. alsabar.notifications.font_size, @@ -94,7 +95,7 @@ end local function worker(args) local args = args or {} - local timeout = args.timeout or 5 + local timeout = args.timeout or 1 local settings = args.settings or function() end local width = args.width or 63 local height = args.heigth or 1 @@ -127,28 +128,33 @@ local function worker(args) -- Capture mixer control state: [5%] ... ... [on] local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") - if volu == nil then - volu = 0 - mute = "off" - end + volu = tonumber(volu) or 0 + if mute == "" then mute = "off" - alsabar._current_level = tonumber(volu) - alsabar.bar:set_value(alsabar._current_level / 100) - if not mute and tonumber(volu) == 0 or mute == "off" - then - alsabar._muted = true - alsabar.tooltip:set_text (" [Muted] ") - alsabar.bar:set_color(alsabar.colors.mute) - else - alsabar._muted = false - alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu)) - alsabar.bar:set_color(alsabar.colors.unmute) - end + if alsabar._current_level ~= volu or alsabar._status ~= mute then - volume_now = {} - volume_now.level = tonumber(volu) - volume_now.status = mute - settings() + alsabar._current_level = volu + alsabar._status = mute + + alsabar.bar:set_value(alsabar._current_level / 100) + + if not mute and volu == 0 or mute == "off" + then + alsabar._muted = true + alsabar.tooltip:set_text (" [Muted] ") + alsabar.bar:set_color(alsabar.colors.mute) + else + alsabar._muted = false + alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu)) + alsabar.bar:set_color(alsabar.colors.unmute) + end + + volume_now = {} + volume_now.level = volu + volume_now.status = mute + + settings() + end end alsabar.bar:buttons (awful.util.table.join ( diff --git a/widgets/base.lua b/widgets/base.lua index 2f377f7..88478b0 100644 --- a/widgets/base.lua +++ b/widgets/base.lua @@ -6,9 +6,7 @@ --]] -local newtimer = require("lain.helpers").newtimer -local read_pipe = require("lain.helpers").read_pipe - +local helpers = require("lain.helpers") local wibox = require("wibox") local setmetatable = setmetatable @@ -19,19 +17,24 @@ local setmetatable = setmetatable local function worker(args) local base = {} local args = args or {} - local timeout = args.timeout or 5 + local timeout = args.timeout or 1 local cmd = args.cmd or "" local settings = args.settings or function() end base.widget = wibox.widget.textbox('') + helpers.set_map(cmd, '') function base.update() - output = read_pipe(cmd) - widget = base.widget - settings() + output = helpers.read_pipe(cmd) + + if helpers.get_map(cmd) ~= output then + widget = base.widget + settings() + helpers.set_map(cmd, output) + end end - newtimer(cmd, timeout, base.update) + helpers.newtimer(cmd, timeout, base.update) return setmetatable(base, { __index = base.widget }) end diff --git a/widgets/bat.lua b/widgets/bat.lua index 61828ec..d18af87 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -7,9 +7,7 @@ --]] -local newtimer = require("lain.helpers").newtimer -local first_line = require("lain.helpers").first_line - +local helpers = require("lain.helpers") local naughty = require("naughty") local wibox = require("wibox") @@ -48,6 +46,11 @@ local function worker(args) bg = "#FFFFFF" } + helpers.set_map(battery .. "status", "N/A") + helpers.set_map(battery .. "perc", "N/A") + helpers.set_map(battery .. "time", "N/A") + helpers.set_map(battery .. "watt", "N/A") + function update() bat_now = { status = "Not present", @@ -58,22 +61,22 @@ local function worker(args) local bstr = "/sys/class/power_supply/" .. battery - local present = first_line(bstr .. "/present") + local present = helpers.first_line(bstr .. "/present") if present == "1" then - local rate = first_line(bstr .. "/power_now") or - first_line(bstr .. "/current_now") + local rate = helpers.first_line(bstr .. "/power_now") or + helpers.first_line(bstr .. "/current_now") - local ratev = first_line(bstr .. "/voltage_now") + local ratev = helpers.first_line(bstr .. "/voltage_now") - local rem = first_line(bstr .. "/energy_now") or - first_line(bstr .. "/charge_now") + local rem = helpers.first_line(bstr .. "/energy_now") or + helpers.first_line(bstr .. "/charge_now") - local tot = first_line(bstr .. "/energy_full") or - first_line(bstr .. "/charge_full") + local tot = helpers.first_line(bstr .. "/energy_full") or + helpers.first_line(bstr .. "/charge_full") - bat_now.status = first_line(bstr .. "/status") or "N/A" + bat_now.status = helpers.first_line(bstr .. "/status") or "N/A" rate = tonumber(rate) or 1 ratev = tonumber(ratev) @@ -97,7 +100,7 @@ local function worker(args) bat_now.time = string.format("%02d:%02d", hrs, min) - bat_now.perc = first_line(bstr .. "/capacity") + bat_now.perc = helpers.first_line(bstr .. "/capacity") if not bat_now.perc then local perc = (rem / tot) * 100 @@ -115,11 +118,21 @@ local function worker(args) else bat_now.watt = "N/A" end - end - widget = bat.widget - settings() + if bat_now.status ~= helpers.get_map(battery .. "status") + or bat_now.perc ~= helpers.get_map(battery .. "perc") + or bat_now.time ~= helpers.get_map(battery .. "time") + or bat_now.watt ~= helpers.get_map(battery .. "watt") + then + widget = bat.widget + settings() + + helpers.set_map(battery .. "status", bat_now.status) + helpers.set_map(battery .. "perc", bat_now.perc) + helpers.set_map(battery .. "time", bat_now.time) + helpers.set_map(battery .. "watt", bat_now.watt) + end -- notifications for low and critical states if bat_now.status == "Discharging" and notify == "on" and bat_now.perc ~= nil @@ -141,9 +154,9 @@ local function worker(args) end end - newtimer(battery, timeout, update) + helpers.newtimer(battery, timeout, update) - return setmetatable(bat, { __index = bat.widget }) + return bat.widget end -return setmetatable({}, { __call = function(_, ...) return worker(...) end }) +return setmetatable(bat, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/cpu.lua b/widgets/cpu.lua index ec84101..1554443 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -7,16 +7,13 @@ --]] -local first_line = require("lain.helpers").first_line -local newtimer = require("lain.helpers").newtimer - +local helpers = require("lain.helpers") local wibox = require("wibox") local math = { ceil = math.ceil } local string = { format = string.format, gmatch = string.gmatch } local tostring = tostring - local setmetatable = setmetatable -- CPU usage @@ -28,16 +25,18 @@ local cpu = { local function worker(args) local args = args or {} - local timeout = args.timeout or 2 + local timeout = args.timeout or 1 local settings = args.settings or function() end cpu.widget = wibox.widget.textbox('') + helpers.set_map("cpuactive", 0) + helpers.set_map("cputotal", 0) function update() -- Read the amount of time the CPUs have spent performing -- different kinds of work. Read the first line of /proc/stat -- which is the sum of all CPUs. - local times = first_line("/proc/stat") + local times = helpers.first_line("/proc/stat") local at = 1 local idle = 0 local total = 0 @@ -54,22 +53,26 @@ local function worker(args) end local active = total - idle - -- Read current data and calculate relative values. - local dactive = active - cpu.last_active - local dtotal = total - cpu.last_total + if helpers.get_map("cpuactive") ~= active + or helpers.get_map("cputotal") ~= total + then + -- Read current data and calculate relative values. + local dactive = active - cpu.last_active + local dtotal = total - cpu.last_total - cpu_now = {} - cpu_now.usage = tostring(math.ceil((dactive / dtotal) * 100)) + cpu_now = {} + cpu_now.usage = tostring(math.ceil((dactive / dtotal) * 100)) - widget = cpu.widget - settings() + widget = cpu.widget + settings() - -- Save current data for the next run. - cpu.last_active = active - cpu.last_total = total + -- Save current data for the next run. + helpers.set_map("cpuactive", active) + helpers.set_map("cputotal", total) + end end - newtimer("cpu", timeout, update) + helpers.newtimer("cpu", timeout, update) return cpu.widget end diff --git a/widgets/fs.lua b/widgets/fs.lua index a1d5d95..8b2886b 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -26,7 +26,8 @@ local setmetatable = setmetatable -- File system disk space usage -- lain.widgets.fs local fs = {} -local fs_notification = nil + +local fs_notification = nil function fs:hide() if fs_notification ~= nil then @@ -41,11 +42,11 @@ function fs:show(t_out) local ws = helpers.read_pipe(helpers.scripts_dir .. "dfs"):gsub("\n*$", "") if fs.followmouse then - fs.notification_preset.screen = mouse.screen + fs_notification_preset.screen = mouse.screen end fs_notification = naughty.notify({ - preset = fs.notification_preset, + preset = fs_notification_preset, text = ws, timeout = t_out }) @@ -66,6 +67,7 @@ local function worker(args) fs.widget = wibox.widget.textbox('') helpers.set_map(partition, false) + helpers.set_map("fsused", 0) function update() fs_info = {} @@ -92,8 +94,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 - widget = fs.widget - settings() + if helpers.get_map("fsused") ~= fs_now.used then + widget = fs.widget + settings() + helpers.set_map("fsused", fs_now.used) + end if fs_now.used >= 99 and not helpers.get_map(partition) then diff --git a/widgets/imap.lua b/widgets/imap.lua index ea763df..350e1ad 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -65,8 +65,10 @@ local function worker(args) _, mailcount = string.gsub(f, "%d+", "") _ = nil - widget = imap.widget - settings() + if mailcount ~= helpers.get_map(mail) then + widget = imap.widget + settings() + end if mailcount >= 1 and mailcount > helpers.get_map(mail) then diff --git a/widgets/maildir.lua b/widgets/maildir.lua index eed6138..8cb821d 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -25,7 +25,7 @@ local setmetatable = setmetatable -- Maildir check -- lain.widgets.maildir -local maildir = {} +local maildir = { total = 0 } local function worker(args) local args = args or {} @@ -65,7 +65,7 @@ local function worker(args) end until line == nil - p:close() + p:close() table.sort(boxes) newmail = "no mail" @@ -88,8 +88,10 @@ local function worker(args) end end - widget = maildir.widget - settings() + if maildir.total ~= total then + widget = maildir.widget + settings() + end end newtimer(mailpath, timeout, update, true) diff --git a/widgets/mem.lua b/widgets/mem.lua index f6213b2..dc72279 100644 --- a/widgets/mem.lua +++ b/widgets/mem.lua @@ -7,27 +7,33 @@ --]] -local newtimer = require("lain.helpers").newtimer +local helpers = require("lain.helpers") +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) +-- Memory usage -- lain.widgets.mem local mem = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 2 + local timeout = args.timeout or 1 local settings = args.settings or function() end mem.widget = wibox.widget.textbox('') + helpers.set_map("mem_last_total", 0) + helpers.set_map("mem_last_free", 0) + helpers.set_map("mem_last_buf", 0) + helpers.set_map("mem_last_cache", 0) + helpers.set_map("mem_last_swap", 0) + helpers.set_map("mem_last_swapf", 0) + function update() mem_now = {} for line in io.lines("/proc/meminfo") @@ -44,14 +50,29 @@ local function worker(args) end end - mem_now.used = mem_now.total - (mem_now.free + mem_now.buf + mem_now.cache) - mem_now.swapused = mem_now.swap - mem_now.swapf + if mem_now.total ~= helpers.set_map("mem_last_total") + or mem_now.free ~= helpers.set_map("mem_last_free") + or mem_now.buf ~= helpers.set_map("mem_last_buf") + or mem_now.cache ~= helpers.set_map("mem_last_cache") + or mem_now.swap ~= helpers.set_map("mem_last_swap") + or mem_now.swapf ~= helpers.set_map("mem_last_swapf") + then + mem_now.used = mem_now.total - (mem_now.free + mem_now.buf + mem_now.cache) + mem_now.swapused = mem_now.swap - mem_now.swapf - widget = mem.widget - settings() + widget = mem.widget + settings() + + helpers.set_map("mem_last_total", mem_now.total) + helpers.set_map("mem_last_free", mem_now.free) + helpers.set_map("mem_last_buf", mem_now.buf) + helpers.set_map("mem_last_cache", mem_now.cache) + helpers.set_map("mem_last_swap", mem_now.swap) + helpers.set_map("mem_last_swapf", mem_now.swapf) + end end - newtimer("mem", timeout, update) + helpers.newtimer("mem", timeout, update) return mem.widget end diff --git a/widgets/mpd.lua b/widgets/mpd.lua index c437347..1d2c617 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -30,7 +30,7 @@ local mpd = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 2 + local timeout = args.timeout or 1 local password = args.password or "" local host = args.host or "127.0.0.1" local port = args.port or "6600" @@ -49,10 +49,11 @@ local function worker(args) mpd_notification_preset = { title = "Now playing", - timeout = 6 + timeout = 5 } - helpers.set_map("current mpd track", nil) + helpers.set_map("current mpd track", "") + helpers.set_map("current mpd file", "") function mpd.update() async.request(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh, function (f) @@ -84,8 +85,13 @@ local function worker(args) mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist, mpd_now.album, mpd_now.date, mpd_now.title) - widget = mpd.widget - settings() + + if mpd_now.file ~= helpers.get_map("current mpd file") + then + widget = mpd.widget + settings() + helpers.set_map("current mpd file", mpd_now.file) + end if mpd_now.state == "play" then diff --git a/widgets/net.lua b/widgets/net.lua index a578ae4..983da41 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -21,10 +21,7 @@ local setmetatable = setmetatable -- Network infos -- lain.widgets.net -local net = { - last_t = 0, - last_r = 0 -} +local net = {} function net.get_device() local ws = helpers.read_pipe("ip link show | cut -d' ' -f2,9") @@ -38,7 +35,7 @@ end local function worker(args) local args = args or {} - local timeout = args.timeout or 2 + local timeout = args.timeout or 1 local units = args.units or 1024 --kb local notify = args.notify or "on" local screen = args.screen or 1 @@ -49,35 +46,44 @@ local function worker(args) net.widget = wibox.widget.textbox('') helpers.set_map(iface, true) + helpers.set_map("net_t", 0) + helpers.set_map("net_r", 0) function update() - net_now = {} + net_now = { + sent = "0.0", + received = "0.0" + } if iface == "" or string.match(iface, "network off") then iface = net.get_device() end - net_now.carrier = helpers.first_line('/sys/class/net/' .. iface .. - '/carrier') or "0" - net_now.state = helpers.first_line('/sys/class/net/' .. iface .. - '/operstate') or "down" local now_t = helpers.first_line('/sys/class/net/' .. iface .. '/statistics/tx_bytes') or 0 local now_r = helpers.first_line('/sys/class/net/' .. iface .. '/statistics/rx_bytes') or 0 - net_now.sent = (now_t - net.last_t) / timeout / units - net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ",", ".") + if now_t ~= helpers.get_map("net_t") + or now_r ~= helpers.get_map("net_r") then + net_now.carrier = helpers.first_line('/sys/class/net/' .. iface .. + '/carrier') or "0" + net_now.state = helpers.first_line('/sys/class/net/' .. iface .. + '/operstate') or "down" - net_now.received = (now_r - net.last_r) / timeout / units - net_now.received = string.gsub(string.format('%.1f', net_now.received), ",", ".") + net_now.sent = (now_t - net.last_t) / timeout / units + net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ",", ".") - widget = net.widget - settings() + net_now.received = (now_r - net.last_r) / timeout / units + net_now.received = string.gsub(string.format('%.1f', net_now.received), ",", ".") - net.last_t = now_t - net.last_r = now_r + widget = net.widget + settings() + + helpers.set_map("net_t", now_t) + helpers.set_map("net_r", now_r) + end if net_now.carrier ~= "1" and notify == "on" then @@ -99,7 +105,8 @@ local function worker(args) end end - helpers.newtimer(iface, timeout, update) + helpers.newtimer(iface, timeout, update, false) + return net.widget end diff --git a/widgets/sysload.lua b/widgets/sysload.lua index d8e4713..9472235 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -7,8 +7,7 @@ --]] -local newtimer = require("lain.helpers").newtimer - +local helpers = require("lain.helpers") local wibox = require("wibox") local io = { open = io.open } @@ -22,10 +21,13 @@ local sysload = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 2 + local timeout = args.timeout or 1 local settings = args.settings or function() end sysload.widget = wibox.widget.textbox('') + helpers.set_map("load_1", 0) + helpers.set_map("load_5", 0) + helpers.set_map("load_15", 0) function update() local f = io.open("/proc/loadavg") @@ -34,11 +36,21 @@ local function worker(args) load_1, load_5, load_15 = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") - widget = sysload.widget - settings() + if load_1 ~= helpers.get_map("load_1") + or load_5 ~= helpers.get_map("load_5") + or load_15 ~= helpers.get_map("load_15") + then + widget = sysload.widget + settings() + + helpers.set_map("load_1", load_1) + helpers.set_map("load_5", load_5) + helpers.set_map("load_15", load_15) + end end - newtimer("sysload", timeout, update) + helpers.newtimer("sysload", timeout, update) + return sysload.widget end diff --git a/widgets/temp.lua b/widgets/temp.lua index 67c9456..6831588 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -6,8 +6,7 @@ --]] -local newtimer = require("lain.helpers").newtimer - +local helpers = require("lain.helpers") local wibox = require("wibox") local io = { open = io.open } @@ -21,11 +20,12 @@ local temp = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 2 + local timeout = args.timeout or 1 local tempfile = args.tempfile or "/sys/class/thermal/thermal_zone0/temp" local settings = args.settings or function() end temp.widget = wibox.widget.textbox('') + helpers.set_map("temp_last", 0) function update() local f = io.open(tempfile) @@ -37,11 +37,15 @@ local function worker(args) coretemp_now = "N/A" end - widget = temp.widget - settings() + if helpers.get_map("temp_last") ~= coretemp_now then + widget = temp.widget + settings() + helpers.set_map("temp_last", coretemp_now) + end end - newtimer("coretemp", timeout, update) + helpers.newtimer("coretemp", timeout, update) + return temp.widget end diff --git a/wiki b/wiki index d7aa1a7..78879bd 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit d7aa1a7b8428211a1c4c71865fd64302e013d62b +Subproject commit 78879bd1208d713dcbb9216f226a34b51f886421 From 7de62e4d9fe0d3a7521fc72a66c905d6f343c27b Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Mon, 12 Oct 2015 12:24:30 +0200 Subject: [PATCH 546/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index 78879bd..35cc75d 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 78879bd1208d713dcbb9216f226a34b51f886421 +Subproject commit 35cc75dcb382fccdec6941698a1e96cc875fae1f From 554d206f5fbc1e04e8863b07b7e2448163857050 Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Tue, 13 Oct 2015 15:32:29 +0200 Subject: [PATCH 547/572] project was added to OWM FOSS keys list; #146 --- widgets/weather.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/weather.lua b/widgets/weather.lua index 68abae9..baf82d7 100644 --- a/widgets/weather.lua +++ b/widgets/weather.lua @@ -30,7 +30,7 @@ local setmetatable = setmetatable local function worker(args) local weather = {} local args = args or {} - local APPID = args.APPID or 1 -- mandatory + local APPID = args.APPID or "3e321f9414eaedbfab34983bda77a66e" -- lain default local timeout = args.timeout or 900 -- 15 min local timeout_forecast = args.timeout or 86400 -- 24 hrs local current_call = "curl -s 'http://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s&APPID=%s'" From 69ec77e16aa8188062f74ceae785e9f9460006e6 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Mon, 19 Oct 2015 08:48:14 +0200 Subject: [PATCH 548/572] wiki updated! --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index d7aa1a7..35cc75d 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit d7aa1a7b8428211a1c4c71865fd64302e013d62b +Subproject commit 35cc75dcb382fccdec6941698a1e96cc875fae1f From 0b80b45bc9bca17f08e8055d364bac17f96129bd Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Tue, 20 Oct 2015 15:17:44 +0200 Subject: [PATCH 549/572] revert to previous stable --- helpers.lua | 12 +++------- widgets/abase.lua | 19 ++++++---------- widgets/alsa.lua | 17 ++++---------- widgets/alsabar.lua | 54 ++++++++++++++++++++------------------------- widgets/base.lua | 19 +++++++--------- widgets/bat.lua | 49 +++++++++++++++------------------------- widgets/cpu.lua | 37 ++++++++++++++----------------- widgets/fs.lua | 15 +++++-------- widgets/imap.lua | 6 ++--- widgets/maildir.lua | 10 ++++----- widgets/mem.lua | 49 ++++++++++++---------------------------- widgets/mpd.lua | 17 +++++--------- widgets/net.lua | 45 ++++++++++++++++--------------------- widgets/sysload.lua | 24 +++++--------------- widgets/temp.lua | 16 +++++--------- 15 files changed, 142 insertions(+), 247 deletions(-) diff --git a/helpers.lua b/helpers.lua index 503c40e..4e90e16 100644 --- a/helpers.lua +++ b/helpers.lua @@ -76,16 +76,10 @@ end helpers.timer_table = {} -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 - +function helpers.newtimer(name, timeout, fun, nostart) + helpers.timer_table[name] = capi.timer({ timeout = timeout }) helpers.timer_table[name]:connect_signal("timeout", fun) - + helpers.timer_table[name]:start() if not nostart then helpers.timer_table[name]:emit_signal("timeout") end diff --git a/widgets/abase.lua b/widgets/abase.lua index 87af872..98f7818 100644 --- a/widgets/abase.lua +++ b/widgets/abase.lua @@ -6,9 +6,9 @@ --]] -local helpers = require("lain.helpers") -local async = require("lain.asyncshell") -local wibox = require("wibox") +local newtimer = require("lain.helpers").newtimer +local async = require("lain.asyncshell") +local wibox = require("wibox") local setmetatable = setmetatable @@ -19,26 +19,21 @@ local setmetatable = setmetatable local function worker(args) local abase = {} local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 5 local cmd = args.cmd or "" local settings = args.settings or function() end abase.widget = wibox.widget.textbox('') - helpers.set_map(cmd, '') function abase.update() async.request(cmd, function(f) output = f - - if helpers.get_map(cmd) ~= output then - widget = abase.widget - settings() - helpers.set_map(cmd, output) - end + widget = abase.widget + settings() end) end - helpers.newtimer(cmd, timeout, abase.update) + newtimer(cmd, timeout, abase.update) return setmetatable(abase, { __index = abase.widget }) end diff --git a/widgets/alsa.lua b/widgets/alsa.lua index 0bb2059..85d5311 100644 --- a/widgets/alsa.lua +++ b/widgets/alsa.lua @@ -19,14 +19,11 @@ local setmetatable = setmetatable -- ALSA volume -- lain.widgets.alsa -local alsa = { - level = "0", - status = "off", -} +local alsa = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 5 local settings = args.settings or function() end alsa.cmd = args.cmd or "amixer" @@ -57,14 +54,8 @@ local function worker(args) end end - if alsa.level ~= volume_now.level or alsa.status ~= volume_now.status - then - widget = alsa.widget - settings() - - alsa.level = volume_now.level - alsa.status = volume_now.status - end + widget = alsa.widget + settings() end timer_id = string.format("alsa-%s-%s", alsa.cmd, alsa.channel) diff --git a/widgets/alsabar.lua b/widgets/alsabar.lua index fc45c72..c7498d2 100644 --- a/widgets/alsabar.lua +++ b/widgets/alsabar.lua @@ -47,8 +47,7 @@ local alsabar = { }, _current_level = 0, - _muted = false, - _status = "off" + _muted = false } function alsabar.notify() @@ -57,7 +56,7 @@ function alsabar.notify() local preset = { title = "", text = "", - timeout = 1, + timeout = 5, screen = alsabar.notifications.screen, font = alsabar.notifications.font .. " " .. alsabar.notifications.font_size, @@ -95,7 +94,7 @@ end local function worker(args) local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 5 local settings = args.settings or function() end local width = args.width or 63 local height = args.heigth or 1 @@ -128,33 +127,28 @@ local function worker(args) -- Capture mixer control state: [5%] ... ... [on] local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") - volu = tonumber(volu) or 0 - if mute == "" then mute = "off" - - if alsabar._current_level ~= volu or alsabar._status ~= mute then - - alsabar._current_level = volu - alsabar._status = mute - - alsabar.bar:set_value(alsabar._current_level / 100) - - if not mute and volu == 0 or mute == "off" - then - alsabar._muted = true - alsabar.tooltip:set_text (" [Muted] ") - alsabar.bar:set_color(alsabar.colors.mute) - else - alsabar._muted = false - alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu)) - alsabar.bar:set_color(alsabar.colors.unmute) - end - - volume_now = {} - volume_now.level = volu - volume_now.status = mute - - settings() + if volu == nil then + volu = 0 + mute = "off" end + + alsabar._current_level = tonumber(volu) + alsabar.bar:set_value(alsabar._current_level / 100) + if not mute and tonumber(volu) == 0 or mute == "off" + then + alsabar._muted = true + alsabar.tooltip:set_text (" [Muted] ") + alsabar.bar:set_color(alsabar.colors.mute) + else + alsabar._muted = false + alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu)) + alsabar.bar:set_color(alsabar.colors.unmute) + end + + volume_now = {} + volume_now.level = tonumber(volu) + volume_now.status = mute + settings() end alsabar.bar:buttons (awful.util.table.join ( diff --git a/widgets/base.lua b/widgets/base.lua index 88478b0..2f377f7 100644 --- a/widgets/base.lua +++ b/widgets/base.lua @@ -6,7 +6,9 @@ --]] -local helpers = require("lain.helpers") +local newtimer = require("lain.helpers").newtimer +local read_pipe = require("lain.helpers").read_pipe + local wibox = require("wibox") local setmetatable = setmetatable @@ -17,24 +19,19 @@ local setmetatable = setmetatable local function worker(args) local base = {} local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 5 local cmd = args.cmd or "" local settings = args.settings or function() end base.widget = wibox.widget.textbox('') - helpers.set_map(cmd, '') function base.update() - output = helpers.read_pipe(cmd) - - if helpers.get_map(cmd) ~= output then - widget = base.widget - settings() - helpers.set_map(cmd, output) - end + output = read_pipe(cmd) + widget = base.widget + settings() end - helpers.newtimer(cmd, timeout, base.update) + newtimer(cmd, timeout, base.update) return setmetatable(base, { __index = base.widget }) end diff --git a/widgets/bat.lua b/widgets/bat.lua index d18af87..626239b 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -7,7 +7,9 @@ --]] -local helpers = require("lain.helpers") +local newtimer = require("lain.helpers").newtimer +local first_line = require("lain.helpers").first_line + local naughty = require("naughty") local wibox = require("wibox") @@ -19,9 +21,9 @@ local setmetatable = setmetatable -- Battery infos -- lain.widgets.bat +local bat = {} local function worker(args) - local bat = {} local args = args or {} local timeout = args.timeout or 30 local battery = args.battery or "BAT0" @@ -46,11 +48,6 @@ local function worker(args) bg = "#FFFFFF" } - helpers.set_map(battery .. "status", "N/A") - helpers.set_map(battery .. "perc", "N/A") - helpers.set_map(battery .. "time", "N/A") - helpers.set_map(battery .. "watt", "N/A") - function update() bat_now = { status = "Not present", @@ -61,22 +58,22 @@ local function worker(args) local bstr = "/sys/class/power_supply/" .. battery - local present = helpers.first_line(bstr .. "/present") + local present = first_line(bstr .. "/present") if present == "1" then - local rate = helpers.first_line(bstr .. "/power_now") or - helpers.first_line(bstr .. "/current_now") + local rate = first_line(bstr .. "/power_now") or + first_line(bstr .. "/current_now") - local ratev = helpers.first_line(bstr .. "/voltage_now") + local ratev = first_line(bstr .. "/voltage_now") - local rem = helpers.first_line(bstr .. "/energy_now") or - helpers.first_line(bstr .. "/charge_now") + local rem = first_line(bstr .. "/energy_now") or + first_line(bstr .. "/charge_now") - local tot = helpers.first_line(bstr .. "/energy_full") or - helpers.first_line(bstr .. "/charge_full") + local tot = first_line(bstr .. "/energy_full") or + first_line(bstr .. "/charge_full") - bat_now.status = helpers.first_line(bstr .. "/status") or "N/A" + bat_now.status = first_line(bstr .. "/status") or "N/A" rate = tonumber(rate) or 1 ratev = tonumber(ratev) @@ -100,7 +97,7 @@ local function worker(args) bat_now.time = string.format("%02d:%02d", hrs, min) - bat_now.perc = helpers.first_line(bstr .. "/capacity") + bat_now.perc = first_line(bstr .. "/capacity") if not bat_now.perc then local perc = (rem / tot) * 100 @@ -118,21 +115,11 @@ local function worker(args) else bat_now.watt = "N/A" end + end - if bat_now.status ~= helpers.get_map(battery .. "status") - or bat_now.perc ~= helpers.get_map(battery .. "perc") - or bat_now.time ~= helpers.get_map(battery .. "time") - or bat_now.watt ~= helpers.get_map(battery .. "watt") - then - widget = bat.widget - settings() - - helpers.set_map(battery .. "status", bat_now.status) - helpers.set_map(battery .. "perc", bat_now.perc) - helpers.set_map(battery .. "time", bat_now.time) - helpers.set_map(battery .. "watt", bat_now.watt) - end + widget = bat.widget + settings() -- notifications for low and critical states if bat_now.status == "Discharging" and notify == "on" and bat_now.perc ~= nil @@ -154,7 +141,7 @@ local function worker(args) end end - helpers.newtimer(battery, timeout, update) + newtimer(battery, timeout, update) return bat.widget end diff --git a/widgets/cpu.lua b/widgets/cpu.lua index 1554443..ec84101 100644 --- a/widgets/cpu.lua +++ b/widgets/cpu.lua @@ -7,13 +7,16 @@ --]] -local helpers = require("lain.helpers") +local first_line = require("lain.helpers").first_line +local newtimer = require("lain.helpers").newtimer + local wibox = require("wibox") local math = { ceil = math.ceil } local string = { format = string.format, gmatch = string.gmatch } local tostring = tostring + local setmetatable = setmetatable -- CPU usage @@ -25,18 +28,16 @@ local cpu = { local function worker(args) local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 2 local settings = args.settings or function() end cpu.widget = wibox.widget.textbox('') - helpers.set_map("cpuactive", 0) - helpers.set_map("cputotal", 0) function update() -- Read the amount of time the CPUs have spent performing -- different kinds of work. Read the first line of /proc/stat -- which is the sum of all CPUs. - local times = helpers.first_line("/proc/stat") + local times = first_line("/proc/stat") local at = 1 local idle = 0 local total = 0 @@ -53,26 +54,22 @@ local function worker(args) end local active = total - idle - if helpers.get_map("cpuactive") ~= active - or helpers.get_map("cputotal") ~= total - then - -- Read current data and calculate relative values. - local dactive = active - cpu.last_active - local dtotal = total - cpu.last_total + -- Read current data and calculate relative values. + local dactive = active - cpu.last_active + local dtotal = total - cpu.last_total - cpu_now = {} - cpu_now.usage = tostring(math.ceil((dactive / dtotal) * 100)) + cpu_now = {} + cpu_now.usage = tostring(math.ceil((dactive / dtotal) * 100)) - widget = cpu.widget - settings() + widget = cpu.widget + settings() - -- Save current data for the next run. - helpers.set_map("cpuactive", active) - helpers.set_map("cputotal", total) - end + -- Save current data for the next run. + cpu.last_active = active + cpu.last_total = total end - helpers.newtimer("cpu", timeout, update) + newtimer("cpu", timeout, update) return cpu.widget end diff --git a/widgets/fs.lua b/widgets/fs.lua index 8b2886b..a1d5d95 100644 --- a/widgets/fs.lua +++ b/widgets/fs.lua @@ -26,8 +26,7 @@ local setmetatable = setmetatable -- File system disk space usage -- lain.widgets.fs local fs = {} - -local fs_notification = nil +local fs_notification = nil function fs:hide() if fs_notification ~= nil then @@ -42,11 +41,11 @@ function fs:show(t_out) local ws = helpers.read_pipe(helpers.scripts_dir .. "dfs"):gsub("\n*$", "") if fs.followmouse then - fs_notification_preset.screen = mouse.screen + fs.notification_preset.screen = mouse.screen end fs_notification = naughty.notify({ - preset = fs_notification_preset, + preset = fs.notification_preset, text = ws, timeout = t_out }) @@ -67,7 +66,6 @@ local function worker(args) fs.widget = wibox.widget.textbox('') helpers.set_map(partition, false) - helpers.set_map("fsused", 0) function update() fs_info = {} @@ -94,11 +92,8 @@ 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 - if helpers.get_map("fsused") ~= fs_now.used then - widget = fs.widget - settings() - helpers.set_map("fsused", fs_now.used) - end + widget = fs.widget + settings() if fs_now.used >= 99 and not helpers.get_map(partition) then diff --git a/widgets/imap.lua b/widgets/imap.lua index 350e1ad..ea763df 100644 --- a/widgets/imap.lua +++ b/widgets/imap.lua @@ -65,10 +65,8 @@ local function worker(args) _, mailcount = string.gsub(f, "%d+", "") _ = nil - if mailcount ~= helpers.get_map(mail) then - widget = imap.widget - settings() - end + widget = imap.widget + settings() if mailcount >= 1 and mailcount > helpers.get_map(mail) then diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 8cb821d..eed6138 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -25,7 +25,7 @@ local setmetatable = setmetatable -- Maildir check -- lain.widgets.maildir -local maildir = { total = 0 } +local maildir = {} local function worker(args) local args = args or {} @@ -65,7 +65,7 @@ local function worker(args) end until line == nil - p:close() + p:close() table.sort(boxes) newmail = "no mail" @@ -88,10 +88,8 @@ local function worker(args) end end - if maildir.total ~= total then - widget = maildir.widget - settings() - end + widget = maildir.widget + settings() end newtimer(mailpath, timeout, update, true) diff --git a/widgets/mem.lua b/widgets/mem.lua index dc72279..f6213b2 100644 --- a/widgets/mem.lua +++ b/widgets/mem.lua @@ -7,33 +7,27 @@ --]] -local helpers = require("lain.helpers") -local wibox = require("wibox") +local newtimer = require("lain.helpers").newtimer -local io = { lines = io.lines } -local math = { floor = math.floor } -local string = { gmatch = string.gmatch } +local wibox = require("wibox") -local setmetatable = setmetatable +local io = { lines = io.lines } +local math = { floor = math.floor } +local string = { gmatch = string.gmatch } --- Memory usage +local setmetatable = setmetatable + +-- Memory usage (ignoring caches) -- lain.widgets.mem local mem = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 2 local settings = args.settings or function() end mem.widget = wibox.widget.textbox('') - helpers.set_map("mem_last_total", 0) - helpers.set_map("mem_last_free", 0) - helpers.set_map("mem_last_buf", 0) - helpers.set_map("mem_last_cache", 0) - helpers.set_map("mem_last_swap", 0) - helpers.set_map("mem_last_swapf", 0) - function update() mem_now = {} for line in io.lines("/proc/meminfo") @@ -50,29 +44,14 @@ local function worker(args) end end - if mem_now.total ~= helpers.set_map("mem_last_total") - or mem_now.free ~= helpers.set_map("mem_last_free") - or mem_now.buf ~= helpers.set_map("mem_last_buf") - or mem_now.cache ~= helpers.set_map("mem_last_cache") - or mem_now.swap ~= helpers.set_map("mem_last_swap") - or mem_now.swapf ~= helpers.set_map("mem_last_swapf") - then - 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.used = mem_now.total - (mem_now.free + mem_now.buf + mem_now.cache) + mem_now.swapused = mem_now.swap - mem_now.swapf - widget = mem.widget - settings() - - helpers.set_map("mem_last_total", mem_now.total) - helpers.set_map("mem_last_free", mem_now.free) - helpers.set_map("mem_last_buf", mem_now.buf) - helpers.set_map("mem_last_cache", mem_now.cache) - helpers.set_map("mem_last_swap", mem_now.swap) - helpers.set_map("mem_last_swapf", mem_now.swapf) - end + widget = mem.widget + settings() end - helpers.newtimer("mem", timeout, update) + newtimer("mem", timeout, update) return mem.widget end diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 1d2c617..5af898b 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -30,7 +30,7 @@ local mpd = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 2 local password = args.password or "" local host = args.host or "127.0.0.1" local port = args.port or "6600" @@ -49,11 +49,10 @@ local function worker(args) mpd_notification_preset = { title = "Now playing", - timeout = 5 + timeout = 6 } - helpers.set_map("current mpd track", "") - helpers.set_map("current mpd file", "") + helpers.set_map("current mpd track", nil) function mpd.update() async.request(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh, function (f) @@ -72,7 +71,6 @@ local function worker(args) 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) @@ -85,13 +83,8 @@ local function worker(args) mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist, mpd_now.album, mpd_now.date, mpd_now.title) - - if mpd_now.file ~= helpers.get_map("current mpd file") - then - widget = mpd.widget - settings() - helpers.set_map("current mpd file", mpd_now.file) - end + widget = mpd.widget + settings() if mpd_now.state == "play" then diff --git a/widgets/net.lua b/widgets/net.lua index 983da41..a578ae4 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -21,7 +21,10 @@ local setmetatable = setmetatable -- Network infos -- lain.widgets.net -local net = {} +local net = { + last_t = 0, + last_r = 0 +} function net.get_device() local ws = helpers.read_pipe("ip link show | cut -d' ' -f2,9") @@ -35,7 +38,7 @@ end local function worker(args) local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 2 local units = args.units or 1024 --kb local notify = args.notify or "on" local screen = args.screen or 1 @@ -46,44 +49,35 @@ local function worker(args) net.widget = wibox.widget.textbox('') helpers.set_map(iface, true) - helpers.set_map("net_t", 0) - helpers.set_map("net_r", 0) function update() - net_now = { - sent = "0.0", - received = "0.0" - } + net_now = {} if iface == "" or string.match(iface, "network off") then iface = net.get_device() end + net_now.carrier = helpers.first_line('/sys/class/net/' .. iface .. + '/carrier') or "0" + net_now.state = helpers.first_line('/sys/class/net/' .. iface .. + '/operstate') or "down" local now_t = helpers.first_line('/sys/class/net/' .. iface .. '/statistics/tx_bytes') or 0 local now_r = helpers.first_line('/sys/class/net/' .. iface .. '/statistics/rx_bytes') or 0 - if now_t ~= helpers.get_map("net_t") - or now_r ~= helpers.get_map("net_r") then - net_now.carrier = helpers.first_line('/sys/class/net/' .. iface .. - '/carrier') or "0" - net_now.state = helpers.first_line('/sys/class/net/' .. iface .. - '/operstate') or "down" + net_now.sent = (now_t - net.last_t) / timeout / units + net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ",", ".") - net_now.sent = (now_t - net.last_t) / timeout / units - net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ",", ".") + net_now.received = (now_r - net.last_r) / timeout / units + net_now.received = string.gsub(string.format('%.1f', net_now.received), ",", ".") - net_now.received = (now_r - net.last_r) / timeout / units - net_now.received = string.gsub(string.format('%.1f', net_now.received), ",", ".") + widget = net.widget + settings() - widget = net.widget - settings() - - helpers.set_map("net_t", now_t) - helpers.set_map("net_r", now_r) - end + net.last_t = now_t + net.last_r = now_r if net_now.carrier ~= "1" and notify == "on" then @@ -105,8 +99,7 @@ local function worker(args) end end - helpers.newtimer(iface, timeout, update, false) - + helpers.newtimer(iface, timeout, update) return net.widget end diff --git a/widgets/sysload.lua b/widgets/sysload.lua index 9472235..d8e4713 100644 --- a/widgets/sysload.lua +++ b/widgets/sysload.lua @@ -7,7 +7,8 @@ --]] -local helpers = require("lain.helpers") +local newtimer = require("lain.helpers").newtimer + local wibox = require("wibox") local io = { open = io.open } @@ -21,13 +22,10 @@ local sysload = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 2 local settings = args.settings or function() end sysload.widget = wibox.widget.textbox('') - helpers.set_map("load_1", 0) - helpers.set_map("load_5", 0) - helpers.set_map("load_15", 0) function update() local f = io.open("/proc/loadavg") @@ -36,21 +34,11 @@ local function worker(args) load_1, load_5, load_15 = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)") - if load_1 ~= helpers.get_map("load_1") - or load_5 ~= helpers.get_map("load_5") - or load_15 ~= helpers.get_map("load_15") - then - widget = sysload.widget - settings() - - helpers.set_map("load_1", load_1) - helpers.set_map("load_5", load_5) - helpers.set_map("load_15", load_15) - end + widget = sysload.widget + settings() end - helpers.newtimer("sysload", timeout, update) - + newtimer("sysload", timeout, update) return sysload.widget end diff --git a/widgets/temp.lua b/widgets/temp.lua index 6831588..67c9456 100644 --- a/widgets/temp.lua +++ b/widgets/temp.lua @@ -6,7 +6,8 @@ --]] -local helpers = require("lain.helpers") +local newtimer = require("lain.helpers").newtimer + local wibox = require("wibox") local io = { open = io.open } @@ -20,12 +21,11 @@ local temp = {} local function worker(args) local args = args or {} - local timeout = args.timeout or 1 + local timeout = args.timeout or 2 local tempfile = args.tempfile or "/sys/class/thermal/thermal_zone0/temp" local settings = args.settings or function() end temp.widget = wibox.widget.textbox('') - helpers.set_map("temp_last", 0) function update() local f = io.open(tempfile) @@ -37,15 +37,11 @@ local function worker(args) coretemp_now = "N/A" end - if helpers.get_map("temp_last") ~= coretemp_now then - widget = temp.widget - settings() - helpers.set_map("temp_last", coretemp_now) - end + widget = temp.widget + settings() end - helpers.newtimer("coretemp", timeout, update) - + newtimer("coretemp", timeout, update) return temp.widget end From 2b8a2bc2ae974072cb48e293db0c05e9517cff06 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 25 Oct 2015 10:02:40 +0100 Subject: [PATCH 550/572] forgot to refix #141 --- widgets/bat.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 626239b..61828ec 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -21,9 +21,9 @@ local setmetatable = setmetatable -- Battery infos -- lain.widgets.bat -local bat = {} local function worker(args) + local bat = {} local args = args or {} local timeout = args.timeout or 30 local battery = args.battery or "BAT0" @@ -143,7 +143,7 @@ local function worker(args) newtimer(battery, timeout, update) - return bat.widget + return setmetatable(bat, { __index = bat.widget }) end -return setmetatable(bat, { __call = function(_, ...) return worker(...) end }) +return setmetatable({}, { __call = function(_, ...) return worker(...) end }) From 305e0e57b20e324f30758fd2c8202180dd8908d6 Mon Sep 17 00:00:00 2001 From: Dario Gjorgjevski Date: Mon, 2 Nov 2015 22:50:32 +0100 Subject: [PATCH 551/572] improve icon and notification text handling --- widgets/weather.lua | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/widgets/weather.lua b/widgets/weather.lua index baf82d7..ab87ff8 100644 --- a/widgets/weather.lua +++ b/widgets/weather.lua @@ -46,11 +46,13 @@ local function worker(args) function (day, desc, tmin, tmax) return string.format("%s: %s, %d - %d ", day, desc, tmin, tmax) end + local weather_na_markup = args.weather_na_markup or " N/A " local followmouse = args.followmouse or false local settings = args.settings or function() end - weather.widget = wibox.widget.textbox('') - weather.icon = wibox.widget.imagebox() + weather.widget = wibox.widget.textbox(weather_na_text) + weather.icon_path = icons_path .. "na.png" + weather.icon = wibox.widget.imagebox(weather.icon_path) function weather.show(t_out) weather.hide() @@ -60,7 +62,8 @@ local function worker(args) end weather.notification = naughty.notify({ - text = weather.notification_text, + text = weather.notification_text + or "Waiting for the server to respond...", icon = weather.icon_path, timeout = t_out, preset = notification_preset @@ -106,7 +109,6 @@ local function worker(args) end end else - weather.icon_path = icons_path .. "na.png" weather.notification_text = "API/connection error or bad/not set city ID" end end) @@ -120,13 +122,14 @@ local function worker(args) if not err and weather_now ~= nil and tonumber(weather_now["cod"]) == 200 then weather.icon_path = icons_path .. weather_now["weather"][1]["icon"] .. ".png" - weather.icon:set_image(weather.icon_path) widget = weather.widget settings() else - weather.widget._layout.text = " N/A " -- tries to avoid textbox bugs - weather.icon:set_image(icons_path .. "na.png") + weather.icon_path = icons_path .. "na.png" + weather.widget:set_markup(weather_na_markup) end + + weather.icon:set_image(weather.icon_path) end) end From 9f8eb5d0a2fa32b81df9bd70cd0761773955b724 Mon Sep 17 00:00:00 2001 From: Dario Gjorgjevski Date: Mon, 2 Nov 2015 22:51:57 +0100 Subject: [PATCH 552/572] fix variable name --- widgets/weather.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/weather.lua b/widgets/weather.lua index ab87ff8..173601a 100644 --- a/widgets/weather.lua +++ b/widgets/weather.lua @@ -50,7 +50,7 @@ local function worker(args) local followmouse = args.followmouse or false local settings = args.settings or function() end - weather.widget = wibox.widget.textbox(weather_na_text) + weather.widget = wibox.widget.textbox(weather_na_markup) weather.icon_path = icons_path .. "na.png" weather.icon = wibox.widget.imagebox(weather.icon_path) From d659c34974ee8e2c136bbac2424c5d95b889492d Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Wed, 11 Nov 2015 18:25:51 +0100 Subject: [PATCH 553/572] #150 fix; wiki updated --- widgets/net.lua | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/widgets/net.lua b/widgets/net.lua index a578ae4..702937c 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -21,22 +21,20 @@ local setmetatable = setmetatable -- Network infos -- lain.widgets.net -local net = { - last_t = 0, - last_r = 0 -} - -function net.get_device() - local ws = helpers.read_pipe("ip link show | cut -d' ' -f2,9") - ws = ws:match("%w+: UP") or ws:match("ppp%w+: UNKNOWN") - if ws ~= nil then - return ws:match("(%w+):") - else - return "network off" - end -end local function worker(args) + local net = { last_t = 0, last_r = 0 } + + function net.get_device() + local ws = helpers.read_pipe("ip link show | cut -d' ' -f2,9") + ws = ws:match("%w+: UP") or ws:match("ppp%w+: UNKNOWN") + if ws ~= nil then + return ws:match("(%w+):") + else + return "network off" + end + end + local args = args or {} local timeout = args.timeout or 2 local units = args.units or 1024 --kb @@ -100,7 +98,8 @@ local function worker(args) end helpers.newtimer(iface, timeout, update) - return net.widget + + return setmetatable(net, { __index = net.widget }) end -return setmetatable(net, { __call = function(_, ...) return worker(...) end }) +return setmetatable({}, { __call = function(_, ...) return worker(...) end }) From d58ac139b6198118314a4fe640abe18e3f816380 Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Wed, 11 Nov 2015 18:30:59 +0100 Subject: [PATCH 554/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index 35cc75d..cb5d545 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 35cc75dcb382fccdec6941698a1e96cc875fae1f +Subproject commit cb5d5455987533d08c37fd17fec7dfa757b7130a From da1410677b338d57f4e4082587197b3a38985207 Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Wed, 11 Nov 2015 18:52:40 +0100 Subject: [PATCH 555/572] #150 fix 2 --- widgets/net.lua | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/widgets/net.lua b/widgets/net.lua index 702937c..af823a8 100644 --- a/widgets/net.lua +++ b/widgets/net.lua @@ -35,14 +35,13 @@ local function worker(args) end end - local args = args or {} - local timeout = args.timeout or 2 - local units = args.units or 1024 --kb - local notify = args.notify or "on" - local screen = args.screen or 1 + local args = args or {} + local timeout = args.timeout or 2 + local units = args.units or 1024 --kb + local notify = args.notify or "on" + local screen = args.screen or 1 local settings = args.settings or function() end - - iface = args.iface or net.get_device() + local iface = args.iface or net.get_device() net.widget = wibox.widget.textbox('') From 11e448e5e2260fbbcb63f1303bbc00d0d8ddcbbd Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Thu, 12 Nov 2015 11:51:53 +0100 Subject: [PATCH 556/572] (re)merged #142 --- widgets/mpd.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/widgets/mpd.lua b/widgets/mpd.lua index 5af898b..1972050 100644 --- a/widgets/mpd.lua +++ b/widgets/mpd.lua @@ -59,6 +59,7 @@ local function worker(args) mpd_now = { state = "N/A", file = "N/A", + name = "N/A", artist = "N/A", title = "N/A", album = "N/A", @@ -71,6 +72,7 @@ local function worker(args) 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) From 418e475b5b4eb8404e115d74fdb3756169877278 Mon Sep 17 00:00:00 2001 From: Sudo Nice Date: Wed, 18 Nov 2015 11:02:16 +0300 Subject: [PATCH 557/572] helpers: spairs() added --- helpers.lua | 20 ++++++++++++++++++++ widgets/maildir.lua | 7 +++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/helpers.lua b/helpers.lua index 4e90e16..4ece329 100644 --- a/helpers.lua +++ b/helpers.lua @@ -13,6 +13,7 @@ local io = { open = io.open, lines = io.lines, popen = io.popen } local rawget = rawget +local table = { sort = table.sort } -- Lain helper functions for internal use -- lain.helpers @@ -113,4 +114,23 @@ end -- }}} +--{{{ Iterate over table of records sorted by keys +function helpers.spairs(t) + -- collect the keys + local keys = {} + for k in pairs(t) do keys[#keys+1] = k end + + table.sort(keys) + + -- return the iterator function + local i = 0 + return function() + i = i + 1 + if keys[i] then + return keys[i], t[keys[i]] + end + end +end +--}}} + return helpers diff --git a/widgets/maildir.lua b/widgets/maildir.lua index eed6138..79d28b5 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -9,6 +9,7 @@ local newtimer = require("lain.helpers").newtimer local read_pipe = require("lain.helpers").read_pipe +local spairs = require("lain.helpers").spairs local wibox = require("wibox") @@ -19,7 +20,6 @@ local os = { getenv = os.getenv } local pairs = pairs local string = { len = string.len, match = string.match } -local table = { sort = table.sort } local setmetatable = setmetatable @@ -65,14 +65,13 @@ local function worker(args) end until line == nil - p:close() - table.sort(boxes) + p:close() newmail = "no mail" -- Count the total number of mails irrespective of where it was found total = 0 - for box, number in pairs(boxes) + for box, number in spairs(boxes) do -- Add this box only if it's not to be ignored. if not util.element_in_table(box, ignore_boxes) From 1539a1b5d4394c6a397e3a68f36f9ba66d161a4b Mon Sep 17 00:00:00 2001 From: Lee Watson Date: Sat, 21 Nov 2015 11:49:22 +0000 Subject: [PATCH 558/572] Add ability to run an external mail update command, and support multi-level maildirs containing multiple accounts. --- widgets/maildir.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 79d28b5..4f3fc79 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -33,14 +33,19 @@ local function worker(args) local mailpath = args.mailpath or os.getenv("HOME") .. "/Mail" local ignore_boxes = args.ignore_boxes or {} local settings = args.settings or function() end + local ext_mail_cmd = args.external_mail_cmd maildir.widget = wibox.widget.textbox('') function update() + if ext_mail_cmd ~= nil + then + awful.util.spawn(ext_mail_cmd) + end -- Find pathes to mailboxes. local p = io.popen("find " .. mailpath .. - " -mindepth 1 -maxdepth 1 -type d" .. - " -not -name .git") + " -mindepth 1 -maxdepth 2 -type d" .. + " -not -name .git") local boxes = {} repeat line = p:read("*l") @@ -56,7 +61,7 @@ local function worker(args) "-not -name '.*' -printf a") -- Strip off leading mailpath. - local box = string.match(line, mailpath .. "/*([^/]+)") + local box = string.match(line, mailpath .. "/(.*)") local nummails = string.len(mailstring) if nummails > 0 then From 94204ac2dad82e8b9b206cb596b3a27fb8379640 Mon Sep 17 00:00:00 2001 From: Lee Watson Date: Sat, 21 Nov 2015 11:53:19 +0000 Subject: [PATCH 559/572] Styling to match upstream --- widgets/maildir.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 4f3fc79..12f3545 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -44,8 +44,8 @@ local function worker(args) end -- Find pathes to mailboxes. local p = io.popen("find " .. mailpath .. - " -mindepth 1 -maxdepth 2 -type d" .. - " -not -name .git") + " -mindepth 1 -maxdepth 2 -type d" .. + " -not -name .git") local boxes = {} repeat line = p:read("*l") From 35957f391460172500255ffe20cf1b34622d93f1 Mon Sep 17 00:00:00 2001 From: Lee Watson Date: Sat, 21 Nov 2015 11:56:32 +0000 Subject: [PATCH 560/572] Fix missing awful --- widgets/maildir.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 12f3545..2476601 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -13,6 +13,7 @@ local spairs = require("lain.helpers").spairs local wibox = require("wibox") +local awful = require("awful") local util = require("lain.util") local io = { popen = io.popen } From 7dd6443f0a87e0816f5b6323a23bf3e8ca364aee Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Sun, 22 Nov 2015 09:16:35 +0100 Subject: [PATCH 561/572] maildir: spaceline added --- widgets/maildir.lua | 1 + wiki | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/widgets/maildir.lua b/widgets/maildir.lua index 2476601..c9937b4 100644 --- a/widgets/maildir.lua +++ b/widgets/maildir.lua @@ -43,6 +43,7 @@ local function worker(args) then awful.util.spawn(ext_mail_cmd) end + -- Find pathes to mailboxes. local p = io.popen("find " .. mailpath .. " -mindepth 1 -maxdepth 2 -type d" .. diff --git a/wiki b/wiki index cb5d545..cefdc88 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit cb5d5455987533d08c37fd17fec7dfa757b7130a +Subproject commit cefdc887c46f0f7c5d837d1449927e7dbf66b19e From fca030d084f6b1f37e11d6f5eecbe7d731c5fb5f Mon Sep 17 00:00:00 2001 From: aajjbb Date: Sat, 2 Jan 2016 22:14:37 -0200 Subject: [PATCH 562/572] fixing issue of battery widget showing above 100% percentage values --- widgets/bat.lua | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 61828ec..60bd71c 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -96,20 +96,21 @@ local function worker(args) if min < 0 then min = 0 elseif min > 59 then min = 59 end bat_now.time = string.format("%02d:%02d", hrs, min) + + local perc = tonumber(first_line(bstr .. "/capacity")) - bat_now.perc = first_line(bstr .. "/capacity") - - if not bat_now.perc then - local perc = (rem / tot) * 100 - if perc <= 100 then - bat_now.perc = string.format("%d", perc) - elseif perc > 100 then - bat_now.perc = "100" - elseif perc < 0 then - bat_now.perc = "0" - end - end - + if not perc then + perc = (rem / tot) * 100 + end + + if perc <= 100 then + bat_now.perc = string.format("%d", perc) + elseif perc > 100 then + bat_now.perc = "100" + elseif perc < 0 then + bat_now.perc = "0" + end + if rate ~= nil and ratev ~= nil then bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) else From 99fb25a3c7edca96e01de0629c8599a83ad87f9d Mon Sep 17 00:00:00 2001 From: aajjbb Date: Sat, 2 Jan 2016 22:19:21 -0200 Subject: [PATCH 563/572] erasing .orig files --- widgets/contrib/init.lua.orig | 23 ----- widgets/contrib/moc.lua.orig | 117 ---------------------- widgets/contrib/task.lua.orig | 176 ---------------------------------- 3 files changed, 316 deletions(-) delete mode 100644 widgets/contrib/init.lua.orig delete mode 100644 widgets/contrib/moc.lua.orig delete mode 100644 widgets/contrib/task.lua.orig diff --git a/widgets/contrib/init.lua.orig b/widgets/contrib/init.lua.orig deleted file mode 100644 index 3ad0835..0000000 --- a/widgets/contrib/init.lua.orig +++ /dev/null @@ -1,23 +0,0 @@ - ---[[ - - Lain - Layouts, widgets and utilities for Awesome WM - - Users contributed widgets section - - Licensed under GNU General Public License v2 -<<<<<<< HEAD - * (c) 2013, Luke Bonham -======= - * (c) 2013, Luke Bonham ->>>>>>> upstream/master - ---]] - -local wrequire = require("lain.helpers").wrequire -local setmetatable = setmetatable - -local widgets = { _NAME = "lain.widgets.contrib" } - -return setmetatable(widgets, { __index = wrequire }) diff --git a/widgets/contrib/moc.lua.orig b/widgets/contrib/moc.lua.orig deleted file mode 100644 index fb8afec..0000000 --- a/widgets/contrib/moc.lua.orig +++ /dev/null @@ -1,117 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2014, anticlockwise - ---]] - -local helpers = require("lain.helpers") -local async = require("lain.asyncshell") - -local escape_f = require("awful.util").escape -local naughty = require("naughty") -local wibox = require("wibox") - -local io = { popen = io.popen } -local os = { execute = os.execute, - getenv = os.getenv } -local string = { format = string.format, - gmatch = string.gmatch } - -local setmetatable = setmetatable - -local moc = {} - -local function worker(args) - local args = args or {} - local timeout = args.timeout or 2 - 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 "" -<<<<<<< HEAD -======= - local followmouse = args.followmouse or false ->>>>>>> upstream/master - local settings = args.settings or function() end - - local mpdcover = helpers.scripts_dir .. "mpdcover" - - moc.widget = wibox.widget.textbox('') - - moc_notification_preset = { - title = "Now playing", - timeout = 6 - } - - helpers.set_map("current moc track", nil) - - function moc.update() - -- mocp -i will produce output like: - -- Artist: Travis - -- Album: The Man Who - -- etc. - async.request("mocp -i", function(f) - moc_now = { - state = "N/A", - file = "N/A", - artist = "N/A", - title = "N/A", - album = "N/A", - elapsed = "N/A", - total = "N/A" - } - -<<<<<<< HEAD - for line in f:lines() do -======= - for line in string.gmatch(f, "[^\n]+") do ->>>>>>> upstream/master - for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do - if k == "State" then moc_now.state = v - elseif k == "File" then moc_now.file = v - elseif k == "Artist" then moc_now.artist = escape_f(v) - elseif k == "SongTitle" then moc_now.title = escape_f(v) - elseif k == "Album" then moc_now.album = escape_f(v) - elseif k == "CurrentTime" then moc_now.elapsed = escape_f(v) - elseif k == "TotalTime" then moc_now.total = escape_f(v) - end - end - end - - moc_notification_preset.text = string.format("%s (%s) - %s\n%s", moc_now.artist, - moc_now.album, moc_now.total, moc_now.title) - widget = moc.widget - settings() - - if moc_now.state == "PLAY" then - if moc_now.title ~= helpers.get_map("current moc track") then - helpers.set_map("current moc track", moc_now.title) - os.execute(string.format("%s %q %q %d %q", mpdcover, "", - moc_now.file, cover_size, default_art)) - -<<<<<<< HEAD -======= - if followmouse then - moc_notification_preset.screen = mouse.screen - end - ->>>>>>> upstream/master - moc.id = naughty.notify({ - preset = moc_notification_preset, - icon = "/tmp/mpdcover.png", - replaces_id = moc.id, - }).id - end - elseif moc_now.state ~= "PAUSE" then - helpers.set_map("current moc track", nil) - end - end) - end - - helpers.newtimer("moc", timeout, moc.update) - - return setmetatable(moc, { __index = moc.widget }) -end - -return setmetatable(moc, { __call = function(_, ...) return worker(...) end }) diff --git a/widgets/contrib/task.lua.orig b/widgets/contrib/task.lua.orig deleted file mode 100644 index d84e55f..0000000 --- a/widgets/contrib/task.lua.orig +++ /dev/null @@ -1,176 +0,0 @@ - ---[[ - - Licensed under GNU General Public License v2 - * (c) 2013, Jan Xie - ---]] - -local icons_dir = require("lain.helpers").icons_dir - -local awful = require("awful") -local beautiful = require("beautiful") -local naughty = require("naughty") - -<<<<<<< HEAD -======= -local mouse = mouse ->>>>>>> upstream/master -local io = io -local string = { len = string.len } -local tonumber = tonumber - -local setmetatable = setmetatable - --- Taskwarrior notification --- lain.widgets.contrib.task -local task = {} - -local task_notification = nil - -function task:hide() - if task_notification ~= nil then - naughty.destroy(task_notification) - task_notification = nil - end -end - -<<<<<<< HEAD -function task:show() -======= -function task:show(scr_pos) ->>>>>>> upstream/master - task:hide() - - local f, c_text - -<<<<<<< HEAD -======= - if task.followmouse then - local scrp = mouse.screen - else - local scrp = scr_pos or task.scr_pos - end - ->>>>>>> upstream/master - f = io.popen('task') - c_text = "" - .. f:read("*all"):gsub("\n*$", "") - .. "" - f:close() - - task_notification = naughty.notify({ title = "[task next]", - text = c_text, - icon = task.notify_icon, - position = task.position, - fg = task.fg, - bg = task.bg, - timeout = task.timeout, -<<<<<<< HEAD -======= - screen = scrp ->>>>>>> upstream/master - }) -end - -function task:prompt_add() - awful.prompt.run({ prompt = "Add task: " }, - mypromptbox[mouse.screen].widget, - function (...) - local f = io.popen("task add " .. ...) - c_text = "\n" - .. f:read("*all") - .. "" - f:close() - - naughty.notify({ - text = c_text, - icon = task.notify_icon, - position = task.position, - fg = task.fg, - bg = task.bg, - timeout = task.timeout, - }) - end, - nil, - awful.util.getdir("cache") .. "/history_task_add") -end - -function task:prompt_search() - awful.prompt.run({ prompt = "Search task: " }, - mypromptbox[mouse.screen].widget, - function (...) - local f = io.popen("task " .. ...) - c_text = f:read("*all"):gsub(" \n*$", "") - f:close() - - if string.len(c_text) == 0 - then - c_text = "No results found." - else - c_text = "" - .. c_text - .. "" - end - - naughty.notify({ - title = "[task next " .. ... .. "]", - text = c_text, - icon = task.notify_icon, - position = task.position, - fg = task.fg, - bg = task.bg, - timeout = task.timeout, -<<<<<<< HEAD -======= - screen = mouse.screen ->>>>>>> upstream/master - }) - end, - nil, - awful.util.getdir("cache") .. "/history_task") -end - -function task:attach(widget, args) -<<<<<<< HEAD - 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.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 -======= - 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.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 ->>>>>>> upstream/master - - task.notify_icon = icons_dir .. "/taskwarrior/task.png" - task.notify_icon_small = icons_dir .. "/taskwarrior/tasksmall.png" - -<<<<<<< HEAD - widget:connect_signal("mouse::enter", function () task:show() end) -======= - widget:connect_signal("mouse::enter", function () task:show(task.scr_pos) end) ->>>>>>> upstream/master - widget:connect_signal("mouse::leave", function () task:hide() end) -end - -return setmetatable(task, { __call = function(_, ...) return create(...) end }) From c1bbfdac79bf6a61fbf3cecb8b00f7c4a1b606a7 Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Sun, 3 Jan 2016 11:20:17 +0100 Subject: [PATCH 564/572] widgets/bat: fixing tabs --- widgets/bat.lua | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 60bd71c..7d8f9d3 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -96,21 +96,21 @@ local function worker(args) if min < 0 then min = 0 elseif min > 59 then min = 59 end bat_now.time = string.format("%02d:%02d", hrs, min) - - local perc = tonumber(first_line(bstr .. "/capacity")) + + local perc = tonumber(first_line(bstr .. "/capacity")) if not perc then - perc = (rem / tot) * 100 - end - - if perc <= 100 then - bat_now.perc = string.format("%d", perc) - elseif perc > 100 then - bat_now.perc = "100" - elseif perc < 0 then - bat_now.perc = "0" - end - + perc = (rem / tot) * 100 + end + + if perc <= 100 then + bat_now.perc = string.format("%d", perc) + elseif perc > 100 then + bat_now.perc = "100" + elseif perc < 0 then + bat_now.perc = "0" + end + if rate ~= nil and ratev ~= nil then bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) else From e966fd310ef6754b40b85a9fa22609bf64e65189 Mon Sep 17 00:00:00 2001 From: copycat-killer Date: Sun, 3 Jan 2016 11:35:10 +0100 Subject: [PATCH 565/572] clean failed rebase and repatch #160 2 --- widgets/bat.lua | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 60bd71c..1730494 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -96,21 +96,18 @@ local function worker(args) if min < 0 then min = 0 elseif min > 59 then min = 59 end bat_now.time = string.format("%02d:%02d", hrs, min) - - local perc = tonumber(first_line(bstr .. "/capacity")) - if not perc then - perc = (rem / tot) * 100 - end - - if perc <= 100 then - bat_now.perc = string.format("%d", perc) - elseif perc > 100 then - bat_now.perc = "100" - elseif perc < 0 then - bat_now.perc = "0" - end - + local perc = first_line(bstr .. "/capacity") or (rem / tot) * 100 + + local perc = (rem / tot) * 100 + if perc <= 100 then + bat_now.perc = string.format("%d", perc) + elseif perc > 100 then + bat_now.perc = "100" + elseif perc < 0 then + bat_now.perc = "0" + end + if rate ~= nil and ratev ~= nil then bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12) else From bd8442c2ef8b51eac261c9722e16ec1afd1ac13b Mon Sep 17 00:00:00 2001 From: aajjbb Date: Sun, 3 Jan 2016 12:19:31 -0200 Subject: [PATCH 566/572] fixing small issue on previous commit, first_line function returns string, not integer --- widgets/bat.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index 1730494..aa0ce61 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -97,10 +97,9 @@ local function worker(args) bat_now.time = string.format("%02d:%02d", hrs, min) - local perc = first_line(bstr .. "/capacity") or (rem / tot) * 100 + local perc = tonumber(first_line(bstr .. "/capacity")) or (rem / tot) * 100 - local perc = (rem / tot) * 100 - if perc <= 100 then + if perc <= 100 then bat_now.perc = string.format("%d", perc) elseif perc > 100 then bat_now.perc = "100" From a4d4d7a5f364d9f1150dcb78be5ec1e1f66e5b95 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 17 Jan 2016 11:49:10 +0100 Subject: [PATCH 567/572] new widget: pulseaudio #157 #164 --- widgets/contrib/kbdlayout.lua | 6 ++++-- widgets/contrib/moc.lua | 2 ++ wiki | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/widgets/contrib/kbdlayout.lua b/widgets/contrib/kbdlayout.lua index 39857af..64ea6b3 100644 --- a/widgets/contrib/kbdlayout.lua +++ b/widgets/contrib/kbdlayout.lua @@ -16,6 +16,9 @@ local string = { match = string.match } local setmetatable = setmetatable +-- Keyboard layout switcher +-- lain.widgets.contrib.kblayout + local function worker (args) local kbdlayout = {} kbdlayout.widget = wibox.widget.textbox('') @@ -24,9 +27,8 @@ local function worker (args) local settings = args.settings or function () end local add_us_secondary = true local timeout = args.timeout or 5 - local idx = 1 - + if args.add_us_secondary == false then add_us_secondary = false end -- Mouse bindings diff --git a/widgets/contrib/moc.lua b/widgets/contrib/moc.lua index b818bb6..b79dbe2 100644 --- a/widgets/contrib/moc.lua +++ b/widgets/contrib/moc.lua @@ -21,6 +21,8 @@ local string = { format = string.format, local setmetatable = setmetatable +-- MOC audio player +-- lain.widgets.contrib.moc local moc = {} local function worker(args) diff --git a/wiki b/wiki index cefdc88..cb5d545 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit cefdc887c46f0f7c5d837d1449927e7dbf66b19e +Subproject commit cb5d5455987533d08c37fd17fec7dfa757b7130a From 42070bba6e69b17cf6db4eae3456ff65a159924b Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Sun, 17 Jan 2016 12:28:50 +0100 Subject: [PATCH 568/572] #162 fix; #163 rejected (duplicate) --- widgets/bat.lua | 4 ++-- wiki | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/widgets/bat.lua b/widgets/bat.lua index aa0ce61..d55be17 100644 --- a/widgets/bat.lua +++ b/widgets/bat.lua @@ -97,9 +97,9 @@ local function worker(args) bat_now.time = string.format("%02d:%02d", hrs, min) - local perc = tonumber(first_line(bstr .. "/capacity")) or (rem / tot) * 100 + local perc = tonumber(first_line(bstr .. "/capacity")) or math.floor((rem / tot) * 100) - if perc <= 100 then + if perc <= 100 then bat_now.perc = string.format("%d", perc) elseif perc > 100 then bat_now.perc = "100" diff --git a/wiki b/wiki index cb5d545..cdab3e6 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit cb5d5455987533d08c37fd17fec7dfa757b7130a +Subproject commit cdab3e6a03146f4bfe7d7209d27360d16aeec386 From d3365503d9186bcce53b005030923868bb89d3aa Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 20 Jan 2016 09:25:49 +0100 Subject: [PATCH 569/572] forgot to really add the widget; #157 #164 --- widgets/pulseaudio.lua | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 widgets/pulseaudio.lua diff --git a/widgets/pulseaudio.lua b/widgets/pulseaudio.lua new file mode 100644 index 0000000..b675276 --- /dev/null +++ b/widgets/pulseaudio.lua @@ -0,0 +1,48 @@ + +--[[ + + Licensed under GNU General Public License v2 + * (c) 2016, Luke Bonham + +--]] + +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 setmetatable = setmetatable + +-- PulseAudio volume +-- lain.widgets.pulseaudio +local pulseaudio = {} + +local function worker(args) + local args = args or {} + local timeout = args.timeout or 5 + local settings = args.settings or function() end + + pulseaudio.sink = args.sink or 0 -- user defined or first one + pulseaudio.cmd = args.cmd or string.format("pacmd list-sinks | grep -e 'index: %d' -e 'volume: front' -e 'muted'", pulseaudio.sink) + pulseaudio.widget = wibox.widget.textbox('') + + function pulseaudio.update() + local s = read_pipe(pulseaudio.cmd) + + volume_now = {} + volume_now.left = tonumber(string.match(s, "left.-(%d+)%%")) + volume_now.right = tonumber(string.match(s, "right.-(%d+)%%")) + volume_now.muted = string.match(s, "muted: (%S+)") + + widget = pulseaudio.widget + settings() + end + + newtimer(string.format("pulseaudio-%s", pulseaudio.sink), timeout, pulseaudio.update) + + return setmetatable(pulseaudio, { __index = pulseaudio.widget }) +end + +return setmetatable(pulseaudio, { __call = function(_, ...) return worker(...) end }) From 638dccf87030a517f23625e8b9fd9cc5d0cf5b10 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 20 Jan 2016 09:28:47 +0100 Subject: [PATCH 570/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index cdab3e6..e340b71 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit cdab3e6a03146f4bfe7d7209d27360d16aeec386 +Subproject commit e340b7147692db45166360f65066ce3af53b14d5 From bb3e0cb61d1e09bdc3f4c08fdb752c727c0f79a3 Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 20 Jan 2016 09:30:37 +0100 Subject: [PATCH 571/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index e340b71..053064f 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit e340b7147692db45166360f65066ce3af53b14d5 +Subproject commit 053064f7fc7e0b3035c0e9af8114c0c1add00db5 From 27ebd0a30d9634ea403a4c9f3c2139c2498faaea Mon Sep 17 00:00:00 2001 From: Luke Bonham Date: Wed, 20 Jan 2016 09:45:31 +0100 Subject: [PATCH 572/572] wiki updated --- wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiki b/wiki index 053064f..dcce6dd 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 053064f7fc7e0b3035c0e9af8114c0c1add00db5 +Subproject commit dcce6dd58791c7c1d2e2e3f046b4da0d5b9700a7