From: Simon Ruderich Date: Sat, 2 Jun 2018 11:37:39 +0000 (+0200) Subject: Merge branch 'vim' X-Git-Url: https://ruderich.org/simon/gitweb/?p=config%2Fdotfiles.git;a=commitdiff_plain;h=dcd322819bcff59f34bde4a4a82e4d20afb1b1d6;hp=58f1d82fd556e0aec9c69b41c7f0faf8fe6369b6 Merge branch 'vim' --- diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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. But first, please read +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..23d5991 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +all: + @./setup.sh + +.PHONY: all diff --git a/README b/README new file mode 100644 index 0000000..d94ea97 --- /dev/null +++ b/README @@ -0,0 +1,11 @@ +README +====== + +Git repository to store my configuration, designed to by cloned to +`~/.config/dotfiles`. `~/.config` is not used to allow a separate directory +hierarchy than just the program names which is custom for `~/.config`. + +NOTE: This repository must contain only public data as it will be stored on +many hosts! + +// vim: ft=asciidoc diff --git a/archive.sh b/archive.sh new file mode 100755 index 0000000..26a0e8d --- /dev/null +++ b/archive.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +# Create an archive of my configuration file which can be uploaded on a +# server. +# +# Usage: ./archive.sh + +# Copyright (C) 2010-2013 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +git_clone() { + git clone "$1" "$2" >/dev/null + ( cd "$2" && git remote rm origin && git gc ) +} + + +# Don't overwrite an existing file/directory. +if test -e tmp; then + echo 'tmp/ already exists!' + exit 1 +fi + +git_clone . tmp/dotfiles +for name in browser shell vcs vim x11; do + test -d $name || continue + + echo "cloning $name to tmp/" + git_clone $name tmp/dotfiles/$name +done + +archive=dotfiles.tar.gz +echo "creating $archive" +tar cf tmp/$archive -C tmp -z dotfiles +echo "moving $archive to ." +mv tmp/$archive . + +rm -rf tmp diff --git a/lib.m4 b/lib.m4 new file mode 100644 index 0000000..2f008e4 --- /dev/null +++ b/lib.m4 @@ -0,0 +1,25 @@ +dnl Contains additional macros for m4. +dnl +dnl The following macros are defined: IF and FI. Example: +dnl IF(OS, debian) +dnl ... +dnl FI +dnl +dnl Copyright (C) 2009-2013 Simon Ruderich +dnl +dnl This program is free software: you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program. If not, see . +dnl +dnl +define(`IF', `ifelse(`$1', `$2',dnl')dnl +define(`FI', `)dnl')dnl diff --git a/lib.sh b/lib.sh new file mode 100644 index 0000000..70be68d --- /dev/null +++ b/lib.sh @@ -0,0 +1,219 @@ +# Setup functions and settings used in subdirectories. +# +# Their setup.sh script sources this file. + +# Copyright (C) 2009-2014 Simon Ruderich +# +# 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 3 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, see . + + +# csh gives the error "Unknown colorls variable `su'." when used with newer +# options supported by Zsh or GNU ls. +unset LS_COLORS + + +# Check if the given program is installed. `type` is portable, `which` is not. +installed() { + type "$1" >/dev/null 2>&1 +} +# Get the path of the given program. Thanks to Gilles on [1] (read on +# 2013-03-10) for the PATH-walking idea. `which` is not portable and `type` +# has no well-formed output format. +# +# [1]: http://unix.stackexchange.com/questions/4988/how-do-i-test-to-see-if-an-application-exists-in-path/4991 +installed_path() { + test -z "$1" && return 1 + + # Keep IFS change local. + ( + IFS=: + # Walk PATH. + for directory in $PATH; do + if test -x "$directory/$1"; then + printf '%s\n' "$directory/$1" + return 0 + fi + done + + return 1 + ) +} + +# Usage: cmd_i ... +# +# Run with all arguments (including the last file) and write the result +# to the temporary file .tmp and then rename that file to . This +# can't be done in-place (e.g. cmd file) because it truncates the file. +cmd_i() { + # Get last argument. + last= + for x; do + last="$x" + done + + "$@" >"$last".tmp + mv "$last".tmp "$last" +} + +# Usage: sed_i ... +# +# sed -i is not compatible due to different implementations. See cmd_i. +sed_i() { + cmd_i sed "$@" +} +grep_i() { + cmd_i grep "$@" +} + +# Usage: perl_line_filter ... +# +# Run the perl command cmd on each line before printing it. +perl_line_filter() { + cmd="$1" + shift + + # Can't use -pe because it uses <> which treats the arguments as files. + perl -e "use strict; use warnings; while () { $cmd; print; }" "$@" +} + +# Usage: simple_cpp .. -- ... +# +# Replaces each FIRST (on word boundaries) with like a +# simple cpp replacement. +simple_cpp() { + cmd='my $i = 0;' + + for x; do + shift + + if test x"$x" = x--; then + break + fi + + cmd="$cmd s/\b$x\b/\$ARGV[\$i]/g; \$i++;" + done + + perl_line_filter "$cmd" -- "$@" +} + +# Print the current OS. The following OS are supported at the moment: +# +# - Debian (debian) +# - Gentoo (gentoo) +# - Mac OS X (darwin) +# - Solaris/OpenSolaris (sun) +# - FreeBSD (freebsd) +# +# If an unsupported OS is used an error is printed. +os() { + if test -f /etc/debian_version; then + echo debian + elif test -f /etc/gentoo-release; then + echo gentoo + elif test x`uname` = xDarwin; then + echo darwin + elif test x`uname` = xSunOS; then + echo sun + elif test x`uname` = xFreeBSD; then + echo freebsd + else + echo 'unsupported OS!' >&2 + return 1 + fi +} + +# Creates a symbolic link for file $1 in dirname of $2 with name of basename +# $2. +# +# `./link.sh example ~/.examplerc` creates a symbolic link to example +# (wherever it is located) in ~/ named .examplerc. +link() { + local pwd base source target >/dev/null 2>&1 || true + + # Get all necessary paths. + pwd=`pwd` + base=`printf '%s' "$2" | sed "s|\~|$HOME|"` # expand ~, some sh don't do it + base=`dirname "$base"` + source=`printf '%s' "$pwd/$1" | sed "s|$base/||"` + target=`basename "$2"` + + # Go to the directory where the link is going to be created. + cd "$base" || return 1 + + # Abort if the target file exists and is no symbolic link. Prevents + # overwriting real files. + if test -e "$target" && test ! -h "$target"; then + printf "link(): target '%s' exists already and is no symbolic link!\n" \ + "$target" >&2 + exit 1 + fi + + # Make sure the source exists. + if test ! -e "$source"; then + printf "link(): source '%s' doesn't exist!\n" "$source" >&2 + exit 1 + fi + + # Create the new symbolic link; remove the old one if necessary. + printf "link(): linking '%s' to '%s'\n" "$source" "$target" + rm -f "$target" + ln -s "$source" "$target" + + # Go back to the directory where we were before. + cd "$pwd" +} + +# Generate a file from a source file using a given command. A warning not to +# edit it is automatically added to the created file. +# +# Usage: generate +# +# If an empty extension is provided, the file is modified in-place (through a +# temporary file). +generate() { + local file >/dev/null 2>&1 || true + local file_tmp >/dev/null 2>&1 || true + local extension >/dev/null 2>&1 || true + + # Get command and target file. + file="$1" + extension="$2" + shift + shift + + if test -z "$extension"; then + file_tmp="$file.tmp" + else + # We only need this message if we generate a new file. + printf "%s: generating from '%s' (%s)\n" \ + "$file" "$file$extension" "$1" + + echo '###################################' >"$file" + echo '# WARNING! DO NOT EDIT THIS FILE! #' >>"$file" + echo '###################################' >>"$file" + echo >>"$file" + printf "# It was generated from '%s' on %s.\n" \ + "$file$extension" "`date`" >>"$file" + echo >>"$file" + + file_tmp="$file" + fi + + # Generate $file from $file$extension using the given command. + "$@" <"$file$extension" >>"$file_tmp" + + if test -z "$extension"; then + mv "$file_tmp" "$file" + fi +} diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..d2a3815 --- /dev/null +++ b/setup.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +# Runs setup.sh in all configuration directories. Must be run in the main +# configuration directory. + +# Copyright (C) 2009-2018 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +for path in */setup.sh; do + # Skip non executable setup.sh files as an easy way to deactivate one. + test ! -x "$path" && continue + + project=`printf '%s' "$path" | sed 's|/setup.sh$||'` + + printf 'running setup.sh in "%s"\n' "$project" + ( cd "$project" && ./setup.sh >/dev/null ) || { + printf '%s/setup.sh failed\n' "$project" >&2 + exit 1 + } +done diff --git a/shell/.gitignore b/shell/.gitignore new file mode 100644 index 0000000..c08e6d5 --- /dev/null +++ b/shell/.gitignore @@ -0,0 +1,17 @@ +# Ignore generated files. +/digrc +/htoprc +/screenrc +/shell/aliases +/shell/dircolors +/tmux.conf +/tmux-window1.conf +/tmux-window2.conf +# Ignore temporary files. +/lesshistory +/zsh/cache +/zsh/history* +# Ignore unimportant files. +/crontab.d/crontab.dotfiles-vim +/crontab.d/crontab.jobs +/zsh/libcoloredstderr.so diff --git a/shell/Makefile b/shell/Makefile new file mode 100644 index 0000000..23d5991 --- /dev/null +++ b/shell/Makefile @@ -0,0 +1,4 @@ +all: + @./setup.sh + +.PHONY: all diff --git a/shell/bash/logout b/shell/bash/logout new file mode 100644 index 0000000..12f1e5d --- /dev/null +++ b/shell/bash/logout @@ -0,0 +1,21 @@ +# Bash logout file. + +# Copyright (C) 2011-2012 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +source_config ~/.shell/logout + +# vim: ft=sh diff --git a/shell/bash/profile b/shell/bash/profile new file mode 100644 index 0000000..db373e9 --- /dev/null +++ b/shell/bash/profile @@ -0,0 +1,23 @@ +# Bash login configuration file. + +# Copyright (C) 2011-2014 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +if [[ -f ~/.bashrc ]]; then + . ~/.bashrc +fi + +# vim: ft=sh diff --git a/shell/bash/rc b/shell/bash/rc new file mode 100644 index 0000000..d876fe9 --- /dev/null +++ b/shell/bash/rc @@ -0,0 +1,46 @@ +# Main bash configuration file. +# +# Is sourced by all interactive bash shells and other shells like scp or rcp. + +# Copyright (C) 2011-2013 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +. ~/.shell/functions + +source_config ~/.shell/env + + +# Check if this is an interactive shell. Abort if not to prevent problems with +# scp and rcp. Taken from default Debian bashrc. Thanks. +if [[ $- != *i* ]]; then + return +fi + + +# Set the prompt; hostname and current working directory are displayed. +# Hostname is displayed in bold green, current directory in yellow. +PS1='\[\033[01;32m\]\h\[\033[00m\]:\[\033[33m\]\w\[\033[00m\] \$ ' + +# Use Vi(m) style readline mappings in bash. +set -o vi + + +source_config ~/.shell/aliases +source_config ~/.shell/rc + +source_config ~/.bash/rc.local + +# vim: ft=sh diff --git a/shell/bin/README b/shell/bin/README new file mode 100644 index 0000000..ad0164a --- /dev/null +++ b/shell/bin/README @@ -0,0 +1,7 @@ +README +====== + +Contains shell related programs useful on all computers. Wrapper scripts are +prefixed with "s". All programs are licensed under GPL v3+. + +Available through a symbolic link in shell: ~/.shell/bin/ diff --git a/shell/bin/battery.pl b/shell/bin/battery.pl new file mode 100755 index 0000000..c7e812e --- /dev/null +++ b/shell/bin/battery.pl @@ -0,0 +1,94 @@ +#!/usr/bin/perl + +# Copyright (C) 2011-2013 Simon Ruderich +# +# 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 3 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, see . + + +use strict; +use warnings; + + +if (scalar @ARGV != 1 and (scalar @ARGV != 2 or not $ARGV[0] =~ /-[st]/)) { + print STDERR "Usage: $0 [-s | -t] \n"; + print STDERR "\n"; + print STDERR "Normally this is /sys/class/power_supply/BAT*.\n"; + exit 1; +} +if (scalar @ARGV == 1) { + @ARGV = ('', $ARGV[0]); +} + +my $path = "$ARGV[1]/uevent"; + +# No battery available. +if (not -e $path) { + print STDERR "'$path' not found.\n"; + exit 1; +} + +my $screen_mode = ($ARGV[0] eq '-s'); +my $tmux_mode = ($ARGV[0] eq '-t'); + +my %battery; + +open my $file, '<', $path or die $!; +while (<$file>) { + /^POWER_SUPPLY_([A-Z_]+)=(.+)$/; + $battery{$1} = $2; +} +close $file or die $!; + +# New names ... +if (defined $battery{ENERGY_NOW}) { + $battery{CHARGE_NOW} = $battery{ENERGY_NOW}; + $battery{CHARGE_FULL} = $battery{ENERGY_FULL}; +} + +my $charge = int($battery{CHARGE_NOW} / $battery{CHARGE_FULL} * 100); +my $charging = ''; +if ($battery{STATUS} eq 'Charging' or $battery{STATUS} eq 'Full') { + $charging = '^'; +} + +# GNU screen mode with colors: 0-20 red, 20-40 yellow, 40-100 green. +if ($screen_mode) { + my $color; + if ($charge < 20) { + $color = 'b r'; + } elsif ($charge < 40) { + $color = 'b y'; + } else { + $color = 'b g'; + } + + print "\005{+$color}$charge%\005{-}$charging\n"; + +# Same in tmux mode. +} elsif ($tmux_mode) { + my $color; + if ($charge < 20) { + $color = 'red'; + } elsif ($charge < 40) { + $color = 'yellow'; + } else { + $color = 'green'; + } + + print "#[fg=$color,bold]$charge%#[default]$charging\n"; + +# Plain text output. +} else { + print "$charge%$charging\n"; +} diff --git a/shell/bin/calc b/shell/bin/calc new file mode 100755 index 0000000..ea3cbd3 --- /dev/null +++ b/shell/bin/calc @@ -0,0 +1,49 @@ +#!/bin/sh + +# Copyright (C) 2011-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +exec python -i -c ' + +# Math functions. +from math import * + +def ld(x): + return log(x)/log(2) +def lg(x): + return log10(x) + +def binom(n,k): + return reduce(lambda a,b: a*(n-b)/(b+1),xrange(k),1) + +# Convert number to scientific notation (e.g. 5e6). +def s(x): + print "%e" % x + + +# Time/Date functions. +import time + +# Convert time in seconds since epoch to readable string. +def stime(seconds): + print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(seconds)) + + +print "Welcome to the ultimate calculator."' + +# vim: ft=python diff --git a/shell/bin/chronic b/shell/bin/chronic new file mode 100755 index 0000000..a9fa47b --- /dev/null +++ b/shell/bin/chronic @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +=head1 NAME + +chronic - runs a command quietly unless it fails + +=head1 SYNOPSIS + +chronic COMMAND... + +=head1 DESCRIPTION + +chronic runs a command, and arranges for its standard out and standard +error to only be displayed if the command fails (exits nonzero or crashes). +If the command succeeds, any extraneous output will be hidden. + +A common use for chronic is for running a cron job. Rather than +trying to keep the command quiet, and having to deal with mails containing +accidental output when it succeeds, and not verbose enough output when it +fails, you can just run it verbosely always, and use chronic to hide +the successful output. + + 0 1 * * * chronic backup # instead of backup >/dev/null 2>&1 + +=head1 AUTHOR + +Copyright 2010 by Joey Hess + +Original concept and "chronic" name by Chuck Houpt. + +Licensed under the GNU GPL version 2 or higher. + +=cut + +use warnings; +use strict; +use IPC::Run qw( start pump finish timeout ); + +if (! @ARGV) { + die "usage: chronic [-l LOGFILE] COMMAND...\n"; +} + +my $logfile; +if (@ARGV >= 3 and $ARGV[0] eq '-l') { + $logfile = $ARGV[1]; + shift @ARGV; + shift @ARGV; +} + +my ($out, $err); +my $h = IPC::Run::start \@ARGV, \*STDIN, \$out, \$err; +$h->finish; +my $ret=$h->full_result; + +if (defined $logfile) { + open my $fh, '>', $logfile + or showout_and_die("failed to open logfile '$logfile'"); + print $fh $err; # stderr is more interesting, show it first + print $fh $out; + close $fh + or showout_and_die("failed to close logfile '$logfile'"); +} + +if ($ret >> 8) { # child failed + showout(); + exit ($ret >> 8); +} +elsif ($ret != 0) { # child killed by signal + showout(); + exit 1; +} +else { + exit 0; +} + +sub showout { + print STDOUT $out; + print STDERR $err; +} +sub showout_and_die { + my $errno = $!; + showout(); + die "chronic: $_[0]: $errno\n"; +} diff --git a/shell/bin/chronic-log b/shell/bin/chronic-log new file mode 100755 index 0000000..e8dc7ea --- /dev/null +++ b/shell/bin/chronic-log @@ -0,0 +1,38 @@ +#!/bin/sh + +# Simple wrapper around (my) chronic which writes the log files to +# ~/.tmp/logs/. + +# Copyright (C) 2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +if test $# -lt 2; then + echo "Usage: $0 .." >&2 + exit 1 +fi + + +name="$1" +shift + +today=`date '+%Y-%m-%d'` +now=`date '+%H:%M:%S'` + +logdir="$HOME/.tmp/logs/$today" +mkdir -p "$logdir" +exec chronic -l "$logdir/$name-$now" "$@" diff --git a/shell/bin/mv-p b/shell/bin/mv-p new file mode 100755 index 0000000..7259d33 --- /dev/null +++ b/shell/bin/mv-p @@ -0,0 +1,30 @@ +#!/bin/sh + +# Wrapper command for `mv` which creates the target directory before moving +# the file there. + +# Copyright (C) 2011-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +# Get last argument. +for last; do + : +done + +mkdir -p "`dirname "$last"`" \ + && mv "$@" diff --git a/shell/bin/notify.py b/shell/bin/notify.py new file mode 100755 index 0000000..3caa7d2 --- /dev/null +++ b/shell/bin/notify.py @@ -0,0 +1,79 @@ +#!/usr/bin/python + +# notify.py is a simple notification program displaying a message on the +# screen. + +# Copyright (C) 2011-2013 Simon Ruderich +# +# 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 3 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, see . + + +import sys +import locale + +import pygtk +pygtk.require('2.0') # there might be a GTK 1 version installed, ignore it +import gtk +import pango +import gobject + + +# Pressing the mouse inside the window quits notify. +def mouse_press_callback(widget, event): + gtk.main_quit() + + +if __name__ == '__main__': + if len(sys.argv) != 2: + sys.stderr.write("Usage: %s \n" % (sys.argv[0])) + sys.exit(1) + + # Display configuration. + BOLD = True + FG_COLOR = 'blue' + BG_COLOR = 'yellow' + + # We need a popup so the window manager doesn't touch our window. + window = gtk.Window(gtk.WINDOW_POPUP) + # No window border or close/resize buttons. + window.set_decorated(False) + # In case set_decorated(False) doesn't work with the used window manager + # quit when the window is manually closed. + window.connect('delete-event', gtk.main_quit) + # Enable mouse click events, by default windows don't receive them. + window.add_events(gtk.gdk.BUTTON_PRESS_MASK) + window.connect('button-press-event', mouse_press_callback) + + # Background color. + window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(BG_COLOR)) + + string = sys.argv[1].decode(locale.getdefaultlocale()[1]) + + # Colored message string. + label_message = gtk.Label(string) + label_message.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(FG_COLOR)) + window.add(label_message) + + if BOLD: + attributes = pango.AttrList() + attributes.insert(pango.AttrWeight(pango.WEIGHT_HEAVY, end_index=-1)) + label_message.set_attributes(attributes) + + # Display at the top at full screen width. + screen = window.get_screen() + window.resize(screen.get_width(), 30) + window.move(0, 15) + + window.show_all() + gtk.main() diff --git a/shell/bin/print-constant.pl b/shell/bin/print-constant.pl new file mode 100755 index 0000000..f0205db --- /dev/null +++ b/shell/bin/print-constant.pl @@ -0,0 +1,258 @@ +#!/usr/bin/perl + +# Print values of C constants. + +# Copyright (C) 2012 Simon Ruderich +# +# 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 3 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, see . + + +use strict; +use warnings; + +use Getopt::Long (); +use File::Temp (); + +our $VERSION = '0.01'; + + +my $option_help = 0; +my $option_version = 0; +my @option_include = (); +my $option_pathconf = undef; +my $option_quiet = 0; +my $option_sysconf = 0; +my $option_type = 'd'; +if (not Getopt::Long::GetOptions( + 'help|h|?' => \$option_help, + 'version|v' => \$option_version, + # + 'include|i=s' => \@option_include, + 'pathconf|p=s' => \$option_pathconf, + 'quiet|q' => \$option_quiet, + 'sysconf|s' => \$option_sysconf, + 'type|t=s' => \$option_type, + )) { + require Pod::Usage; + Pod::Usage::pod2usage(2); +} +if ($option_help) { + require Pod::Usage; + Pod::Usage::pod2usage(1); +} +if ($option_version) { + print <. +EOF + exit 0; +} + +# We need the constant name as argument. +if (scalar @ARGV != 1) { + require Pod::Usage; + Pod::Usage::pod2usage(2); +} + + +my $constant = $ARGV[0]; +# Check for non-constant name inputs - also prevents running arbitrary code on +# the machine. +if (not $constant =~ /^[a-zA-Z0-9_]+$/) { + print STDERR "Invalid constant name: '$constant'!\n"; + exit 1; +} + +# Some sanity checks. +if (not $option_type =~ /^[a-zA-Z]+$/) { + print STDERR "Invalid type: '$option_type'!\n"; + exit 1; +} +if ($option_sysconf and defined $option_pathconf) { + print STDERR "--sysconf and --pathconf can't be used together!\n"; + exit 1; +} +foreach my $include (@option_include) { + if (not $include =~ m{^[a-zA-Z0-9./_-]+$}) { + print STDERR "Invalid include: '$include'!\n"; + exit 1; + } +} + +my $constant_display = $constant; +# Pass the constant to sysconf()/pathconf() instead of using it directly. +if ($option_sysconf) { + $constant = "sysconf($constant)"; + $constant_display = $constant; +} elsif (defined $option_pathconf) { + $constant_display = "pathconf(\"$option_pathconf\", $constant)"; + # Use the current directory to prevent escape problems for the path, see + # below. + $constant = "pathconf(\".\", $constant)"; +} + + +# Use "limits.h" and "unistd.h" as default include - but only if the user +# specified no other includes, in case it conflicts with "limits.h". +if (scalar @option_include == 0) { + push @option_include, 'limits.h'; + push @option_include, 'unistd.h'; +} + + +# Temporary directory where the following C program which prints the constant +# is built. +my $tempdir = File::Temp::tempdir(CLEANUP => 1) or die $!; +chdir $tempdir or die $!; + +# Write the C file which prints the constant value. +my $c_template = <<'EOF'; +#include +#include +%s + +int main(int argc, char **argv) { + printf("%s\n", %s); + + return EXIT_SUCCESS; +} +EOF +open my $fh, '>', 'constant.c' or die $!; +printf $fh $c_template, + join("\n", map { "#include <$_>" } @option_include), + '%' . $option_type, + $constant; +close $fh or die $!; + +# Compile the constant C file. +my @args = ('cc', '-o', 'constant', 'constant.c'); +if (system(@args) != 0) { + print STDERR "Compilation failure (message above).\n"; + + chdir; # see below + exit 1; +} + +# pathconf() needs a path, we use the current directory - therefore we have to +# chdir to the given path. This prevents escape problems with the path. +if (defined $option_pathconf) { + chdir $option_pathconf; +} + +my $value = `$tempdir/constant`; + +if ($option_quiet) { + print $value; +} else { + print "$constant_display: $value"; +} + +# Change the working directory or File::Temp can't remove our temporary +# directory. +chdir; + + +__END__ + +=head1 NAME + +print-constant - print values of C constants + +=head1 SYNOPSIS + +B [I] I + +=head1 DESCRIPTION + +print-constant prints the values of C constants. Useful to find out certain +system constants without having to write a small C program to print them. + +=head1 OPTIONS + +=over 8 + +=item B<-i> I, B<--include> I + +Use I as include file. Adds C<#include EincludeE> to the +beginning of the C file used to print the constant. By default C and +C are used as headers. If this option is specified I default +includes are used. Can be specified multiple times. + +=item B<-p> I, B<--pathconf> I + +Pass the constant to pathconf(3) and print the result. I is the first +argument for pathconf(3). Conflicts with B<--sysconf>. + +=item B<-q>, B<--quiet> + +Display only the constant's value. + +=item B<-s>, B<--sysconf> + +Pass the constant to sysconf(3) and print the result. Conflicts with +B<--pathconf>. + +=item B<-t> I, B<--type> I + +Use I as type of the constant, used in printf(3). By default C is +used. + +=item B<-h>, B<-?>, B<--help> + +Print available options. + +=item B<-v>, B<--version> + +Print version number and license. + +=back + +=head1 AUTHOR + +Simon Ruderich, Esimon@ruderich.orgE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2012 by Simon Ruderich + +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 3 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, see . + +=head1 SEE ALSO + +L, L + +=cut diff --git a/shell/bin/remove-continuation.pl b/shell/bin/remove-continuation.pl new file mode 100755 index 0000000..3deb7d7 --- /dev/null +++ b/shell/bin/remove-continuation.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl + +# Remove continuation lines from stdin/file. Leading whitespace on the next +# line is removed. + +# Copyright (C) 2012 Simon Ruderich +# +# 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 3 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, see . + + +use strict; +use warnings; + + +my $continuation = 0; +while () { + # Remove leading whitespace if the last line was a line continuation. + if ($continuation) { + s/^\s+//; + } + + if (/^(.+?)\\$/) { + print $1; + $continuation = 1; + } else { + print $_; + $continuation = 0; + } +} +# Handle line continuation on the last line. +print "\n" if $continuation; diff --git a/shell/bin/rsleep b/shell/bin/rsleep new file mode 100755 index 0000000..9b953c5 --- /dev/null +++ b/shell/bin/rsleep @@ -0,0 +1,31 @@ +#!/usr/bin/perl + +# Sleep randomly between 0 and $ARGV[0] seconds. + +# Copyright (C) 2013-2014 Simon Ruderich +# +# 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 3 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, see . + + +use strict; +use warnings; + + +if (scalar @ARGV != 1) { + print STDERR "Usage: $0 \n"; + exit 1; +} + +srand; +sleep int rand $ARGV[0]; diff --git a/shell/bin/sc b/shell/bin/sc new file mode 100755 index 0000000..506e90a --- /dev/null +++ b/shell/bin/sc @@ -0,0 +1,53 @@ +#!/bin/bash + +# Small wrapper for systemctl which provides some shortcuts. + +# Copyright (C) 2015 Simon Ruderich +# +# 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 3 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, see . + +set -eu + + +args=( ) +found= +for arg; do + # This heuristic replaces the first occurrence of a shortcut with its + # expansion. This is not perfect (e.g. `systemctl status s` would result + # in `systemctl status status`) but works even when options are used and + # doesn't require us to duplicate systemctl's parsing of command line + # arguments. + if [[ -z $found ]]; then + found=1 + case "$arg" in + c) arg=cat ;; + d) arg=disable ;; + e) arg=enable ;; + k) arg=kill ;; + m) arg=mask ;; + r) arg=restart ;; + rl) arg=reload ;; + s) arg=status ;; + sa) arg=start ;; + so) arg=stop ;; + u) arg=unmask ;; + # No match, try it again for the next parameter. + *) found= ;; + esac + fi + args+=( "$arg" ) +done + +set +u # empty $args causes an error, I think this is a bug in bash +exec systemctl "${args[@]}" diff --git a/shell/bin/slocate b/shell/bin/slocate new file mode 100755 index 0000000..43e1eb2 --- /dev/null +++ b/shell/bin/slocate @@ -0,0 +1,23 @@ +#!/bin/sh + +# Search only in the local `locate` database. Created with `supdatedb`. + +# Copyright (C) 2012-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +exec locate -d "$HOME/.tmp/locatedb" "$@" diff --git a/shell/bin/srandom-order b/shell/bin/srandom-order new file mode 100755 index 0000000..45297be --- /dev/null +++ b/shell/bin/srandom-order @@ -0,0 +1,31 @@ +#!/bin/sh + +# Run all files in the current directory (recursively) in a random order with +# the given program. + +# Copyright (C) 2012-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +if test "$#" -eq 0; then + echo "Usage: $0 .." >&2 + exit 2 +fi + +find . -type f -print0 \ + | sort --random-sort --zero-terminated \ + | xargs -0 "$@" diff --git a/shell/bin/srsync b/shell/bin/srsync new file mode 100755 index 0000000..8402bb3 --- /dev/null +++ b/shell/bin/srsync @@ -0,0 +1,38 @@ +#!/bin/sh + +# rsync shortcut with options "everybody" needs. + +# Be careful when restoring /boot with --sparse, GRUB doesn't support sparse +# files (e.g. the kernel). Therefore don't use --sparse in this case. + +# Copyright (C) 2011-2015 Simon Ruderich +# +# 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 3 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, see . + + +set -eu +set -x + +exec rsync \ + --verbose \ + --itemize-changes \ + --human-readable \ + --archive \ + --acls \ + --xattrs \ + --hard-links \ + --sparse \ + --numeric-ids \ + --one-file-system \ + "$@" diff --git a/shell/bin/srsync-incremental b/shell/bin/srsync-incremental new file mode 100755 index 0000000..187e6b6 --- /dev/null +++ b/shell/bin/srsync-incremental @@ -0,0 +1,66 @@ +#!/bin/sh + +# Perform incremental backups using rsync and hardlinks. +# +# Thanks to http://www.sanitarium.net/golug/rsync_backups_2010.html for the +# idea. + +# Copyright (C) 2011-2017 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +if test "$#" -lt 2; then + echo "Usage: $0 " >&2 + echo + echo "Note: The target directory is the _first_ argument!" >&2 + exit 2 +fi + + +cd "$1" +shift + +# Get path to last backup directory. +dest=./ +for x in backup-*; do + test -d "$x" || continue + dest="../$x" # relative to destination directory +done + +target="backup-$(date '+%Y-%m-%d-%H-%M-%S')" +target_tmp="partial-$target" + +mkdir "$target_tmp" +rsync \ + --verbose --itemize-changes --human-readable \ + --archive --acls --xattrs --hard-links --sparse --numeric-ids \ + --one-file-system \ + --link-dest="$dest" \ + "$@" "$target_tmp" \ +|| { + # Try to remove the target directory without changing the exit code. In + # case the connection failed without transferring any files, we want to + # remove the empty directory. + code=$? + rmdir "$target_tmp" 2>/dev/null || true + exit $code +} +# --dry-run (-n) creates an empty directory. Remove it to prevent using it for +# further incremental backups (which would do a full backup). +rmdir "$target_tmp" 2>/dev/null && exit 0 || true + +mv "$target_tmp" "$target" diff --git a/shell/bin/supdatedb b/shell/bin/supdatedb new file mode 100755 index 0000000..4f5fac0 --- /dev/null +++ b/shell/bin/supdatedb @@ -0,0 +1,27 @@ +#!/bin/sh + +# Generate `locate` database for my home directory only. Exclude backups and +# other temporary files. + +# Copyright (C) 2012-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +exec updatedb \ + --localpaths="$HOME" \ + --prunepaths="$HOME/.tmp $HOME/tmp" \ + --output="$HOME/.tmp/locatedb" diff --git a/shell/bin/svalgrind b/shell/bin/svalgrind new file mode 100755 index 0000000..bcb68da --- /dev/null +++ b/shell/bin/svalgrind @@ -0,0 +1,22 @@ +#!/bin/sh + +# Copyright (C) 2011-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +exec valgrind --leak-check=full --show-reachable=yes --error-exitcode=1 \ + --track-fds=yes --quiet "$@" diff --git a/shell/bin/temperature.pl b/shell/bin/temperature.pl new file mode 100755 index 0000000..42eaffe --- /dev/null +++ b/shell/bin/temperature.pl @@ -0,0 +1,96 @@ +#!/usr/bin/perl + +# Copyright (C) 2011-2012 Simon Ruderich +# +# 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 3 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, see . + + +use strict; +use warnings; + + +if (scalar @ARGV != 1 and (scalar @ARGV != 2 or not $ARGV[0] =~ /-[st]/)) { + print STDERR "Usage: $0 [-s | -t] \n"; + print STDERR "\n"; + print STDERR "Normally this is /sys/devices/platform/*.\n"; + exit 1; +} +if (scalar @ARGV == 1) { + @ARGV = ('', $ARGV[0]); +} + +my $temperature_path = "$ARGV[1]/temp1_input"; +my $critical_path = "$ARGV[1]/temp1_crit"; + +# No temperature information available. +if (not -e $temperature_path or not -e $critical_path) { + print STDERR "'$temperature_path' or '$critical_path' not found.\n"; + exit 1; +} + +my $screen_mode = ($ARGV[0] eq '-s'); +my $tmux_mode = ($ARGV[0] eq '-t'); + +my $temperature; +my $critical; + +my $file; +open $file, '<', $temperature_path or die $!; +$temperature = <$file>; +close $file or die $!; +open $file, '<', $critical_path or die $!; +$critical = <$file>; +close $file or die $!; + +my $value = int($temperature / 1000); +my $risk = ($critical - $temperature)/$critical; + +$value .= "\xb0"; # degree symbol in UTF-8 + +# GNU screen mode with colors. +if ($screen_mode) { + my $color; + if ($risk < 0) { + $color = 'br r'; # bold reverse + } elsif ($risk < 0.1) { + $color = 'b r'; + } elsif ($risk < 0.2) { + $color = 'b y'; + } else { + $color = 'b g'; + } + + print "\005{+$color}$value\005{-}\n"; + +# Same in tmux mode. +} elsif ($tmux_mode) { + my $color; + my $style = 'bold'; + if ($risk < 0) { + $color = 'red'; + $style = 'reverse'; # blink doesn't work for me + } elsif ($risk < 0.1) { + $color = 'red'; + } elsif ($risk < 0.2) { + $color = 'yellow'; + } else { + $color = 'green'; + } + + print "#[fg=$color,$style]$value#[default]\n"; + +# Plain text output. +} else { + print "$value\n"; +} diff --git a/shell/colordiffrc b/shell/colordiffrc new file mode 100644 index 0000000..d8f91db --- /dev/null +++ b/shell/colordiffrc @@ -0,0 +1,24 @@ +# Colordiff configuration file. + +# Copyright (C) 2011-2012 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Custom colors for the diff output which is more similar to TextMate's output +# (new: green, old: red). +newtext=green +oldtext=red +diffstuff=magenta +cvsstuff=yellow diff --git a/shell/crontab.d/Makefile b/shell/crontab.d/Makefile new file mode 100644 index 0000000..23d5991 --- /dev/null +++ b/shell/crontab.d/Makefile @@ -0,0 +1,4 @@ +all: + @./setup.sh + +.PHONY: all diff --git a/shell/crontab.d/README b/shell/crontab.d/README new file mode 100644 index 0000000..56121ce --- /dev/null +++ b/shell/crontab.d/README @@ -0,0 +1,8 @@ +README +====== + +`setup.sh` combines all 'crontab.*' files in this directory into a single +crontab file and loads it with `crontab`. + +This replaces the current crontab! If no 'crontab.*' files were found, the +current crontab is removed. diff --git a/shell/crontab.d/jobs b/shell/crontab.d/jobs new file mode 100644 index 0000000..8426b7a --- /dev/null +++ b/shell/crontab.d/jobs @@ -0,0 +1,44 @@ +# Run jobs on regular bases. Similar to /etc/cron.*/. +# +# Symlink to crontab.jobs to enable it. + +# Copyright (C) 2013-2014 Simon Ruderich +# +# 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 3 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, see . + + +# Include user's binaries in PATH. Expanding $HOME doesn't work with cron, +# `setup.sh` handles that! +PATH=$HOME/bin:$HOME/.shell/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games +# `rsleep` (random sleep) is used to reduce concurrent commands if this +# crontab file is used by multiple users. + + +# Taken from Debian's /etc/crontab from cron package 3.0pl1-124 and modified. +# Thanks. +17 * * * * rsleep 60; run-parts --report .crontab.d/jobs.hourly +25 6 * * * rsleep 1800; run-parts --report .crontab.d/jobs.daily +47 6 * * 7 rsleep 3600; run-parts --report .crontab.d/jobs.weekly +52 6 1 * * rsleep 3600; run-parts --report .crontab.d/jobs.monthly + +# Run on system startup. +@reboot run-parts --report .crontab.d/jobs.reboot + +# Run every minute. +* * * * * run-parts --report .crontab.d/jobs.minutely +# Run every x hours. +31 */6 * * * rsleep 600; run-parts --report .crontab.d/jobs.hourly6 +39 */8 * * * rsleep 600; run-parts --report .crontab.d/jobs.hourly8 + +# vim: ft=crontab diff --git a/shell/crontab.d/jobs.daily/.gitignore b/shell/crontab.d/jobs.daily/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/shell/crontab.d/jobs.daily/prune-logs b/shell/crontab.d/jobs.daily/prune-logs new file mode 100755 index 0000000..74aa1f2 --- /dev/null +++ b/shell/crontab.d/jobs.daily/prune-logs @@ -0,0 +1,32 @@ +#!/bin/sh + +# Remove log files created by schronic which are older than two weeks. + +# Copyright (C) 2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + + +logdir="$HOME/.tmp/logs" +if test ! -d "$logdir"; then + exit 0 +fi + +# Remove empty directories. +rmdir "$logdir"/* 2>/dev/null || true + +exec find "$logdir/" -type f -mtime +14 -delete diff --git a/shell/crontab.d/jobs.hourly/.gitignore b/shell/crontab.d/jobs.hourly/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/shell/crontab.d/jobs.hourly6/.gitignore b/shell/crontab.d/jobs.hourly6/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/shell/crontab.d/jobs.hourly8/.gitignore b/shell/crontab.d/jobs.hourly8/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/shell/crontab.d/jobs.minutely/.gitignore b/shell/crontab.d/jobs.minutely/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/shell/crontab.d/jobs.monthly/.gitignore b/shell/crontab.d/jobs.monthly/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/shell/crontab.d/jobs.reboot/.gitignore b/shell/crontab.d/jobs.reboot/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/shell/crontab.d/jobs.weekly/.gitignore b/shell/crontab.d/jobs.weekly/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/shell/crontab.d/setup.sh b/shell/crontab.d/setup.sh new file mode 100755 index 0000000..46ebb56 --- /dev/null +++ b/shell/crontab.d/setup.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +# Combine all crontab.* files in ~/.crontab.d/ into a single crontab file and +# load it with `crontab`. +# +# An existing crontab entry not generated with this script is not overwritten. + +# Copyright (C) 2012-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + + +HEADER_WARNING='# WARNING! DO NOT EDIT THIS FILE! #' + +# Don't overwrite existing crontab entries. Not race condition free but that +# can't be helped. +if crontab -l >/dev/null 2>&1; then + if crontab -l | head -n3 | grep -F -x "$HEADER_WARNING" >/dev/null; then + : + else + echo 'Existing crontab entry found, please remove it manually.' + exit 2 + fi +fi + + +DIRECTORY="$HOME/.crontab.d" +if test ! -d "$DIRECTORY" || test ! -O "$DIRECTORY"; then + exit 1 +fi + +# `set -e` aborts when `mktemp` fails. +CRONTAB=`mktemp --tmpdir="$DIRECTORY" update-crontab.XXXXXXXXXXXX` + +echo '###################################' >"$CRONTAB" +echo "$HEADER_WARNING" >>"$CRONTAB" +echo '###################################' >>"$CRONTAB" +echo >>"$CRONTAB" +printf "# It was generated from '%s/*' on %s." \ + "$DIRECTORY" "`LANG=C date '+%a, %d %b %Y %H:%M:%S %z'`" >>"$CRONTAB" + +# Enforce C sort order. +LC_ALL=C + +NO_MATCHES= +for file in "$DIRECTORY"/crontab.*; do + # No crontab.* files exist, abort. + if test ! -e "$file"; then + NO_MATCHES=y + break + fi + + printf "Found '%s'.\n" "$file" + + printf '\n\n## %s:\n' "$file" >>"$CRONTAB" + + # Strip licenses, multiple empty lines and fix $HOME variables in PATH + # (cron doesn't expand variables). + START_REGEX='^# This [a-zA-Z]* is free software: you can redistribute it' + END_REGEX='^# along with this [a-zA-Z]*. If not, see <[^>]*>\.' + <"$file" sed -e "/$START_REGEX/,/$END_REGEX/ d" \ + -e "/^#[ ]*$/ d" \ + -e "/^# Copyright (C) [0-9][0-9]* / d" \ + | cat --squeeze-blank \ + | sed "/^PATH/ s:\$HOME:$HOME:g" \ + >>"$CRONTAB" +done + +# Update crontab with the crontab.* files. +if test -z "$NO_MATCHES"; then + echo + echo 'Updating crontab.' + crontab "$CRONTAB" + +# No files found, remove the existing crontab entry. Ignore errors in case no +# crontab entry existed in the first place. +else + echo 'No files found, removing old crontab (if it exists).' + crontab -r || true +fi + +rm "$CRONTAB" diff --git a/shell/csh/rc b/shell/csh/rc new file mode 100644 index 0000000..0fdc66a --- /dev/null +++ b/shell/csh/rc @@ -0,0 +1,26 @@ +# Csh configuration file. + +# Copyright (C) 2011-2013 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Start Zsh in interactive login mode if available, otherwise do nothing. -l +# is used so Zsh sources .zlogin and .zlogout. +if ($?prompt) then + # csh doesn't use `type` .. yeah POSIX. + which zsh >/dev/null && exec zsh -l +endif + +# vim: ft=csh diff --git a/shell/digrc.in b/shell/digrc.in new file mode 100644 index 0000000..c686042 --- /dev/null +++ b/shell/digrc.in @@ -0,0 +1,23 @@ +# Dig configuration file. +# +# dig doesn't support comments in ~/.digrc. They must be stripped before using +# this file. + +# Copyright (C) 2014 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Use the search list or domain directive as defined in /etc/resolv.conf. ++search diff --git a/shell/haskeline b/shell/haskeline new file mode 100644 index 0000000..ecf2428 --- /dev/null +++ b/shell/haskeline @@ -0,0 +1,39 @@ +-- Configuration file for haskeline (an incomplete readline "clone"). + +-- Copyright (C) 2014 Simon Ruderich +-- +-- This file 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 3 of the License, or +-- (at your option) any later version. +-- +-- This file 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 file. If not, see . + + +-- Activate Vi editing mode. +editMode: Vi + +-- Never ring any bell. +bellStyle: NoBell + +-- Increase history size. +maxHistorySize: Just 50000 +-- Don't add consecutive duplicate lines to the history. +historyDuplicates: IgnoreConsecutive + + +-- KEY BINDINGS + +-- / with the additional effect that only lines starting with the +-- current input are matched. Very useful to recall old commands quickly - +-- just type the first few characters. +bind: ctrl-p meta-k +bind: ctrl-n meta-j + +-- vim: ft=haskell diff --git a/shell/htoprc.in b/shell/htoprc.in new file mode 100644 index 0000000..194328d --- /dev/null +++ b/shell/htoprc.in @@ -0,0 +1,76 @@ +# htop configuration file. + +# Useful mappings: +# +# Use \ to limit to only matching processes (like l in mutt). _Very_ useful. + +# Copyright (C) 2011-2014 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Ordered in the same way htop orders them for easy diffing. + +# Display the following fields (trailing whitespace for easy diffing ...): +# +# - PID (0) +# - USER (48) +# - NICE (18) +# - M_SIZE (38): virtual memory +# - M_RESIDENT (39): resident memory +# - M_SHARE (40): shared memory +# - STATE (2) +# - PERCENT_CPU (46) +# - PERCENT_MEM (47) +# - TIME (49) +# - STARTTIME (20) +# - Command (1) +fields=0 48 18 38 39 40 2 46 47 49 20 1 + +# Don't display kernel threads. +hide_kernel_threads=1 +# But display userland threads. +hide_userland_threads=0 +# Display thread names. The command line is displayed in the tree view as +# parent of the threads. +show_thread_names=1 + +# Highlight program base name. +highlight_base_name=1 +# Highlight megabytes in memory usage. +highlight_megabytes=1 +# Highlight threads. +highlight_threads=1 + +# Display detailed CPU information, including IO-Wait. +detailed_cpu_time=1 + +# Display the following meters. +# +# left: - first part of CPU usage, bar (LeftCPUs) +# - memory usage, bar (Memory) +# - swap usage, bar (Swap) +# - hostname, text (Hostname) +# +# right: - second part of CPU usage, bar (RightCPUs) +# - task statistics, text (Tasks) +# - load average, text (LoadAverage) +# - uptime, text (Uptime) +# +left_meters=LeftCPUs Memory Swap Hostname +left_meter_modes=1 1 1 2 +right_meters=RightCPUs Tasks LoadAverage Uptime +right_meter_modes=1 2 2 2 + +# vim: ft=cfg diff --git a/shell/inputrc b/shell/inputrc new file mode 100644 index 0000000..aa74013 --- /dev/null +++ b/shell/inputrc @@ -0,0 +1,54 @@ +# Configuration file for readline. + +# Copyright (C) 2011-2015 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Only one is necessary to get a list of all possible options. +set show-all-if-ambiguous on +set show-all-if-unmodified on + +# Always complete all items no matter how many there are. +set completion-query-items -1 +# And make sure we use a pager for completions (this is also the default). +set page-completions on + +# Add character to files denoting the type when completing file names. +set visible-stats on + +# Activate Vi editing mode. +set editing-mode vi + + +# KEY BINDINGS + +# Insert mode. + +# Use jk to exit insert mode (jj is too slow to type). +"jk": vi-movement-mode + +# / with the additional effect that only lines starting with the +# current input are matched. Very useful to recall old commands quickly - just +# type the first few characters. +"\C-p": history-search-backward +"\C-n": history-search-forward + +# Allow in Vi normal mode to clear the screen. +"\C-L": clear-screen + +# Command mode. +set keymap vi + +# No bindings yet. diff --git a/shell/lessfilter b/shell/lessfilter new file mode 100755 index 0000000..1403df4 --- /dev/null +++ b/shell/lessfilter @@ -0,0 +1,44 @@ +#!/bin/sh + +# Copyright (C) 2011-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +case "$1" in + # Color diff files. + *.diff | *.patch) + colordiff <"$1" + ;; + + *.nfo) + iconv -f latin1 -t utf-8 <"$1" + ;; + + *) + # Display directory contents. + if test -d "$1"; then + printf '=> Contents of %s:\n' "$1" + ls -- "$1" + exit 0 + fi + + # We don't handle this format. + exit 1 +esac + +# No further processing by lesspipe necessary. +exit 0 diff --git a/shell/lesskey b/shell/lesskey new file mode 100644 index 0000000..247679b --- /dev/null +++ b/shell/lesskey @@ -0,0 +1,56 @@ +# Lesskey configuration file for less. + +# Copyright (C) 2011-2013 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +#command + +# Map "-" to go up one screen like in mutt. +- back-screen +# Map h and l to work like in Vim (go left/right). To display the help use H. +h left-scroll +l right-scroll + + +#line-edit + +# Vim-like up/down to replace the arrow keys. +^P up +^N down + + +#env + +# Set options for less. +# +# no-init: Disable initialization termcap as it causes the screen to get +# cleared on some systems. +# quit-if-one-screen: If the output fits on the current screen quit less. +# RAW-CONTROL-CHARS: Display ANSI "color" escape sequences to allow colored +# output. Other escape sequences are drawn in caret +# notation. +# ignore-case: Ignore case if the search string doesn't contain any uppercase +# letters. If there are uppercase letters respect case. +# +# Don't use search-skip-screen as it makes it easy to miss matches on the +# current page. +LESS = --no-init --quit-if-one-screen --RAW-CONTROL-CHARS --ignore-case + +# Store less' history file in this directory. HISTORY_PATH is replaced by +# setup.sh because lesskey doesn't expand ~/. +LESSHISTFILE = HISTORY_PATH +# Increase the history size, default is 100. +LESSHISTSIZE = 1000 diff --git a/shell/reminders.in b/shell/reminders.in new file mode 100644 index 0000000..a146029 --- /dev/null +++ b/shell/reminders.in @@ -0,0 +1,54 @@ +# remind reminder file. + +# Copyright (C) 2012-2013 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# FUNCTIONS + +# Todo item. Prevents cluttering the calendar by displaying the entry only +# today. Thanks to http://wiki.43folders.com/index.php/Remind_FAQ (read on +# 2011-06-24). Additionally %"%" is used in todo items which omits them from +# the calendar view completely. Combined this way supports `rem -c` (no todo +# items) and `rem '*3'` (todo items only once). +FSET todo() trigger(realtoday()) + + + +# TODO LIST + +# Header. +#REM [todo()] MSG %"%" TODO: % + +#REM [todo()] MSG %"%" - Example todo entry. % + +# Empty line. +#REM [todo()] MSG %"%" % + + + +# REMINDERS + +#REM 04 April 2012 +10 MSG Example reminder entry. % + + + +# DAEMON REMINDERS + +IF $Daemon > 0 + #REM AT 00:00 MSG Example reminder. +ENDIF + +# vim: ft=remind diff --git a/shell/screenrc.in b/shell/screenrc.in new file mode 100644 index 0000000..a403083 --- /dev/null +++ b/shell/screenrc.in @@ -0,0 +1,158 @@ +# GNU screen configuration file. +# +# Features which are only available in (very) recent screen releases or in +# current Git are marked with "(GIT)" so they can be removed by the setup +# script on machines with older versions. +# +# (BATTERY) is only used on laptops, (ROOT) only if running as root. + +# Copyright (C) 2011-2013 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Automatically lock the screen after 10 minutes of inactivity if running as +# root. +#idle 600 lockscreen # handled by setup script + +# Don't display startup message. +startup_message off + +# Use visual bell instead of audible bell. +vbell on + +# Increase the scrollback buffer. +defscrollback 50000 + +# Ignore case when searching. +ignorecase on + +# I prefer zsh as my shell. GNU screen displays a warning if the shell isn't +# available. +shell zsh + +# Don't "login" windows (= add them to the utmp database) by default. Not +# useful for me and the "$" flag clutters the window flags (displayed with +# %Lw). +deflogin off + + +# TERMINAL + +# Enable 256 color mode. +term screen-256color +# Allow bold colors in XTerm (not necessary for Rxvt), not sure why this is +# necessary. Otherwise normal and bold colors are switched. Thanks to +# http://www.frexx.de/xterm-256-notes/. +attrcolor b ".I" + + +# CAPTION AND HARDSTATUS + +# Use white on light blue background for highlighting and text messages (and +# for window borders in split mode). +sorendition = Bw + +# Display current battery charge if running on a laptop. Redisplay every 3 +# minutes. +backtick 1 180 180 $HOME/.shell/bin/battery.pl -s BATTERY # (BATTERY) +# Display current temperature if running on a laptop. Redisplay every minute. +backtick 2 60 60 $HOME/.shell/bin/temperature.pl -s TEMPERATURE # (TEMPERATURE) + +# Make sure the temporary variable we use is empty. Thanks to +# http://gist.github.com/133000 for the idea to use setenv and to TauPan in +# #screen on Freenode (2010-03-10 16:11 CET) for reminding me of it and +# searching it again. +unsetenv s + +# Always display the caption. +setenv s "$s%{= Bw}" # - white on light blue background, also reset all + # attributes (necessary so everything is displayed + # correctly) +setenv s "$s%?%P" # - is copy mode enabled? (GIT) +setenv s "$s%{= wB}" # - if so change colors to light blue on white (GIT) +setenv s "$s%?" # - end if (GIT) +setenv s "$s%3n" # - window number +setenv s "$s " # - space +setenv s "$s%t" # - window name +caption always "$s" +unsetenv s +# Always display the status line with open windows and the hostname. +setenv s "$s%Lw" # - number and names of windows, L displays window flags +setenv s "$s%=" # - right align the following text +setenv s "$s%l" # - load average +setenv s "$s " # - space +setenv s "$s%H" # - hostname +setenv s "$s " # - space (TEMPERATURE) +setenv s "$s%2`" # - temperature (TEMPERATURE) +setenv s "$s " # - space (BATTERY) +setenv s "$s%1`" # - battery status (BATTERY) +hardstatus alwayslastline "$s" +unsetenv s + + +# BINDINGS + +# Remove some bindings I don't use to prevent using them accidentally. You +# probably don't want to copy this. +bind K # kill +bind k # kill +bind ^K # kill +bind \\ # quit +bind ^\ # quit +bind ^Z # suspend +bind z # suspend +bind ^S # xoff +bind s # xoff +bind ^Q # xon +bind q # xon +bind ^G # visual bell +bind D # power detach + +# Bindings for fast switching to windows 10 to 19. Thanks to skizzhg in +# #screen on Freenode (2010-10-31 21:49 CET) for the suggestion. +bind ; command -c window +bind -c window 0 select 10 +bind -c window 1 select 11 +bind -c window 2 select 12 +bind -c window 3 select 13 +bind -c window 4 select 14 +bind -c window 5 select 15 +bind -c window 6 select 16 +bind -c window 7 select 17 +bind -c window 8 select 18 +bind -c window 9 select 19 +# And bindings for windows 20 to 29 with e.g. ;;1. Thanks to Kays in #irssi on +# Freenode (2012-10-18 16:25 CEST) for the suggestion to use ;;. +bind -c window ; command -c window2 +bind -c window2 0 select 20 +bind -c window2 1 select 21 +bind -c window2 2 select 22 +bind -c window2 3 select 23 +bind -c window2 4 select 24 +bind -c window2 5 select 25 +bind -c window2 6 select 26 +bind -c window2 7 select 27 +bind -c window2 8 select 28 +bind -c window2 9 select 29 + +# Run urlview on current screen content. Very useful to follow links. Make +# sure hardcopy_append is off before using this command. +bind ^B eval "hardcopy $HOME/.tmp/screen-urlview" "screen urlview $HOME/.tmp/screen-urlview" + + +# DIGRAPHS + +digraph (, 「 +digraph ), 」 diff --git a/shell/setup.sh b/shell/setup.sh new file mode 100755 index 0000000..eec1ded --- /dev/null +++ b/shell/setup.sh @@ -0,0 +1,291 @@ +#!/bin/sh + +# Setup script for shell configuration files. + +# Copyright (C) 2011-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +. ../lib.sh + + +# Helper functions. +terminal_info() { + infocmp "$@" 2>&1 +} +terminal_available() { + terminal_info "$@" > /dev/null +} +# Usage: +apply_optional_replacement() { + if test -n "$4"; then + printf '%s: using %s %s\n' "$1" "$2" "$4" + generate "$1" '' simple_cpp \ + "$3" -- "$4" + else + printf '%s: removing %s display\n' "$1" "$2" + grep_i -v "$3" "$1" + fi +} +# Check if `infocmp` is available. +if ! infocmp >/dev/null 2>&1; then + echo 'Warning: `infocmp` not available! 256color checks will fail.' + echo +fi + + +# DIRECTORY SETUP + +# Create private temporary directory used by many tools (including GNU screen +# and tmux). +mkdir -p ~/.tmp +chmod 0700 ~/.tmp + +# Create rlwrap history directory. +mkdir -p shell/rlwrap +# Create zsh cache directory. +mkdir -p zsh/cache + + +# FILE SETUP + +# Generate ~/.less with lesskey. Prevent cluttering ~/ by storing the history +# file in this directory; this requires replacing the constant HISTORY_PATH in +# lesskey. +echo 'lesskey: generating .lesskey' +simple_cpp shell/dircolors + dircolors -b shell/dircolors.in >>shell/dircolors +fi + +# Find the required options to get colored ls output. GNU ls is preferred. See +# shell/aliases.in for details. Doing this here instead of in shell/aliases +# speeds up shell starts. +# +# GNU ls with colors available. +if ls --color >/dev/null 2>&1; then + ls_args='command ls --color' +# Normal (BSD) ls with colors available. +elif ls -G >/dev/null 2>&1; then + # Don't display hidden files by default when running as root (-I), I use + # `la` for that. + ls_args='CLICOLOR_FORCE=1 command ls -G -I' +# OpenBSD has no colored ls, use colorls instead. +elif colorls -G >/dev/null 2>&1; then + ls_args='CLICOLOR_FORCE=1 colorls -G' +# Simple ls with no colors. +else + ls_args='command ls' +fi + +# Also check if `column -t` is available. +if echo test | column -t >/dev/null 2>&1; then + column=' | column -t' +else + column= +fi + +generate shell/aliases .in simple_cpp \ + LS_ARGS COLUMN -- \ + "$ls_args" "$column" + +# If `tig` is not available use my simple replacement. +if ! installed tig; then + echo "alias tig='git tig'" >>shell/aliases +fi + +# Check if grep supports --color=auto. +if echo test | grep --color=auto test >/dev/null 2>&1; then + : +else + echo 'shell/aliases: removing grep --color=auto' + sed_i '/^alias grep=/ s/^/#/' shell/aliases +fi + +generate screenrc .in cat +# As screen-256color is not widely supported use it only on machines where the +# matching terminfo entry is available. This also requires a terminal emulator +# which supports 256 colors. Also used for tmux. +use_256colors= +if terminal_available screen-256color; then + # GNU/Linux's virtual terminal doesn't support 256 colors. If setup.sh is + # run one one, assume this user is mostly used from the terminal. + if test x"$TERM" = xlinux || test x"$TERM" = xscreen.linux; then + echo 'screenrc: running on virtual terminal, disabling 256 colors' + # Called through SSH connection, assume the local system supports 256 + # colors. + elif test -n "${SSH_CONNECTION:+set}"; then + use_256colors=1 + # We have rxvt-unicode installed, check if it supports 256 colors. + elif installed urxvt; then + # Thanks to deryni in #rxvt-unicode on Freenode (2012-10-14 22:54 + # CEST) for the strings/grep idea. The grep check is for "correct" 256 + # rxvt-unicode binaries (e.g. Debian's rxvt-unicode-256color), the + # terminal_info check for manual installations which modify + # rxvt-unicode's terminfo entry. + urxvt_path=`installed_path urxvt` + urxvt_grep=`strings "$urxvt_path" | grep '^TERM=rxvt-'` + if test x"$urxvt_grep" = 'xTERM=rxvt-unicode-256color' \ + || terminal_info rxvt-unicode \ + | grep -F 'colors#256' >/dev/null; then + use_256colors=1 + fi + # Check if XTerm supports 256 colors (not a perfect check, but most XTerm + # support 256 colors). + elif terminal_available xterm-256color; then + use_256colors=1 + fi +fi +if test -z "$use_256colors"; then + echo 'screenrc: removing 256 colors' + sed_i 's/Enable 256 color/Disable 256 color/; + s/screen-256color/screen/' screenrc +fi +# Some options are only necessary when running as root. They are marked as +# "(ROOT)". +if test "`id -u`" -ne 0; then + echo 'screenrc: removing root options' + grep_i -v '(ROOT)' screenrc +fi +# I use some features of GNU screen which are only in Git or very recent GNU +# screen versions. Drop them on machines which have older versions. They are +# marked as "(GIT)". +if test ! -d "$HOME/development/shell/screen"; then + echo 'screenrc: removing Git features' + grep_i -v '(GIT)' screenrc +fi +# Rxvt doesn't need the attrcolor "fix". As I prefer rxvt assume I use it when +# it's installed. +if installed rxvt; then + echo 'screenrc: removing attrcolor "fix"' + sed_i 's/attrcolor b ".I"/#attrcolor b ".I"/' screenrc +fi +# Display current battery charge on computers with a battery. Necessary lines +# are marked as "(BATTERY)". Also used for Tmux. +battery= +for x in /sys/class/power_supply/BAT*; do + test -d "$x" || continue + battery="$x" +done +apply_optional_replacement screenrc \ + battery BATTERY "$battery" +# Display current temperature. Necessary lines are marked as "(TEMPERATURE)". +# Also used for Tmux. +temperature=/sys/devices/platform/coretemp.0 +if ! test -d "$temperature"; then + temperature= +fi +apply_optional_replacement screenrc \ + temperature TEMPERATURE "$temperature" + + +if installed tmux; then + generate tmux.conf .in cat + + apply_optional_replacement tmux.conf \ + battery BATTERY "$battery" + apply_optional_replacement tmux.conf \ + temperature TEMPERATURE "$temperature" + + # Old Tmux versions can't handle that. + generate tmux.conf '' ./bin/remove-continuation.pl + + # Add mappings to switch to windows 10-29 quickly. See tmux-window.pl for + # details. + perl ./tmux-window.pl 1 "`pwd`/tmux-window2.conf" >tmux-window1.conf + perl ./tmux-window.pl 2 >tmux-window2.conf + # Set absolute path to tmux-window1.conf in tmux.conf. + generate tmux.conf '' simple_cpp \ + TMUX_WINDOW_PATH -- "`pwd`/tmux-window1.conf" + + # 256 colors not available. + if test -z "$use_256colors"; then + echo 'tmux.conf: removing 256 colors' + sed_i 's/Enable 256 color/Disable 256 color/; + s/screen-256color/screen/' tmux.conf + fi + # Tmux doesn't display a warning if the shell wasn't found! + if test ! -x '/bin/zsh'; then + echo 'tmux.conf: removing /bin/zsh as shell' + sed_i 's/zsh/sh/' tmux.conf + fi +fi + +# Htop overwrites the comments in its configuration file. +generate htoprc .in cat + +if installed dig; then + # dig doesn't support any comments in digrc. + grep -v -E '^#' digrc.in >digrc +fi + + +# LINK SETUP + +# Link setup for shells. +link shell ~/.shell +link bash ~/.bash +link bash/rc ~/.bashrc +link bash/profile ~/.bash_profile +link bash/logout ~/.bash_logout +if installed csh; then + link csh/rc ~/.cshrc +fi +link zsh ~/.zsh +link zsh/env ~/.zshenv +link zsh/rc ~/.zshrc +link zsh/logout ~/.zlogout + +if installed tmux; then + link terminfo ~/.terminfo +fi + +# Link setup for additional files. +if installed crontab; then + link crontab.d ~/.crontab.d +fi +link lessfilter ~/.lessfilter +if installed colordiff; then + link colordiffrc ~/.colordiffrc +fi +link inputrc ~/.inputrc +if installed ghci; then + link haskeline ~/.haskeline +fi +link screenrc ~/.screenrc +if installed tmux; then + link tmux.conf ~/.tmux.conf +fi +if installed htop; then + link htoprc ~/.htoprc + # New location for htoprc. Use both for compatibility. + mkdir -p ~/.config/htop + link htoprc ~/.config/htop/htoprc +fi +if test -d ~/.ssh && test -O ~/.ssh; then + mkdir -p ~/.ssh/master + link ssh_config ~/.ssh/config +fi +if installed dig; then + link digrc ~/.digrc +fi diff --git a/shell/shell/aliases.in b/shell/shell/aliases.in new file mode 100644 index 0000000..69270cc --- /dev/null +++ b/shell/shell/aliases.in @@ -0,0 +1,134 @@ +# Aliases and similar functions which can be used by all shells (supporting +# them). + +# Copyright (C) 2011-2015 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Shortcuts for often used programs. +alias c=clear +alias d=cd +alias e=elinks +alias g=git +alias h=htop +alias l=ls +alias m=make +alias p=less # p for pager +alias s=ssh +alias t=tig +alias v=vim +alias x=exit +# Shortcuts for a little less used programs. +alias ga='git annex' +alias gr=grep +alias gri='grep -i' +alias grr='grep -r' +alias grri='grep -ri' +alias mc='make clean' +alias mj='make -j$(nproc)' +alias mu=mutt +alias rs=reset # like git's reset alias +alias sa='ssh-add -t 1h' +alias te=tree +# systemd ... (sc is provided as shell script for better completion) +alias jc=journalctl +alias lc=loginctl +alias mc=machinectl + + +unalias mv cp 2>/dev/null +# Ask for confirmation before overwriting files. Especially useful when moving +# to a different directory. No alias for `rm` because I specify the files to +# remove directly, so I know what will happen. +alias mv='mv -i' +# Additionally preserve all file attributes when copying, this includes +# copying symbolic links as is without dereferencing them. +alias cp='cp -i -a' + + +# Make sure there is no alias named ls as it causes problems with the +# following ls function on (at least) bash 4.0.35. +unalias ls 2>/dev/null +# Improved ls which displays the files in columns (-C), visualizes +# directories, links and other special files (-F) and pages everything through +# less. +# +# If available use GNU ls with colorized output. If it isn't available try +# normal ls which needs CLICOLOR_FORCE so it displays colors when used with a +# pager. If none work no colors are used. +# +# See `setup.sh` for details. LS_* are replaced with the appropriate values +# when this file is generated. +ls() { + LS_ARGS -C -F "$@" 2>&1 | less +} + +unalias ll lt la lal lat 2>/dev/null +# List the files in list format with access rights, etc. +alias ll='ls -l' +# List the files sorted by last modification date. +alias lt='ls -l -t' +# List all files. +alias la='ls -a' +# List all files in list format with access rights, etc. +alias lal='ls -al' +# List all files sorted by last modification date. +alias lat='ls -al -t' + + +# Make going up directories simple. +alias ..='cd ..' +alias ...='cd ../..' +alias ....='cd ../../..' +alias .....='cd ../../../..' + +# Automatically use unified diffs. +alias diff='diff -u' + +# COLUMN is set to `| column -t` if it's available, empty otherwise. + +# Display all files (-s), use human readable sizes (-h) and display the +# complete size (-c). +alias du='du -shc' +# Use human readable sizes and format it nicely, thanks to climagic +# (http://twitter.com/climagic/status/49623386762129408). +df() { + command df -hP "$@" COLUMN +} + +# Highlight matched strings. Doesn't work with a pager! +alias grep='grep --color=auto' + +# Pipe output through less. +tree() { + command tree -C "$@" | less +} + +# Better viewer for info pages .. just pipe everything into less. +info() { + command info "$@" 2>/dev/null | less +} + +# Using su (or sudo) as root to a less privileged user might allow the other +# user to run arbitrary commands as root. See also Debian bugs #628843 and +# #657784. +if test "`id -u`" -eq 0; then + su() { + echo 'never su as root' >&2 + return 1 + } +fi + +# vim: ft=sh diff --git a/shell/shell/bin b/shell/shell/bin new file mode 120000 index 0000000..19f285a --- /dev/null +++ b/shell/shell/bin @@ -0,0 +1 @@ +../bin \ No newline at end of file diff --git a/shell/shell/dircolors.in b/shell/shell/dircolors.in new file mode 100644 index 0000000..82bafc6 --- /dev/null +++ b/shell/shell/dircolors.in @@ -0,0 +1,93 @@ +# Color settings for GNU ls. Read by `dircolors` to write the $LS_COLORS +# environment variable. + +# Copyright (C) 2013 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# See `dircolors --print-database` for possible colors. + +RESET 00 +# Normal files: no color. +NORMAL 00 + +# Regular files: normal. +FILE 00 +# Executable files: bold red. +EXEC 31;01 + +# Symbolic links: cyan (other possible value: "target", color based on target +# type). +LINK 36 +# Orphaned symbolic links (nonexistent or not-statable): cyan with red +# background. +ORPHAN 36;41 +# Regular files with multiple hard links: underlined. +MULTIHARDLINK 04 + +# setuid and setgid files: bold red with yellow background (red because they +# are executables). +SETUID 31;43;01 +SETGID 31;43;01 + +# Directories: bold blue. +DIR 34;01 +# Directories writable by other users and not sticky: bold blue with red +# background. +OTHER_WRITABLE 34;41;01 +# Directories with sticky bit and writable by others: bold blue with green +# background. +STICKY_OTHER_WRITABLE 34;42;01 +# Directories with sticky bit and not writable by others: bold blue with +# yellow background. +STICKY 34;43;01 + +# Named pipes: green. +FIFO 32 +# Sockets: green. +SOCK 32 +# Block devices: normal. +BLK 00 +# Character devices: normal. +CHR 00 + + +# Color important files which might be overlooked in full directories. +# +# `ls` can't color matching files, only matching extensions and suffixes; +# therefore use the suffix (which is a superset of matching extensions). As +# most filenames have no weird suffixes like "filenameNEWS", this should work +# fine most of the time. +# +# *foo matches files ending with foo, .foo only files with a foo extension +# (e.g. example.foo). + +# Read-me files (e.g. README, program.readme, etc.): bold magenta. +*README 35;01 +*README.adoc 35;01 +*README.txt 35;01 +*README.md 35;01 +*README.mkd 35;01 +*readme 35;01 +# Misc files: bold magenta. +*NEWS 35;01 +*FAQ 35;01 +*faq 35;01 +*TODO 35;01 +*todo 35;01 +# Makefiles: bold magenta. +*Makefile 35;01 + +# vim: ft=dircolors diff --git a/shell/shell/env b/shell/shell/env new file mode 100644 index 0000000..f3e4293 --- /dev/null +++ b/shell/shell/env @@ -0,0 +1,142 @@ +# Configuration file for environment related options for all shells. + +# Copyright (C) 2011-2015 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Use UTF-8 encoding in the terminal. Don't use LC_ALL as it's used for +# debugging purposes. Thanks to twb in #screen on Freenode (2009-10-02 10:25 +# CET). +LANG=en_US.UTF-8 +export LANG +# Use C locale when sorting. +LC_COLLATE=C +export LC_COLLATE + +# Just in case a nice administrator tries to force LC_ALL on us ... +unset LC_ALL +# Also reset the rest just in case. +unset LC_ADDRESS +unset LC_CTYPE +unset LC_IDENTIFICATION +unset LC_MEASUREMENT +unset LC_MESSAGES +unset LC_MONETARY +unset LC_NAME +unset LC_NUMERIC +unset LC_PAPER +unset LC_TELEPHONE +unset LC_TIME +# Make sure $LANGUAGE is not set. It's a GNU extension which can overwrite +# variables like $LANG or $LC_ALL. +unset LANGUAGE + +# Add ~/bin, ~/.bin and ~/.shell/bin to PATH if available. +if test -d "$HOME/.shell/bin"; then + PATH="$HOME/.shell/bin:$PATH" +fi +if test -d "$HOME/.bin"; then + PATH="$HOME/.bin:$PATH" +fi +if test -d "$HOME/bin"; then + PATH="$HOME/bin:$PATH" +fi + +# Use Vim as editor. +EDITOR=vim +export EDITOR + +# Set less as pager, its configuration is done through the ~/.less file. +PAGER=less +export PAGER + +escape=`printf '\033'` +# Color man pages viewed with less, thanks to [1]. +# +# [1]: http://nion.modprobe.de/blog/archives/572-less-colors-for-man-pages.html +# +# Color bold strings in bold blue. +LESS_TERMCAP_md="${escape}[01;34m" +LESS_TERMCAP_me="${escape}[0m" +export LESS_TERMCAP_md LESS_TERMCAP_me +# Color underlined strings in bold yellow and underlined. +LESS_TERMCAP_us="${escape}[01;4;33m" +LESS_TERMCAP_ue="${escape}[0m" +export LESS_TERMCAP_us LESS_TERMCAP_ue +# Color standout mode in bold black with yellow background. +LESS_TERMCAP_so="${escape}[01;30;43m" +LESS_TERMCAP_se="${escape}[0m" +export LESS_TERMCAP_so LESS_TERMCAP_se + +# Prefer a private and most likely fast directory (tmpfs) for temporary files +# to reduce security problems on multi-user systems. +if test -n "$XDG_RUNTIME_DIR" && test -d "$XDG_RUNTIME_DIR"; then + TMP="$XDG_RUNTIME_DIR" +# Use ~/.tmp and ~/.tmp as fallback. +elif test -d "$HOME/.tmp"; then + TMP="$HOME/.tmp" +elif test -d "$HOME/tmp"; then + TMP="$HOME/tmp" +else + TMP= +fi +if test -n "$TMP"; then + TEMP="$TMP" + TMPDIR="$TMP" + export TMP TEMP TMPDIR +fi + +# Change rlwrap's home directory to prevent cluttering ~/. +RLWRAP_HOME="$HOME/.shell/rlwrap" +export RLWRAP_HOME + +# Set colors for GNU ls (and Zsh completions). +if test -f "$HOME/.shell/dircolors"; then + . "$HOME/.shell/dircolors" +fi +# Set the same colors for non GNU ls, except for special cases which aren't +# supported. +LSCOLORS='ExgxxxxxBxxxxxBdBdExEb' +# ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ +# | | | | | | | | | | | +# | | | | | | | | | | *- directory writable to others, without sticky bit +# | | | | | | | | | *--- directory writable to others, with sticky bit +# | | | | | | | | *----- executable with setgid bit set +# | | | | | | | *------- executable with setuid bit set +# | | | | | | *--------- character special +# | | | | | *----------- block special +# | | | | *------------- executable +# | | | *--------------- pipe +# | | *----------------- socket +# | *------------------- symbolic link +# *--------------------- directory +export LSCOLORS + +# Setup lesspipe to view multiple file-types (like .gz, .zip, etc.) with less. +# Useful in combination with the "p" alias. Inspired by Debian's default bash +# files. Thanks. +if test -x /usr/bin/lesspipe; then + # Don't use eval $(lesspipe) which breaks on a few systems (e.g. Gentoo) + # due to a different lesspipe implementation. + LESSOPEN='| /usr/bin/lesspipe %s' + LESSCLOSE='/usr/bin/lesspipe %s %s' + export LESSOPEN LESSCLOSE +fi + +# Additional command line options for `mtr`. +MTR_OPTIONS='--show-ips' +export MTR_OPTIONS + +# vim: ft=sh diff --git a/shell/shell/functions b/shell/shell/functions new file mode 100644 index 0000000..838968b --- /dev/null +++ b/shell/shell/functions @@ -0,0 +1,30 @@ +# Shell functions useful to all shells. + +# Copyright (C) 2011-2014 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Source $1 if it exists. And $1.local if it exists as well. +source_config() { + if test -f "$1"; then + . "$1" + fi + + if test -f "$1.local"; then + . "$1.local" + fi +} + +# vim: ft=sh diff --git a/shell/shell/logout b/shell/shell/logout new file mode 100644 index 0000000..a5e1bbc --- /dev/null +++ b/shell/shell/logout @@ -0,0 +1,31 @@ +# Shell logout file usable by all shells. + +# Copyright (C) 2011-2013 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# When leaving the console clear the screen to increase privacy. Taken from +# Debian default bash files and modified. Thanks. + +if test -x /usr/bin/clear_console; then + /usr/bin/clear_console -q +else + clear +fi + +# Make sure sudo rights are removed. +sudo -k >/dev/null 2>&1 + +# vim: ft=sh diff --git a/shell/shell/rc b/shell/shell/rc new file mode 100644 index 0000000..d0261bb --- /dev/null +++ b/shell/shell/rc @@ -0,0 +1,117 @@ +# Shell configuration file. + +# Copyright (C) 2013-2014 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Normal umask for root (readable by all users). +if test "`id -u`" -eq 0; then + umask 022 +# Restricted umask for normal users (readable only by me). +else + umask 077 +fi + +# Disable flow control (^s and ^q). I use GNU Screen/Tmux which also supports +# this in a similar way (entering copy mode) and enabling flow control by +# accident is annoying. +if test -t 0; then + stty -ixon -ixoff +fi + +# Auto-logout after timeout on TTYs. It's easy to forget to logout after +# switching back to X11 from a TTY. +timeout_setup_screen_lock() { + echo "Locking GNU screen after $timeout seconds (TTY detected)." + screen -X idle $timeout lockscreen + echo +} +timeout_setup_tmux_lock() { + if type vlock >/dev/null; then + echo "Locking Tmux after $timeout seconds (TTY detected)." + tmux set-option lock-after-time $timeout + echo + + else + echo "vlock not found, locking won't work in Tmux!" >&2 + echo "Falling back to shell timeout." >&2 + echo + + timeout_setup_shell_logout + fi +} +timeout_setup_shell_logout() { + echo "Auto-logout after $timeout seconds (TTY detected)." + TMOUT=$timeout + echo +} +# Timeout in seconds. +local timeout >/dev/null 2>&1 +timeout=600 +case "$TERM" in + # `tty` doesn't work inside a pseudo-terminal as provided by GNU + # Screen/Tmux. + # + # The following settings for GNU Screen/Tmux will only auto-lock new + # sessions, not when attaching to existing sessions! + screen*) + if test -n "$STY"; then + case "$STY" in + *.tty[0-9]*.*) + timeout_setup_screen_lock + ;; + esac + elif test -n "$TMUX"; then + case "`tmux display -p '#{client_tty}'`" in + /dev/tty[0-9]*) + timeout_setup_tmux_lock + ;; + /dev/*) + # Not on TTY, nothing to do. + ;; + *) + echo 'Tmux < 1.8 found, TTY check might be incorrect!' >&2 + + local client >/dev/null 2>&1 + client=`printf '%s' "$TMUX" | sed 's/^.*,\([0-9]*\)$/\1/'` + + case "`tmux list-clients \ + | grep -E "^/dev/.*?: $client "`" in + /dev/tty[0-9]*) + timeout_setup_tmux_lock + ;; + esac + ;; + esac + else + echo 'TERM=screen but neither $STY nor $TMUX found!' >&2 + timeout_setup_shell_logout + fi + ;; + + *) + case `tty` in + /dev/tty[0-9]*) + timeout_setup_shell_logout + ;; + esac + ;; +esac +unset timeout +unset timeout_setup_screen_lock +unset timeout_setup_tmux_lock +unset timeout_setup_screen_lock + +# vim: ft=sh diff --git a/shell/ssh_config b/shell/ssh_config new file mode 100644 index 0000000..09995ab --- /dev/null +++ b/shell/ssh_config @@ -0,0 +1,137 @@ +# SSH configuration file. +# +# Some options are set even if they are default to prevent /etc/ssh/ssh_config +# from overwriting them. + +# Copyright (C) 2011-2016 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + +# Undocumented (and not very well tested) feature. This drops the connection +# after 5 seconds of inactivity. Thanks to shad0VV in #openssh on Freenode +# (2012-11-04 18:40 CET) for telling me about this undocumented feature. +# +# ServerAliveCountMax 0 +# ServerAliveInterval 5 + + +# Options are parsed top-to-bottom, the first matching option is used. Later +# assignments to the same option are ignored, thanks to anonJD in #openssh on +# Freenode (2011-05-18 21:40 CEST) for letting me know. Therefore put all +# affected host specific rules here, before the global rules. +# +# For example to change the MACs option for a specific host, use: +# +# Host host +# # Old SSH daemon which needs SHA1 (SHA-512 in case it gets updated). +# MACs hmac-sha2-512,hmac-sha1 + + +# Rules for all hosts. +Host * + +# Force protocol version 2 which is more secure (default). + Protocol 2 + +# Use stronger algorithms. If some hosts require weaker versions then use Host +# groups to enable them only for those specific machines. + +# Don't use SHA1 and disable elliptic curves whose security regarding the +# parameters is still in debate. + KexAlgorithms diffie-hellman-group-exchange-sha256 +# Use stronger cipher versions. Disable CBC ciphers to prevent (unlikely) +# plaintext recovery attack [1], disable RC4 because it's broken [2]; this +# leaves only AES. No GCM ciphers yet because they are still very new. +# +# [1]: http://www.openssh.com/txt/cbc.adv +# [2]: http://www.schneier.com/blog/archives/2013/03/new_rc4_attack.html + Ciphers aes256-ctr +# Don't use weak MACs like MD5 or SHA1. However strong MACs are not as +# important as strong ciphers because an attacker must be able to break a MAC +# in real time to modify the data in transmit. Prefer "-etm" algorithms which +# use encrypt-then-mac which is more secure than the default encrypt-and-mac +# in SSH [1] (available since 6.2). +# +# [1]: http://cseweb.ucsd.edu/~mihir/papers/oem.html + MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-512 +# Disable DSA host keys because they are weak (only 1024 bit) and elliptic +# curves. I don't need certificates, therefore disable those algorithms as +# well (*-cert-*). + HostKeyAlgorithms ssh-rsa + +# Disable X11 and agent forwarding for security reasons (defaults). + ForwardX11 no + ForwardAgent no +# Don't trust remote X11 clients. If enabled allows bad admins complete access +# to local X11! + ForwardX11Trusted no + +# Disable authentication methods I don't use. + ChallengeResponseAuthentication no + GSSAPIAuthentication no + HostbasedAuthentication no + KbdInteractiveAuthentication no +# Only enable those I need. + PasswordAuthentication yes + PubkeyAuthentication yes + +# Use only authentication identity files configured in ~/.ssh/config even if +# ssh-agent offers more identities. + IdentitiesOnly yes + +# Bind local forwardings to loopback only. This way no remote hosts can access +# them (default). + GatewayPorts no +# Abort if not all requested port forwardings can be set up. + ExitOnForwardFailure yes + +# Allow using -M (ControlMaster) to create a master SSH session which +# "tunnels" other connections to the same host, thus reducing the number of +# authentications (which are relatively slow) and TCP connections. The master +# sockets are stored in ~/.ssh (by default ControlPath is not set). Using %r +# (remote user name) might leak information to other users on the current +# system (e.g. via netstat or lsof). + ControlPath ~/.ssh/master/%l-%h-%p-%r +# Automatically create a new master session if there's none yet or use an +# existing one. This way the user doesn't have to use -M to enable a master +# manually. Don't set this option to "yes" or all SSH commands try to become +# the master session which is obviously not possible. + ControlMaster auto +# When the connection for a master is closed (e.g. logout of remote shell), +# move the master connection in the background. If there's no other active +# connection using the master, close it after x seconds. This prevents the +# client of the master connection from blocking because it waits for all +# connections using it to terminate which is very annoying. The timeout +# prevents stale master connections. + ControlPersist 10 + +# Don't permit running local commands (default). + PermitLocalCommand no + +# Don't send any environment variables (default). + SendEnv + +# Don't hash any hosts in ~/.ssh/known_hosts. It doesn't help if the ssh hosts +# are stored in the shell's history file or in this file as shortcut so it's +# rather useless (default). + HashKnownHosts no + +# Check host IP in known_hosts when connecting to detect DNS spoofing +# (default). + CheckHostIP yes +# Ask before adding any host keys to ~/.ssh/known_hosts (default). + StrictHostKeyChecking ask +# Check host keys from DNS' SSHFP resource records but ask apply +# StrictHostKeyChecking before trusting them. + VerifyHostKeyDNS ask diff --git a/shell/sshd_config b/shell/sshd_config new file mode 100644 index 0000000..0b7d95a --- /dev/null +++ b/shell/sshd_config @@ -0,0 +1,84 @@ +# SSH daemon configuration file. +# +# Some options are set even if they are default to document that they are +# important and to prevent upstream changes from affecting them. + +# Copyright (C) 2013-2016 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Listen on port 22 (default). +Port 22 + +# Only use protocol 2. Protocol 1 is insecure. (default) +Protocol 2 + +# Stronger algorithms. See ssh_config for details. +KexAlgorithms diffie-hellman-group-exchange-sha256 +Ciphers aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-512 + +# Use privilege separation for increased security. "sandbox" applies +# additional restrictions on the unprivileged process. +UsePrivilegeSeparation sandbox + +# Don't use PAM because it may circumvent other authentication methods used +# below (default). +UsePAM no +# Disable authentication methods I don't use. +ChallengeResponseAuthentication no +GSSAPIAuthentication no +HostbasedAuthentication no +KbdInteractiveAuthentication no +KerberosAuthentication no +PasswordAuthentication no +# Only enable those I need. +PubkeyAuthentication yes + +# Don't allow empty passwords (default). +PermitEmptyPasswords no +# Allow root-login only with public keys. +PermitRootLogin without-password + +# Be strict when checking user file permissions (default). +StrictModes yes + +# Allow more sessions per network connection (e.g. from ControlMaster/-M). +# When not enough sessions are available this message is sent by ssh: +# "mux_client_request_session: session request failed: Session open refused by +# peer". +MaxSessions 30 + +# Don't accept any environment variables from the client (default). +AcceptEnv +# Don't use ~/.ssh/environment and environment= options in +# ~/.ssh/authorized_keys because LD_PRELOAD could be used to circumvent +# authentications (default). +PermitUserEnvironment no + +# Send a message after the given seconds of inactivity through the encrypted +# channel. Used to detect stale connections more quickly. Not necessary on all +# servers. +#ClientAliveInterval 60 +# Disconnect the client if more than max count alive messages were lost +# (default). With the setting above this detects a broken connection after 3 +# minutes. +ClientAliveCountMax 3 + +# Enable sftp (and sshfs) usage. internal-sftp also works in chroots. +Subsystem sftp internal-sftp + +# Only allow logins for certain users. +AllowUsers root diff --git a/shell/terminfo/README b/shell/terminfo/README new file mode 100644 index 0000000..3c91b00 --- /dev/null +++ b/shell/terminfo/README @@ -0,0 +1,5 @@ +README +====== + +screen-it-256color is a modified screen-256color terminfo which handles italic +text for Tmux correctly. diff --git a/shell/terminfo/s/screen-it-256color b/shell/terminfo/s/screen-it-256color new file mode 100644 index 0000000..8651f3c Binary files /dev/null and b/shell/terminfo/s/screen-it-256color differ diff --git a/shell/tmux-window.pl b/shell/tmux-window.pl new file mode 100644 index 0000000..5e2601c --- /dev/null +++ b/shell/tmux-window.pl @@ -0,0 +1,93 @@ +#!/usr/bin/perl + +# Helper script to support quick window jumping with a prefix key for 0-9 in +# Tmux. + +# At the moment Tmux doesn't support mappings with multiple keys, e.g. prefix +# ;0, prefix ;1 etc. (where ; is the common secondary prefix key). But this +# works in GNU screen and is very useful to switch to windows quickly, e.g. +# prefix ;3 to switch to window 13 or prefix ;;5 to switch to window 25. +# +# To simulate this missing feature ; and 0-9 must be rebound when prefix ; is +# used, and unbound when ; or 0-9 was pressed and the window selected. This +# script generates these tedious mappings. +# +# For each number (0-9) the following mapping is generated (example with 0): +# +# bind-key -n 0 unbind-key -n 0 \; \ +# ... +# unbind-key -n 9 \; \ +# unbind-key -n \\; \ # this unmaps ; +# select-window -t :10 \; +# +# Due to Tmux's handling of errors, they abort the rest of the mapping, the +# select-window command is executed as last part of the mapping. +# +# If a secondary chaining (e.g. prefix ;;3) is requested, a second file like +# the generated one must be loaded with ; to jump to windows 20-29. Therefore +# the following line is added in this case. +# +# bind-key -n \; source-file "/path/to/second/file" +# +# To use these mappings first create the files using this script. To switch to +# windows 10-19 with ;0-;9 and to 20-29 with ;;0-;;9 run these commands (can +# be chained indefinitely): +# +# $ perl ./tmux-window.pl 1 "`pwd`/tmux-window2.conf" > tmux-window1.conf +# $ perl ./tmux-window.pl 2 > tmux-window2.conf +# +# Then add the following to your tmux.conf: +# +# bind-key \; source-file "/path/to/tmux-window1.conf" +# +# tmux-window1.conf automatically contains the path to tmux-window2.conf, +# therefore chaining for ;;3 will work to jump to window 23. + +# Copyright (C) 2012-2013 Simon Ruderich +# +# 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 3 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, see . + + +use strict; +use warnings; + + +if (scalar @ARGV != 1 && scalar @ARGV != 2) { + print STDERR "Usage: $0 []\n"; + exit 1; +} + +my $level = $ARGV[0]; +my $path = $ARGV[1]; + +if (defined $path and $path !~ m{^/}) { + print STDERR " must be an absolute path!\n"; + exit 2; +} + + +for (my $i = 0; $i < 10; $i++) { + print "bind-key -n $i "; + for (my $j = 0; $j < 10; $j++) { + print "unbind-key -n $j \\; "; + } + print "unbind-key -n \\\\; \\; "; + # Do the select-window last. If the window doesn't exist the failing + # select-window command prevents unbinding the other keys. + print "select-window -t :$level$i\n"; +} + +if (defined $path) { + print "bind-key -n \\; source-file \"$path\"\n"; +} diff --git a/shell/tmux.conf.in b/shell/tmux.conf.in new file mode 100644 index 0000000..6d582d9 --- /dev/null +++ b/shell/tmux.conf.in @@ -0,0 +1,133 @@ +# Tmux configuration file. +# +# Notes: +# +# - To swap/renumber windows (like GNU screen's :number command) use +# :swap-window -t . +# - GNU screen's screen -x can be replicated with tmux new-session -t. + +# Copyright (C) 2011-2013 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# GENERAL + +# Use vlock to lock the screen. Tmux doesn't have an internal lock program +# like GNU screen! +set-option -g lock-command "vlock" +# Lock sessions individually. Otherwise lock-after-time will wait on all other +# sessions to idle before it locks this session. +set-option -g lock-server off + +# Use Zsh as shell. Tmux does not display a warning if the shell isn't +# available! +set-option -g default-shell "/bin/zsh" + +# Use a larger window history, in lines. +set-option -g history-limit 50000 + +# Display Tmux messages for a longer time, in milliseconds. +set-option -g display-time 3000 + +# Open new windows with the current working directory used when Tmux was +# started, and not the working directory of the current pane. +set-option -g default-path "." + + +# TERMINAL + +# Enable 256 color mode. +set-option -g default-terminal "screen-256color" + +# Disable alternative screen feature. This way e.g. Vim's window content stays +# visible after quitting Vim. This is quite useful to copy data (needs tmux +# 1.5 to work (almost) completely). +set-window-option -g alternate-screen off + +# Set title for outer terminal. +set-option -g set-titles on + +# Don't rename windows to the currently running program, my zshrc does this +# for me (with some additional features). +set-window-option -g automatic-rename off + + +# STATUS LINE + +# White text. +set-option -g status-fg white +# Bright blue background color (colour12). +set-option -g status-bg colour12 + +# Nothing left of window list. +set-option -g status-left "" +# Current load average and hostname (#H) on the right. +set-option -g status-right "#(uptime | sed 's/^.*load averages*: //; s/,//g') \ + #H \ + #(~/.shell/bin/temperature.pl -t TEMPERATURE)\ + #[] #(~/.shell/bin/battery.pl -t BATTERY)\ + " + +# Format for windows in the window list in the status line. #I window index, +# #W window number, #F window flags. +set-window-option -g window-status-format "#I #W#F" +set-window-option -g window-status-current-format "#I #W#F" + +# Update status line commands (#(..)) only every minute. +set-option -g status-interval 60 + + +# BINDINGS + +# Use Vi(m) key bindings. +set-option -g status-keys vi +set-window-option -g mode-keys vi + +# Use Ctrl-A as escape binding, like in GNU screen. +set-option -g prefix C-a +# Ctrl-A a sends Ctrl-A to the process, like in GNU screen. +bind-key a send-prefix +unbind-key C-b + +# GNU screen like bindings (with C-x). +bind-key C-c new-window +bind-key C-a last-window +bind-key C-n next-window +bind-key C-p previous-window +bind-key C-[ copy-mode +bind-key C-] paste-buffer + +# Arrow-key replacements for tmux's prompt. +bind-key -t vi-edit C-n history-down +bind-key -t vi-edit C-p history-up + +# Display date/time, similar to GNU screen's ^a ^t. Tmux's default ^a t just +# displays the current time, but I often want to know the current date. +bind-key C-t display-message + +# Run urlview on the current screen content. Very useful to follow links. +# Thanks to Arch wiki (https://wiki.archlinux.org/index.php/Tmux) for the +# basic idea how to enable this in tmux. +bind-key C-b capture-pane \; \ + save-buffer ~/.tmp/tmux-urlview \; \ + delete-buffer \; \ + new-window "urlview <~/.tmp/tmux-urlview" + +# Binding for fast switching to windows 10 to 29 (and more if necessary). +# Thanks to Kays in #irssi on Freenode (2012-10-18 16:25 CEST) for reminding +# me of this issue in Tmux. See tmux-windows.pl for details how it works. +bind-key \; source-file "TMUX_WINDOW_PATH" + +# vim: ft=tmux diff --git a/shell/zsh/env b/shell/zsh/env new file mode 100644 index 0000000..30483a0 --- /dev/null +++ b/shell/zsh/env @@ -0,0 +1,35 @@ +# Zsh configuration file for environment related options. + +# Copyright (C) 2011-2014 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +. ~/.shell/functions + +source_config ~/.shell/env + + +# Make sure elements in PATH are unique. +typeset -U path PATH + +# Use $TMPDIR/zsh as directory for temporary Zsh files to prevent symlink +# attacks - only helps if $TMPDIR points to a safe directory (which should be +# true with the settings in shell/env). +TMPPREFIX="$TMPDIR/zsh" + + +source_config ~/.zsh/env.local + +# vim: ft=zsh diff --git a/shell/zsh/functions/_systemctl b/shell/zsh/functions/_systemctl new file mode 100644 index 0000000..c440dd7 --- /dev/null +++ b/shell/zsh/functions/_systemctl @@ -0,0 +1,418 @@ +#compdef systemctl + +(( $+functions[_systemctl_command] )) || _systemctl_command() +{ + local -a _systemctl_cmds + _systemctl_cmds=( + "list-sockets:List sockets" + "list-timers:List timers" + "list-units:List units" + "start:Start (activate) one or more units" + "stop:Stop (deactivate) one or more units" + "reload:Reload one or more units" + "restart:Start or restart one or more units" + "condrestart:Restart one or more units if active" + "try-restart:Restart one or more units if active" + "reload-or-restart:Reload one or more units if possible, otherwise start or restart" + "force-reload:Reload one or more units if possible, otherwise restart if active" + "hibernate:Hibernate the system" + "hybrid-sleep:Hibernate and suspend the system" + "reload-or-try-restart:Reload one or more units if possible, otherwise restart if active" + "isolate:Start one unit and stop all others" + "kill:Send signal to processes of a unit" + "is-active:Check whether units are active" + "is-failed:Check whether units are failed" + "status:Show runtime status of one or more units" + "show:Show properties of one or more units/jobs or the manager" + "cat:Show the source unit files and drop-ins" + "reset-failed:Reset failed state for all, one, or more units" + "list-unit-files:List installed unit files" + "enable:Enable one or more unit files" + "disable:Disable one or more unit files" + "reenable:Reenable one or more unit files" + "preset:Enable/disable one or more unit files based on preset configuration" + "set-default:Set the default target" + "get-default:Query the default target" + "edit:Edit one or more unit files" + "is-system-running:Query overall status of the system" + "help:Show documentation for specified units" + "list-dependencies:Show unit dependency tree" + "mask:Mask one or more units" + "unmask:Unmask one or more units" + "link:Link one or more units files into the search path" + "is-enabled:Check whether unit files are enabled" + "list-jobs:List jobs" + "cancel:Cancel all, one, or more jobs" + "snapshot:Create a snapshot" + "delete:Remove one or more snapshots" + "show-environment:Dump environment" + "set-environment:Set one or more environment variables" + "unset-environment:Unset one or more environment variables" + "daemon-reload:Reload systemd manager configuration" + "daemon-reexec:Reexecute systemd manager" + "default:Enter system default mode" + "rescue:Enter system rescue mode" + "emergency:Enter system emergency mode" + "halt:Shut down and halt the system" + "suspend:Suspend the system" + "poweroff:Shut down and power-off the system" + "reboot:Shut down and reboot the system" + "kexec:Shut down and reboot the system with kexec" + "exit:Ask for user instance termination" + "switch-root:Change root directory" + ) + + if (( CURRENT == 1 )); then + _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@" + else + local curcontext="$curcontext" expl + + cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}" + # Deal with any aliases + case $cmd in + condrestart) cmd="try-restart";; + force-reload) cmd="reload-or-try-restart";; + esac + + # CHANGED: my aliases + case $words[1] in + c) cmd=cat ;; + d) cmd=disable ;; + e) cmd=enable ;; + k) cmd=kill ;; + m) cmd=mask ;; + r) cmd=restart ;; + rl) cmd=reload ;; + s) cmd=status ;; + sa) cmd=start ;; + so) cmd=stop ;; + u) cmd=unmask ;; + esac + + if (( $#cmd )); then + curcontext="${curcontext%:*:*}:systemctl-${cmd}:" + + local update_policy + zstyle -s ":completion:${curcontext}:" cache-policy update_policy + if [[ -z "$update_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy + fi + + _call_function ret _systemctl_$cmd || _message 'no more arguments' + else + _message "unknown systemctl command: $words[1]" + fi + return ret + fi +} + +__systemctl() +{ + systemctl $_sys_service_mgr --full --no-legend --no-pager "$@" +} + + +# Fills the unit list +_systemctl_all_units() +{ + if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) && + ! _retrieve_cache SYS_ALL_UNITS; + then + _sys_all_units=( ${${(f)"$(__systemctl list-units --all)"}%% *} ) + _store_cache SYS_ALL_UNITS _sys_all_units + fi +} + +# Fills the unit list including all file units +_systemctl_really_all_units() +{ + local -a all_unit_files; + local -a really_all_units; + if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS ) && + ! _retrieve_cache SYS_REALLY_ALL_UNITS; + then + all_unit_files=( ${${(f)"$(__systemctl list-unit-files)"}%% *} ) + _systemctl_all_units + really_all_units=($_sys_all_units $all_unit_files) + _sys_really_all_units=(${(u)really_all_units}) + _store_cache SYS_REALLY_ALL_UNITS _sys_really_all_units + fi +} + +_filter_units_by_property() { + local property=$1 value=$2 ; shift ; shift + local -a units ; units=($*) + local props + for props in ${(ps:\n\n:)"$(_call_program units "$service show --no-pager --property="Id,$property" -- ${units} 2>/dev/null")"}; do + props=(${(f)props}) + if [[ "${props[2]}" = "$property=$value" ]]; then + echo -E - " ${props[1]#Id=}" + fi + done +} + +_systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files)"}##*@.[^[:space:]]##}%%@.*}\@ } + + +_systemctl_active_units() {_sys_active_units=( ${${(f)"$(__systemctl list-units)"}%% *} )} + +_systemctl_startable_units(){ + _sys_startable_units=( $( _filter_units_by_property ActiveState inactive $( + _filter_units_by_property CanStart yes $( + __systemctl $mode list-unit-files --state enabled,disabled,static | \ + { while read -r a b; do [[ $a =~ @\. ]] || echo -E - " $a"; done; } + __systemctl $mode list-units --state inactive,failed | \ + { while read -r a b; do echo -E - " $a"; done; } )) ) ) +} + +_systemctl_restartable_units(){ + _sys_restartable_units=( $(_filter_units_by_property CanStart yes $( + __systemctl $mode list-unit-files --state enabled,disabled,static | \ + { while read -r a b; do [[ $a =~ @\. ]] || echo -E - " $a"; done; } + __systemctl $mode list-units | \ + { while read -r a b; do echo -E - " $a"; done; } )) ) +} + +_systemctl_failed_units() {_sys_failed_units=( ${${(f)"$(__systemctl list-units --failed)"}%% *} ) } +_systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__systemctl list-unit-files) ) } + +local fun +# Completion functions for ALL_UNITS +for fun in is-active is-failed is-enabled status show cat mask preset help list-dependencies edit ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_really_all_units + _wanted systemd-units expl unit \ + compadd "$@" -a - _sys_really_all_units + } +done + +# Completion functions for ENABLED_UNITS +(( $+functions[_systemctl_disable] )) || _systemctl_disable() +{ + local _sys_unit_state; _systemctl_unit_state + _wanted systemd-units expl 'enabled unit' \ + compadd "$@" - ${(k)_sys_unit_state[(R)enabled]} +} + +(( $+functions[_systemctl_reenable] )) || _systemctl_reenable() +{ + local _sys_unit_state; _systemctl_unit_state + _wanted systemd-units expl 'enabled/disabled unit' \ + compadd "$@" - ${(k)_sys_unit_state[(R)(enabled|disabled)]} $(_systemctl_get_template_names) +} + +# Completion functions for DISABLED_UNITS +(( $+functions[_systemctl_enable] )) || _systemctl_enable() +{ + local _sys_unit_state; _systemctl_unit_state + _wanted systemd-units expl 'disabled unit' \ + compadd "$@" - ${(k)_sys_unit_state[(R)disabled]} $(_systemctl_get_template_names) +} + +# Completion functions for FAILED_UNITS +(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed() +{ + local _sys_failed_units; _systemctl_failed_units + _wanted systemd-units expl 'failed unit' \ + compadd "$@" -a - _sys_failed_units || _message "no failed unit found" +} + +# Completion functions for STARTABLE_UNITS +(( $+functions[_systemctl_start] )) || _systemctl_start() +{ + local _sys_startable_units; _systemctl_startable_units + _wanted systemd-units expl 'startable unit' \ + compadd "$@" - ${_sys_startable_units[*]} $(_systemctl_get_template_names) +} + +# Completion functions for STOPPABLE_UNITS +for fun in stop kill try-restart condrestart ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + local _sys_active_units; _systemctl_active_units + _wanted systemd-units expl 'stoppable unit' \ + compadd "$@" - $( _filter_units_by_property CanStop yes \ + ${_sys_active_units[*]} ) + } +done + +# Completion functions for ISOLATABLE_UNITS +(( $+functions[_systemctl_isolate] )) || _systemctl_isolate() +{ + _systemctl_all_units + _wanted systemd-units expl 'isolatable unit' \ + compadd "$@" - $( _filter_units_by_property AllowIsolate yes \ + ${_sys_all_units[*]} ) +} + +# Completion functions for RELOADABLE_UNITS +for fun in reload reload-or-try-restart force-reload ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + local _sys_active_units; _systemctl_active_units + _wanted systemd-units expl 'reloadable unit' \ + compadd "$@" - $( _filter_units_by_property CanReload yes \ + ${_sys_active_units[*]} ) + } +done + +# Completion functions for RESTARTABLE_UNITS +for fun in restart reload-or-restart ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + local _sys_restartable_units; _systemctl_restartable_units + _wanted systemd-units expl 'restartable unit' \ + compadd "$@" - ${_sys_restartable_units[*]} $(_systemctl_get_template_names) + } +done + +# Completion functions for MASKED_UNITS +(( $+functions[_systemctl_unmask] )) || _systemctl_unmask() +{ + local _sys_unit_state; _systemctl_unit_state + _wanted systemd-units expl 'masked unit' \ + compadd "$@" - ${(k)_sys_unit_state[(R)masked]} || _message "no masked units found" +} + +# Completion functions for JOBS +(( $+functions[_systemctl_cancel] )) || _systemctl_cancel() +{ + _wanted systemd-jobs expl job \ + compadd "$@" - ${${(f)"$(__systemctl list-jobs)"}%% *} || + _message "no jobs found" +} + +# Completion functions for SNAPSHOTS +(( $+functions[_systemctl_delete] )) || _systemctl_delete() +{ + _wanted systemd-snapshots expl snapshot \ + compadd "$@" - ${${(f)"$(__systemctl list-units --type snapshot --all)"}%% *} || + _message "no snapshots found" +} + +# Completion functions for TARGETS +(( $+functions[_systemctl_set-default] )) || _systemctl_set-default() +{ + _wanted systemd-targets expl target \ + compadd "$@" - ${${(f)"$(__systemctl list-unit-files --type target --all)"}%% *} || + _message "no targets found" +} + +# Completion functions for ENVS +for fun in set-environment unset-environment ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + local fun=$0 ; fun=${fun##_systemctl_} + local suf + if [[ "${fun}" = "set-environment" ]]; then + suf='-S=' + fi + _wanted systemd-environment expl 'environment variable' \ + compadd "$@" ${suf} - ${${(f)"$(systemctl show-environment)"}%%=*} + } +done + +(( $+functions[_systemctl_link] )) || _systemctl_link() { + _sd_unit_files +} + +(( $+functions[_systemctl_switch-root] )) || _systemctl_switch-root() { + _files +} + +# no systemctl completion for: +# [STANDALONE]='daemon-reexec daemon-reload default +# emergency exit halt kexec list-jobs list-units +# list-unit-files poweroff reboot rescue show-environment' +# [NAME]='snapshot' + +_systemctl_caching_policy() +{ + local _sysunits + local -a oldcache + + # rebuild if cache is more than a day old + oldcache=( "$1"(mh+1) ) + (( $#oldcache )) && return 0 + + _sysunits=(${${(f)"$(__systemctl --all)"}%% *}) + + if (( $#_sysunits )); then + for unit in $_sysunits; do + [[ "$unit" -nt "$1" ]] && return 0 + done + fi + + return 1 +} + +_unit_states() { + local -a _states + _states=(loaded failed active inactive not-found listening running waiting plugged mounted exited dead masked) + _values -s , "${_states[@]}" +} + +_unit_types() { + local -a _types + _types=(automount busname device mount path service snapshot socket swap target timer) + _values -s , "${_types[@]}" +} + +_unit_properties() { + if ( [[ ${+_sys_all_properties} -eq 0 ]] || _cache_invalid SYS_ALL_PROPERTIES ) && + ! _retrieve_cache SYS_ALL_PROPERTIES; + then + _sys_all_properties=( ${${(M)${(f)"$(__systemctl show --all; + /lib/systemd/systemd --dump-configuration-items)"}##[[:alnum:]]##=*}%%=*} + ) + _store_cache SYS_ALL_PROPRTIES _sys_all_properties + fi + _values -s , "${_sys_all_properties[@]}" +} + +_job_modes() { + local -a _modes + _modes=(fail replace replace-irreversibly isolate ignore-dependencies ignore-requirements flush) + _values -s , "${_modes[@]}" +} + +local -a _modes; _modes=("--user" "--system") +local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]:---system} +_arguments -s \ + {-h,--help}'[Show help]' \ + '--version[Show package version]' \ + {-t+,--type=}'[List only units of a particular type]:unit type:_unit_types' \ + '--state=[Display units in the specified state]:unit state:_unit_states' \ + '--job-mode=[Specify how to deal with other jobs]:mode:_job_modes' \ + {-p+,--property=}'[Show only properties by specific name]:unit property:_unit_properties' \ + {-a,--all}'[Show all units/properties, including dead/empty ones]' \ + '--reverse[Show reverse dependencies]' \ + '--after[Show units ordered after]' \ + '--before[Show units ordered before]' \ + '--failed[Show only failed units]' \ + {-l,--full}"[Don't ellipsize unit names on output]" \ + '--show-types[When showing sockets, show socket type]' \ + {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \ + {-q,--quiet}'[Suppress output]' \ + '--no-block[Do not wait until operation finished]' \ + '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--system[Connect to system manager]' \ + '--user[Connect to user service manager]' \ + "--no-wall[Don't send wall message before halt/power-off/reboot]" \ + '--global[Enable/disable unit files globally]' \ + "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \ + '--no-ask-password[Do not ask for system passwords]' \ + '--kill-who=[Who to send signal to]:killwho:(main control all)' \ + {-s+,--signal=}'[Which signal to send]:signal:_signals' \ + {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \ + '--root=[Enable unit files in the specified root directory]:directory:_directories' \ + '--runtime[Enable unit files only temporarily until next reboot]' \ + {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ + {-P,--privileged}'[Acquire privileges before execution]' \ + {-n+,--lines=}'[Journal entries to show]:number of entries' \ + {-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \ + '--firmware-setup[Tell the firmware to show the setup menu on next boot]' \ + '--plain[When used with list-dependencies, print output as a list]' \ + '*::systemctl command:_systemctl_command' diff --git a/shell/zsh/functions/extract b/shell/zsh/functions/extract new file mode 100644 index 0000000..5a73454 --- /dev/null +++ b/shell/zsh/functions/extract @@ -0,0 +1,41 @@ +# Author: Copyright © 2005 Eric P. Mangold - teratorn (-at-) gmail (-dot) com +# License: MIT. http://www.opensource.org/licenses/mit-license.html +# http://zshwiki.org/home/examples/functions + +local old_dirs current_dirs lower +lower=${(L)1} +old_dirs=( *(N/) ) +if [[ $lower == *.tar.gz || $lower == *.tgz ]]; then + tar zxfv $1 +elif [[ $lower == *.gz ]]; then + gunzip $1 +elif [[ $lower == *.tar.bz2 || $lower == *.tbz ]]; then + bunzip2 -c $1 | tar xfv - +elif [[ $lower == *.bz2 ]]; then + bunzip2 $1 +elif [[ $lower == *.zip ]]; then + unzip $1 +elif [[ $lower == *.rar ]]; then + unrar e $1 +elif [[ $lower == *.tar ]]; then + tar xfv $1 +elif [[ $lower == *.lha ]]; then + lha e $1 +else + print "Unknown archive type: $1" + return 1 +fi +# Change in to the newly created directory, and +# list the directory contents, if there is one. +current_dirs=( *(N/) ) +for i in {1..${#current_dirs}}; do + if [[ $current_dirs[$i] != $old_dirs[$i] ]]; then + cd $current_dirs[$i] + ls + break + fi +done + +#compdef '_files -g "*.gz *.tgz *.bz2 *.tbz *.zip *.rar *.tar *.lha"' extract_archive + +# vim: ft=zsh diff --git a/shell/zsh/logout b/shell/zsh/logout new file mode 100644 index 0000000..a540ec8 --- /dev/null +++ b/shell/zsh/logout @@ -0,0 +1,21 @@ +# Zsh logout file. + +# Copyright (C) 2011-2012 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +source_config ~/.shell/logout + +# vim: ft=zsh diff --git a/shell/zsh/rc b/shell/zsh/rc new file mode 100644 index 0000000..7222619 --- /dev/null +++ b/shell/zsh/rc @@ -0,0 +1,1119 @@ +# Zsh configuration file. + +# Copyright (C) 2011-2014 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Warn when creating global variables from inside a function. Needs to be set +# before declaring a function. +setopt warn_create_global + + +# HELPER FUNCTIONS + +# Return the name of the program which is called in the foreground with `fg`. +# $1 is the name of the program (optional). If it's not 'fg' or 'fg *' it's +# returned unchanged. +zshrc_resolve_fg_to_resumed_job_name() { + # $REPLY is used by convention for scalars ($reply for arrays) to return + # values from functions. unset it here to prevent problems when REPLY is + # bound to an integer or similar. Thanks to Mikachu in #zsh on Freenode + # (2012-09-27 17:14 CEST) for this hint. + unset REPLY + + # Replace fg with the resumed job name. + if [[ $1 == fg ]]; then + REPLY=${jobtexts[%+]} + elif [[ $1 == fg\ * ]]; then + REPLY=${jobtexts[${1#fg }]} + # Normal program, return as is. + else + REPLY=$1 + fi +} + + +# MISCELLANEOUS SETTINGS + +# Prevent warnings. +typeset -g TMOUT +# Load general shell setup commands. NOTE: Expand this when publishing the +# config. +source_config ~/.shell/rc + +# Disable beeps. +setopt nobeep + +# Prevent overwriting existing files with '> filename', use '>| filename' +# (or >!) instead. +setopt noclobber + +# Entering the name of a directory (if it's not a command) will automatically +# cd to that directory. +setopt autocd + +# When entering a nonexistent command name automatically try to find a similar +# one. +setopt correct + +# Enable zsh's extended glob abilities. +setopt extendedglob + +# Don't exit if is pressed. Prevents exiting the shell by accident (e.g. +# pressing twice). +setopt ignoreeof + +# Also display PID when suspending a process. +setopt longlistjobs + + +# KEY BINDINGS + +# Not all bindings are done here, only those not specific to a given section. + +# Use Vi(m) style key bindings. +bindkey -v + +# Use jk to exit insert mode (jj is too slow to type). +bindkey 'jk' vi-cmd-mode + +# I don't need the arrow keys, I use ^N and ^P for this (see below). +bindkey -r '^[OA' '^[OB' '^[OC' '^[OD' '^[[A' '^[[B' '^[[C' '^[[D' +# Also not in Vi mode. +bindkey -a -r '^[OA' '^[OB' '^[OC' '^[OD' '^[[A' '^[[B' '^[[C' '^[[D' + + +# FUNCTION SETTINGS + +# Make sure every entry in $fpath is unique. +typeset -U fpath +# ~/.zsh/functions/completion is a symbolic link to the Completion directory +# of a Zsh Git checkout. Use it to get the newest completions if available. +if [[ -d ~/.zsh/functions/completion ]]; then + fpath=(~/.zsh/functions/completion/*/*(/) $fpath) +fi +# Set correct fpath to allow loading my functions (including completion +# functions). +fpath=(~/.zsh/functions $fpath) +# Autoload my functions (except completion functions and hidden files). Thanks +# to caphuso from the Zsh example files for this idea. +if [[ -d ~/.zsh/functions ]]; then + autoload -Uz ${fpath[1]}/^_*(^/:t) +fi + +# Simulate hooks using _functions arrays for Zsh versions older than 4.3.4. At +# the moment only precmd(), preexec() and chpwd() are simulated. +if [[ $ZSH_VERSION != (4.3.<4->*|4.<4->*|<5->*) ]]; then + # Run all functions defined in the ${precmd,preexec,chpwd}_functions + # arrays. + function precmd() { + for function in $precmd_functions; do + $function "$@" + done + } + function preexec() { + for function in $preexec_functions; do + $function "$@" + done + } + function chpwd() { + for function in $chpwd_functions; do + $function "$@" + done + } +fi + +# Load zmv (zsh move) which is a powerful file renamer. +autoload -Uz zmv + + +# HISTORY SETTINGS + +# Use history and store it in ~/.zsh/history. +HISTSIZE=1000000 +SAVEHIST=1000000 +HISTFILE=~/.zsh/history +# Append to the history file instead of overwriting it and do it immediately +# when a command is executed. +setopt appendhistory +setopt incappendhistory +# If the same command is run multiple times store it only once in the history. +setopt histignoredups +# Don't add lines starting with a space to the history. +setopt histignorespace + +# Vim like completions of previous executed commands (also enter Vi-mode). If +# called at the beginning it just recalls old commands (like cursor up), if +# called after typing something, only lines starting with the typed text are +# returned. Very useful to get old commands quickly - in addition to the +# history commands (!..). Thanks to Mikachu in #zsh on Freenode (2010-01-17 +# 12:47 CET) for the information how to a use function with bindkey. +zle -N zshrc-vi-history-beginning-search-backward +zshrc-vi-history-beginning-search-backward() { + local not_at_beginning_of_line + if [[ $CURSOR -ne 0 ]]; then + not_at_beginning_of_line=yes + fi + + zle history-beginning-search-backward + + # Start Vi-mode and stay at the same position (Vi-mode moves one left, + # this counters it). + zle vi-cmd-mode + if [[ -n $not_at_beginning_of_line ]]; then + zle vi-forward-char + fi +} +bindkey '^P' zshrc-vi-history-beginning-search-backward +bindkey -a '^P' history-beginning-search-backward # binding for Vi-mode +# Here only Vi-mode is necessary as ^P enters Vi-mode and ^N only makes sense +# after calling ^P. +bindkey -a '^N' history-beginning-search-forward + +# Enable incremental search which is especially useful when the string is an +# argument and not the command. +bindkey '^R' history-incremental-pattern-search-backward +# Also enable my usual use of Ctrl-P/Ctrl-N to get the previous/next matching +# history entry. +if [[ $ZSH_VERSION == (4.<4->*|<5->*) ]]; then + bindkey -M isearch '^P' history-incremental-pattern-search-backward + bindkey -M isearch '^N' history-incremental-pattern-search-forward +fi + +# Automatically push cd-ed directories on the directory stack. +setopt autopushd +# Don't push duplicates on the directory stack. +setopt pushdignoredups +# Exchange the meaning of + and - when specifying a directory on the stack. +# This way cd - lists the last used directory first, which is more +# natural because cd - goes to the last directory. +setopt pushdminus + + +# PROMPT SETTINGS + +# Use colorized output, necessary for prompts and completions. +autoload -Uz colors; colors + +# Necessary for $EPOCHSECONDS, the UNIX time. +zmodload zsh/datetime + +# Some shortcuts for colors. The %{...%} tells zsh that the data in between +# doesn't need any space, necessary for correct prompt drawing. Use %F{color} +# in more recent zsh versions (here compatibility is important). +local red="%{${fg[red]}%}" +local blue="%{${fg[blue]}%}" +local green="%{${fg[green]}%}" +local yellow="%{${fg[yellow]}%}" +local default="%{${fg[default]}%}" + +# vcs_info was added in 4.3.9 but it works in earlier versions too. So load it +# if the necessary files are available in ~/.zsh/functions/vcs_info (often a +# symbolic link to current checkout of Zsh's sources). +if [[ $ZSH_VERSION == (4.3.<9->*|4.<4->*|<5->*) || + -d ~/.zsh/functions/vcs_info ]]; then + # Update fpath to allow loading the vcs_info functions. + if [[ -d ~/.zsh/functions/vcs_info ]]; then + fpath=(~/.zsh/functions/vcs_info/ + ~/.zsh/functions/vcs_info/Backends + $fpath) + fi + + # Load vcs_info to display information about version control repositories. + autoload -Uz vcs_info + # Only look for certain VCS. + zstyle ':vcs_info:*' enable git + # Check the repository for changes so they can be used in %u/%c (see + # below). This comes with a speed penalty for bigger repositories. + zstyle ':vcs_info:*' check-for-changes yes + + # Set style of vcs_info display. The current branch (green) and VCS (blue) + # is displayed. If there is an special action going on (merge, rebase) + # it's also displayed (red). Also display if there are unstaged or staged + # (%u/%c) changes. + if [[ $ZSH_VERSION == (4.3.<11->*|4.<4->*|<5->*) || + -d ~/.zsh/functions/vcs_info ]]; then + zstyle ':vcs_info:*' formats \ + "(${green}%b%u%c${default}:${blue}%s${default}%m)" \ + "${green}%u%c${default}" + zstyle ':vcs_info:*' actionformats \ + "(${green}%b%u%c${default}/${red}%a${default}:${blue}%s${default}%m)" \ + "${green}%u%c${default}" + else + # In older versions %u and %c are not defined yet and are not + # correctly expanded. + zstyle ':vcs_info:*' formats \ + "(${green}%b${default}:${blue}%s${default})" + zstyle ':vcs_info:*' actionformats \ + "(${green}%b${default}/${red}%a${default}:${blue}%s${default})" + fi + # Set style for formats/actionformats when unstaged (%u) and staged (%c) + # changes are detected in the repository; check-for-changes must be set to + # true for this to work. Thanks to Bart Trojanowski + # (http://jukie.net/~bart/blog/pimping-out-zsh-prompt) for the idea + # (2010-03-11 00:20 CET). + zstyle ':vcs_info:*' unstagedstr '¹' + zstyle ':vcs_info:*' stagedstr '²' + + # Default to run vcs_info. If possible we prevent running it later for + # speed reasons. If set to a non empty value vcs_info is run. + zshrc_force_run_vcs_info=1 + + # Cache system inspired by Bart Trojanowski + # (http://jukie.net/~bart/blog/pimping-out-zsh-prompt). + zstyle ':vcs_info:*+pre-get-data:*' hooks pre-get-data + +vi-pre-get-data() { + # Only Git and Mercurial support and need caching. Abort if any other + # VCS is used. + [[ $vcs != git && $vcs != hg ]] && return + + # If the shell just started up or we changed directories (or for other + # custom reasons) we must run vcs_info. + if [[ -n $zshrc_force_run_vcs_info ]]; then + zshrc_force_run_vcs_info= + return + fi + + # Don't run vcs_info by default to speed up the shell. + ret=1 + # If a git/hg command was run then run vcs_info as the status might + # need to be updated. + case $(fc -ln $(($HISTCMD-1))) in + git* | g\ *) + ret=0 + ;; + hg*) + ret=0 + ;; + esac + } + + # Display number of WIP stashes (this excludes manually named commits + # which might be used for something else), thanks to + # http://eseth.org/2010/git-in-zsh.html (viewed on 2013-04-27) for the + # idea to display the stash count. + function +vi-git-stashes() { + if [[ -s ${hook_com[base]/.git/refs/stash} ]]; then + local -a stashes + # Thanks to Valodim in #zsh on Freenode (2013-07-01 14:14 CEST) + # for the solution to "grep" the output with (M) and :#(...). + stashes=( ${(M)${(f)"$(git stash list 2>/dev/null)"}:#(*WIP*)} ) + + if [[ ${#stashes} -gt 0 ]]; then + hook_com[misc]+=" ${yellow}${#stashes}s${default}" + fi + fi + } + + # Apply hooks to Git. + zstyle ':vcs_info:git*+set-message:*' hooks git-stashes + + # Must run vcs_info when changing directories. + prompt_chpwd() { + zshrc_force_run_vcs_info=1 + } + chpwd_functions+=(prompt_chpwd) + + # Used by prompt code below to determine if vcs_info should be run. + zshrc_use_vcs_info=1 +else + zshrc_use_vcs_info= +fi + +typeset -a zshrc_longrun_data +zshrc_longrun_data=() +# Display runtime in seconds for long running programs (> 60 seconds) and send +# a bell to notify me. +zshrc_longrun_preexec() { + local program=$3 + + # Handle fg. + local REPLY + zshrc_resolve_fg_to_resumed_job_name $program + program=$REPLY + + # No background process found. + if [[ -z $program ]]; then + return + fi + + # Don't track the time for certain (possible) long running processes which + # need no automatic notification. + local ignore + for ignore in elinks man mutt vim; do + case $program in + $ignore | $ignore\ *) + zshrc_longrun_data=() + return + ;; + esac + done + + zshrc_longrun_data=($program $EPOCHSECONDS) +} +zshrc_longrun_precmd() { + # No previous timestamp available or disabled for this command, ignore. + if [[ -z $zshrc_longrun_data ]]; then + return + fi + + local difference=$(( EPOCHSECONDS - zshrc_longrun_data[2] )) + if [[ $difference -gt 60 ]]; then + echo + echo -n "${fg[yellow]}" + echo -n "~> ${(V)zshrc_longrun_data[1]} took $difference seconds." + echo -n "${fg[default]}" + echo "\a" # send bell + fi + + # Clear status. Prevents displaying old status information when pressing + # enter with an empty command line. + zshrc_longrun_data=() +} +preexec_functions+=(zshrc_longrun_preexec) +precmd_functions+=(zshrc_longrun_precmd) + +# Set the prompt. A two line prompt is used. On the top left the current +# working directory is displayed, on the right vcs_info (if available) and the +# current time in hex. On the bottom left current user name and host is shown, +# the exit code of the last command if it wasn't 0, the number of running jobs +# if not 0. +# +# The prompt is in green and blue to make easily detectable, the error exit +# code in red and bold and the job count in yellow. Designed for dark +# terminals. +# +# Thanks to Adam's prompt for the basic idea of this prompt. +zshrc_prompt_precmd() { + # Regex to remove elements which take no space. Used to calculate the + # width of the top prompt. Thanks to Bart's and Adam's prompt code in + # Functions/Prompts/prompt_*_setup. + local zero='%([BSUbfksu]|([FB]|){*})' + + # Call vcs_info before every prompt. + if [[ -n $zshrc_use_vcs_info ]]; then + vcs_info + else + vcs_info_msg_0_= + vcs_info_msg_1_= + fi + + # Setup. Create variables holding the formatted content. + + # Current directory in yellow, truncated if necessary (WIDTH is replaced + # below). + local directory="${yellow}%WIDTH<..<%~%<<${default}" + # Minimal information about the VCS, only displayed if there are + # unstaged/staged changes. + local vcs_staged=${vcs_info_msg_1_} + + # Information about the VCS in this directory. + local vcs=${vcs_info_msg_0_} + # Current time (seconds since epoch) in Hex in bright blue. + local seconds="${blue}%B0x$(([##16] EPOCHSECONDS))%b${default}" + + # User name (%n) in bright green. + local user="${green}%B%n%b${default}" + # Host name (%m) in bright green; underlined if running on a remote system + # through SSH. + local host="${green}%B%m%b${default}" + if [[ -n $SSH_CONNECTION ]]; then + host="%U${host}%u" + fi + + # Number of background processes in yellow if not zero. + local background="%(1j.${yellow}%j${default}.)" + # Exit code in bright red in parentheses if not zero. + local exitcode="%(?..(${red}%B%?%b${default}%) )" + # Prompt symbol, % for normal users, # in red for root. + local symbol="%(!.${red}#${default}.%%)" + + # Prefix characters in first and second line. + local top_prefix="${blue}%B.-%b${default}" + local bottom_prefix="${blue}%B'%b${default}" + + # Combine them to create the prompt. + + local top_left=${vcs_staged} + local top_right="${vcs}(${seconds})" + + local width_top_prefix=${#${(S%%)top_prefix//$~zero/}} + local width_top_left=${#${(S%%)top_left//$~zero/}} + local width_top_right=${#${(S%%)top_right//$~zero/}} + + # Calculate the maximum width of ${top_left}. -2 are the braces of + # ${top_left}, -1 is one separator from ${top_separator} (we want at least + # one between left and right parts). + local top_left_width_max=$(( + COLUMNS - $width_top_prefix + - $width_top_left - 2 + - 1 + - $width_top_right + )) + # Truncate directory if necessary. + top_left="(${directory/WIDTH/${top_left_width_max}})${top_left}" + width_top_left=${#${(S%%)top_left//$~zero/}} + + # Calculate the width of the top prompt to fill the middle with "-". + local width=$(( + COLUMNS - width_top_prefix - width_top_left - width_top_right + )) + local top_separator="%B${blue}${(l:${width}::-:)}%b${default}" + + PROMPT="${top_prefix}${top_left}${top_separator}${top_right} +${bottom_prefix}${user}@${host} ${background}${symbol} ${exitcode}" +} +precmd_functions+=(zshrc_prompt_precmd) + + +# When GNU screen, tmux, xterm or rxvt is used set the name of the window to +# the currently running program. +# +# When a program is started preexec() sets the window's name to it; when it +# stops precmd() resets the window's name to 'zsh'. 'fg' is supported and sets +# the window's name to the resumed job. +# +# It works with GNU screen, tmux, xterm and rxvt. +# +# If a command is run with sudo or if the shell is running as root then a ! is +# added at the beginning of the command to make this clear. If a command is +# running on a different computer with ssh a @ is added at the beginning. If +# screen/tmux is running on the remote machine instead of @screen @:hostname +# (or @tmux ..; hostname replaced by the machine's hostname) is displayed. +# This only works if the .zshrc on the server also uses this command. +# +# screen* is necessary as `screen` uses screen.linux for example for a linux +# console. +if [[ $TERM == screen* || $TERM == xterm* || $TERM == rxvt* ]]; then + # Is set to a non empty value to reset the window name in the next + # precmd() call. + zshrc_window_reset=yes + + zshrc_window_preexec() { + # Get the program name with its arguments. + local program_name=$1 + + # When sudo is used, use real program name instead, but with an + # exclamation mark at the beginning (handled below). + local program_sudo= + if [[ $program_name == sudo* ]]; then + program_name=${program_name#sudo } + program_sudo=yes + fi + + # Handle fg. + local REPLY + zshrc_resolve_fg_to_resumed_job_name $program_name + program_name=$REPLY + + # Remove all arguments from the program name. + program_name=${program_name%% *} + + # Ignore often used commands which are only running for a very short + # time. This prevents a "blinking" name when it's changed to "cd" for + # example and then some milliseconds later back to "zsh". + [[ $program_name == (cd*|d|ls|l|la|ll|clear|c) ]] && return + + # Change my shortcuts so the real name of the program is displayed. + case $program_name in + e) + program_name=elinks + ;; + g) + program_name=git + ;; + m) + program_name=make + ;; + p) + program_name=less + ;; + v) + program_name=vim + ;; + mu) + program_name=mutt + ;; + esac + + # Add an exclamation mark at the beginning if running with sudo or if + # running zsh as root. + if [[ -n $program_sudo || $UID -eq 0 ]]; then + program_name=!$program_name + fi + + # Add an at mark at the beginning if running through ssh on a + # different computer. + if [[ -n $SSH_CONNECTION ]]; then + program_name="@$program_name" + + # If screen is running in SSH then display "@:hostname" as title + # in the term/outer screen. + if [[ $program_name == @screen || $program_name == @tmux ]]; then + program_name="@:${HOST//.*/}" + # Use "@:!hostname" for root screens. + elif [[ $program_name == @!screen || $program_name == @!tmux ]]; then + program_name="@:!${HOST//.*/}" + fi + fi + + # Set the window name to the currently running program. + zshrc_window_title $program_name + + # Tell precmd() to reset the window name when the program stops. + zshrc_window_reset=yes + } + + zshrc_window_precmd() { + # Abort if no window name reset is necessary. + [[ -z $zshrc_window_reset ]] && return + + # Reset the window name to 'zsh'. + local name=zsh + # If the function was called with an argument then reset the window + # name to '.zsh' (used by clear alias). + if [[ -n $1 ]]; then + name=.zsh + fi + + # Prepend prefixes like in zshrc_window_preexec(). + if [[ $UID -eq 0 ]]; then + name="!$name" + fi + if [[ -n $SSH_CONNECTION ]]; then + name="@$name" + fi + zshrc_window_title $name + + # Just reset the name, so no screen reset necessary for the moment. + zshrc_window_reset= + } + + # Sets the window title. Works with GNU screen, tmux (which uses screen as + # TERM), xterm and rxvt. (V) escapes all non-printable characters, thanks + # to Mikachu in #zsh on Freenode (2010-08-07 17:09 CEST). + if [[ $TERM == screen* ]]; then + zshrc_window_title() { + print -n "\ek${(V)1}\e\\" + } + elif [[ $TERM == xterm* || $TERM == rxvt* ]]; then + zshrc_window_title() { + print -n "\e]2;${(V)1}\e\\" + } + else + # Fallback if another TERM is used. + zshrc_window_title() { } + fi + + # Add the preexec() and precmd() hooks. + preexec_functions+=(zshrc_window_preexec) + precmd_functions+=(zshrc_window_precmd) +else + # Fallback if another TERM is used, necessary to run screen (see below in + # "RUN COMMANDS"). + zshrc_window_preexec() { } +fi + + +# COMPLETION SETTINGS + +# Load the complist module which provides additional features to completion +# lists (coloring, scrolling). +zmodload zsh/complist +# Use new completion system, store dumpfile in ~/.zsh/cache to prevent +# cluttering of ~/. $fpath must be set before calling this. Thanks to Adlai in +# #zsh on Freenode (2009-08-07 21:05 CEST) for reminding me of the $fpath +# problem. +autoload -Uz compinit; compinit -d ~/.zsh/cache/zcompdump + +# Use cache to speed up some slow completions (dpkg, perl modules, etc.). +zstyle ':completion:*' use-cache yes +zstyle ':completion:*' cache-path ~/.zsh/cache + +# List all files in the current directory when pressing tab on an empty input, +# behave like complete-word otherwise. Thanks to John Eikenberry [1] for the +# code, read on 2014-03-15. +# +# [1]: http://unix.stackexchange.com/a/32426 +complete-word-or-complete-list-of-files() { + if [[ $#BUFFER == 0 ]]; then + BUFFER='ls ' + CURSOR=3 + zle list-choices + zle backward-kill-word + else + zle complete-word + fi +} +zle -N complete-word-or-complete-list-of-files +# Let the completion system handle all completions, including expanding of +# shell wildcards (which is handled by other shell mechanisms if the default +# expand-or-complete is used). +bindkey '^I' complete-word-or-complete-list-of-files +# If there are multiple matches after pressing always display them +# immediately without requiring another . a completes to aa and +# lists aaa, aab, aac as possible completions if the directory contains aaa, +# aab, aac, bbb instead of only completing to aa. +setopt nolistambiguous +# Support completions in the middle of a word, without this option zsh jumps +# to the end of the word before the completion process begins. Is required for +# the _prefix completer. +setopt completeinword + +# Force a reload of the completion system if nothing matched; this fixes +# installing a program and then trying to tab-complete its name. Thanks to +# Alex Munroe [1] for the code, read on 2014-03-03. +# +# [1]: https://github.com/eevee/rc/blob/master/.zshrc +_force_rehash() { + if (( CURRENT == 1 )); then + rehash + fi + # We didn't really complete anything. + return 1 +} + +zstyle ':completion:::::' completer \ + _force_rehash _expand _complete _prefix _ignored _approximate + +# Match specification to be tried when completing items. Each group ('...') is +# tried after another if no matches were found, once matches are found no +# other groups are tried. Thanks to Mikachu in #zsh on Freenode (2012-08-28 +# 18:48 CEST) for explanations. +# +# When matching also include the uppercase variant of typed characters +# ('m:{a-z}={A-Z}'); using '' before this group would try the unmodified match +# first, but I prefer to get all matches immediately (e.g. if Makefile and +# makefile exist in the current directory echo m matches both, with '' it +# would only match makefile because it found one match). This allows typing in +# lowercase most of the time and completion fixes the case, which is faster. +# +# Don't perform these fixes in _approximate to prevent it from changing the +# input too much. Thanks to the book "From Bash to Z Shell" page 249. +zstyle ':completion:*:(^approximate):*' matcher-list 'm:{a-z}={A-Z}' + +# Allow one mistake per three characters. Thanks to the book "From Bash to Z +# Shell" page 248. +zstyle -e ':completion:*:approximate:*' max-errors \ + 'reply=( $(( ($#PREFIX + $#SUFFIX) / 3 )) )' + +# Expand shell wildcards to all matching files after . echo * +# results in a b c if the directory contains the files a, b, c. Thanks to the +# book "From Bash to Z Shell" page 246. +zstyle ':completion:*:expand:*' tag-order all-expansions +# Keep prefixes unexpanded if possible: $HOME/ doesn't expand $HOME, +# while $HOME does. +zstyle ':completion:*:expand:*' keep-prefix yes + +# When completing multiple path components display all matching ambiguous +# components. For example /u/s/d/r/README lists all matching READMEs +# instead of just the matching paths up to the r/ component. Can be slow if +# there are many matching files. +zstyle ':completion:*' list-suffixes yes + +# Use ls-like colors for completions. +zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} + +# Make completion lists scrollable so "do you wish to see all n possibilities" +# is no longer displayed. Display current position in percent (%p). +zstyle ':completion:*:default' list-prompt '%p' +# Display group name (%d) (like 'external command', 'alias', etc.), in bold. +# Also display a message if _approximate found errors and no matches were +# found. +zstyle ':completion:*' format ' %B%d%b:' +zstyle ':completion:*:corrections' format ' %B%d%b (errors: %e)' +zstyle ':completion:*:warnings' format ' %Bno matches for %d%b' +# Display different types of matches separately. +zstyle ':completion:*' group-name '' + +# Separate man pages by section. +zstyle ':completion:*' separate-sections yes + +# Don't draw trailing / in bold (new in zsh 4.3.11). Thanks to Mikachu in #zsh +# on Freenode for the fix (2010-12-17 13:46 CET). +zle_highlight=(suffix:none) + +# Ignore completion functions. +zstyle ':completion:*:functions' ignored-patterns '_*' + +# When offering typo corrections, do not propose anything which starts with an +# underscore (such as many of Zsh's shell functions). Thanks to paradigm [1] +# for the idea (read on 2013-04-07). +# +# [1]: https://github.com/paradigm/dotfiles/blob/master/.zshrc +CORRECT_IGNORE='_*' + +# Ignore parent directory. +zstyle ':completion:*:(cd|mv|cp):*' ignore-parents parent pwd +# Always complete file names only once in the current line. This makes it easy +# to complete multiple file names because I can just press tab to get all +# possible values. Otherwise I would have to skip the first value again and +# again. Thanks to Mikachu in #zsh on Freenode (2011-08-11 14:42 CEST) for the +# hint to use other. other is necessary so prefix lists both prefix and +# prefixrest if the directory contains prefix and prefixrest. +zstyle ':completion:*:all-files' ignore-line other +# Except for mv and cp, because I often want to use to similar names, so I +# complete to the same and change it. +zstyle ':completion:*:(mv|cp):all-files' ignore-line no + +# Don't complete ./config.* files, this makes running ./configure much +# simpler. Thanks to Nomexous in #zsh on Freenode (2010-03-16 01:54 CET) +zstyle ':completion:*:*:-command-:*' ignored-patterns './config.*' +# Don't complete unwanted files with Vim. Thanks to Nomexous in #zsh on +# Freenode (2010-06-06 04:54 CEST). See below for a way to complete them. +zstyle ':completion:*:*:vim:*:all-files' ignored-patterns \ + '*.aux' '*.log' '*.pdf' '*.bbl' '*.blg' '*.out' '*-blx.bib' '*.run.xml' \ + '*.o' \ + '*.pyc' \ + '*.class' + +# Provide a fallback completer which always completes files. Useful when Zsh's +# completion is too "smart". Thanks to Frank Terbeck +# (http://www.zsh.org/mla/users/2009/msg01038.html). +zle -C complete-files complete-word _generic +zstyle ':completion:complete-files:*' completer _files +bindkey '^F' complete-files + +# Completion for my wrapper scripts. +compdef slocate=locate +compdef srsync=rsync +compdef srsync-incremental=rsync +compdef svalgrind=valgrind +compdef sc=systemctl + + +# CUSTOM ALIASES AND FUNCTIONS + +# If ^C is pressed while typing a command, add it to the history so it can be +# easily retrieved later and then abort like ^C normally does. This is useful +# when I want to abort an command to do something in between and then finish +# typing the command. +# +# Thanks to Vadim Zeitlin for a fix (--) so lines +# starting with - don't cause errors; and to Nadav Har'El +# for a fix (-r) to handle whitespace/quotes +# correctly, both on the Zsh mailing list. +TRAPINT() { + # Don't store this line in history if histignorespace is enabled and the + # line starts with a space. + if [[ -o histignorespace && ${BUFFER[1]} = ' ' ]]; then + return $1 + fi + + # Store the current buffer in the history. + zle && print -s -r -- $BUFFER + + # Return the default exit code so Zsh aborts the current command. + return $1 +} + +# Load aliases and similar functions also used by other shells. +if [[ -f ~/.shell/aliases ]]; then + . ~/.shell/aliases +fi + +# Make sure aliases are expanded when using sudo. +alias sudo='sudo ' + +# Global aliases for often used redirections. +alias -g E='2>&1' +alias -g N='>/dev/null' +alias -g EN='2>/dev/null' +alias -g L='2>&1 | less' +alias -g LS='2>&1 | less -S' # -S prevents wrapping of long lines +alias -g D='2>&1 | colordiff | less' +# Global aliases for often used commands. +alias -g A='| awk' +alias -g A1="| awk '{ print \$1 }'" +alias -g A2="| awk '{ print \$2 }'" +alias -g A3="| awk '{ print \$3 }'" +alias -g G='| grep' +alias -g GB='| grep -vE "^Binary file .+ matches\$"' +alias -g H='| head' +alias -g P='| perl' +alias -g S='| sort' +alias -g SL='| sort | less' +alias -g T='| tail' +alias -g U='| uniq' +alias -g X='`xsel -p || xclip -o`' # X selection + +# Make going up directories simple. +alias -g ...='../..' +alias -g ....='../../..' +alias -g .....='../../../..' + +# If the window naming feature is used (see above) then use ".zsh" (leading +# dot) as title name after running clear so it's clear to me that the window +# is empty. I open so much windows that I don't know in which I have something +# important. This helps me to remember which windows are empty (I run clear +# after I finished my work in a window). +if [[ -n $zshrc_window_reset ]]; then + alias clear='clear; zshrc_window_reset=yes; zshrc_window_precmd reset' +fi + + +# CUSTOM COMMANDS + +# Display all branches (except stash) in gitk but only 200 commits as this is +# much faster. Also put in the background and disown. Thanks to drizzd in #git +# on Freenode (2010-04-03 17:55 CEST). +(( $+commands[gitk] )) && gitk() { + command gitk --max-count=200 --branches --remotes --tags "$@" & + disown %command +} +# Same for tig (except the disown part as it's no GUI program). +(( $+commands[tig] )) && tig() { + command tig --max-count=200 --branches --remotes --tags "$@" +} + +# Choose the "best" PDF viewer available. Also setup completion for `pdf`. +if (( $+commands[katarakt] )); then + pdf() { + command katarakt "$@" 2>/dev/null & + disown %command + } + # No completion for katarakt yet. + compdef pdf=xpdf +elif (( $+commands[xpdf] )); then + pdf() { + command xpdf "$@" 2>/dev/null & + disown %command + } + compdef pdf=xpdf +elif (( $+commands[zathura] )); then + pdf() { + command zathura "$@" 2>/dev/null & + disown %command + } + # No completion for zathura yet. + compdef pdf=xpdf +fi + + +# OS SPECIFIC SETTINGS + +if [[ $OSTYPE == linux* ]]; then + # Settings when creating Debian packages. + export DEBEMAIL=simon@ruderich.org + export DEBFULLNAME='Simon Ruderich' +fi + + +# LOAD ADDITIONAL CONFIGURATION FILES + +# Configuration options for rc.local. + +# Multiplexer to use. By default GNU screen is used. Possible values: screen, +# tmux and empty (no multiplexer). +zshrc_use_multiplexer=screen +# Additional arguments for fortune. +zshrc_fortune_arguments=() + +source_config ~/.zsh/rc.local + + +# RUN COMMANDS + +# Make sure the multiplexer is available. Otherwise the exec terminates our +# session. +if [[ -n $zshrc_use_multiplexer ]]; then + if ! (( $+commands[$zshrc_use_multiplexer] )); then + echo "Multiplexer '$zshrc_use_multiplexer' not found." >&2 + zshrc_use_multiplexer= + fi +fi + +# If not already in screen or tmux, reattach to a running session or create a +# new one. This also starts screen/tmux on a remote server when connecting +# through ssh. +if [[ $TERM != dumb && $TERM != dialup && $TERM != linux + && -z $STY && -z $TMUX ]]; then + # Get running detached sessions. + if [[ $zshrc_use_multiplexer = screen ]]; then + session=$(screen -list | grep 'Detached' | awk '{ print $1; exit }') + elif [[ $zshrc_use_multiplexer = tmux ]]; then + session=$(tmux list-sessions 2>/dev/null \ + | sed '/(attached)$/ d; s/^\([0-9]\{1,\}\).*$/\1/; q') + fi + + # As we exec later we have to set the title here. + if [[ $zshrc_use_multiplexer = screen ]]; then + zshrc_window_preexec screen + elif [[ $zshrc_use_multiplexer = tmux ]]; then + zshrc_window_preexec tmux + fi + + # Create a new session if none is running. + if [[ -z $session ]]; then + if [[ $zshrc_use_multiplexer = screen ]]; then + exec screen + elif [[ $zshrc_use_multiplexer = tmux ]]; then + exec tmux + fi + # Reattach to a running session. + else + if [[ $zshrc_use_multiplexer = screen ]]; then + exec screen -r $session + elif [[ $zshrc_use_multiplexer = tmux ]]; then + exec tmux attach-session -t $session + fi + fi +fi + +# Colorize stderr in bold red. Very useful when looking for errors. +if [[ $LD_PRELOAD != *libcoloredstderr.so* ]]; then + # coloredstderr found, use it. + if [[ -f ~/.zsh/libcoloredstderr.so ]]; then + export LD_PRELOAD="$HOME/.zsh/libcoloredstderr.so:$LD_PRELOAD" + export COLORED_STDERR_FDS=2, + export COLORED_STDERR_PRE=$'\033[91m' # bright red + export COLORED_STDERR_IGNORED_BINARIES=/usr/bin/tset + # Use the fallback solution. + # + # Thanks to http://gentoo-wiki.com/wiki/Zsh for the basic script and + # Mikachu in #zsh on Freenode (2010-03-07 04:03 CET) for some improvements + # (-r, printf). It's not yet perfect and doesn't work with su and git for + # example, but it can handle most interactive output quite well (even with + # no trailing new line) and in cases it doesn't work, the E alias can be + # used as workaround. + # + # Moved in the "run commands" section to prevent one unnecessary zsh + # process when starting GNU screen/tmux (see above). + else + exec 2>>(while read -r -k -u 0 line; do + printf '\e[91m%s\e[0m' $line + print -n $'\0' + done &) + + # Reset doesn't work with this hack. + reset() { + command reset "$@" 2>&1 + } + fi +fi + +# Display possible log messages from ~/.xinitrc (if `xmessage` wasn't +# installed). No race condition as xinitrc has finished before a shell is +# executed and only one shell is started on login. +if [[ -f ~/.xinitrc.errors ]]; then + echo "${fg_bold[red]}xinitrc failed!${fg_bold[default]}" + echo + cat ~/.xinitrc.errors + rm ~/.xinitrc.errors + echo +fi + +# Run the following programs every 4 hours (and when zsh starts). +PERIOD=14400 +periodic() { + # Display fortunes. + (( $+commands[fortune] )) && fortune -ac "${zshrc_fortune_arguments[@]}" + # Display reminders. + (( $+commands[rem] )) && [[ -f ~/.reminders ]] && rem -h +} + + +# RESTART SETTINGS + +zmodload -F zsh/stat b:zstat + +# Remember startup time. Used to perform automatic restarts when ~/.zshrc is +# modified. +zshrc_startup_time=$EPOCHSECONDS + +# Automatically restart Zsh if ~/.zshrc was modified. +zshrc_restart_precmd() { + local stat + if ! zstat -A stat +mtime ~/.zshrc; then + return + fi + + # ~/.zshrc wasn't modified, nothing to do. + if [[ $stat -le $zshrc_startup_time ]]; then + return + fi + + local startup + strftime -s startup '%Y-%m-%d %H:%M:%S' $zshrc_startup_time + + echo -n "${fg[magenta]}" + echo -n "~/.zshrc modified since startup ($startup) ... " + echo -n "${fg[default]}" + + if [[ -n $zshrc_disable_restart ]]; then + echo 'automatic restart disabled.' + return + fi + + # Don't exec if we have background processes because execing will let us + # lose control over them. + if [[ ${#${(k)jobstates}} -ne 0 ]]; then + echo 'active background jobs!' + return + fi + + # Try to start a new interactive shell. If it fails, something is wrong. + # Don't kill our current session by execing it, abort instead. + zsh -i -c 'exit 42' + if [[ $? -ne 42 ]]; then + echo -n ${fg_bold[red]} + echo 'failed to start new zsh!' + echo -n ${fg_bold[default]} + return + fi + + echo 'restarting zsh.' + echo + + exec zsh +} +precmd_functions+=(zshrc_restart_precmd) + + +# RELOAD SETTINGS + +zshenv_reload_time=0 # load before first command +zshenv_boot_time=$(date -d "$(uptime -s)" '+%s') # uptime in epoch seconds + +# Automatically source ~/.zsh/env.update when the file changes (and exists). +# Can be used e.g. to update SSH_AGENT_PID and GPG_AGENT_INFO variables in +# running zsh processes. Sourced immediately before executing shell commands +# (preexec) to ensure the environment is always up to date. +zshenv_reload_preexec() { + local file + file=~/.zsh/env.update + + local stat + if ! zstat -A stat +mtime $file 2>/dev/null; then + return + fi + # File was modified before reboot. Skip it to prevent loading of old + # values. + if [[ $stat -lt $zshenv_boot_time ]]; then + return + fi + # File wasn't modified, nothing to do. + if [[ $stat -le $zshenv_reload_time ]]; then + return + fi + zshenv_reload_time=$EPOCHSECONDS + + unsetopt warn_create_global + . $file + setopt warn_create_global +} +preexec_functions+=(zshenv_reload_preexec) + +# vim: ft=zsh diff --git a/vcs/.gitignore b/vcs/.gitignore new file mode 100644 index 0000000..a296e88 --- /dev/null +++ b/vcs/.gitignore @@ -0,0 +1,2 @@ +cvsrc +gitconfig diff --git a/vcs/Makefile b/vcs/Makefile new file mode 100644 index 0000000..23d5991 --- /dev/null +++ b/vcs/Makefile @@ -0,0 +1,4 @@ +all: + @./setup.sh + +.PHONY: all diff --git a/vcs/bin/tig.pl b/vcs/bin/tig.pl new file mode 100755 index 0000000..881583d --- /dev/null +++ b/vcs/bin/tig.pl @@ -0,0 +1,126 @@ +#!/usr/bin/perl + +# tig-like git log output. Used when tig is not available or broken. + +# Copyright (C) 2013 Simon Ruderich +# +# 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 3 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, see . + + +use strict; +use warnings; + +use POSIX (); +use Term::ANSIColor qw(colored); + + +my $color_graph = 'yellow'; +my $color_hash = 'cyan'; +my $color_ref_sep = 'cyan'; +my $color_ref_head = 'cyan bold'; +my $color_ref_branch = 'green bold'; +my $color_ref_reference = 'red bold'; +my $color_author = 'magenta'; + + +# Aliases in Git with "! ..." are always run in the top-level-directory. +# GIT_PREFIX contains the relative path to the current subdirectory. Thanks to +# dr_lepper in #git on Freenode (2013-04-03 23:17 CEST) for telling me about +# GIT_PREFIX. +if (defined $ENV{GIT_PREFIX} and $ENV{GIT_PREFIX} ne '') { + chdir $ENV{GIT_PREFIX} or die $!; +} + +my $format = '%x00' # separator from --graph + . '%h' . '%x00' # abbreviated commit hash + . '%at' . '%x00' # author date + . '%an' . '%x00' # author name + . '%s' . '%x00' # subject + . '%d'; # ref names +my @cmd = ('git', 'log', '--graph', "--format=$format", + # use either given arguments or --all to list all commits + (scalar @ARGV) ? @ARGV : '--all'); +open my $fh, '-|', @cmd or die $!; + +my $pager = $ENV{PAGER}; +# Try to find an usable pager without searching $PATH. +if (not defined $pager) { + foreach my $path (qw(/usr/bin/less /bin/less /usr/bin/more /bin/more)) { + next if not -x $path; + + $pager = $path; + last; + } +} +# Use a pager if STDOUT is a terminal. +if (-t STDOUT and defined $pager) { + open STDOUT, '|-', $pager or die $!; +} + +while (<$fh>) { + # History graph line. + if (m{^([|/\\_ ]+)$}) { + print colored($_, $color_graph); + next; + } + + # Commit line. + /^([ *|.\\-]+)\x00(.+)\x00(.+)\x00(.+)\x00(.*)\x00(.*)$/ or die $_; + my $prefix = $1; + my $hash = colored($2, $color_hash); + my $date = POSIX::strftime('%Y-%m-%d', localtime($3)); + my $author = colored($4, $color_author); + my $message = $5; + my $refs = $6; + + # Strip trailing whitespace. + $prefix =~ s/\s+$//; + # Color "graph". + $prefix =~ s/\|/colored($&, $color_graph)/ge; + + # Strip leading whitespace and braces. + $refs =~ s/^\s+//; + $refs =~ tr/()//d; + + # Color refs. + $refs = join colored(', ', $color_ref_sep), map { + my $color; + if ($_ eq 'HEAD') { + $color = $color_ref_head; + } elsif (m{/}) { + $color = $color_ref_reference; + } else { + $color = $color_ref_branch; + } + colored($_, $color); + } split /, /, $refs; + + if ($refs ne '') { + $refs = ' ' + . colored('(', $color_ref_sep) + . $refs + . colored(')', $color_ref_sep); + } + + printf "%s %s %s %s%s %s\n", + $prefix, $hash, $date, $author, $refs, $message; +} + +close $fh or die $!; + +# Necessary for the redirection to a pager or the pager terminates after our +# script finishes without displaying all data. +if (defined $pager) { + close STDOUT or die $!; +} diff --git a/vcs/cvsrc.in b/vcs/cvsrc.in new file mode 100644 index 0000000..90b11b4 --- /dev/null +++ b/vcs/cvsrc.in @@ -0,0 +1,30 @@ +# CVS configuration file. + +# CVS doesn't support comments and newlines in ~/.cvsrc. They must be stripped +# before using this file. + +# Copyright (C) 2011-2014 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Don't display all checked directories. +cvs -q + +# Use unified diffs. +diff -u +# Create any directories which were removed locally. +update -d + +# vim: ft=cvsrc diff --git a/vcs/gitattributes b/vcs/gitattributes new file mode 100644 index 0000000..8258ef8 --- /dev/null +++ b/vcs/gitattributes @@ -0,0 +1,20 @@ +# Global Git configuration file for attributes. + +# Copyright (C) 2013 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +*.pdf diff=pdf +*.gz diff=gzip diff --git a/vcs/gitconfig.in b/vcs/gitconfig.in new file mode 100644 index 0000000..50d88a9 --- /dev/null +++ b/vcs/gitconfig.in @@ -0,0 +1,249 @@ +# Global Git configuration file. + +# Copyright (C) 2011-2017 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +[user] + name = Simon Ruderich + email = simon@ruderich.org + +[color] + ui = auto + +[color "diff"] + # Meta information. + meta = yellow bold + # Hunk header. + frag = magenta bold + # Function in hunk header. + func = blue bold + # Removed lines. + old = red bold + # Added lines. + new = green bold + # Commit headers. + commit = cyan + +[color "grep"] + # GNU grep-like colors. + filename = magenta + linenumber = green + +[core] + editor = vim + # Global gitattributes file. Thanks to canton7 in #git on Freenode + # (2011-11-09 13:23 CET). + attributesfile = PWD/gitattributes + +[pager] + # Use pager for the following commands. + status = true + tag = true + +[interactive] + # Don't require in interactive commands which require only a + # single key, for example `git add --patch`. Requires Perl module + # Term::Readkey. + singlekey = true + +[alias] + ## Shortcuts for often used commands. + # + ## Local. + c = commit --verbose + ca = commit --verbose --amend + cad = commit --verbose --amend --date= + d = diff + dw = diff --color-words + ds = diff --stat + dc = diff --cached + dcw = diff --cached --color-words + dcs = diff --cached --stat + g = grep + gi = grep --ignore-case + s = status + l = log + ls = log --stat + lp = log --patch + lpw = log --patch --color-words + ld = show --date=short -s --pretty='format:%h (\"%s\", %ad)' # describe + a = add + ap = add --patch + au = add --update + rs = reset + rsh = reset --hard + rsp = reset --patch + rv = revert + cl = clean -ndx + clf = clean -fdx + ## Branches. + co = checkout + b = branch -a -v + br = branch + m = merge + mo = merge origin/master + re = rebase + rei = rebase --interactive + rec = rebase --continue + cp = cherry-pick + ## Submodules. + sm = submodule + ## Remote. + f = fetch + t = tag + p = push + # Parallel git remote update. Also strips unnecessary output. + ru = "! git remote \ + | xargs -d '\\n' -n1 -P0 git remote update 2>&1 \ + | sed '/^$/d; \ + /^Please make sure you have the correct access rights$/d; \ + /^and the repository exists\\.$/d;'" + # Push to all remotes. Thanks to albel727 in #git on Freenode + # (2011-06-04 16:06 CEST) for the idea. Modified to push in parallel + # and to strip unnecessary output. + rp = "! git remote \ + | xargs -d '\\n' -n1 -P0 git push 2>&1 \ + | sed '/^$/d; \ + /^Please make sure you have the correct access rights$/d; \ + /^and the repository exists\\.$/d;'" + ## Patches. + fp = format-patch + ## Maintenance. + # (Redirection of stderr is necessary to prevent missing output with + # my "color stderr" solution in Zsh.) + fs = ! git fsck --strict --full 2>&1 + fg = ! git fs && git gc --aggressive 2>&1 # fsck and compress repo + ## Misc. + sl = stash list + ss = stash save + ssk = stash save --keep-index + ssu = stash save --include-untracked + sa = stash apply --index + sp = stash pop --index + + ## Custom commands. + # + # tig-like log view. Similar to the following but with author/date + # information. --pretty=format is not used because it doesn't allow + # precise enough control over formats and colors. + # + # tig = log --pretty=oneline --graph --all --decorate --abbrev-commit + tig = ! PWD/bin/tig.pl + + # Create backup of uncommitted and untracked changes. + ssb = "! git stash save --include-untracked \ + \"Backup on $(LANG=C date '+%a, %d %b %Y %H:%M:%S %z')\" \ + >/dev/null \ + && git stash apply >/dev/null" + + # Display list and content of untracked files. Untracked directories + # and symbolic links are only listed. + u = "! git ls-files --other --exclude-standard --directory -z \ + | xargs -0 sh -c '\ + for x; do \ + printf \"\\033[1;33m-> %s\\033[0m:\" \"$x\"; \ + if test -d \"$x\"; then \ + echo \" directory\"; \ + elif test -h \"$x\"; then \ + echo \" symbolic link\"; \ + else \ + echo; \ + cat \"$x\"; \ + fi; \ + echo; \ + done' argv0 \ + | less" + +[diff] + # Detect copies and renames. + renames = copy + + # Diff algorithm to use. + algorithm = histogram + + # Highlight moved code in a different color. + colorMoved = zebra + + # Replace "a/" and "b/" prefix in diffs with characters describing the + # context (e.g. "i/"ndex and "w/"ork tree). + mnemonicprefix = true + + # Change the definition of a word as used by diff --color-words to be + # shorter (not only spaces) and thus simplify the generated diffs. + # Words ([a-zA-Z0-9_]+) are matched, or a single non-word character + # ([^a-zA-Z0-9_]), therefore changes to words are shown in complete + # (e.g. from "word" to "newword" as "[-word-]{+newword+}"), but + # changes to non-word characters are shown character wise (e.g. from + # "==" to "!=" as "[-=-]{+!+}="); [-..-] is removal, {+..+} is + # addition. See t/ for some tests and examples. + wordRegex = [a-zA-Z0-9_]+|[^a-zA-Z0-9_] + +# Allow diffing of some binary files. +# +# "sh -c '..' ARGV0" is used when the programs require additional arguments +# which are passed after ARGV0 by git. +[diff "gzip"] + textconv = gzip -d -c +[diff "pdf"] + textconv = sh -c 'exec pdftotext "$@" -' ARGV0 +[diff "sqlite"] + textconv = sh -c 'exec sqlite3 "$@" .dump' ARGV0 + +[log] + # Display branches/tag names in log (same as log's --decorate option). + decorate = short + # If a single file is given to `git log`, automatically use --follow. + follow = true + +[merge] + tool = vimdiff + + # Merge upstream branch if `git merge` is called without arguments. + defaultToUpstream = true + +[rebase] + # Use single-letter command names in git rebase -i which are faster to + # change. + abbreviateCommands = true + +[push] + # When running git push without a refspec push only the current + # branch, see man page git-config(1) for details. Default since Git + # 2.0. + default = simple + +[format] + # When using git format-patch use threads and add all patches as + # replies to the first one. + thread = shallow + +[transfer] + # Automatically fsck objects when receiving them (respected by git + # receive-pack and git fetch (>= 1.7.8, for fetch)). + fsckObjects = true + +[advice] + # Disable annoying advice messages. + waitingForEditor = false + + +# NON-GIT SETTINGS + +[annex] + # My SSH config already uses ControlMaster where appropriate. + sshcaching = false + +# vim: ft=gitconfig diff --git a/vcs/hgrc b/vcs/hgrc new file mode 100644 index 0000000..ee4de57 --- /dev/null +++ b/vcs/hgrc @@ -0,0 +1,62 @@ +# This is the Mercurial configuration file. + +# Copyright (C) 2011-2012 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +[ui] +username = Simon Ruderich + +# Use git diffs with support for renames, binaries, access rights, etc. +[diff] +git = True + +[extensions] +# Convert other vcs to mercurial. +hgext.convert = +# Simplify pull and merge processes. +hgext.fetch = +# Log output similar to hg view but as ASCII. +hgext.graphlog = +# Enable hg view. +hgext.hgk = +# Patch stack support. +hgext.mq = +# Use a pager for all output. +hgext.pager = +# Partial commit utility. +hgext.record = +# Allows cherry-picking and rebasing. +hgext.transplant = + +# Necessary for hg view. +[hgk] +path = /usr/share/mercurial/hgk + +[hooks] +# Precommit hook which runs tests if they exist. +precommit = precommit-runtests +# Prevent "hg pull" if MQ patches are applied. +prechangegroup.mq-no-pull = ! hg qtop > /dev/null 2>&1 +# Prevent "hg push" if MQ patches are applied. +preoutgoing.mq-no-push = ! hg qtop > /dev/null 2>&1 + +# Use colordiff and less as pager so that output from diff is colored and +# everything is easily readable in a terminal. +[pager] +pager = colordiff | less +ignore = record, qrecord, view, clone + +# vim: ft=cfg diff --git a/vcs/setup.sh b/vcs/setup.sh new file mode 100755 index 0000000..bf22f99 --- /dev/null +++ b/vcs/setup.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# Setup script for VCS configuration files. + +# Copyright (C) 2011-2013 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +. ../lib.sh + + +if installed git; then + generate gitconfig .in simple_cpp PWD -- "`pwd`" + + # Older Git versions don't support push.default = simple. + if ! git status >/dev/null 2>&1; then + echo 'gitconfig: removing push.default = simple' + grep_i -v '^[[:space:]]default = simple$' gitconfig + fi + # Even older Git versions don't support color.function. + if ! git status >/dev/null 2>&1; then + echo 'gitconfig: removing color.function' + sed_i 's/^[[:space:]]*function = .*//' gitconfig + fi + # Even older Git versions don't support git log --patch but only -p. + if ! git log --patch >/dev/null 2>&1; then + echo 'gitconfig: replacing git log --patch with -p' + sed_i 's/log --patch/log -p/' gitconfig + fi + + # If coloredstderr is used to color stderr then remove the workaround for + # missing output to stderr. + if test -n "${LD_PRELOAD:+set}" \ + && printf '%s' "$LD_PRELOAD" | grep libcoloredstderr.so >/dev/null; then + echo 'gitconfig: removing stderr fix' + sed_i '/^\t\(fs\|fg\) =/ s/2>&1//' gitconfig + fi + + link gitconfig ~/.gitconfig +fi + +if installed tig; then + if tig --version | grep -F 'tig version 1.' >/dev/null; then + link tigrc.old ~/.tigrc + else + link tigrc ~/.tigrc + fi +fi + +if installed hg; then + link hgrc ~/.hgrc +fi + +if installed cvs; then + # CVS doesn't support any comments nor empty lines in cvsrc. + grep -E -v '^#' cvsrc.in | grep -E -v '^$' >cvsrc + + link cvsrc ~/.cvsrc +fi diff --git a/vcs/t/expected-empty.txt b/vcs/t/expected-empty.txt new file mode 100644 index 0000000..19c91bf --- /dev/null +++ b/vcs/t/expected-empty.txt @@ -0,0 +1,31 @@ +diff --git a/test.txt b/test.txt +--- a/test.txt ++++ b/test.txt +@@ -1,26 +1,27 @@ +Tests +==== + +Short sentence with words! + +Longer sentence even more words, ain't that nice! + +And other one, just testing. + +option: new value +option-two: new-value-two +option-three: "value-three" + +function testme() { + firstCall(); + while (a != b) { + if (!second_var) { + third_call() && fourth_call() \ + || fifth_call(); + } + } + return 42; +} + +allow = $0 $! $? $. +allow = $! $? +allow = $0 $! $? diff --git a/vcs/t/expected-nonspaces.txt b/vcs/t/expected-nonspaces.txt new file mode 100644 index 0000000..d6b3558 --- /dev/null +++ b/vcs/t/expected-nonspaces.txt @@ -0,0 +1,32 @@ +diff --git a/test.txt b/test.txt +--- a/test.txt ++++ b/test.txt +@@ -1,26 +1,27 @@ +Tests +[-=====-]{+====+} + +[-Simple-]{+Short+} sentence with [-a few words.-]{+words!+} + +Longer sentence[-with-] even more [-words ..-]{+words,+} ain't that [-nice?-]{+nice!+} + +And [-another-]{+other+} one, just testing. + +option: {+new+} value +option-two: [-value-two-]{+new-value-two+} +option-three: [-value-three-]{+"value-three"+} + +function testme() { + [-first_call();-] +[- if-]{+firstCall();+} +{+ while+} (a [-==-]{+!=+} b) { + if [-(!second_call())-]{+(!second_var)+} { + [-third_call();-]{+third_call() && fourth_call() \+} +{+ || fifth_call();+} + } + } + return 42; +} + +allow = {+$0+} $! $? $. +allow = $! $?[-$.-] +allow = {+$0+} $! $?[-$.-] diff --git a/vcs/t/expected-word-nonword.txt b/vcs/t/expected-word-nonword.txt new file mode 100644 index 0000000..76b34ac --- /dev/null +++ b/vcs/t/expected-word-nonword.txt @@ -0,0 +1,31 @@ +diff --git a/test.txt b/test.txt +--- a/test.txt ++++ b/test.txt +@@ -1,26 +1,27 @@ +Tests +====[-=-] + +S[-imple-]{+hort+} sentence with [-a few -]words[-.-]{+!+} + +Longer sentence [-with -]even more words[- ..-]{+,+} ain't that nice[-?-]{+!+} + +And [-an-]other one, just testing. + +option: {+new +}value +option-two: {+new-+}value-two +option-three: {+"+}value-three{+"+} + +function testme() { + first[-_c-]{+C+}all(); + {+wh+}i[-f-]{+le+} (a [-=-]{+!+}= b) { + if (!second_{+var) {+} +{+ third_+}call(){+ && fourth_call(+}) [-{-]{+\+} +{+ +} {+|| fif+}th[-ird-]_call(); + } + } + return 42; +} + +allow = ${+0 $+}! $? $. +allow = $! $?[- $.-] +allow = $[-!-]{+0+} $[-?-]{+!+} $[-.-]{+?+} diff --git a/vcs/t/expected-words-nonword.txt b/vcs/t/expected-words-nonword.txt new file mode 100644 index 0000000..5e0f6b1 --- /dev/null +++ b/vcs/t/expected-words-nonword.txt @@ -0,0 +1,31 @@ +diff --git a/test.txt b/test.txt +--- a/test.txt ++++ b/test.txt +@@ -1,26 +1,27 @@ +Tests +====[-=-] + +[-Simple-]{+Short+} sentence with [-a few -]words[-.-]{+!+} + +Longer sentence [-with -]even more words[- ..-]{+,+} ain't that nice[-?-]{+!+} + +And [-another-]{+other+} one, just testing. + +option: {+new +}value +option-two: {+new-+}value-two +option-three: {+"+}value-three{+"+} + +function testme() { + [-first_call-]{+firstCall+}(); + [-if-]{+while+} (a [-=-]{+!+}= b) { + if (![-second_call()-]{+second_var+}) { + third_call(){+ && fourth_call() \+} +{+ || fifth_call()+}; + } + } + return 42; +} + +allow = ${+0 $+}! $? $. +allow = $! $?[- $.-] +allow = $[-!-]{+0+} $[-?-]{+!+} $[-.-]{+?+} diff --git a/vcs/t/expected-words-nonwords-spaces.txt b/vcs/t/expected-words-nonwords-spaces.txt new file mode 100644 index 0000000..cbc70dc --- /dev/null +++ b/vcs/t/expected-words-nonwords-spaces.txt @@ -0,0 +1,31 @@ +diff --git a/test.txt b/test.txt +--- a/test.txt ++++ b/test.txt +@@ -1,26 +1,27 @@ +Tests +[-=====-]{+====+} + +[-Simple-]{+Short+} sentence with [-a few -]words[-.-]{+!+} + +Longer sentence [-with -]even more words[- .. -]{+, +}ain't that nice[-?-]{+!+} + +And [-another-]{+other+} one, just testing. + +option: {+new +}value +option-two: {+new-+}value-two +option-three[-: -]{+: "+}value-three{+"+} + +function testme() { + [-first_call-]{+firstCall+}(); + [-if-]{+while+} (a[- == -]{+ != +}b) { + if (![-second_call()) {-]{+second_var) {+} + third_call{+() && fourth_call() \+} +{+ || fifth_call+}(); + } + } + return 42; +} + +allow[- = $! $? $.-]{+ = $0 $! $? $.+} +allow[- = $! $? $.-]{+ = $! $?+} +allow[- = $! $? $.-]{+ = $0 $! $?+} diff --git a/vcs/t/expected-words-nonwords.txt b/vcs/t/expected-words-nonwords.txt new file mode 100644 index 0000000..cbc70dc --- /dev/null +++ b/vcs/t/expected-words-nonwords.txt @@ -0,0 +1,31 @@ +diff --git a/test.txt b/test.txt +--- a/test.txt ++++ b/test.txt +@@ -1,26 +1,27 @@ +Tests +[-=====-]{+====+} + +[-Simple-]{+Short+} sentence with [-a few -]words[-.-]{+!+} + +Longer sentence [-with -]even more words[- .. -]{+, +}ain't that nice[-?-]{+!+} + +And [-another-]{+other+} one, just testing. + +option: {+new +}value +option-two: {+new-+}value-two +option-three[-: -]{+: "+}value-three{+"+} + +function testme() { + [-first_call-]{+firstCall+}(); + [-if-]{+while+} (a[- == -]{+ != +}b) { + if (![-second_call()) {-]{+second_var) {+} + third_call{+() && fourth_call() \+} +{+ || fifth_call+}(); + } + } + return 42; +} + +allow[- = $! $? $.-]{+ = $0 $! $? $.+} +allow[- = $! $? $.-]{+ = $! $?+} +allow[- = $! $? $.-]{+ = $0 $! $?+} diff --git a/vcs/t/expected-words-nonwordspaces-spaces.txt b/vcs/t/expected-words-nonwordspaces-spaces.txt new file mode 100644 index 0000000..11769da --- /dev/null +++ b/vcs/t/expected-words-nonwordspaces-spaces.txt @@ -0,0 +1,31 @@ +diff --git a/test.txt b/test.txt +--- a/test.txt ++++ b/test.txt +@@ -1,26 +1,27 @@ +Tests +[-=====-]{+====+} + +[-Simple-]{+Short+} sentence with [-a few -]words[-.-]{+!+} + +Longer sentence [-with -]even more words[- ..-]{+,+} ain't that nice[-?-]{+!+} + +And [-another-]{+other+} one, just testing. + +option: {+new +}value +option-two: {+new-+}value-two +option-three: {+"+}value-three{+"+} + +function testme() { + [-first_call-]{+firstCall+}(); + [-if-]{+while+} (a [-==-]{+!=+} b) { + if (![-second_call())-]{+second_var)+} { + third_call{+() && fourth_call() \+} +{+ || fifth_call+}(); + } + } + return 42; +} + +allow = {+$0 +}$! $? $. +allow = $! $?[- $.-] +allow = {+$0 +}$! $?[- $.-] diff --git a/vcs/t/expected-words-nonwordspaces.txt b/vcs/t/expected-words-nonwordspaces.txt new file mode 100644 index 0000000..ce5d927 --- /dev/null +++ b/vcs/t/expected-words-nonwordspaces.txt @@ -0,0 +1,31 @@ +diff --git a/test.txt b/test.txt +--- a/test.txt ++++ b/test.txt +@@ -1,26 +1,27 @@ +Tests +[-=====-]{+====+} + +[-Simple-]{+Short+} sentence with[-a few-] words[-.-]{+!+} + +Longer sentence[-with-] even more words[-..-]{+,+} ain't that nice[-?-]{+!+} + +And [-another-]{+other+} one, just testing. + +option: {+new+} value +option-two: {+new-+}value-two +option-three: {+"+}value-three{+"+} + +function testme() { + [-first_call-]{+firstCall+}(); + [-if-]{+while+} (a [-==-]{+!=+} b) { + if (![-second_call())-]{+second_var)+} { + third_call{+() && fourth_call() \+} +{+ || fifth_call+}(); + } + } + return 42; +} + +allow = {+$0+} $! $? $. +allow = $! $?[-$.-] +allow = {+$0+} $! $?[-$.-] diff --git a/vcs/t/test.sh b/vcs/t/test.sh new file mode 100755 index 0000000..6f1084b --- /dev/null +++ b/vcs/t/test.sh @@ -0,0 +1,111 @@ +#!/bin/sh + +# Small test file to check different --word-diff-regex settings in Git. + +# Copyright (C) 2012-2014 Simon Ruderich +# +# 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 3 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, see . + + +set -eu + +git_diff() { + git diff --color=never --word-diff=plain --word-diff-regex="$1" \ + | grep -v '^index ' >"result-$2.txt" + diff -u "../expected-$2.txt" "result-$2.txt" +} + + +# Setup test directory/files. +mkdir test +cd test + +git init >/dev/null +cat >test.txt </dev/null + +cat >test.txt <. + + +# Don't display uncommitted changes. +set show-changes = no + +# Ignore case when searching. +set ignore-case = yes + +# Don't write ~/.tig_history. +set history-size = 0 + + +# DISPLAY + +# Same as the default, but use relative dates. +set main-view = date:relative author:full commit-title:yes,graph,refs + + +# BINDINGS + +# Allow moving in the main menu while displaying a diff in the bottom of the +# screen. +bind generic J next +bind generic K previous + +# Mutt like bindings to move to first and last line. +bind generic = move-first-line +bind generic * move-last-line + +# Close current view like in mutt. +bind diff i view-close + +# Unbind unnecessary views. I only use the main view and view diffs of +# commits. +bind generic m none +bind generic d none +bind generic l none +bind generic t none +bind generic f none +bind generic b none +bind generic r none +bind generic s none +bind generic S none +bind generic c none +bind generic y none +bind generic g none +bind generic p none +# Unbind commands which may change the repository. I use tig only as a viewer. +bind main C none + + +# COLORS + +# Try to mimic gitk's colors. + +color date default default +color delimiter default default # ~ if text is too long + +# Main window. +color cursor black cyan # currently selected line +color author default default +color graph-commit magenta default # commit dots in graph +color main-head green default bold # HEAD +color main-ref green default # branches +color main-remote yellow default # remote branches +color main-tag yellow default bold # tags +color main-local-tag yellow default bold # local tags (normal tags) + +# Information at the top of the commit diff. +color commit default default +color "Author: " default default +color "Commit: " default default +color pp-merge default default +color "Date: " default default +color "AuthorDate: " default default +color "CommitDate: " default default +color pp-refs default default +# Special parts of the commit message. +color " Signed-off-by" default default +color " Acked-by" default default + +# Diff coloring. +color diff-header default default bold # diff --git a/.. b/.. +color diff-index default default bold # index abc..def +color diff-chunk cyan default # @@ -.. +.. @@ + +# vim: ft=muttrc diff --git a/vcs/tigrc.old b/vcs/tigrc.old new file mode 100644 index 0000000..8824257 --- /dev/null +++ b/vcs/tigrc.old @@ -0,0 +1,104 @@ +# tig configuration file. + +# Copyright (C) 2011-2012 Simon Ruderich +# +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . + + +# Show the revision graph like gitk does. +set show-rev-graph = yes + +# Use relative dates. +set show-date = relative + +# Don't display uncommitted changes. +set show-changes = no + +# Ignore case when searching. +set ignore-case = yes + + +# BINDINGS + +# Allow moving in the main menu while displaying a diff in the bottom of the +# screen. +bind generic J next +bind generic K previous + +# Mutt like bindings to move to first and last line. +bind generic = move-first-line +bind generic * move-last-line + +# Close current view like in mutt. +bind diff i view-close + +# Unbind unnecessary views. I only use the main view and view diffs of +# commits. +bind generic m none +bind generic d none +bind generic l none +bind generic t none +bind generic f none +bind generic B none +bind generic H none +bind generic p none +bind generic S none +bind generic c none +# Unbind commands which may change the repository. I use tig only as a viewer. +bind generic C none +bind generic u none +bind generic ! none +bind generic M none +bind generic 1 none +bind generic @ none +bind generic e none +bind generic G none + + +# COLORS + +# Try to mimic gitk's colors. + +color date default default +color delimiter default default # ~ if text is too long + +# Main window. +color cursor black cyan # currently selected line +color main-author default default # just 'author' in newer versions +color graph-commit magenta default # commit dots in graph +color main-head green default bold # HEAD +color main-ref green default # branches +color main-remote yellow default # remote branches +color main-tag yellow default bold # tags +color main-local-tag yellow default bold # local tags (normal tags) + +# Information at the top of the commit diff. +color commit default default +color pp-author default default +color pp-commit default default +color pp-merge default default +color pp-date default default +color pp-adate default default +color pp-cdate default default +color pp-refs default default +# Special parts of the commit message. +color signoff default default +color acked default default + +# Diff coloring. +color diff-header default default bold # diff --git a/.. b/.. +color diff-index default default bold # index abc..def +color diff-chunk cyan default # @@ -.. +.. @@ + +# vim: ft=muttrc