Unix environment

The terminal is a basic interface for the communication between a human and a computer. Every programmer should know how to use a terminal 😉

In this course, we will be using a Unix environment, which is vastly superior to the standard terminal available in Windows. If you use a Linux or macOS operating systems, you should be ready to get started. If you use Windows, you will need to install some additional software.

Installation on Windows

There are several options, sorted here from the best to the least convenient:

If you have a problem with your setup, feel free to ask me during the class or send me an email 😉

Configuration for VSCode on Windows

If you have WSL, you can install the WSL extension for remote development. See the WSL tutorial to get started.

If you have Git for Windows, it should be available as a built-in terminal in VSCode.

If you have MSYS2, you can configure VSCode to open it in its terminal using these instructions

Shell introduction

The program that interprets the commands entered in a terminal is called a shell. The default shell in VSCode/VSCodium on Windows is PowerShell, but in other environments (WSL, MSYS2, macOS, Linux) the default is typically bash, sometimes zsh.

The Unix environment contains a standard set of traditional commands, such as ls, rm, cp, mv, etc. See The Unix Shell tutorial for an introduction to using these tools.

We will use many other tools in PROP that can be used from a terminal. Every program can be launched from a Unix shell, including graphical programs.

Shell programming

Bash provides all common programming features, such as variables, conditions, loops, etc. Furthermore, other important concepts are:

Let‘s learn the syntax and write some shell script!

Shell configuration

Bash is highly configurable, let me comment on two config files that I use on my own systems:

  1. The ~/.inputrc configures the behavior of various keyboard shortcuts, tab completion, history navigation, etc.
# do not clear or convert the eighth bit of input characters, pass them directly
# to the terminal
set meta-flag on
set input-meta on
set convert-meta off
set output-meta on

# TAB completion
set show-all-if-ambiguous on
set show-all-if-unmodified on

# do not bell on tab-completion
set bell-style none

# character denoting file's type appended to filename (like ls -F)
set visible-stats on
# display possible completions using different colors to indicate their file type
set colored-stats on

# case-insensitive completion
set completion-ignore-case on

# prefix-search navigation in command history
"\e[A": history-search-backward
"\e[B": history-search-forward

$if mode=emacs

# for linux console and RH/Debian xterm
"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[7~": beginning-of-line
"\e[3~": delete-char
"\e[2~": quoted-insert
"\e[5C": forward-word
"\e[5D": backward-word
"\e\e[C": forward-word
"\e\e[D": backward-word
"\e[1;5C": forward-word
"\e[1;5D": backward-word

# for rxvt
"\e[8~": end-of-line

# for non RH/Debian xterm, can't hurt for RH/DEbian xterm
"\eOH": beginning-of-line
"\eOF": end-of-line

# for freebsd console
"\e[H": beginning-of-line
"\e[F": end-of-line
$endif
  1. The ~/.bashrc file contains configuration of the shell itself, including prompt and aliases for common commands:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return

# bash options
shopt -s checkwinsize       # update the value of LINES and COLUMNS after each command if altered
shopt -s cmdhist            # save multi-line commands in history as single line
shopt -s histappend         # do not overwrite history

# source useful files
[[ -r /usr/share/bash-completion/bash_completion ]] && source /usr/share/bash-completion/bash_completion
[[ -r /usr/share/git/completion/git-prompt.sh ]] && source /usr/share/git/completion/git-prompt.sh

# function setting prompt string
bash_prompt() {
    # some colors
    local color_reset="\033[00m"
    local red="\033[01;31m"
    local green="\033[01;32m"
    local yellow="\033[01;33m"
    local blue="\033[01;34m"
    local magenta="\033[01;35m"
    local cyan="\033[01;36m"

    # green for user
    local user_color="$green"
    # red for root
    [[ $UID == 0 ]] && user_color="$red"

    # green for local session
    local host_color="$green"
    # cyan for SSH sessions
    [[ -n "$SSH_CONNECTION" ]] && host_color="$cyan"

    # colorized return value of last command
    local ret="\$(if [[ \$? == 0 ]]; then echo \"\[$green\]\$?\"; else echo \"\[$red\]\$?\"; fi)"

    # blue for writable directories, yellow for non-writable directories
    local dir="\$(if [[ -w \$PWD ]]; then echo \"\[$blue\]\"; else echo \"\[$yellow\]\"; fi)\w"

    if [[ $(type -t "__git_ps1") == "function" ]]; then
        # configuration for __git_ps1 function
        GIT_PS1_SHOWDIRTYSTATE=1
        GIT_PS1_SHOWSTASHSTATE=1
        GIT_PS1_SHOWUPSTREAM="auto"

        # check if we're on local filesystem and skip git prompt on remote paths
        local git="\$(if [[ \"\$(df --output=fstype . | tail -n +2)\" != \"fuse.sshfs\" ]]; then __git_ps1; fi)"
    else
        local git=""
    fi

    PS1="$ret \[$user_color\]\u\[$host_color\]@\h\[$color_reset\]:$dir\[$magenta\]$git\[$color_reset\]\$ "
}
bash_prompt

case ${TERM} in
  Eterm*|alacritty*|aterm*|foot*|gnome*|konsole*|kterm*|putty*|rxvt*|tmux*|xterm*)
    PROMPT_COMMAND+=('printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"')

    ;;
  screen*)
    PROMPT_COMMAND+=('printf "\033_%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"')
    ;;
esac

# set history variables
unset HISTFILESIZE
HISTSIZE=100000
HISTCONTROL=ignoredups:ignorespace

# update the $HISTFILE immediately after it is executed
PROMPT_COMMAND+=('history -a')

# define useful aliases
alias grep='grep --color=auto'
alias ip='ip --color=auto'
alias ls='ls --color=auto'
alias ll='ls -alFh'
alias la='ls -A'
alias l='ls -CF'
alias mv='mv -i'
alias cp='cp -i --preserve=all --reflink=auto'
alias rm='rm -i'
alias du='du -h'
alias df='df -h'
alias free='free -h'