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:
- Install the Windows Subsystem for Linux (WSL) (requires administrator privileges).
- Install Git for Windows (bundled with Git that we will use later; see instructions).
- Install MSYS2 (does not require administrator privileges).
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.
python
/python3
- compilers for C++:
g++
,clang++
- debuggers for C++:
gdb
,lldb
clang-format
clang-tidy
valgrind
cmake
ssh
,ssh-keygen
git
- and others…
Shell programming
Bash provides all common programming features, such as variables, conditions, loops, etc. Furthermore, other important concepts are:
- exit code
- input/output redirection
- composition of commands (pipes)
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:
- 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
- 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'