]> ruderich.org/simon Gitweb - config/dotfiles.git/commitdiff
Merge branch 'vcs'
authorSimon Ruderich <simon@ruderich.org>
Sat, 2 Jun 2018 11:31:07 +0000 (13:31 +0200)
committerSimon Ruderich <simon@ruderich.org>
Sat, 2 Jun 2018 11:31:07 +0000 (13:31 +0200)
72 files changed:
COPYING [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
archive.sh [new file with mode: 0755]
lib.m4 [new file with mode: 0644]
lib.sh [new file with mode: 0644]
setup.sh [new file with mode: 0755]
shell/.gitignore [new file with mode: 0644]
shell/Makefile [new file with mode: 0644]
shell/bash/logout [new file with mode: 0644]
shell/bash/profile [new file with mode: 0644]
shell/bash/rc [new file with mode: 0644]
shell/bin/README [new file with mode: 0644]
shell/bin/battery.pl [new file with mode: 0755]
shell/bin/calc [new file with mode: 0755]
shell/bin/chronic [new file with mode: 0755]
shell/bin/chronic-log [new file with mode: 0755]
shell/bin/mv-p [new file with mode: 0755]
shell/bin/notify.py [new file with mode: 0755]
shell/bin/print-constant.pl [new file with mode: 0755]
shell/bin/remove-continuation.pl [new file with mode: 0755]
shell/bin/rsleep [new file with mode: 0755]
shell/bin/sc [new file with mode: 0755]
shell/bin/slocate [new file with mode: 0755]
shell/bin/srandom-order [new file with mode: 0755]
shell/bin/srsync [new file with mode: 0755]
shell/bin/srsync-incremental [new file with mode: 0755]
shell/bin/supdatedb [new file with mode: 0755]
shell/bin/svalgrind [new file with mode: 0755]
shell/bin/temperature.pl [new file with mode: 0755]
shell/colordiffrc [new file with mode: 0644]
shell/crontab.d/Makefile [new file with mode: 0644]
shell/crontab.d/README [new file with mode: 0644]
shell/crontab.d/jobs [new file with mode: 0644]
shell/crontab.d/jobs.daily/.gitignore [new file with mode: 0644]
shell/crontab.d/jobs.daily/prune-logs [new file with mode: 0755]
shell/crontab.d/jobs.hourly/.gitignore [new file with mode: 0644]
shell/crontab.d/jobs.hourly6/.gitignore [new file with mode: 0644]
shell/crontab.d/jobs.hourly8/.gitignore [new file with mode: 0644]
shell/crontab.d/jobs.minutely/.gitignore [new file with mode: 0644]
shell/crontab.d/jobs.monthly/.gitignore [new file with mode: 0644]
shell/crontab.d/jobs.reboot/.gitignore [new file with mode: 0644]
shell/crontab.d/jobs.weekly/.gitignore [new file with mode: 0644]
shell/crontab.d/setup.sh [new file with mode: 0755]
shell/csh/rc [new file with mode: 0644]
shell/digrc.in [new file with mode: 0644]
shell/haskeline [new file with mode: 0644]
shell/htoprc.in [new file with mode: 0644]
shell/inputrc [new file with mode: 0644]
shell/lessfilter [new file with mode: 0755]
shell/lesskey [new file with mode: 0644]
shell/reminders.in [new file with mode: 0644]
shell/screenrc.in [new file with mode: 0644]
shell/setup.sh [new file with mode: 0755]
shell/shell/aliases.in [new file with mode: 0644]
shell/shell/bin [new symlink]
shell/shell/dircolors.in [new file with mode: 0644]
shell/shell/env [new file with mode: 0644]
shell/shell/functions [new file with mode: 0644]
shell/shell/logout [new file with mode: 0644]
shell/shell/rc [new file with mode: 0644]
shell/ssh_config [new file with mode: 0644]
shell/sshd_config [new file with mode: 0644]
shell/terminfo/README [new file with mode: 0644]
shell/terminfo/s/screen-it-256color [new file with mode: 0644]
shell/tmux-window.pl [new file with mode: 0644]
shell/tmux.conf.in [new file with mode: 0644]
shell/zsh/env [new file with mode: 0644]
shell/zsh/functions/_systemctl [new file with mode: 0644]
shell/zsh/functions/extract [new file with mode: 0644]
shell/zsh/logout [new file with mode: 0644]
shell/zsh/rc [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
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. <http://fsf.org/>
+ 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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 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 <http://www.gnu.org/licenses/>.
+
+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:
+
+    <program>  Copyright (C) <year>  <name of author>
+    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
+<http://www.gnu.org/licenses/>.
+
+  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
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
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 (executable)
index 0000000..26a0e8d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 (file)
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 <http://www.gnu.org/licenses/>.
+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 (file)
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 <http://www.gnu.org/licenses/>.
+
+
+# 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 <cmd> ... <file>
+#
+# Run <cmd> with all arguments (including the last file) and write the result
+# to the temporary file <file>.tmp and then rename that file to <file>. This
+# can't be done in-place (e.g. cmd <file >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 ... <file>
+#
+# 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 <cmd> ...
+#
+# 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 (<STDIN>) { $cmd; print; }" "$@"
+}
+
+# Usage: simple_cpp <FIRST> <SECOND> .. -- <replacement-for-first> ...
+#
+# Replaces each FIRST (on word boundaries) with <replacement-for-first> 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 <file> <extension> <cmd..>
+#
+# 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 (executable)
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 <http://www.gnu.org/licenses/>.
+
+
+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 (file)
index 0000000..c08e6d5
--- /dev/null
@@ -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 (file)
index 0000000..23d5991
--- /dev/null
@@ -0,0 +1,4 @@
+all:
+       @./setup.sh
+
+.PHONY: all
diff --git a/shell/bash/logout b/shell/bash/logout
new file mode 100644 (file)
index 0000000..12f1e5d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+source_config ~/.shell/logout
+
+# vim: ft=sh
diff --git a/shell/bash/profile b/shell/bash/profile
new file mode 100644 (file)
index 0000000..db373e9
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+if [[ -f ~/.bashrc ]]; then
+    . ~/.bashrc
+fi
+
+# vim: ft=sh
diff --git a/shell/bash/rc b/shell/bash/rc
new file mode 100644 (file)
index 0000000..d876fe9
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+. ~/.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 (file)
index 0000000..ad0164a
--- /dev/null
@@ -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 (executable)
index 0000000..c7e812e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+use strict;
+use warnings;
+
+
+if (scalar @ARGV != 1 and (scalar @ARGV != 2 or not $ARGV[0] =~ /-[st]/)) {
+    print STDERR "Usage: $0 [-s | -t] <path/to/device>\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 (executable)
index 0000000..ea3cbd3
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 (executable)
index 0000000..a9fa47b
--- /dev/null
@@ -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 <joey@kitenet.net>
+
+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 (executable)
index 0000000..e8dc7ea
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+set -eu
+
+if test $# -lt 2; then
+    echo "Usage: $0 <logfile> <cmd> <args>.." >&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 (executable)
index 0000000..7259d33
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 (executable)
index 0000000..3caa7d2
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 <message>\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 (executable)
index 0000000..f0205db
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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;
+print-constant $VERSION  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 <http://www.gnu.org/licenses/>.
+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 <stdio.h>
+#include <stdlib.h>
+%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<print-constant> [I<options>] I<CONSTANT_NAME>
+
+=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<include>, B<--include> I<include>
+
+Use I<include> as include file. Adds C<#include E<lt>includeE<gt>> to the
+beginning of the C file used to print the constant. By default C<limits.h> and
+C<unistd.h> are used as headers. If this option is specified I<no> default
+includes are used. Can be specified multiple times.
+
+=item B<-p> I<path>, B<--pathconf> I<path>
+
+Pass the constant to pathconf(3) and print the result. I<path> 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<type>, B<--type> I<type>
+
+Use I<type> as type of the constant, used in printf(3). By default C<d> 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, E<lt>simon@ruderich.orgE<gt>
+
+=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 <http://www.gnu.org/licenses/>.
+
+=head1 SEE ALSO
+
+L<sysconf(3)>, L<pathconf(3)>
+
+=cut
diff --git a/shell/bin/remove-continuation.pl b/shell/bin/remove-continuation.pl
new file mode 100755 (executable)
index 0000000..3deb7d7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+use strict;
+use warnings;
+
+
+my $continuation = 0;
+while (<STDIN>) {
+    # 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 (executable)
index 0000000..9b953c5
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+use strict;
+use warnings;
+
+
+if (scalar @ARGV != 1) {
+    print STDERR "Usage: $0 <maximum sleep time in seconds>\n";
+    exit 1;
+}
+
+srand;
+sleep int rand $ARGV[0];
diff --git a/shell/bin/sc b/shell/bin/sc
new file mode 100755 (executable)
index 0000000..506e90a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+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 (executable)
index 0000000..43e1eb2
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+set -eu
+
+exec locate -d "$HOME/.tmp/locatedb" "$@"
diff --git a/shell/bin/srandom-order b/shell/bin/srandom-order
new file mode 100755 (executable)
index 0000000..45297be
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+set -eu
+
+if test "$#" -eq 0; then
+    echo "Usage: $0 <program-args>.." >&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 (executable)
index 0000000..8402bb3
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 (executable)
index 0000000..187e6b6
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+set -eu
+
+if test "$#" -lt 2; then
+    echo "Usage: $0 <backups-directory> <arguments to rsync>" >&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 (executable)
index 0000000..4f5fac0
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 (executable)
index 0000000..bcb68da
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 (executable)
index 0000000..42eaffe
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+use strict;
+use warnings;
+
+
+if (scalar @ARGV != 1 and (scalar @ARGV != 2 or not $ARGV[0] =~ /-[st]/)) {
+    print STDERR "Usage: $0 [-s | -t] <path/to/device>\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 (file)
index 0000000..d8f91db
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..23d5991
--- /dev/null
@@ -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 (file)
index 0000000..56121ce
--- /dev/null
@@ -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 (file)
index 0000000..8426b7a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
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 (executable)
index 0000000..74aa1f2
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 (file)
index 0000000..e69de29
diff --git a/shell/crontab.d/jobs.hourly6/.gitignore b/shell/crontab.d/jobs.hourly6/.gitignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/shell/crontab.d/jobs.hourly8/.gitignore b/shell/crontab.d/jobs.hourly8/.gitignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/shell/crontab.d/jobs.minutely/.gitignore b/shell/crontab.d/jobs.minutely/.gitignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/shell/crontab.d/jobs.monthly/.gitignore b/shell/crontab.d/jobs.monthly/.gitignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/shell/crontab.d/jobs.reboot/.gitignore b/shell/crontab.d/jobs.reboot/.gitignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/shell/crontab.d/jobs.weekly/.gitignore b/shell/crontab.d/jobs.weekly/.gitignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/shell/crontab.d/setup.sh b/shell/crontab.d/setup.sh
new file mode 100755 (executable)
index 0000000..46ebb56
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 (file)
index 0000000..0fdc66a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..c686042
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..ecf2428
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+-- 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
+
+-- <Up>/<Down> 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 (file)
index 0000000..194328d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..aa74013
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# Only one <Tab> 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
+
+# <Up>/<Down> 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 <C-L> 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 (executable)
index 0000000..1403df4
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+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 (file)
index 0000000..247679b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+#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 (file)
index 0000000..a146029
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..a403083
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (executable)
index 0000000..eec1ded
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+set -eu
+
+. ../lib.sh
+
+
+# Helper functions.
+terminal_info() {
+    infocmp "$@" 2>&1
+}
+terminal_available() {
+    terminal_info "$@" > /dev/null
+}
+# Usage: <file> <name> <grep-string> <value>
+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 <lesskey \
+    HISTORY_PATH -- "`pwd`/lesshistory" \
+    | lesskey -
+chmod 0600 ~/.less
+
+# Custom colors for GNU ls.
+if installed dircolors; then
+    echo '# WARNING! DO NOT EDIT THIS FILE!' >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 (file)
index 0000000..69270cc
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (symlink)
index 0000000..19f285a
--- /dev/null
@@ -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 (file)
index 0000000..82bafc6
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..f3e4293
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..838968b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..a5e1bbc
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..d0261bb
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..09995ab
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+# 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 (file)
index 0000000..0b7d95a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..3c91b00
--- /dev/null
@@ -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 (file)
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 (file)
index 0000000..5e2601c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+use strict;
+use warnings;
+
+
+if (scalar @ARGV != 1 && scalar @ARGV != 2) {
+    print STDERR "Usage: $0 <level> [</path/to/tmux-window.conf>]\n";
+    exit 1;
+}
+
+my $level = $ARGV[0];
+my $path  = $ARGV[1];
+
+if (defined $path and $path !~ m{^/}) {
+    print STDERR "<path> 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 (file)
index 0000000..6d582d9
--- /dev/null
@@ -0,0 +1,133 @@
+# Tmux configuration file.
+#
+# Notes:
+#
+# - To swap/renumber windows (like GNU screen's :number command) use
+#   :swap-window -t <number>.
+# - 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 <http://www.gnu.org/licenses/>.
+
+
+# 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 (file)
index 0000000..30483a0
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+. ~/.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 (file)
index 0000000..c440dd7
--- /dev/null
@@ -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 (file)
index 0000000..5a73454
--- /dev/null
@@ -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 (file)
index 0000000..a540ec8
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+source_config ~/.shell/logout
+
+# vim: ft=zsh
diff --git a/shell/zsh/rc b/shell/zsh/rc
new file mode 100644 (file)
index 0000000..7222619
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+
+# 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 <C-D> is pressed. Prevents exiting the shell by accident (e.g.
+# pressing <C-D> 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 -<Tab> 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 <Tab> always display them
+# immediately without requiring another <Tab>. a<Tab> 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<tab> 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 <Tab>. echo *<Tab>
+# 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/<Tab> doesn't expand $HOME,
+# while $HOME<Tab> does.
+zstyle ':completion:*:expand:*' keep-prefix yes
+
+# When completing multiple path components display all matching ambiguous
+# components. For example /u/s/d/r/README<Tab> 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<Tab> 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 <ft@bewatermyfriend.org>
+# (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 <vz-zsh@zeitlins.org> for a fix (--) so lines
+# starting with - don't cause errors; and to Nadav Har'El
+# <nyh@math.technion.ac.il> 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