aboutsummaryrefslogtreecommitdiff
path: root/bin/clwr.sh
Commit message (Collapse)AuthorAgeFilesLines
* Apply runtime shebanging to POSIX shellTom Ryder2017-04-051-0/+23
kdown-body h1 code, .markdown-body h2 tt, .markdown-body h2 code, .markdown-body h3 tt, .markdown-body h3 code, .markdown-body h4 tt, .markdown-body h4 code, .markdown-body h5 tt, .markdown-body h5 code, .markdown-body h6 tt, .markdown-body h6 code { font-size: inherit; } .markdown-body h1 { font-size: 28px; color: #000; } .markdown-body h2 { font-size: 24px; border-bottom: 1px solid #ccc; color: #000; } .markdown-body h3 { font-size: 18px; } .markdown-body h4 { font-size: 16px; } .markdown-body h5 { font-size: 14px; } .markdown-body h6 { color: #777; font-size: 14px; } .markdown-body p, .markdown-body blockquote, .markdown-body ul, .markdown-body ol, .markdown-body dl, .markdown-body table, .markdown-body pre { margin: 15px 0; } .markdown-body hr { background: transparent url("/dirty-shade.png") repeat-x 0 0; border: 0 none; color: #ccc; height: 4px; padding: 0; } .markdown-body>h2:first-child, .markdown-body>h1:first-child, .markdown-body>h1:first-child+h2, .markdown-body>h3:first-child, .markdown-body>h4:first-child, .markdown-body>h5:first-child, .markdown-body>h6:first-child { margin-top: 0; padding-top: 0; } .markdown-body a:first-child h1, .markdown-body a:first-child h2, .markdown-body a:first-child h3, .markdown-body a:first-child h4, .markdown-body a:first-child h5, .markdown-body a:first-child h6 { margin-top: 0; padding-top: 0; } .markdown-body h1+p, .markdown-body h2+p, .markdown-body h3+p, .markdown-body h4+p, .markdown-body h5+p, .markdown-body h6+p { margin-top: 0; } .markdown-body li p.first { display: inline-block; } .markdown-body ul, .markdown-body ol { padding-left: 30px; } .markdown-body ul.no-list, .markdown-body ol.no-list { list-style-type: none; padding: 0; } .markdown-body ul li>:first-child, .markdown-body ul li ul:first-of-type, .markdown-body ul li ol:first-of-type, .markdown-body ol li>:first-child, .markdown-body ol li ul:first-of-type, .markdown-body ol li ol:first-of-type { margin-top: 0px; } .markdown-body ul li p:last-of-type, .markdown-body ol li p:last-of-type { margin-bottom: 0; } .markdown-body ul ul, .markdown-body ul ol, .markdown-body ol ol, .markdown-body ol ul { margin-bottom: 0; } .markdown-body dl { padding: 0; } .markdown-body dl dt { font-size: 14px; font-weight: bold; font-style: italic; padding: 0; margin: 15px 0 5px; } .markdown-body dl dt:first-child { padding: 0; } .markdown-body dl dt>:first-child { margin-top: 0px; } .markdown-body dl dt>:last-child { margin-bottom: 0px; } .markdown-body dl dd { margin: 0 0 15px; padding: 0 15px; } .markdown-body dl dd>:first-child { margin-top: 0px; } .markdown-body dl dd>:last-child { margin-bottom: 0px; } .markdown-body blockquote { border-left: 4px solid #DDD; padding: 0 15px; color: #777; } .markdown-body blockquote>:first-child { margin-top: 0px; } .markdown-body blockquote>:last-child { margin-bottom: 0px; } .markdown-body table th { font-weight: bold; } .markdown-body table th, .markdown-body table td { border: 1px solid #ccc; padding: 6px 13px; } .markdown-body table tr { border-top: 1px solid #ccc; background-color: #fff; } .markdown-body table tr:nth-child(2n) { background-color: #f8f8f8; } .markdown-body img { max-width: 100%; -moz-box-sizing: border-box; box-sizing: border-box; } .markdown-body span.frame { display: block; overflow: hidden; } .markdown-body span.frame>span { border: 1px solid #ddd; display: block; float: left; overflow: hidden; margin: 13px 0 0; padding: 7px; width: auto; } .markdown-body span.frame span img { display: block; float: left; } .markdown-body span.frame span span { clear: both; color: #333; display: block; padding: 5px 0 0; } .markdown-body span.align-center { display: block; overflow: hidden; clear: both; } .markdown-body span.align-center>span { display: block; overflow: hidden; margin: 13px auto 0; text-align: center; } .markdown-body span.align-center span img { margin: 0 auto; text-align: center; } .markdown-body span.align-right { display: block; overflow: hidden; clear: both; } .markdown-body span.align-right>span { display: block; overflow: hidden; margin: 13px 0 0; text-align: right; } .markdown-body span.align-right span img { margin: 0; text-align: right; } .markdown-body span.float-left { display: block; margin-right: 13px; overflow: hidden; float: left; } .markdown-body span.float-left span { margin: 13px 0 0; } .markdown-body span.float-right { display: block; margin-left: 13px; overflow: hidden; float: right; } .markdown-body span.float-right>span { display: block; overflow: hidden; margin: 13px auto 0; text-align: right; } .markdown-body code, .markdown-body tt { margin: 0 2px; padding: 0px 5px; border: 1px solid #eaeaea; background-color: #f8f8f8; border-radius: 3px; } .markdown-body code { white-space: nowrap; } .markdown-body pre>code { margin: 0; padding: 0; white-space: pre; border: none; background: transparent; } .markdown-body .highlight pre, .markdown-body pre { background-color: #f8f8f8; border: 1px solid #ccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-radius: 3px; } .markdown-body pre code, .markdown-body pre tt { margin: 0; padding: 0; background-color: transparent; border: none; } pre { line-height: 125%; margin: 0; } td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #ffffff; } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */

Dotfiles (Tom Ryder)

This is my personal repository of configuration files and scripts for $HOME, including most of the settings that migrate well between machines.

This repository began as a simple way to share Vim and tmux configuration, but a lot of scripts and shell configuration have been added over time, making it into a personal suite of custom Unix tools.

Installation

$ mkdir -p ~/.local/src
$ git clone https://dev.sanctum.geek.nz/code/dotfiles.git ~/.local/src/dotfiles
$ cd ~/.local/src/dotfiles
$ git submodule init
$ git submodule update
$ make
$ make -n install  # Check output carefully
$ make install

For the default all target, you'll need a POSIX-fearing userland, including make(1) and m4(1).

The installation Makefile overwrites things standing in the way of its installed files without backing them up, so read the output of make -n install before running make install carefully, to make sure you aren't going to lose anything unexpected. If you're still not sure, install it in a temporary directory first, so you can explore:

$ tmpdir=$(mktemp -d)
$ make install HOME="$tmpdir"
$ env -i HOME="$tmpdir" TERM="$TERM" "$SHELL" -l

The default install target will install these targets and all their dependencies:

The install-login-shell target looks at your SHELL environment variable, and tries to figure out which shell's configuration files to install, falling back on install-sh.

The remaining files can be installed with the other install-* targets. Try awk -f bin/mftl.awk Makefile in the project's root directory to see a list.

Configuration

To keep a set of make targets useful for a specific user or host, you can list them in a newline-separated file ~/.config/dotfiles/config, and install using that with the special install-conf target. This can include macro settings for the Makefile, too:

$ cd
$ cat .config/dotfiles/config
install-bash
install-bin
EMAIL=you@example.com
$ make -C .local/src/dotfiles install-conf

Tools

Configuration is included for:

There is also some slightly customized support for multi-version environment management for three major scripting languages:

The configurations for shells, Mutt, tmux, and Vim are the most likely to be of interest. The i3 configuration is limited mainly to changing window switching key bindings to match Vim's.

Shell

On GNU/Linux, I use Bash; on *BSD, I use some variant of Korn Shell, preferably ksh93 if it's available.

POSIX core

My ~/.profile and other files in sh are written in POSIX shell script, so they should work in most POSIX-conforming sh(1) implementations. Please email me if you find a case where they don't!

Further shell snippets to run on login are sourced from ~/.profile.d by ~/.profile. Most of these boil down to exporting variables appropriate to the system and the software it has available.

Configuration that should be sourced for all conforming interactive shells is kept in ~/.shrc, with subscripts read from ~/.shrc.d. There's a ~/.shinit shim to act as ENV.

GNU Bash

My Bash scripts are written to work with GNU Bash v3.0 or newer. This is why I use older syntax for certain things such as appending items to arrays:

array[${#array[@]}]=$item

This doesn't work for arrays with sparse indices; compare this to the much nicer syntax available since 3.1-alpha1, which does:

array+=("$item")

I do use some features that are only available in versions after v3.0, such as newer shopt options like dirspell, or variables like PROMPT_DIRTRIM. These are set only after testing BASH_VERSINFO appropriately.

Prompt

A terminal session with my prompt looks something like this:

~$ ssh remote
remote:~$ cd .local/src/dotfiles
remote:~/.local/src/dotfiles(master+!)$ git status
 M README.md
M  bash/bashrc.d/prompt.bash
A  init
remote:~/.local/src/dotfiles(master+!)$ foobar
foobar: command not found
remote:~/.local/src/dotfiles(master+!)<127>$ sleep 5 &
[1] 28937
remote:~/.local/src/dotfiles(master+!){1}$

The hostname is elided if not connected via SSH. The working directory with tilde abbreviation for $HOME is always shown. The rest of the prompt expands based on context to include these elements, in this order:

You can set PROMPT_COLOR, PROMPT_PREFIX, and PROMPT_SUFFIX too, which all do about what you'd expect.

If you start up GNU Bash, Korn shell, or Z shell, and that doesn't match your login shell, the prompt should display an appropriate prefix.

This is all managed within the prompt function. There's some mildly hacky logic on tput codes included such that it should work correctly for most common terminals using both termcap(5) and terminfo(5), including *BSD systems. It's also designed to degrade gracefully for eight-color and no-color terminals.

Functions

If a function can be written in POSIX sh without too much hackery, I put it in sh/shrc.d to be loaded by any POSIX interactive shell. Those include:

There are a few other little tricks defined for other shells providing non-POSIX features, as compatibility allows:

Completion

I find the bash-completion package a bit too heavy for my tastes, and turn it off using a stub file installed in ~/.config/bash_completion. The majority of the time I just want to complete paths anyway, and this makes for a quicker startup without a lot of junk functions in my Bash namespace.

I do make some exceptions with completions defined in files in ~/.bash_completion.d for things I really do get tired of typing repeatedly:

For commands that pretty much always want to operate on text, such as text file or stream editors, I exclude special file types and extensions I know are binary. I don't actually read the file, so this is more of a heuristic thing, and sometimes it will get things wrong.

I also add completions for my own scripts and functions where useful. The completions are dynamically loaded if Bash is version 4.0 or greater. Otherwise, they're all loaded on startup.

Korn shell

These are experimental; they are mostly used to tinker with MirBSD mksh, AT&T ksh93, and OpenBSD pdksh. All shells in this family default to a yellow prompt if detected.

Z shell

These are experimental; I do not like Z shell much at the moment. The files started as a joke (exec bash). zsh shells default to having a prompt colored cyan.

Mutt

My mail is kept in individual Maildir-format directories under ~/mail, with the system mail spool in e.g. /var/mail/tejr being where most unfiltered new mail is spooled. I use Getmail, maildrop, and msmtp; the configurations for these are not included here. I sign whenever I have some indication that the recipient might be using a PGP implementation, and I encrypt whenever I have a public key available for them. The GnuPG and S/MIME interfacing is done with GPGme, rather than defining commands for each crypto operation. I wrote an article about this setup if it sounds appealing.

You'll need Abook installed if you want to use the query_command I have defined, and msmtp for the sendmail command.

tmux

These are just generally vi-friendly settings, and there isn't much out of the ordinary. Note that the configuration presently uses a hard-coded 256-color color scheme, and uses non-login shells, with an attempt to control the environment to stop shells thinking they have access to an X display.

The shell scripts in bin include tm(1df), a shortcut to make attach into the default command if no arguments are given and sessions do already exist. My ~/.inputrc file binds Alt+M to run that, and Tmux in turn binds the same key combination to detach.

Vim

The majority of the Vim configuration is just setting options, with a fair few mappings and remappings, both global and buffer-local. It's extensively commented.

XDG Basedirs

The XDG Base Directory Specification's environment variables are checked on startup, and appropriate directories are added to the start and end of 'runtimepath'. I use these separate directories for machine-local configuration, usually in ~/.config/vim, while all the files that this suite installs land in ~/.vim. Backups, swap files, persistent undo data, saved views, and the viminfo file all live under XDG_CACHE_HOME, normally ~/.cache/vim.

Filetypes

I define my own filetype.vim and scripts.vim, so that filetype detection works in a way I like, and loads quickly. They are unlikely to suit you as they are, but if you want to use it, you can extend them with your favorite filetypes in custom ftdetect rules.

Plugins

If the logic for doing something involves more than a few lines or any structures like functions that can be decoupled from $MYVIMRC, I like to implement it as a plugin in ~/.vim/plugin and/or ~/.vim/autoload, with documentation for each in ~/.vim/doc.

They eventually get either discarded if I stop using them, or spun off into their own repositories and added to this repository as submodules under vim/bundle if I don't. Some of them I upload to vim.org.

Filetype plugins

I apply some replacement or supplementary configuration specific to file types I often edit in ~/.vim and ~/.vim/after, in the ftplugin, indent, and syntax subdirectories. Some of these filetype plugins or extensions may also eventually be removed to be separately distributed, and installed via submodules instead.

Compilers

I define a few of my own :compiler scripts for ~/.vim/compiler to check and lint appropriate filetypes. I bind checking---"does it run?"---and linting---"is it good?"---with separate local leader maps; for example, for perl filetypes, <LocalLeader>c switches makeprg to perl -c for checking, and <LocalLeader>l to perlcritic for linting.

No Neovim support

The configuration doesn't explicitly support Neovim, although most of it will probably work; you would probably just comment out the settings for a few of the removed options.

Scripts

Where practical, I make short scripts into POSIX (but not Bourne) sh(1), awk(1), or sed(1) scripts in ~/.local/bin. I try to use shell functions only when I actually need to, which tends to be when I need to change the state of the user's current shell, or to limit a change in behavior only to interactive shells.

These scripts are installed by the install-bin target:

There's some silly stuff in install-games:

Manuals

The install-bin and install-games targets install manuals for each script. If you want to read the manuals, you may need to add ~/.local/share/man to your ~/.manpath or /etc/manpath configuration, depending on your system.

Testing

You can check that both sets of shell scripts are syntactically correct with make check-bash or make check-sh, or make check for everything including the scripts in bin and games. There's no proper test suite for the actual functionality (yet).

There are also optional lint targets, if you have the appropriate tools available to run them:

Future development

See IDEAS.md.

Known issues

See ISSUES.md.

License

Public domain; see the included UNLICENSE file. It's just configuration and simple scripts, so do whatever you like with it if any of it's useful to you. If you're feeling generous, please join and/or donate to a free software advocacy group, and let me know you did it because of this project: