Skip to content

fniessen/shell-leuven

Repository files navigation

Shell-Leuven

How Shell-Leuven is different from the default configuration

Shell-Leuven is a set of configuration files to customize your Bash and Zsh experience on Windows (with Cygwin or Git BASH), Linux and Mac OS.

The features that differentiate Shell-Leuven from the default configuration include:

  • Autosuggestions – Shell-Leuven suggests commands (in muted gray) as you type, based on your command history and command completions.
  • Man Page Completions – Shell-Leuven generates command completion options automatically by parsing installed man pages.
  • Syntax highlighting – Shell-Leuven uses different colors for parts of commands to help users focus on different things (e.g., commands versus arguments).
  • Improved command line history – Persists across sessions. Searchable incrementally (C-r and C-s). History expansion (e.g. !!, !<string>, and !$).

Installation

Try Online

Run the following command in your shell to try Shell-Leuven without installing anything:

# Source .zshrc and .shellrc.
curl -sSL https://raw.githubusercontent.com/fniessen/shell-leuven/master/.zshrc_leuven | zsh
curl -sSL https://raw.githubusercontent.com/fniessen/shell-leuven/master/.shellrc_leuven | zsh

Manual Installation

Download and source XXX.bash or XXX.zsh in your shell config.

Startup files

There are 3 types of shells:

  • (interactive) login

    (for which c:/cygwin/etc/profile and .profile are read, which sources .bashrc as well)

  • interactive (non-login)

    (for which .bashrc is read)

  • normal shell

    i.e. one that’s running a script (Bash does not execute any initialization file in this case!)

    $tty is empty.

We just let .profile also read .bashrc and put everything in .bashrc.

Read Zsh/Bash startup files loading order:

  • For Bash, put stuff in ~/.bashrc, and make ~/.bash_profile source it.
# User dependent .bash_profile file

# Source the .bashrc file if it exists;
[[ -f "$HOME"/.bashrc ]] && . "$HOME"/.bashrc
  • For Zsh, put stuff in ~/.zprofile, which is always executed.

To recover the default Bash configuration files, get their copy from /etc/skel.

See http://blog.flowblok.id.au/2013-02/shell-startup-scripts.html for a Dotty graph of the files…

What to put where?

Login shell runs .profile (or .bash_profile or .bash_login) on startup. Set your env variables in there, because sub-shells will inherit the env vars. Then make .profile run your .bashrc:

. .bashrc

Interactive runs .bashrc. Since it inherits envs, but not aliases, put your aliases in this file.

Shell scripts, cron jobs, and the like, run with a bare shell: no bashrc or profiles are run. No kidding you get 4 env vars set, the bare minimum. Therefore your PATH won’t work very well so you often have to give an absolute pathname like in crontab:

right: 0 0 * * 2 /usr/sbin/apachectl restart
wrong: 0 0 * * 2 apachectl restart

From https://www.linuxquestions.org/questions/linux-general-1/difference-between-normal-shell-and-login-shell-14983/#post4828786

What to put in your Zsh startup files

See http://zsh.sourceforge.net/Guide/zshguide02.html.

Bash Configuration

:header-args+: :tangle .bashrc_leuven
# Hey Emacs, this is a -*- sh -*- file
## bash_profile --- Bash configuration file (for interactive shells)

# Copyright (C) 2003-<<current-year()>> Fabrice Niessen

# Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
# Keywords: bash, dotfile, config

# Code:

Prevent “stdin is not a tty” errors when ssh‘ing to a remote machine (or using scp, rcp or rsync):

# If not running interactively, don't do anything.
# isInteractive=$(echo $- | grep i)
[[ "$-" != *i* ]] && return

You don’t want to perform a full-blown initialization every time scripts execute.

It’s important to refrain from outputting anything in those cases.

Make zsh your default shell on Windows

To start directly Zsh when opening Bash on Ubuntu on Windows:

# # If running in terminal...
# if test -t 1; then
#     # ... start Zsh
#     echo "Start Zsh..."
#     exec zsh
# fi

Startup (Where are Leuven customizations?)

Your .bashrc file might resemble the following configuration:

# Source local shell customizations.
source_local_file() {
    local file="$HOME/$1"
    if [ -f "$file" ]; then
        source "$file"
    fi
}

source_local_file ".shellrc_leuven" # Source Leuven shell customizations.
source_local_file ".bashrc_leuven" # Source Leuven Bash customizations.

# Ready for more (from other Leuven repositories)?
# Load rc-<something> scripts for Bash.
shopt -s nullglob
rcfiles=(~/bin/rc-bash-* ~/bin/rc-common-*)
if [ ${#rcfiles[@]} -gt 0 ]; then
    for rcfile in "${rcfiles[@]}"; do
        source "$rcfile"
    done
fi

Colors

Prompt

Note \[...\] used by the shell to count proper length.

if tput setaf 1 &> /dev/null; then
    tput sgr0
    if tput colors &> /dev/null; then
        if [[ $(tput colors) -ge 256 ]]; then
            MAG=$(tput setaf 9)
            ORANGE=$(tput setaf 172)
            GREEN=$(tput setaf 190)
            PURPLE=$(tput setaf 141)
            WHITE=$(tput setaf 256)
        else
            MAG=$(tput setaf 5)
            ORANGE=$(tput setaf 4)
            GREEN=$(tput setaf 2)
            PURPLE=$(tput setaf 1)
            WHITE=$(tput setaf 7)
        fi
        BOLD=$(tput bold)
        RESET=$(tput sgr0)
    else
        MAG="\033[35m"
        ORANGE="\033[33m"
        GREEN="\033[32m"
        PURPLE="\033[35m"
        WHITE="\033[37m"
        BOLD=""
        RESET="\033[m"
    fi
fi

See Easy Bash PS1 Generator

  • Insert an empty line before the prompt
  • Change Bash prompt color based on exit code of last command
# Get the current Git branch.
git_branch() {
    local branch
    branch=$(git branch 2> /dev/null | sed -n '/^*/s/^* //p')
    if [[ -n "$branch" ]]; then
        printf " (%s)" "$branch"
    fi
}
# Colors.
BLK="\[$(tput setaf 0; tput bold)\]"
RED="\[$(tput setaf 1; tput bold)\]"
grn="\[$(tput setaf 2)\]"
GRN="\[$(tput setaf 2; tput bold)\]"
yel="\[$(tput setaf 3)\]"
reset_color="\[$(tput sgr0)\]"

# PS1 --- Default interaction prompt

case "$TERM" in
    "dumb")
        # No fancy multi-line prompt for TRAMP (see `tramp-terminal-type').
        # Don't confuse it!
        PS1="\n> "
        ;;
    cygwin|xterm*|rxvt-unicode)
        # `M-x shell' under Cygwin Emacs.
        # `M-x term' under Cygwin Emacs.
        BEL=$(tput bel)
        PS1='\[\033]0;Bash $PWD\007\]\n\
$(st=$?; if [[ $st -eq 0 ]]; then printf "\[\033[01;32m\]"; else printf "\[\033[01;31m\]$BEL\\u00d7 $st "; fi)\
\[\033[0;34m\]\u@\h\
\[\033[1;30m\]:\
\[\033[0;33m\]\w\
\[\033[36m\]$(git_branch)\
\[\033[1;32m\]>\[\033[0m\] '

# PS1='\[\033]0;$TITLEPREFIX:$PWD\007\]\n\[\033[32m\]\u@\h \[\033[35m\]$MSYSTEM \[\033[33m\]\w\[\033[36m\]`git_branch`\[\033[0m\]\n$ '


        ;;
    *) # emacs
        # `M-x shell' under EmacsW32.
        PS1="\n$?\u@\h:\w \$ "
        ;;
esac
# PS1+='$(if test $? -ne 0; then tput bel; fi)'
export PS2="incomplete? continue here-> "
# PS4 --- Used by "set -x" to prefix tracing output

# Get line numbers when you run with `-x'.
PS4='+'$grn'[$0:$LINENO]+ '${reset_color}

Getting Help

In Zsh, M-h shows the manual page for the current command, if one exists. The Zsh way of doing things is much, much nicer than typing the man command…

Add this functionality to the Bash shell:

# M-h: run-help.
bind '"\eh": "\C-a\eb\ed\C-y\e#man \C-y\C-m\C-p\C-p\C-a\C-d\C-e"'

Syntax Highlighting

Autosuggestions

Tab Completions

# Ignore case while completing filenames.
bind "set completion-ignore-case on"

# Treat hypens and underscores as the same if completion-ignore-case is on.
bind "set completion-map-case on"

Program specific completions:

  • The programs man and whatis show all installed manual pages as completions.
  • The make program uses all targets in the Makefile in the current directory as completions.
  • The mount command uses all mount points specified in fstab as completions.
  • The ssh command uses all hosts that are stored in the known_hosts file as completions. (See the ssh documentation for more information)
  • The su command uses all users on the system as completions.
  • The apt, rpm and yum commands use all installed packages as completions.
complete -A helptopic help
complete -A hostname ssh telnet nmap ftp ping host traceroute nslookup

Changing Working Directory

# When entering a directory, push it to the directory stack and list its
# contents.
cd() {
    builtin pushd "$@" > /dev/null      # = setopt auto_pushd, in Zsh.
    dirs_remove_dups                    # = setopt pushd_ignore_dups, in Zsh.
    ls --color=auto -F
}

# Remove dups.
dirs_remove_dups() {
    declare -a new=() copy=("${DIRSTACK[@]:1}")
    declare -A seen
    local v i
    seen[$PWD]=1
    for v in "${copy[@]}"; do
        if [ -z "${seen[$v]}" ]; then
            new+=("$v")
            seen[$v]=1
        fi
    done
    dirs -c
    for ((i=${#new[@]}-1; i>=0; i--)); do
        builtin pushd -n "${new[i]}" > /dev/null
    done
}

Functions

Variables

PATH variables

Special variables

# Allow Meta (Alt) key bindings [line added to the top of my `.inputrc'].
bind "set convert-meta on"

# Don't strip characters to 7 bits when reading (permit UTF-8).
bind "set input-meta on"

# Denote symlinks to directories with an appended slash.
bind "set mark-symlinked-directories on"

# Do not autocomplete hidden files unless the pattern begins with a dot.
bind "set match-hidden-files off"

# Display characters with the 8th bit set directly rather than as meta-prefixed
# characters (permit UTF-8).
bind "set output-meta on"

Completions:

# # Show all autocomplete results at once instead of via the internal pager.
# bind "set page-completions off"

# Make first press of TAB list all matches (in case multiple possible
# completions are possible).
bind "set show-all-if-ambiguous on"

# bind "set menu-complete-display-prefix on"


bind "set show-all-if-unmodified on"

# Color the common prefix
bind "set colored-completion-prefix on"

# Color the common prefix in menu-complete
bind "set menu-complete-display-prefix on"

# Note that this may cause completion text blink in some terminals (e.g. xterm).
bind "set colored-stats on"


# Factor any text after the cursor position into completion matching.
bind "set skip-completed-text on"

# Show extra file information when completing similar to `ls -F`.
bind "set visible-stats off"
# Automatically cd into a  directory without the `cd' in front of it.
shopt -s autocd

# Correct dir spellings.
shopt -s cdspell

# Make sure display get updated when terminal window get resized.
shopt -q -s checkwinsize

Locale variables

History

Access and modify commands that you had previously typed at the command line.

# When running two Bash windows, allow both to write to the history.
shopt -s histappend

# Make multi-line commands 1 line in history.
shopt -q -s cmdhist
# Set the in-memory history size.  This controls the number of commands
# available for the current session.
export HISTSIZE=5000

# Set the on-disk history size.  This controls the number of commands stored in
# the history file.
export HISTFILESIZE=$HISTSIZE
# Set the history timestamp format to ISO8601 (yyyy-mm-dd hh:mm).
export HISTTIMEFORMAT="%Y-%m-%d %H:%M  "

# Exclude common navigation and administrative commands from history.
export HISTIGNORE="ls:cd:pwd:clear:history:exit:top:df"

Prefix a command with a space to hide it from history (suitable for sensitive information like passwords):

# Ignore duplicate commands and commands starting with spaces.
HISTCONTROL=ignoreboth:erasedups

ignoredups, implied by ignoreboth, doesn’t add a command to history if it’s the same as the immediate previous command. It doesn’t look further back in history.

A value of erasedups causes all previous lines matching the current line to be removed from the history list before that line is saved.

See also Preserve bash history in multiple terminal windows to keep Bash history in sync between multiple terminals.

Le ! en shell permet plein de trucs sympa.

  • !! refait la dernière commande
  • !cmd refait la dernière commande commençant par cmd
  • !cmd:p permet de visualiser sans éxecuter la dernière commande commençant par cmd
  • !$ est le dernier mot de la ligne de commande précédente
  • !cmd:$ est le dernier mot du dernier ligne de commande commençant par cmd
  • !* est l’ensemble de la dernière ligne de commande à part le premier mot

See also http://dvorka.github.io/hstr/ to easily view, navigate and search your command history with shell history suggest box.

alias h="history"

Key Bindings (Command line editor)

The .inputrc file controls the behavior of the command line editor for programs that use the Gnu Readline library. Existing programs include FTP, Bash, and Gdb.

See https://code.google.com/p/mintty/wiki/Tips#Readline_configuration.

By default, Bash uses Emacs style keyboard shortcuts when editing (C-a, C-e, etc.). Check your active Bash keymap with:

bind -v | grep editing-mode
bind -v | grep keymap

View all the readline variables with bind -v.

List both the keybindings and the corresponding function name with bind -p.

The key bindings can also be part of .bashrc (by adding single quotes).

  • Tab completes the current token. Shift, Tab completes the current token and starts the pager’s search mode.
  • Alt+?,Left and Alt+?,Right move the cursor one word left or right (to the next space or punctuation mark), or moves forward/backward in the directory history if the command line is empty. If the cursor is already at the end of the line, and an autosuggestion is available, Alt+?,Right (or Alt+F) accepts the first word in the suggestion.
  • Shift,?,Left and Shift,?,Right move the cursor one word left or right, without stopping on punctuation.
  • ? (Up) and ? (Down) (or Control+P and Control+N for emacs aficionados) search the command history for the previous/next command containing the string that was specified on the commandline before the search was started. If the commandline was empty when the search started, all commands match. See the history section for more information on history searching.
  • Alt+?,Up and Alt+?,Down search the command history for the previous/next token containing the token under the cursor before the search was started. If the commandline was not on a token when the search started, all tokens match. See the history section for more information on history searching.
  • Control+C cancels the entire line.
  • Control+U moves contents from the beginning of line to the cursor to the killring.
  • Control+W moves the previous path component (everything up to the previous “/”, “:” or “@”) to the killring.
  • Control+X copies the current buffer to the system’s clipboard, Control+V inserts the clipboard contents.
  • Alt+d moves the next word to the killring.
  • Alt+h (or F1) shows the manual page for the current command, if one exists.
  • Alt+l lists the contents of the current directory, unless the cursor is over a directory argument, in which case the contents of that directory will be listed.
  • Alt+w prints a short description of the command under the cursor.

Emacs mode commands

  • Home or Control+A moves the cursor to the beginning of the line.
  • End or Control+E moves to the end of line. If the cursor is already at the end of the line, and an autosuggestion is available, End or Control+E accepts the autosuggestion.
  • ? (Left) (or Control+B) and ? (Right) (or Control+F) move the cursor left or right by one character. If the cursor is already at the end of the line, and an autosuggestion is available, the ? (Right) key and the Control+F combination accept the suggestion.
  • Control+K moves contents from the cursor to the end of line to the killring.
  • You can change these key bindings using the bind builtin.

Commands For Moving

# Set <C-left/right> to move by whole words.
bind '"\e[1;5C": forward-word'
bind '"\e[1;5D": backward-word'

Commands For Manipulating The History

# Very nice history search.  Type text (as prefix) and hit up <up/down> to
# search witin command history (no C-r required).
bind '"\e[B": history-search-forward'
bind '"\e[A": history-search-backward'

Commands For Changing Text

# Set Delete/Insert keys to delete/insert chars on line
bind '"\e[3~": delete-char'
bind '"\e[2~": quoted-insert'

Commands For Killing And Yanking

Numeric Arguments

Commands For Completion (Letting Readline Type For You)

# Make each subsequent press of TAB cycle through matches.
bind '"\t": menu-complete'

Keyboard Macros

Miscellaneous Commands

https://www.gnu.org/software/bash/manual/html_node/Bindable-Readline-Commands.html#Bindable-Readline-Commands

This makes M-p (see Fish) append  | less to the line and run it:

bind '"\ep": "\C-e | less\C-m"'

M-s prefixes the current commandline with sudo .

bind '"\es": "\C-asudo \C-e\C-m"'

Others:

Control-o: “> output” C-o is bound to run the macro expressed on the right hand side (that is, to insert the text “> output” into the line)

“\C-k”: kill-whole-line

Key bindingMeaning
M-?Execute the command which cmd where cmd is the current command; similar to which-command in Zsh
bind '"\e?": "\C-awhich \C-m"' # TODO: Ré-écire cmd sur la ligne suivante
# See this example: bind '"\eh": "\C-a\eb\ed\C-y\e#man \C-y\C-m\C-p\C-p\C-a\C-d\C-e"'

FZF Key bindings for command line

  • CTRL-T - Paste the selected files and directories onto the command line Set FZF_CTRL_T_COMMAND to override the default command Set FZF_CTRL_T_OPTS to pass additional options
  • CTRL-R - Paste the selected command from history onto the command line If you want to see the commands in chronological order, press CTRL-R again which toggles sorting by relevance Set FZF_CTRL_R_OPTS to pass additional options
  • ALT-C - cd into the selected directory Set FZF_ALT_C_COMMAND to override the default command Set FZF_ALT_C_OPTS to pass additional options
bind '"\ee": edit-and-execute-command'
bind '"\ev": edit-and-execute-command'
# Same as C-x C-e.
# C-M-u: up-directory
bind '"\e\C-u": "cd ..\n"'

Zsh Configuration

:header-args+: :tangle .zshrc_leuven

Documentation: Zsh Reference Card.

Examples:

# Hey Emacs, this is a -*- sh -*- file
## .zshrc --- Zsh configuration file (for interactive shells)

# Copyright (C) 2009-<<current-year()>> Fabrice Niessen

# Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
# Keywords: zsh, dotfile, config

# Code:

Startup (Where are Leuven customizations?)

Your .zshrc file might resemble the following configuration:

# Source local shell customizations.
source_local_file() {
    local file="$HOME/$1"
    if [ -f "$file" ]; then
        source "$file"
    fi
}

source_local_file ".shellrc_leuven" # Source Leuven shell customizations.
source_local_file ".zshrc_leuven" # Source Leuven Zsh customizations.

# Ready for more (from other Leuven repositories)?
# Load rc-<something> scripts for Zsh.
setopt NULL_GLOB
rcfiles=(~/bin/rc-{zsh,common}-*)
if [ ${#rcfiles[@]} -gt 0 ]; then
    for rcfile in "${rcfiles[@]}"; do
        source "$rcfile"
    done
fi

Colors

Stderr in red

Wrap text that goes to file with descriptor 2 with proper ANSI escape codes, making text red.

# Color stderr.
zmodload zsh/system
color_stderr_red() {
    # Sysread & syswrite are part of `zsh/system'.
    emulate -LR zsh
    local stderr_red_esc_code=$'\e[37;1;41m'
    while sysread; do
        syswrite -o 2 "${stderr_red_esc_code}${REPLY}$terminfo[sgr0]"
    done
}

# Redirect stderr to color_stderr_red function.
exec 2> >(color_stderr_red)

Prompt

# # Don't inherit the value of PS1 from the previous shell (Zsh from Bash).
# PS1=$'%{\e]0;%d\a%}\n%F{grn}%n@%m %F{yel}%d%f\n%# '

Zsh expects that every character in PS1 will advance the cursor one space. Wrap any non-printing escape sequences in %{...%}, and it should work. So use %{\e[31m%}, etc.

Define colors using terminfo See http://superuser.com/questions/239290/how-can-i-make-zsh-show-that-there-are-stashed-revisions-on-a-git-repo-wheneverEND

For the prompt, the tricky part was getting the syntax for testing the exit code. The syntax is %(x.true-string.false-string), where x is some arbitrary testing condition, in this case, ? for exit codes. After the first dot, if the test passes, show true-string; if it fails, show false-string after the second dot.

# Enable Git information in the command prompt.
autoload -Uz vcs_info
precmd_vcs_info() {
    vcs_info
}
precmd_functions+=( precmd_vcs_info )
setopt PROMPT_SUBST                     # Allow parameter expansion in prompt.
zstyle ':vcs_info:git:*' formats ' %F{cyan}(%b)%f'
zstyle ':vcs_info:*' enable git
# Set the command prompt with Git information.
PROMPT="
%B%(?.%F{green}.%F{red}$(tput bel)"$'\u00d7'" %? )%f%b%F{blue}%n@%m%F{black}%B:%b%F{yellow}%~%f\$vcs_info_msg_0_%B%F{green}%(!.#.>)%f%b "
                                        # ? - Exit code of the previous command.
                                        # n - User name.
                                        # m - Machine name.
                                        # . - Abbreviated pwd.
                                        # ! - su?

One of the hardest things is to set the terminal window title “correctly”. Here is what I currently use:

set_terminal_title_and_prompt() {
    local term=${TERM:-dumb}
    if [[ "$term" == "xterm"* || "$term" == "rxvt"* ]]; then
        precmd() {
            print -Pn "\e]0;%m: %~\a"
        }
        preexec() {
            local match
            match=${(q)1//(#m)[$'\000-\037\177-']/${(q)MATCH}}
            print -n "\e]0;Zsh $HOST: $match\a"
        }
    fi
}

set_terminal_title_and_prompt

Insert beep when last command has failed.

BEL=$(tput bel)
PROMPT+='%(?::$BEL)'

To get a blank line /after/ each output, you can simply write a function to echo a blank line and add it to your precmd hooks.

Technically, it doesn’t insert a line after each commands output, but inserts a blank line before building the prompt. However, the end result is the same.

echo_blank() {
    print ""
}

precmd_functions+=echo_blank

Don’t confuse TRAMP:

if [[ "$TERM" = "dumb" ]]; then
    PROMPT="> "
    RPROMPT=""
fi

Add a new theme: Solarized

Karlin Fox ported the Solarized theme to MinTTY (the terminal which comes by default with Cygwin), and it is available at karlin/mintty-colors-solarized.

git clone https://github.com/karlin/mintty-colors-solarized.git \
    "$HOME"/.dotfiles/plugins/mintty-colors-solarized
FILE="$HOME"/.dotfiles/plugins/mintty-colors-solarized/mintty-solarized-dark.sh && test -f "$FILE" && . "$FILE"

# XXX Check for MinTTY
if [[ -d /cygdrive/c/ ]]; then
    echo -ne '\e]4;8;#404040\a'     # bold blk
    echo -ne '\e]4;9;#FF4040\a'     # bold red
    echo -ne '\e]4;10;#40FF40\a'    # bold grn
    echo -ne '\e]4;11;#FFFF40\a'    # bold yel
    echo -ne '\e]4;12;#6060FF\a'    # bold blu
    echo -ne '\e]4;13;#FF40FF\a'    # bold mag
    echo -ne '\e]4;14;#40FFFF\a'    # bold cyn
    echo -ne '\e]4;15;#FFFFFF\a'    # bold wht
fi

https://github.com/oumu/mintty-color-schemes https://github.com/mintty/mintty/wiki/Tips http://mintty.github.io/mintty.1.html#CONFIGURATION https://stackoverflow.com/questions/24229406/how-to-get-vim-on-cygwin-to-display-right-colors

See great (more portable) stuff at https://github.com/jimeh/git-aware-prompt/blob/master/colors.sh!

Install Powerline-patched fonts

Powerline patched versions of the most popular mono fonts are available at powerline/fonts.

Make sure to change the font of MinTTY:

  • Right click the title bar of the Terminal, click Options.
  • Change your font to a Powerline patched font you installed.

Test if UTF-8 characters are correctly rendered:

# Print a sequence of UTF-8 characters to the console to test if they are
# correctly rendered.
echo "\ue0b0 \u00b1 \ue0a0 \u27a6 \u2718 \u26a1 \u2699"

Good-looking fonts:

  • UbuntuMono
  • DejaVuSansMono
  • DroidSansMono (bad?)

For Consolas, use: https://github.com/runsisi/consolas-font-for-powerline.

Install “Oh My Zsh”

Oh My Zsh is just awesome!

git clone https://github.com/ohmyzsh/ohmyzsh.git ~/.oh-my-zsh
if [[ -r "$HOME"/.oh-my-zsh ]]; then
    ZSH="$HOME"/.oh-my-zsh
    ZSH_CUSTOM="$ZSH/custom"

    HIST_STAMPS="yyyy-mm-dd"            # See command `history'.

    COMPLETION_WAITING_DOTS="true"
fi

http://marc-abramowitz.com/archives/2012/04/10/fix-for-oh-my-zsh-git-svn-prompt-slowness/

Change the Oh My Zsh theme to “agnoster”

#

Agnoster Theme Adaption for SVN

# if [[ -r "$ZSH" ]]; then
#     prompt_svn() {
#         local rev branch
#         if in_svn; then
#             rev=$(svn_get_rev_nr)
#             branch=$(svn_get_branch_name)
#             if [[ $(svn_dirty_choose_pwd 1 0) -eq 1 ]]; then
#                 prompt_segment yel blk
#                 echo -n "$rev@$branch"
#                 echo -n " ±"
#             else
#                 prompt_segment grn blk
#                 echo -n "$rev@$branch"
#             fi
#         fi
#     }
# fi

Install Zinc (successor of Powerlevel9k!)

git clone https://gitlab.com/robobenklein/zinc \
    "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}"/themes/zinc
if [[ -r "$HOME"/.dotfiles/plugins/oh-my-zsh/custom/themes/zinc/zinc.zsh ]]; then
    ZSH_THEME=""
    source "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}"/themes/zinc/zinc.zsh

    zinc_default_user="f.niessen"
    zinc_default_host="XIPHIAS"

    # Input your own strftime format: http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html
    zincs_time() {
        REPLY="%D{%H:%M}"
    }

    prompt_zinc_setup fniessen-p9k-port

    prompt_zinc_setup rprompt-previous-line

fi

# # either user and host separate with CONNECT_PREV
# # or zincs_userhost
# zinc_left=(
#   # zincs_user
#   # zincs_host
#   zincs_userhost
#   zincs_cwd
#   zincs_vcs
# )
#
# zinc_right=(
#   zincs_retval
#   zincs_execution_time
#   my_custom_time
#   zincs_jobs
# )
#
# zinc_opts=(
#   zincs_user "white;black;CONDITIONAL;normal"
#   zincs_host "white;black;CONNECT_PREV+CONDITIONAL;normal"
#   zincs_userhost "white;black;CONDITIONAL;normal"
# )
#
# # autohide the user when it's default
# zincs_user_display_hidden() {
#   [[ "$USER" == "$zinc_default_user" ]] && true || false
# }
# zincs_host_display_hidden() {
#   [[ "$HOST" == "$zinc_default_host" ]] && true || false
# }
#
# # or show both when either changes:
# zincs_userhost_display_hidden() {
#   [[ "$HOST" == "$zinc_default_host" ]] && [[ "$USER" == "$zinc_default_user" ]] && true
# }
#
# # set the time format option:
# # http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html
# my_custom_time() {
#   REPLY="%T"
# }
#
# # set the zincs_execution_time min time:
# zincs_execution_time[threshold]=10

Alternative to Zinc: Pure

https://github.com/sindresorhus/pure

Plugins

if [[ -r "$HOME"/.dotfiles/plugins/oh-my-zsh ]]; then
    plugins=(
        colored-man-pages
        extract
        # git                           # Provide many aliases and a few useful functions.
        history
        history-substring-search
        # svn
    )
fi

Colored man pages plugin

if [[ -r "$HOME"/.dotfiles/plugins/oh-my-zsh ]]; then
    # Fix Colorize man pages (with `less` pager) not working in Cygwin MinTTY
    export MANROFFOPT="-c"
    # in your shell rc file. This has the same effect as
    # export GROFF_NO_SGR=1               # For konsole and gnome-terminal.
    # but only affects man. I'm not sure if groff is used for anything else
    # besides man pages, but this seems safer to prevent unintended side
    # effects.
fi

Syntax Highlighting

Besides the syntax highlighting for your shell, this plugin has the capability to verify the correctness of your command.

git clone https://github.com/zsh-users/zsh-syntax-highlighting.git \
    "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}"/plugins/zsh-syntax-highlighting
if [[ -r "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ]]; then
    plugins+=(zsh-syntax-highlighting)
fi

Autosuggestions

Zsh suggests commands based on your command history.

To accept the autosuggestion, hit (right arrow) or Ctrl-F.

git clone https://github.com/zsh-users/zsh-autosuggestions \
    "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}"/plugins/zsh-autosuggestions
if [[ -r "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]]; then
    plugins+=(zsh-autosuggestions)
fi

Load Zsh tools

if [[ -r "$HOME"/.dotfiles/plugins/oh-my-zsh ]]; then
    . "$ZSH"/oh-my-zsh.sh
fi
# Autosuggestions.
if [[ -r "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]]; then
    ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=5'
fi

Tab Completions

# Enable menu select (some kind of graphical menu)
zstyle ':completion:*' menu select

# Extensions to completion listings:
# - ability to highlight matches in such a list,
# - ability to scroll through long lists and
# - different style of menu completion.
zmodload zsh/complist

XXX See Re: completion: highlight matching part for better highlighting:

autoload -U colors ; colors
zstyle -e ':completion:' list-colors 'thingy=${PREFIX##/} reply=( "=(#b)($thingy)(?)*=00=$color[green]=$color[bg-green]" )'

Changing Working Directory

# When entering a directory, push it to the directory stack and list its
# contents.
setopt auto_pushd
setopt pushd_ignore_dups

cd() {
    builtin cd "$@" > /dev/null
    ls --color=auto -F
}

Functions

Variables

PATH variables

Special variables

Changing Directories

setopt AUTO_CD                  # Change directory given just path.

Completion

Zsh will attempt to complete wildcards by expanding them in the command line.

# Load general completion.
autoload -Uz compinit

# Start the Zsh completion system.
compinit -i                     # Silently ignore all insecure files and directories.

How to fix “zsh compinit: insecure directories”? Stripping these directories of the group write permission:

compaudit | xargs chmod g-w

will do the trick, see zsh, Cygwin and Insecure Directories.

setopt AUTO_LIST                # Automatically list choices on an ambiguous completion.

# setopt always_to_end            # when completing from the middle of a word, move the cursor to the end of the word
# setopt auto_menu                # show completion menu on successive tab press. needs unsetop menu_complete to work
# setopt auto_name_dirs           # any parameter that is set to the absolute name of a directory immediately becomes a name for that directory
# unsetopt auto_name_dirs         # do not set auto_name_dirs because it messes up prompts
# setopt complete_in_word         # allow completion from within a word/phrase
# setopt auto_list                # automatically list choices on ambiguous completion.
# unsetopt completealiases        # an alias of a command should complete to the command completion
# unsetopt menu_complete          # do not autoselect the first completion entry
# unsetopt flowcontrol            # do not freezes output to the terminal until you type ^q

20. Completion System

# Small and capital letters will match small and capital letters only if there
# are no case-sensitive matches.
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}'

See also https://superuser.com/questions/1092033/how-can-i-make-zsh-tab-completion-fix-capitalization-errors-for-directorys-and.

Launch Windows applications from CLI (with start script – see babun/babun#299 (comment)):

# compdef '_files -g "*"' start

Expansion and Globbing

setopt EXTENDED_GLOB            # Use additional pattern matching features.
setopt NOMATCH                  # Unmatched patterns cause an error.

Job Control

setopt NOTIFY                   # Immediately report changes in background job status.

Zle

Zsh has its own line editor (ZLE) and doesn’t read readline’s .inputrc.

# Beep when there's an error with the command text you're typing in (e.g. if you
# hit tab and there are no matching files) -- not as a result of normal commands
# returning errors.
setopt BEEP

Make Zsh forward-word behavior same as in Bash / Emacs, where only alphanumeric characters are considered word characters:

autoload -U select-word-style
select-word-style bash

Locale variables

History

HISTFILE=~/.zsh_history         # Zsh doesn't save the history to a file by default.
HISTSIZE=10000                  # In memory.
SAVEHIST=$HISTSIZE              # To file.
setopt APPEND_HISTORY           # Append rather than overwrite history file.
setopt EXTENDED_HISTORY         # Save timestamp and runtime information.
setopt HIST_EXPIRE_DUPS_FIRST   # Allow dups, but expire old ones when I hit HISTSIZE.
setopt HIST_FIND_NO_DUPS        # Don't find duplicates in history.
setopt HIST_IGNORE_ALL_DUPS     #! Ignore duplicate commands regardless of commands in between.
setopt HIST_IGNORE_DUPS         # Ignore duplicate commands.
setopt HIST_REDUCE_BLANKS       # Leave blanks out.
setopt HIST_SAVE_NO_DUPS        # Don't save duplicates.

setopt INC_APPEND_HISTORY       # Write after each command.
setopt SHARE_HISTORY            # Share history between sessions.
# Print full time-date stamps in ISO8601 `yyyy-mm-dd hh:mm' format, and all entries.
alias history="history -i 0"
alias h="history -i 0"

Key Bindings (Command line editor)

10.4 Some interesting keybindings

Key bindingMeaning
M-=complete + EOF
C-kkill line
C-ukill while line (kill-ring)
C-wcopy last word (kill-ring) OR delete last word?
C-yyank (insert kill-ring)
<tab>complete and take first result
C-_undo
M-?which-command
M-’quote-line (”)
esc-qpush line

Useful keybindings of the Zsh command line editor:

M-q
Type another command in the middle of a long command (look at man, etc.): you can push the current command to the buffer stack, and after executing another command, you can see the top of the stack popped.
C-r
Do an interactive search across all of the command history.

Useful commands:

vared VAR
Interactively edit variable VAR.

Run bindkey to get a listing of currently active keybindings.

For a more general approach you start your terminal, press C-v followed by the key combination you want the escape code (the name) of, and put the output for each key combination in between the two quotes.

# Use Emacs keybindings.
bindkey -e

Commands For Moving

Key bindingMeaning
C-aMove to the beginning of the current line
C-eMove to the end of the current line
C-lClear the screen
# Move by whole words.
bindkey '\e[1;5C' forward-word          # <C-right>
bindkey '\e[1;5D' backward-word         # <C-left>

Commands For Manipulating The History

# Search matching commands from the history.
bindkey '\e[A' history-beginning-search-backward # <up>
bindkey '\e[B' history-beginning-search-forward  # <down>
Key bindingMeaning
M-.Insert the last argument of the previous command (and so on); similar to typing !$

Bonus Tip

In Bash, there are some great but lesser-known default bindings. You may know that M-. will insert the last argument of the previous command (e.g. running ls ~/Desktop and then typing cd and pressing M-. will turn it into cd ~/Desktop), but did you know you can actually yank the argument at any index from the last command (without using history or ! operators)?

Just press M-[#], where # is the position of the argument you want, then type M-. to insert it in the current command.

Commands For Changing Text

bindkey "\e[3~" delete-char             # <delete>

# Make Zsh beep like Bash when backspacing on empty line.
backward-delete-char-beep() {
    if (( CURSOR == 0 )); then
        zle beep
    fi
    zle backward-delete-char
}
zle -N backward-delete-char-beep
bindkey "^?" backward-delete-char-beep  # <backspace>

Commands For Killing And Yanking

Numeric Arguments

Commands For Completion (Letting the Z-Shell Line Editor Type For You)

Key bindingMeaning
M-=List the possible completions of the text before point; similar to possible-completions in Bash
# Display possible completions for the current word.
bindkey '\e=' list-choices

Keyboard Macros

Miscellaneous Commands

Key bindingMeaning
M-eEdit the current command line in an external editor ($VISUAL or $EDITOR); similar to the fc (“fix command”) shell built-in
M-vSame as M-e
C-x C-eSame as M-e; default in Bash
M-%Replace string
C-M-uGo up one directory (automatic “cd ..”)
M-sPrepend “sudo ” to the current command line

From Dan Davison: bindkey ‘^W’ kill-region

# Replace string.
autoload -U replace-string
zle -N replace-string
bindkey "\e%" replace-string
# Edit command line.
autoload edit-command-line
zle -N edit-command-line
bindkey "\ee"      edit-command-line
bindkey "\ev"      edit-command-line
bindkey "\C-x\C-e" edit-command-line
# M-s: prepend-sudo
prepend_sudo() {
    zle beginning-of-line
    zle -U "sudo "
}
zle -N prepend-sudo prepend_sudo
bindkey '\es' prepend-sudo

M-p (see Fish) appends the string ” | less” to the current command. The result is that the output of the command will be paged.

# Append " | less" to command
append_less() {
    zle end-of-line
    zle -U " | less"
}
zle -N append-less append_less
bindkey '\ep' append-less               # M-p.
# From https://github.com/romkatv/zsh4humans
# Widgets for changing current working directory.
z4h-redraw-prompt() {
    emulate -L zsh
    local f
    for f in chpwd $chpwd_functions precmd $precmd_functions; do
        (( $+functions[$f] )) && $f &>/dev/null
    done
    zle .reset-prompt
    zle -R
}

# C-M-u: up-directory
up-directory() {
    builtin cd .. && z4h-redraw-prompt
}
zle -N up-directory
bindkey '\e\C-u' up-directory

bindkey -s l ” | less -M -e ” #l bindkey -s XXX ” | xargs ” #x bindkey -s ? ” | grep -i ” #g bindkey -s XXX ” | column -t ” #m

bindkey -s XXX ” | tr ‘\n’ ’ ’ ” #t or p bindkey -s XXX ” | cut -d ’ ’ -f ” #c bindkey -s ? ” | xclip -in ” #i bindkey -s XXX ” xclip -out ” #o bindkey -s d ” find -iname ‘**’ ” #f #see drop() #bindkey -s ” | ”

Abbreviations (aliases)

Some global aliases (expand whatever their position).

alias -g 21="2>&1"                      # Redirect.
alias -g A='| awk'                      # "awk pipe".
alias -g BG='& exit'                    # "bgexit".
alias -g CA="| cat -A"                  # "catA" (Display line endings and tab characters).
alias -g F='| fmt -' ##                 # "Fmt" (Format the output to fit within a specified width).
alias -g G='| grep --color=auto -E' ###### # "Grepe" (Search for pattern in the output).
alias -g H='| head' ###
alias -g J='| jq -C .'
alias -g L="| less" #######
alias -g N='> /dev/null'                # "Null".
alias -g NN='> /dev/null 2>&1'          # "Nullout".
alias -g S='| sort' ###
alias -g T='| tail' ###
alias -g U='| uniq'
alias -g W='| wc -l' ####               # "Wcl" (Count the number of lines in the output).
alias -g X='| xargs'
alias -g XL='| tr "\n" "\0" | xargs -0'
alias -g X1='| xargs -n 1'

# Count and sort
alias -g CS='sort | uniq -c | sort -k1,1nr'

Intuitive Map function (to process a list of items separated by newline characters):

alias -g Map="| tr '\n' '\0' | xargs -0 -n 1"

For example, to list all directories that contain a certain file:

find . -name .git Map dirname
alias -g A1="| awk '{print \$1}'"
alias -g A2="| awk '{print \$2}'"
alias -g A3="| awk '{print \$3}'"
alias -g A4="| awk '{print \$4}'"
alias -g A5="| awk '{print \$5}'"
alias -g A6="| awk '{print \$6}'"
alias -g A7="| awk '{print \$7}'"
alias -g A8="| awk '{print \$8}'"
alias -g A9="| awk '{print \$9}'"
alias -g ,1="| awk -F, '{print \$1}'"
alias -g ,2="| awk -F, '{print \$2}'"
alias -g ,3="| awk -F, '{print \$3}'"
alias -g ,4="| awk -F, '{print \$4}'"
alias -g ,5="| awk -F, '{print \$5}'"
alias -g ,6="| awk -F, '{print \$6}'"
alias -g ,7="| awk -F, '{print \$7}'"
alias -g ,8="| awk -F, '{print \$8}'"
alias -g ,9="| awk -F, '{print \$9}'"
alias -g C1="| awk -F';' '{print \$1}'"
alias -g C2="| awk -F';' '{print \$2}'"
alias -g C3="| awk -F';' '{print \$3}'"
alias -g C4="| awk -F';' '{print \$4}'"
alias -g C5="| awk -F';' '{print \$5}'"
alias -g C6="| awk -F';' '{print \$6}'"
alias -g C7="| awk -F';' '{print \$7}'"
alias -g C8="| awk -F';' '{print \$8}'"
alias -g C9="| awk -F';' '{print \$9}'"
alias -g :1="| awk -F: '{print \$1}'"
alias -g :2="| awk -F: '{print \$2}'"
alias -g :3="| awk -F: '{print \$3}'"
alias -g :4="| awk -F: '{print \$4}'"
alias -g :5="| awk -F: '{print \$5}'"
alias -g :6="| awk -F: '{print \$6}'"
alias -g :7="| awk -F: '{print \$7}'"
alias -g :8="| awk -F: '{print \$8}'"
alias -g :9="| awk -F: '{print \$9}'"
alias -g T1="| awk -F $'\t' '{print \$1}'"
alias -g T2="| awk -F $'\t' '{print \$2}'"
alias -g T3="| awk -F $'\t' '{print \$3}'"
alias -g T4="| awk -F $'\t' '{print \$4}'"
alias -g T5="| awk -F $'\t' '{print \$5}'"
alias -g T6="| awk -F $'\t' '{print \$6}'"
alias -g T7="| awk -F $'\t' '{print \$7}'"
alias -g T8="| awk -F $'\t' '{print \$8}'"
alias -g T9="| awk -F $'\t' '{print \$9}'"

Git

Git this week / month / year:

alias -g Gitthisweek=' --since=1.week.ago'
alias -g Gitthismonth=' --since=1.month.ago'
alias -g Gitthisyear=' --since=1.year.ago'

Shell agnostic Configuration

:header-args+: :tangle .shellrc_leuven

.shellrc contains miscellaneous settings common to Bash and Zsh – it is read by both shells.

# Hey Emacs, this is a -*- sh -*- file
## .shellrc --- Shell agnostic configuration file

# Copyright (C) 2009-<<current-year()>> Fabrice Niessen

# Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
# Keywords: bash, zsh, dotfile, config
# Print the kernel name, the hostname, the kernel release and the machine
# hardware name.
uname -s -n -r -m

Functions

Deal with fatal errors

The exit status follows the conventions for programs such as grep, cmp, and diff: it is 2 (or greater) if an error occurred.

# Define a shell function to log an error message, print an error message to
# stderr, and exit with a non-zero status code.
function die() {
    local message="${1:-Unknown error}"
    logger "$message"
    printf >&2 '%s: Fatal error: %s\n' "$(basename "$0")" "$message"
    exit 2
}

Die must be a function so that the calling script does exit with an error.

command || die "Something happened"

Check if a command exists

To find out if a given command exists (in the user’s PATH), don’t use which (because it is not in POSIX so its output format is unspecified, and it complains when nothing is found instead of being silent):

if $(which ag > /dev/null 2>&1); then alias grep='ag'; fi

Instead use:

command_exists() {
    if ! command -v "$1" > /dev/null 2>&1; then
        printf >&2 "Error: '%s' command not found.\n" "$1"
        return 2
    fi
}
command_exists ag && alias grep='ag'

See also https://unix.stackexchange.com/questions/85249/why-not-use-which-what-to-use-then.

# zombies - list all zombies and their parents to kill
zombies() {
  ps f -eo state,pid,ppid,comm | awk '
    { cmds[$2] = $NF }
    /^Z/ { print $(NF-1) "/" $2 " zombie child of " cmds[$3] "/" $3 }'
}

# null - throw away input
null() {
    LC_ALL=C tr -cd ''
}

# absolute [FILE...] - print absolute file name/PWD
# 18oct2016  +chris+  also abspath
# 18nov2016  +chris+  print hostname to tty when logged in via ssh
absolute abspath () {
  [[ -n "$SSH_CONNECTION" ]] && [[ -t 1 ]] && local prefix="$(hostname -f):"
  print -l $prefix${^${@:-$PWD}:a}
}

# homediff FILE
homediff() {
  diff -u "${1?no file given}" <(curl -sL http://leahneukirchen.org/dotfiles/$1)
}

# ssh-copy-term - copy terminfo via ssh
ssh-copy-term() {
  infocmp $TERM | ssh "$@" 't="$(mktemp)" && cat >"$t" && tic -s "$t"'
}

# cppgrep - grep in C/C++ headers
cppgrep() {
  printf '#include "%s"' "$@[2,-1]" | gcc -E -M -MP -x c++ - |
    awk -F: '/:$/ {print $1}' | xe -N0 grep -nP "$1"
}

# crustdiff - diff of uncrustify result
crustdiff() {
    for f; uncrustify -f $f | diff -u $f -
}

# crustdiff - diff of perltidy result
perltidydiff() {
    for f; perltidy < $f | diff -u --label $f --label $f $f -
}

# ltime - start and run time of last commands
# 05feb2018  +leah+  use tail -n
ltime() {
    fc -liDI | tail -n ${1:-10}
}

# zapply [-jN] [-iv] CMD... -- ARGS... - run up to N CMD in parallel with ARGS
#   CMD will be run as zsh command if it contains a $
#   without explicit '--', assume CMD is first argument
#   {} (or $1) may be used to access argument
zapply() {
  local s="$@[(i)--]" xopt=
  (( s > $# )) && argv[2]=(-- "$argv[2]") && s=2
  zparseopts -D -M -A xopt n: p t P: j:=P v=t i=p   # map to xargs(1) flags
  (( $@[(i){}] < s )) && xopt[-I]={}
  [[ $1 = *'$'* ]] && argv[1]=(zsh -c "$1" --) && (( s += 3 ))
  printf '%s\0' "$@[s+1,-1]" | xargs -0 -r -n 1 ${(kv)=xopt} "$@[1,s-1]"
}

# gman - format manpage using GNU troff
gman() {
  ( man -w "$@" 2>/dev/null || printf '%s\n' "$@" ) |
    xargs cat |
    groff -t -p -I/usr/share/man -Tutf8 -mandoc | less
}

# hman - format manpage as monospace HTML
hman() {
    man -T utf8 "$@" | ul | aha
}

# twoman - show inline "manpage"
twoman() {
  for cmd; do
    sed -n '1{/^[^#][^!]/q;d};0,/^$\|^[^#]/s/^# //p' ${commands[$cmd]?not found}
  done
}

# soak [OUTPUT] - write stdin to OUTPUT (or stdout), not clobbering OUTPUT.
# Also don't clobber on empty input.
soak() {
  perl -we 'undef $/; my $s = <STDIN>;
            $ARGV[0] and $s and open(STDOUT, ">", $ARGV[0]) || die "soak: $!\n";
            print $s;' -- "$@"
}

# inp [FILE] [FILTER...] - run FILTER in-place on FILE
inp() {
    () { "$@[3,-1]" <$2 >$1 && [[ -s $1 ]] && mv $1 $2 } =(:) "$@"
}


# Define a shell function to run a command with input from a file and output to
# another file.
function run_command_with_input_and_output_files() {
    local output_file="$1"
    local input_file="$2"
    shift 2
    "$@" <"$input_file" >"$output_file" && [[ -s "$output_file" ]] && mv "$output_file" "$input_file"
}






# sslcat HOST:PORT - print SSL certificate and details
sslcat() {
  local cert="$(openssl s_client -connect $1 </dev/null | awk '/^--*BEGIN/,/^--*END/')"
  printf '%s\n' "$cert" | openssl x509 -in /dev/stdin -text
  printf '%s\n' "$cert" | openssl x509 -in /dev/stdin -noout -sha1 -fingerprint
  printf '%s\n' "$cert" | openssl x509 -in /dev/stdin -noout -md5 -fingerprint
}

# clot - fill screen with garbage, as visual separator
# 11mar2016  +chris+ print seperate lines
clot() {
  head -c $((LINES*COLUMNS)) </dev/urandom |
    LC_ALL=C tr '\0-\377' ${(l:256::.*o@:)} |
    fold -w $COLUMNS
}

# spot - show changes compared to previous line
spot() {
  awk '{ for (i = 1; i <= length($0); i++)
           printf("%c", ((l = substr($0, i, 1))!=" " && l!="\t" &&
                          substr(p, i, 1)==l ? "." : l))
         printf("\n"); p = $0; }'
}

Variables

PATH variables

Search path

Specify the directories that the shell is to look through to find a command. These directories are searched in the order in which they appear.

The global search PATH is defined in the file /etc/environment.

# Add a directory to PATH if it exists.
add_to_path() {
  if [[ -d "$1" ]]; then
    PATH="$1:$PATH"
  fi
}

# Add directories to PATH.
add_to_path "$HOME/bin"
add_to_path "$HOME/expect"
add_to_path "$HOME/R"

# Add $HOME/winbin to the end of PATH if it exists.
if [[ -d "$HOME/winbin" ]]; then
  PATH="$PATH:$HOME/winbin"
fi

By default, the root shell does not load commands from the current location. If you’re root and if you trust those commands, type ./whatever-command instead.

If you add the CWD (.) to your PATH, just do it:

  • for non-root users,
  • as the last entry (so, the current directory is only checked as a last resort).
# Add the current directory to PATH if not running as root.
[ "$UID" -ne 0 ] && PATH="$PATH:."

CDPATH

Much like the PATH environment variable sets a search order for executable commands, CDPATH allows you to define a selection of directories to be automatically checked when accessing folders. When referencing a directory name, the system will look for it in the directories specified in CDPATH, streamlining navigation without requiring you to type the full path or use the ~cd~ command explicitly.

# Check if the ~/.dotfiles directory exists and set CDPATH accordingly.
if [ -d "$HOME/.dotfiles" ]; then
  CDPATH=".:$HOME:$HOME/.dotfiles"
else
  CDPATH=".:$HOME"
fi
export CDPATH

MANPATH

# If user's private man directory exists, add it to MANPATH.
if [[ -d "$HOME/man" ]]; then
    export MANPATH="$HOME/man:$MANPATH"
fi

INFOPATH

Info readers (standalone + Emacs Info mode).

# Add directories to INFOPATH.
export INFOPATH="/usr/share/info:$INFOPATH"

Tool paths

Java
  • Download Ant and add its /bin directory to PATH.
  • Add C:\Program Files\Java\jdk1.8.0_91 to JAVA_HOME and add %JAVA_HOME%/bin to PATH.

Special variables

umask

# Set umask based on the user's EUID.
umask 022                               # Prevent new dirs and files from being
                                        # group and world writable.

if [[ "$UID" -eq 0 ]]; then
    umask 077                           # Stricter.
fi

BROWSER

# # For Bash on Ubuntu on Windows.
# export BROWSER='/mnt/c/Windows/explorer.exe' # does not work.
# export BROWSER='/mnt/c/Program Files (x86)/Mozilla Firefox/firefox.exe'

Locale variables

See https://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html

LANG, LC_ALL, LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC and LC_TIME set the language option for the shell and subprograms.

You may need to manually set your language environment (among others, for svn with accented file names in the repository).

export LANG=C.UTF-8
# # For scripts in R language.
# export LC_CTYPE=

# For Unicode ruler in diff-so-fancy.  See issue #364.
unset LC_CTYPE

These variables work as follows:

  • LC_ALL forces all the aspects of the locale to the specified value. If LC_ALL is set, all other locale variables will be ignored.
  • The other LC_ variables set the specified aspect of the locale information.
  • LANG is a fallback value, it will be used if none of the LC_ variables are specified.

PAGER

Set the user’s preferred text viewer (cat, more, less or most) that will be used by programs such as man or git diff.

export PAGER="less"

With the less command, you can scroll up in the file (with b, backward one window) as well as scroll down; with the archaic more command, you can only scroll down the file.

alias more='less'

How to get color man pages? Color any command with man-like output, including git help:

export LESS_TERMCAP_mb=$'\e[01;31m'     # Begin bold.
export LESS_TERMCAP_md=$'\e[01;36m'     # Begin blink (section titles in cyan).
export LESS_TERMCAP_me=$'\e[0m'         # Reset bold/blink.
export LESS_TERMCAP_so=$'\e[01;44;33m'  # Begin reverse video.
export LESS_TERMCAP_se=$'\e[0m'         # Reset reverse video.
export LESS_TERMCAP_us=$'\e[01;32m'     # Begin underline.
export LESS_TERMCAP_ue=$'\e[0m'         # Reset underline.

If you see \e[0m etc. appearing when you view the man page, add this line as well:

export LESS='-R'

If you see <E9> (in reverse video) etc. appearing when you view accents in an ISO Latin 1 file (in a UTF-8 terminal), add this:

# Format for displaying non-printable, non-control characters (see `man less').
export LESSBINFMT="*n<%02X>"            # Do not use reverse video.
export LESSBINFMT="*d?"                 # Use bold ?.

Commands for searching:

/pattern
Search forward for matching line.
?pattern
Search backward for matching line.
n
Repeat previous search.
N
Repeat previous search in reverse direction.
ESC-u
Undo (toggle) search highlighting.
&pattern
Display only matching lines.
If pattern is empty (if you type & immediately followed by RET), any filtering is turned off, and all lines are displayed.

Commands for jumping:

g
Jump to start (go to first line in file).
G
Jump to end (go to last line in file).

Miscellaneous commands:

-S
Toggle chop (truncate) long lines rather than wrapping.

Options:

export LESS='-F -i -M -R -X'
# export LESS="-P ?c<- .?f%f:Standard input.  ?n:?eEND:?p%pj\%.. .?c%ccol . ?mFile %i of %m  .?xNext\ %x.%t   Press h for help"
export LESS='--quit-if-one-screen --ignore-case --status-column --LONG-PROMPT --RAW-CONTROL-CHARS --HILITE-UNREAD --tabs=4 --no-init --window=-4'
export LESS=-i -g -M -R -x4 -X -f -F -z-1
export PAGER=less LESS='-wiXz-2$j15' LESSBINFMT=.

less options:

-e or --quit-at-eof
Causes less to automatically exit the /second/ time it reaches EOF. By default, the only way to exit less is via the q command.
-f or –force
Forces non-regular files to be opened. (A non-regular file is a directory or a device special file.) Also suppresses the warning message when a binary file is opened.
-F or –quit-if-one-screen
Causes less to automatically exit if the entire file can be displayed in one screen. This is usually desirable as there is no incentive to stay in less if a single screen can display all the contents.

It means you can just pipe any old thing into it, and if it’s only a couple of lines, you don’t have to quit manually.

-g or –hilite-search
Normally, less will highlight ALL strings which match the last search command. The -g option changes this behavior to highlight only the particular string which was found by the last search command. This can cause less to run somewhat faster than the default.
-i or --ignore-case
Causes searches to ignore case; that is, uppercase and lowercase are considered identical. This option is ignored if any uppercase letters appear in the search pattern; in other words, if a pattern contains uppercase letters, then that search does not ignore case.
-J or –status-column
Displays a status column at the left edge of the screen. The status column indicates the lines that matched the current search, and the first unread line after moving a full page (if the -w or -W option is in effect).
-m or --long-prompt
Causes less to prompt verbosely (like more), with the percent into the file. By default, less prompts with a colon.
-M or --LONG-PROMPT
Causes less to prompt even more verbosely than more.
-r or --raw-control-chars
Causes “raw” control characters to be displayed. The default is to display control characters using the caret notation; for example, a control-A (octal 001) is displayed as ^A.
-R or --RAW-CONTROL-CHARS
(Only) ANSI *”color” escape sequences* (sequences of the form ESC[...m where the ... is zero or more color specification characters, and m ends ANSI color escape sequences) are output in “raw” form.
-w or –hilite-unread
Temporarily highlights the first “new” line after a forward movement of a full page. The first “new” line is the line immediately following the line previously at the bottom of the screen. Also highlights the target line after a g or p command. The highlight is removed at the next command which causes movement. The entire line is highlighted, unless the -J option is in effect, in which case only the status column is high- lighted.
-W or –HILITE-UNREAD
Like -w, but temporarily highlights the first unread line after any scrolling larger than one line.
-x4 or –tabs=4
Sets tab stops at multiples of 4, since most modern text files assume 4-character width for a tab.. The default is 8.
-X or --no-init
Disables sending the termcap initialization and deinitialization strings to the terminal. This is sometimes desirable if the deinitialization string does something unnecessary, like clearing the screen.
-z-4 or –window=-4
Changes the default scrolling window size to 4 lines less than the current screen size, so always keep 4 lines overlapping with previous screen when scrolling with the space key.

DISPLAY

# Set DISPLAY environment variable (with the dynamic IP address of the WSL virtual machine).
export DISPLAY=$(awk '/nameserver/ {print $2; exit}' /etc/resolv.conf):0

Abbreviations (aliases)

An alias is a simple string substitution.

In general, it should not do more than change the default options of a command.

Aliases are abbreviations or alternative names (usually mnemonics) for commands. They are commonly used to specify a few options to commands, and then include the rest of the command line.

Aliases should usually be kept simple. If not, they should be converted to:

  • shell functions, or
  • shell scripts.

An alias cannot have an argument like $1.

History

Print the history lines matching a pattern.

alias hgrep='history | grep -i'

Common aliases

# Display information about the current shell process.
alias which-shell='ps -p $$'

ls options:

-a
Do not ignore entries starting with ..
-C
List entries by columns.
-F
Append indicator (one of */=>@|) to entries.
-g
Like -l, but do not list owner.
--group-directories-first
Group directories before files.
-G
In a long listing, don’t print group names.
-h
With -l and/or -s, print human readable sizes (e.g., 1K 234M 2G).
-l
Use a long listing format.
-s
Print the allocated size of each file, in blocks.
# Set time style (ISO 8601 format) for `ls` command.
export TIME_STYLE=long-iso

# Determine if the terminal supports colors.
if [[ "$TERM" != "dumb" ]]; then
    # Add `--show-control-chars` option.
    LS_OPTIONS="${LS_OPTIONS} --show-control-chars"

    # Create `ls` and `ll` aliases with color options and other formatting
    # options.
    alias ls='ls --color=auto -F'       # Use colors and append file type
                                        # indicators to file names.
    alias ll='ls --color=auto -a --group-directories-first -G -h -l'
                                        # Use colors, list all files, group
                                        # directories first, and use
                                        # human-readable sizes.

    # Generate shell code for directory colors.
    if [[ -f "$HOME"/.dircolors ]]; then
        eval "$(dircolors -b $HOME/.dircolors)"
        # See https://github.com/seebi/dircolors-solarized.
    else
        eval "$(dircolors -b)"
    fi
else
    alias ls='ls -CF'                   # Use basic listing format without
                                        # colors, append file type indicators to
                                        # file names.
fi
Beautify the terminal’s ls command, with color and font-awesome icons https://github.com/athityakumar/colorlsEND

Display the directory tree structure.

# Print a directory tree using ASCII characters.
alias dirtree='find . -type d | sed -e "s/[^-][^\/]*\//  |/g" -e "s/|\([^ ]\)/|-\1/"'

df options:

-h
Print sizes in powers of 1024 (e.g., 1023M).
-k
Like --block-size=1K.
-T
Print file system type.

Display the disk space usage for each mounted file system in a human-readable format.

alias df='df -kTh'

Make du human readable.

alias du='du -h'
alias du1='du -h --max-depth=1'

Sort in descending order of disk usage.

alias dusort='du -ms * | sort -rn'

Summarize the disk usage of all directories in the current directory, ordered by size.

alias du-summary='du --max-depth=1 -k | sort -nr | cut -f2 | xargs -d '\n' du -sh'

List mounted file systems in a readable, tabulated format.

alias mount='mount | column -t'
# Play safe!  Prevent some accidental mistakes.
alias rm='rm -i'                        # Confirm removing file.
alias cp='cp -i'                        # Confirm copy over an existing file.
alias mv='mv -i'                        # Confirm move over an existing file.
# Make an extract function!
alias tgz='tar -zxvf'
alias tbz2='tar -jxvf'

Interesting alias in Oh My Zsh: x / extract to extract an archive of types tar.{bz2,gz,xz,lzma}, bz2, rar, gz, tbz2, tgz, zip, Z, 7z.

# Display the contents of $PATH with each directory separated by a newline character.
alias path='echo "$PATH" | tr ":" "\n"'

# Display information about a command, function, or shell built-in.
alias where='type -a'
# Enable aliases to be sudo’ed.
alias sudo='sudo '

# Become root.
alias root='sudo -i'
# Upgrade everything.
alias upgrade-system='sudo apt update -y \
    && sudo apt full-upgrade -y \
    && sudo apt autoremove -y \
    && sudo apt clean -y \
    && sudo apt autoclean -y'
  1. update - updates the list of packages but do not install
  2. upgrade - install new versions of packages if new versions are available
  3. full-upgrade - performs the function of upgrade but will remove currently installed packages if this is needed to upgrade the system as a whole (fixing bad dependencies then)
  4. autoremove, autoclean and clean - clean old packages which are not needed any more
alias poweroff="systemctl poweroff"
alias reboot="systemctl reboot"
# Make executable.
alias exe='chmod +x'

# Recursively change the owner of all files and directories to the current user.
alias own='sudo chown -R $USER'

Changing Working Directory

# Define aliases for changing directory up levels.
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'

# Define an alias for changing to the previous directory.
alias -- -='cd -'                       # Alias '-' to 'cd -'.
# Print the current directory stack (list directory history).
alias d='dirs -v | head -n 10'

Normally, you can use cd +1 to go to the previous directory in the list, and so on. Here, this even more straightforward; you can use just the number of the entry in the directory history you want to visit: 1.

# Define aliases for changing to recently used directories.
alias 1='cd -'
alias 2='cd +2'
alias 3='cd +3'
alias 4='cd +4'
alias 5='cd +5'
alias 6='cd +6'
alias 7='cd +7'
alias 8='cd +8'
alias 9='cd +9'
# Check if the script is being run from WSL.
if [[ "$WSL_DISTRO_NAME" ]]; then
    # Define aliases for changing to C: and D: drives.
    alias c:='cd /mnt/c'
    alias d:='cd /mnt/d'

    # Define alias for opening the Windows file explorer
    alias explorer='explorer.exe'
fi
# Check if the current operating system is Cygwin.
if [[ "$OSTYPE" = cygwin* ]]; then
    # Define aliases for changing to C: and D: drives.
    alias c:='cd /cygdrive/c'
    alias d:='cd /cygdrive/d'

    # Define aliases for opening files and URLs.
    alias open='cygstart'
    alias xdg-open='cygstart'
fi

Shortcuts (single char for some commands)

alias c='clear'
alias j='jobs -l'
alias l='ls'                            # xx
alias m='man'
# alias p='$PAGER'
alias q='exit'
alias s='sudo'
alias t='tail -f'
# alias x='exit' # Conflict with extract (from Oh-my-Zsh?)

Colorize diff output

Highlight SVN diffs in the Shell (in Cygwin)???

# Make `diff' automatically call `colordiff' (Install `colordiff' package...).
command_exists colordiff && alias diff='colordiff'

Git

alias g='git'
# Go to the root directory of your Git repo.
alias cdroot='git rev-parse && cd "$(git rev-parse --show-toplevel)"'
                                        # That will not blow up cd if you aren't
                                        # in a Git directory.

#! The change in working directory will persist after the function has
#! completed.

http://jonas.nitro.dk/tig/manual.html

alias tigs='tig status'                 # Use it all of the time!
alias tigb='tig blame'
alias tigall='tig --all'
alias tigreleases='tig --all --simplify-by-decoration'

http://stackoverflow.com/tags/tig/hot

Color lines in shell (GRC, Supercat, Highlight, etc.)

http://stackoverflow.com/questions/4267400/colour-highlighting-output-based-on-regex-in-shell

highlight-lines-matching-regexp “ERROR”

SSH-agent / GPG agent

Most of our servers don’t listen to SSH on a public VLAN. I can’t be bothered to keep a tunnel open on my laptop when away from the office:

zugzug() {
    REMOTE_SERVER=$1
    ssh -A -p NON_STANDARD_PORT -t PROXY_SERVER ssh "$REMOTE_SERVER"
}

While it’s a function and not an alias, I find it invaluable.

alias ssh_list_keys='ssh-add -l'        # List all SSH identities.
alias ssh_add_key='ssh-add -t 4h'       # Add a new SSH identity and set a timeout of 4 hours.
alias ssh_remove_keys='ssh-add -D'      # Remove all SSH identities from the agent.
# Search for a GPG key on the pgp.mit.edu keyserver using its fingerprint or
# email address.
function gpg_search_key {
    gpg --keyserver pgp.mit.edu --fingerprint --search-key "$@"
}
# Receive GPG keys from the keys.gnupg.net keyserver.
alias gpg_key='gpg --keyserver keys.gnupg.net --recv-keys'

System admin

:header-args+: :tangle no
# Use `pkill' (which is pgrep + kill in a single command).

# Show only my processes.
alias mytop='top -u $USER'
# My traceroute.
have mtr && alias ping=mtr

# My ping.
have hping3 && alias myping="sudo hping3 -c 100 -2 -p 7 -d 500 $1"
alias rgrep="grep -r"
# Get my current external IP address.
have curl && alias my-external-ip='curl https://ipinfo.io/ip'
# 'dig +short myip.opendns.com @resolver1.opendns.com'

# Get my current internal IP address.
have ifconfig && alias my-internal-ip='ifconfig | grep -Eo "inet (addr:)?([0-9]*\.){3}[0-9]*" | grep -Eo "([0-9]*\.){3}[0-9]*" | grep -v "127.0.0.1" | head -n 1'
alias docker-rm-all='sudo docker ps -a | awk "NR > 1{print \$1}" | xargs sudo docker rm'

alias dk='docker'
alias dkc='docker-compose'
alias dkm='docker-machine'

alias dk-ips="docker ps -q | xargs -n 1 docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}} {{ .Name }}' | sed 's/ \//\t/'"
alias dk-clean='docker-clean'



alias db='docker build'
alias dc='docker-compose'
alias de='docker exec'
alias del='docker exec -it $(docker ps -q | head -n 1) bash'
alias di='docker images'
alias docker-clean='docker-rm-all && docker-prune'
alias docker-prune='docker rmi $(docker images -f "dangling=true" -q)'
alias docker-rm-all='docker rm -f $(docker ps -a -q)'
alias dps='docker ps'
alias dr='docker run'
alias drl="docker-run-last"



alias dl="docker ps -l -q"
alias dps="docker ps"
alias di="docker images"
alias dkd="docker run -d -P"
alias dki="docker run -i -t -P"
alias dex="docker exec -i -t"
# 040319 Send files via `netcat'.
# on sending side:
#  send() {
#      j=$*; tar cpz ${j/%${!#}/} | nc -w 1 ${!#} 51330;
#  }
#  send dir* $HOST
# Info:
#  ${!#} gibt den letzten Parameter (den Hostnamen) zurück,
#  ${j/%${!#}/} die übrigen (Liste der Dateien oder Verzeichnisse).
alias receive='nc -vlp 51330 | tar xzvp'
# Sharing file through http 80 port.
# From the other machine open a web navigator and go to ip from the machine who
# launch netcat, http://ip-address/ If you have some web server listening at 80
# port then you would need stop them or select another port before launch net
# cat ;-) * You need netcat tool installed
# nc -v -l 80 < file.ext
# Recursively delete `.DS_Store` files
alias cleanup="find . -type f -name '*.DS_Store' -ls -delete"

# Empty the Trash on all mounted volumes and the main HDD
alias emptytrash="sudo rm -rfv /Volumes/*/.Trashes; sudo rm -rfv ~/.Trash"

Org

# Run org-mode tests using Emacs batch mode.
function org_test {
    local tmpdir="/tmp/tmp-orgtest"
    (
        cd "$HOME"/Public/Repositories/org-mode" \
            || { echo "Error: Could not change directory to $HOME/Public/Repositories/org-mode"; return 1; }
        mkdir "$tmpdir" 2> /dev/null \
            || { echo "Error: Could not create temporary directory"; return 1; } # TMPDIR must exist!
        TMPDIR="$tmpdir" \
            emacs -Q --batch -L lisp/ -L testing/ -l org-test.el --eval '(setq org-confirm-babel-evaluate nil)' -f org-test-run-batch-tests || { echo "Error: Failed to run org-mode tests"; return 1; }
    )
}

Grep

# Define function to add color to grep output.
function grep {
    # Use the original grep command with the `--color=auto` option.
    command grep --color=auto "$@"
}

# Define function to add color to egrep output.
function egrep {
    # Use the original grep command with the `-E` and `--color=auto` options.
    command grep -E --color=auto "$@"
}

# Define function to add color to fgrep output.
function fgrep {
    # Use the original grep command with the `-F` and `--color=auto` options.
    command grep -F --color=auto "$@"
}

Change the color of grep (bold yellow on blue):

# Define variable for GREP_COLORS.
GREP_COLORS='sl=:cx=:mt=01;37;1;44:ms=01;37;1;44:mc=01;37;1;44:fn=35:ln=32:bn=32:se=36'

# Export GREP_COLORS variable.
export GREP_COLORS
sl
“selected”, which is used for highlighting the currently matching line.
cx
“context”, which is used for highlighting context lines that are adjacent to matching lines.
mt
“match”, which is used for highlighting the matching pattern itself. In this case, it is a yellow text on a blue background with bold and underline effects.
ms
“matching selected”, which is used for highlighting matching text on the selected line.
mc
“matching context”, which is used for highlighting matching text on context lines.
fn
“file name”, which is used for highlighting file names in the output.
ln
“line number”, which is used for highlighting line numbers in the output.
bn
“byte offset number”, which is used for highlighting byte offset numbers in the output.
se
“separator”, which is used for highlighting separator lines in the output.

Paste in a GREP_COLORS string to preview it. Tweak the style the way you want, with a live preview of how it’ll look! See https://dom.hastin.gs/files/grep-colors/

Grep through the running processes.

# Add -f option to pgrep to show full command line.
alias pgrep='pgrep -fl'

# Define alias for ps with grep.
# Usage: ps? <process_name>
alias 'ps?'='ps ax | grep '

Ripgrep

alias rg="rg --colors 'match:bg:yellow' --colors 'match:fg:black' --colors 'match:style:bold'"
alias srg="rg --colors 'match:bg:yellow' --colors 'match:fg:black' --colors 'match:style:bold' --sort-files"

Ag, the Silver Searcher

The Silver Searcher windows port

have ag && alias grep=ag

GraphicsMagick

See also https://image.online-convert.com/fr

# GraphicsMagick.
alias GIF='gm convert -verbose -interlace LINE'
alias thumb='gm convert -geometry 100x100 -interlace LINE -verbose'
alias region='sleep 3; gm import selection$(date "+%Y%m%d%H%M%S").jpg'
alias screenshot='sleep 5; gm import -window root screen$(date "+%Y%m%d%H%M%S").jpg'
alias window='sleep 3; gm import -frame window$(date "+%Y%m%d%H%M%S").jpg'

# Resize images using GraphicsMagick.
gmresize() {
    local scale="1024x768"

    for file in "$@"; do
        if [[ ! -f "$file" ]]; then
            echo "File '$file' not found. Skipping..."
            continue
        fi
        echo "Processing image '$file'..."
        gm convert -scale "$scale" "$file" "${file%.*}-$scale.${file##*.}"
        # Use parameter expansion to remove file extension from filename.
    done
}

# Batch convert PNG files to JPG format.
png2jpg() {
    find . -name "*.png" -print0 \
        | xargs -0 -I {} basename -s ".png" {} \
        | xargs -I {} -n 1 gm convert -quality 85% {}.png {}.jpg
}

Other things to sort

export GS_OPTIONS='-sPAPERSIZE=a4'
alias pdfmerge='gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=./pdf-joined.pdf' # pdfjoin
alias booklet="psbook | psnup -2 | pstops '2:0,1U(21cm,29.7cm)'"
# for Win32, choose gswin32c
# cleanup_files [-r] - Remove useless files (recursively).
cleanup_files() {
    if [[ "$1" = "-r" ]]; then
        find . \(
            -name "#*" \
            -o -name "*~" \
            -o -name ".*~" \
            -o -name "*.~[0-9]*~" \
            -o -name ".*.~[0-9]*~" \
            -o -name "*.~BASE~" \
            -o -name ".*.~BASE~" \
        \) -ok rm "{}" ";"
    else
        rm -i \
            \#* \
            *~ \
            .*~ \
            *.~[0-9]*~ \
            .*.~[0-9]*~ \
            *.~BASE~ \
            .*.~BASE~
    fi
}
# Recursively set permissions for directories and files.
set-sane-perm() {
    # Set directories to 755.
    find . -type d -exec chmod 755 {} +
    # Set files to 644, or use custom permission mode if specified.
    local mode="${1:-644}"
    find . -type f -exec chmod "$mode" {} +
}
# # Search for various types or README file in dir and display them in $PAGER.
# readme() {
#     local files
#     files=(./(#i)*(read*me|lue*m(in|)ut)*(ND))
#     if (($#files)); then
#         $PAGER $files
#     else
#         print 'No README files.'
#     fi
# }
safetmp() {
    test -d "$HOME" || exit 1
    test -d "$HOME"/tmp || mkdir "$HOME"/tmp
    echo "$HOME/tmp/safetmp.$(hostname).$(date +%s).$$"
}
# Open immediately the first match.
texman() {
    locate "$*" | grep pdf | grep texlive | head -1 | xargs open
}

texlist() {
    locate "$*" | grep "\(pdf\|dvi\)" | grep "\ (texlive\|gwTeX\)"
}

Extra

# Commandline Fu
cmdfu() {
    curl "http://www.commandlinefu.com/commands/matching/$(echo "$@" \
        | sed 's/ /-/g')/$(echo -n $@ | base64)/plaintext" ;
}

# Check if websites are down
down4me() {
    curl -s "http://www.downforeveryoneorjustme.com/$1" | sed '/just you/!d;s/<[^>]*>//g';
}
## Google Translate Functions ##

say() {
   find ~/Downloads/en -name "$1.ogg" -exec ogg123 {} \;
   # mplayer -user-agent Mozilla -prefer-ipv4 \
   # "http://translate.google.md/translate_tts?ie=UTF-8&tl="$1"&q=$(echo "$@" \
   # | cut -d ' ' -f2- | sed 's/ /\+/g')" > /dev/null 2>&1 ;
}

say-translation() {
   lang=$1
   trans=$(translate {=$lang} "$(echo "$@" | cut -d ' ' -f2- | sed 's/ /\+/g')" )
   echo $trans
   mplayer -user-agent Mozilla \
   "http://translate.google.com/translate_tts?ie=UTF-8&tl=$lang&q=$trans" > /dev/null 2>&1 ;
}
console() {
    if [[ $# > 0 ]]; then
        query=$(echo "$*" | tr -s ' ' '|')
        tail -f /var/log/system.log | grep -i --color=auto -E "$query"
    else
        tail -f /var/log/system.log
    fi
}

Getting started

Prerequisites for Windows

Install Cygwin (http://mirrors.kernel.org).

PATH

After Cygwin is installed, modify the System PATH variable: prepend it with C:\cygwin64\bin (before %SystemRoot%\system32).

In c:/cygwin64/etc/profile,

  • /usr/local/bin is appended to the PATH!!

    And, except when root, it is almost always wrong to have /usr/local/bin after any system path.

  • TZ (time zone) is set… which gives wrong times (1 hour difference) in Emacs when called from c:/cygwin/Cygwin.bat!!

HOME, the user’s home directory

Add an HOME environment variable (with no trailing backslash!).

Programs like ssh don’t rely on your environment variable HOME for the location of your home directory.

Starting with Cygwin 1.7.34, the recommended way to do this is to add a custom db_home setting (comment the example line) to /etc/nsswitch.conf.

Packages

See http://www.4thinker.com/cygwin-setup.htmlEND

Cygwin Package Search

In order to install Cygwin’s packages through the terminal instead of running the setup every single time you need one, you can install apt-cyg. As a requirement, you’ll need to install wget through the Cygwin setup first. After that, just run the following commands:

wget rawgit.com/transcode-open/apt-cyg/master/apt-cyg
install apt-cyg /bin
  • Archive
    • [X] unzip
    • [X] zip (used by the “Org to ODT” exporter)
  • Database
    • [X] freetds (for tsql)
  • Devel
    • [ ] autoconf
    • [ ] bzr
    • [ ] ctags (Exuberant Ctags)
    • [ ] gcc-core (C compiler)
    • [ ] gcc4 (needed for installing some Perl packages, for CSV2Ledger)
    • [X] gdb
    • [X] git
    • [X] make (for making info for Git Org mode)
    • [X] meld (for diffing – requires xinit)
    • [ ] mercurial (for hg command, used by Beamer)
    • [X] patch
    • [X] patchutils
    • [X] subversion (for svn command)
  • Editors
    • [X] emacs
    • [X] emacs-el (needed to get more up-to-date sources, such as for Org)
    • [X] emacs-w32 (for graphical Cygwin Emacs with the w32 graphics toolkit)
  • Graphics
    • [X] ghostscript (needed by various utilities – texlive for example)
    • [ ] gnuplot
    • [X] graphviz (dot)
    • [X] poppler (for pdftotext)
  • Interpreters
    • [ ] m4
  • Libs
    • [ ] libbz2-devel (needed for installing RODBC inside R)
    • [ ] libiconv
    • [ ] libicu-devel (needed for installing RODBC inside R)
    • [ ] libiodbc-devel (needed for installing RODBC inside R)
  • Math
    • [X] R
  • Net
    • [X] bind-utils (for dig, host, nslookup, etc.)
    • [X] curl
    • [X] inetutils (for getting telnet to work with expect)
    • [ ] nc (see socat)
    • [ ] openssh
    • [ ] ping (Note: Allow to “Run this program as an administrator”)
    • [ ] rsync
    • [X] sitecopy
    • [ ] socat (see nc)
  • Perl
    • [ ] perl
  • Publishing
    • [X] texlive (= TeX only, not LaTeX! It requires fontconfig and ghostscript)
    • [X] texlive-collection-binextra (for latexmk)
    • [X] texlive-collection-fontsextra (for libertine.sty)
    • [X] texlive-collection-fontsrecommended (for marvosym.sty, etc.)
    • [X] texlive-collection-genericrecommended (for ulem.sty, etc.)
    • [X] texlive-collection-langfrench (for frenchb)
    • [X] texlive-collection-latex
    • [X] texlive-collection-latexextra (for draftwatermark.sty, etc.)
    • [X] texlive-collection-science (for siunitx.sty, etc.)
  • Python
    • [X] python
  • Ruby
    • [ ] ruby
  • Shells
    • [ ] rxvt
    • [X] zsh
  • System
    • [X] procps-ng (to get top and pkill)
    • [ ] psmisc (to get killall)
  • Tcl
    • [ ] expect
  • Text
    • [ ] antiword
    • [X] aspell (Note that the Win32 binary has much more dictionaries! Use that one instead if you need “nl” language…)
    • [ ] jq (for displaying JSON)
    • [ ] most
    • [ ] opensp (for nsgmls validator)
    • [X] texinfo (for makeinfo)
    • [ ] tidy
  • Utils
    • [X] colordiff (for svn)
    • [X] dos2unix
    • [X] fdupes
    • [X] file to determine file type
    • [ ] flog (logger, to syslog)
    • [ ] gnupg (for gpg) – requiring libusb0 (though you don’t need to install the Win32 driver which is adviced!)
    • [X] gnupg2 (for gpg2)
    • [X] moreutils (provides sponge)
    • [X] ncurses (provides tput and the clear command used by the TeX Live installer, though you can use C-l to get the same result)
    • [ ] screen
    • [ ] sgrep (installs the XPath command xmllint, with libxml2)
    • [X] the_silver_searcher (ag)
    • [X] tig (Git browser)
    • [X] xmlstarlet
  • X11
    • [ ] fontconfig (needed by XeTeX)
    • [X] xinit (needed by meld) See Display.
  • Web
    • [ ] wget

Many Unix commands have already newer and more feature-rich replacements:

df
pydf
less
most
tail
multitail
top
htop
tracepath
mtr
traceroute
mtr

Terminal emulators

For a better Emacs experience than with the Cygwin console, use:

  • MinTTY
  • (u)rxvt
  • xterm

Terminal types

  • dumb
  • cygwin
  • emacs
  • screen
  • xterm
  • xterm-256color
  • eterm-color

Set the terminal type explicitly to get a nice 256 color palette (instead of the ugly default 8 colors):

# export TERM=xterm-256color
# Set the TERM in the terminal emulator instead!

Initialize the terminal according to the type of terminal in the environmental variable TERM.

# tput init                             # This resets the Solarized color theme!!!

See the number of colors that the terminal supports:

tput colors

GnuPG

When first running gpg:

  • Directory ~/.gnupg created
  • New configuration file ~/.gnupg/gpg.conf created
  • Keyring ~/.gnupg/secring.gpg created (empty)
  • Keyring ~/.gnupg/pubring.gpg created (empty)

Suppress the Cygwin DOS path warning

When first running M-x ediff-buffers, I got this Cygwin warning:

MS-DOS style path detected: c:/Users/...
Preferred POSIX equivalent is: /cygdrive/c/Users/...
CYGWIN environment variable option "nodosfilewarning" turns off this warning.
Consult the user's guide for more details about POSIX paths:
  http://cygwin.com/cygwin-ug-net/using.html#using-pathnames

Though, setting it in .bashrc or something like that does not work. A good place to set it is in the global Windows environment variables.

Basic installation (OBSOLETE)

Shell-Leuven is installed by doing the following:

  1. Clone the repository:
    git clone https://github.com/fniessen/dotfiles ~/.dotfiles
    ~/.dotfiles/install
        
  2. Source Shell-Leuven configuration files
    . ~/.bash_profile
        
    . ~/.zshrc
        

Once you open up a new terminal window with Bash or Zsh, it should load with Shell-Leuven’s configuration.

Custom directory

If you’d like to change the install directory with the ZSH environment variable, either by running

export ZSH=/your/path

before installing.

FAQ

How to run Windows Emacs without showing a terminal window?

Use the run command:

C:\cygwin64\bin\run.exe /usr/bin/emacs

Disable your local ~/.gitconfig by faking out $HOME

Run git show command in a temporary HOME directory set to /dev/null.

HOME=/dev/null git show

About

Shell Bash and Zsh dot files

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages