From 1e1967ebaeaf56127a253439f337e61540d22177 Mon Sep 17 00:00:00 2001 From: Santiago Soler Date: Tue, 20 Oct 2020 15:08:03 -0300 Subject: [PATCH] Refactor bash configuration files and improve prompt (#24) Refactor bash configuration files to reduce the number of files and ease any future modifications. Improve bash prompt into a more Pythonist way, simplify the functions, define variables for each color and add variables for configuring the prompt without changing the functions. Add Python version along with conda environment. Add nerd icons to prompt and set Nerd Fonts Fira Code on xfce4-terminal. --- dotfiles/.bash/aliases.sh | 26 --- dotfiles/.bash/colors.sh | 46 ---- dotfiles/.bash/prompt.sh | 255 ++++++++++++--------- dotfiles/.bash/variables.sh | 35 --- dotfiles/.bashrc | 149 +++++++++--- dotfiles/.config/xfce4/terminal/terminalrc | 2 +- yay_packages.yml | 1 + 7 files changed, 261 insertions(+), 253 deletions(-) delete mode 100644 dotfiles/.bash/aliases.sh delete mode 100644 dotfiles/.bash/colors.sh delete mode 100644 dotfiles/.bash/variables.sh diff --git a/dotfiles/.bash/aliases.sh b/dotfiles/.bash/aliases.sh deleted file mode 100644 index dc62602..0000000 --- a/dotfiles/.bash/aliases.sh +++ /dev/null @@ -1,26 +0,0 @@ -# Define aliases - -alias v="nvim" -alias vim="nvim" -alias cp="cp -i" # confirm before overwriting something -alias ls="ls --group-directories-first --color=auto" # ls in list and human readable -alias ll="ls -lh --group-directories-first --color=auto" # ls in list and human readable -alias du="du -h -d 0" # disk usage with human readable and depth 0 -alias open='xdg-open' -alias xc='xclip -selection clipboard' # copy to clipboard using xclip -alias diceware-es='diceware -d " " --no-caps $DICEWARE_ES' -alias lab='tmux new-session -d -s lab; tmux send-keys -t lab "cd $HOME; jupyter-lab --no-browser" Enter' -alias ta="tmux attach -t" -alias remotelab='tmux new-session -d -s remotelab; tmux send-keys -t remotelab "ssh -N -L localhost:9999:localhost:8888 santi@soler.unsj.edu.ar" Enter' -alias serve='tmux new-session -d -s serve; tmux send-keys -t serve "livereload -p 8080 ." Enter' -alias ca='conda activate' -alias cdtop='cd $(git rev-parse --show-toplevel)' # cd to toplevel of git repo - -# git aliases for misspelling -alias gti="git" -alias gi="git" - -# Add an "alert" alias for long running commands. Use like so: -# sleep 10; alert -alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' - diff --git a/dotfiles/.bash/colors.sh b/dotfiles/.bash/colors.sh deleted file mode 100644 index faa73c3..0000000 --- a/dotfiles/.bash/colors.sh +++ /dev/null @@ -1,46 +0,0 @@ -# Color man pages -export LESS_TERMCAP_mb=$'\E[01;32m' -export LESS_TERMCAP_md=$'\E[01;32m' -export LESS_TERMCAP_me=$'\E[0m' -export LESS_TERMCAP_se=$'\E[0m' -export LESS_TERMCAP_so=$'\E[01;30;44m' -export LESS_TERMCAP_ue=$'\E[01;0m' -export LESS_TERMCAP_us=$'\E[01;36m' -# export LESS=-r - - -# Default Manjaro .bashrc color configuration - -use_color=true - -# dircolors --print-database uses its own built-in database -# instead of using /etc/DIR_COLORS. Try to use the external file -# first to take advantage of user additions. Use internal bash -# globbing instead of external grep binary. -safe_term=${TERM//[^[:alnum:]]/?} # sanitize TERM -match_lhs="" -[[ -f ~/.dir_colors ]] && match_lhs="${match_lhs}$(<~/.dir_colors)" -[[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(/dev/null \ - && match_lhs=$(dircolors --print-database) -[[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true - -if ${use_color} ; then - # Enable colors for ls, etc. Prefer ~/.dir_colors #64489 - if type -P dircolors >/dev/null ; then - if [[ -f ~/.dir_colors ]] ; then - eval $(dircolors -b ~/.dir_colors) - elif [[ -f /etc/DIR_COLORS ]] ; then - eval $(dircolors -b /etc/DIR_COLORS) - fi - fi - - alias ls='ls --color=auto' - alias grep='grep --colour=auto' - alias egrep='egrep --colour=auto' - alias fgrep='fgrep --colour=auto' -fi - -unset use_color safe_term match_lhs sh - diff --git a/dotfiles/.bash/prompt.sh b/dotfiles/.bash/prompt.sh index 6401a15..5a2e09a 100644 --- a/dotfiles/.bash/prompt.sh +++ b/dotfiles/.bash/prompt.sh @@ -4,6 +4,43 @@ # https://github.com/leouieda/dotfiles/blob/7772b82dc35d8d58ff9504cded966ef518cc24ce/.bash/prompt.sh +# Define font colors +white="\[\e[0m\]" +red="\[\e[0;31m\]" +green="\[\e[0;32m\]" +yellow="\[\e[0;33m\]" +blue="\[\e[0;34m\]" +purple="\[\e[0;35m\]" +light_blue="\[\e[0;36m\]" + +white_bold="\[\e[0m\e[1m\]" +red_bold="\[\e[1;31m\]" +green_bold="\[\e[1;32m\]" +yellow_bold="\[\e[1;33m\]" +blue_bold="\[\e[1;34m\]" +purple_bold="\[\e[1;35m\]" +light_blue_bold="\[\e[1;36m\]" + +# Define styles for git and conda information on prompt +CONDA_PROMPT_ENV="$purple_bold " +GIT_PROMPT_BRANCH="$yellow_bold " +GIT_PROMPT_AHEAD="$yellow_bold↑" +GIT_PROMPT_BEHIND="$yellow_bold↓" +GIT_PROMPT_NOUPSTREAM="$yellow_bold!" +GIT_PROMPT_DIVERGED="$red_bold↱" +GIT_PROMPT_CHANGED="$red_bold+" +GIT_PROMPT_STAGED="$green_bold•" +GIT_PROMPT_UNTRACKED="$white_bold|" +GIT_PROMPT_CONFLICT="$red_bold✖" +GIT_PROMPT_STASHED="$purple_bold✹" + +# More configurations +MULTILINE_PROMPT=1 +PROMPT_DIRTRIM=2 # make path shorter +PROMPT_ICON="⮞" +# PROMPT_ICON="❯" + + set_prompt() { # Set the PS1 configuration for the prompt @@ -11,135 +48,139 @@ set_prompt() # Capture last exit code local EXIT="$?" - # Default values for the appearance of the prompt. - local main_style="\[\e[1;32m\]" - local path_style="\[\e[0m\]\[\e[1m\]" - local error_style="\[\e[1;31m\]" - local normal_style="\[\e[0m\]" - local git_style="\[\e[1;33m\]" - local python_style="\[\e[0;35m\]" - local ahead="$git_style↑" - local behind="$git_style↓" - local noupstream="$git_style!" - local diverged="\[\e[1;31m\]↱$normal_style" - local changed="\[\e[1;31m\]+" - local staged="\[\e[1;32m\]•" - local untracked="\[\e[0m\]\[\e[1m\]|" - local conflict="\[\e[1;31m\]✖" - local stashed="\[\e[1;35m\]✹" + # Capture background jobs + local njobs=`jobs | wc -l` + + # Initialize PS1 + PS1="" + + # Add a linebreak before prompt + PS1+="\n" # Basic first part of the PS1 prompt - local host="$main_style`hostname`" - local path="$path_style\w" - PROMPT_DIRTRIM=2 - PS1="\n$main_style$USER$normal_style at $main_style$host$normal_style in $path$main_style" + local user="$green_bold$USER" + local host="$green_bold`hostname`" + local path="$blue_bold\w" + local at_="${white}at" + local on_="${white}on" + local in_="${white}in" + local with_="${white}with" + PS1+="$user $at_ $host $in_ $path" - local njobs=`jobs | wc -l` - if [[ $njobs -ne 0 ]]; then - PS1="$PS1 $normal_style($njobs)" + + # Add git prompt (branch and remote status) + if inside_git_repo; then + PS1+=" $on_ `get_git_prompt`" fi # Conda env - local which_python=`which python` - if [[ $which_python != "/usr/bin/python" ]]; then - local conda_env=`get_conda_env` - PS1="$PS1 $python_style$conda_env" + if [[ `which python` != "/usr/bin/python" ]]; then + PS1+=" $with_ $CONDA_PROMPT_ENV`get_conda_env`" fi - # Build and append the git status symbols + # Add git status if inside_git_repo; then - - # Branch - local git=`get_git_branch` - - # Remote status - local remote_status=`get_git_remote_status` - if [[ $remote_status == "ahead" ]]; then - local remote="$ahead" - elif [[ $remote_status == "behind" ]]; then - local remote="$behind" - elif [[ $remote_status == "noupstream" ]]; then - local remote="$noupstream" - elif [[ $remote_status == "diverged" ]]; then - local remote="$diverged" - else - local remote="" - fi - - if [[ -n $remote ]]; then - local git="$git $remote" - fi - - # Files status - local files_status="" - - local files_staged=`git diff --cached --numstat | wc -l` - if [[ $files_staged -ne 0 ]]; then - local files_status="$files_status$staged$files_staged" - fi - - local files_changed=`git diff --numstat | wc -l` - if [[ $files_changed -ne 0 ]]; then - local files_status="$files_status$changed$files_changed" - fi - - local files_untracked=`git ls-files --others --exclude-standard "$(git rev-parse --show-toplevel)" | wc -l` - if [[ $files_untracked -ne 0 ]]; then - local files_status="$files_status$untracked$files_untracked" - fi - - local files_conflict=`git diff --name-only --diff-filter=U | wc -l` - if [[ $files_conflict -ne 0 ]]; then - local files_status="$files_status$conflict$files_conflict" - fi - - local files_stashed=`git stash list | wc -l` - if [[ $files_stashed -ne 0 ]]; then - local files_status="$files_status $stashed$files_stashed" - fi - - if [[ -n $files_status ]]; then - local git="$git $files_status" - fi - - # Append the git info to the PS1 - if [[ -n $git ]]; then - PS1="$PS1 $git_style$git" + local git_status=$(get_git_status) + if [[ $git_status != "" ]]; then + PS1+=" $white[`get_git_status`$white]" fi fi - # Finish off with the current directory and the end of the prompt - # if [[ $conda_env == "" ]] && [[ $git == "" ]] && [[ $njobs -eq 0 ]]; then - # local end="$main_style$ $normal_style" - # else - # local end="$main_style $ $normal_style" - # fi - - # Change color of prompt symbol based on last exit code - local end="\n" - if [ $EXIT == 0 ]; then - end+="$main_style" + # Enable multiline + if [[ $MULTILINE_PROMPT -ne 0 ]]; then + PS1+="\n" else - end+="$error_style" + PS1+=" " fi - end+="> $normal_style" - PS1="$PS1$end" - - # Append __vte_osc7 function in /etc/profile.d/vte.sh in order to make Tilix open - # the current directory on a new terminal - # https://gnunn1.github.io/tilix-web/manual/vteconfig/ - if [[ $TILIX_ID ]]; then - VTE_PWD_THING="\[$(__vte_osc7)" - PS1="$PS1$VTE_PWD_THING" + # Add number of background jobs to prompt + if [[ $njobs -ne 0 ]]; then + PS1+="$red_bold($njobs) " fi + + # Add prompt symbol (color is set based on last exit code) + local prompt_symbol="" + if [ $EXIT == 0 ]; then + prompt_symbol+="$green_bold" + else + prompt_symbol+="$red_bold" + fi + prompt_symbol+="$PROMPT_ICON " + PS1+="$prompt_symbol" + + # Reset color of prompt + PS1+="$white" } PROMPT_COMMAND=set_prompt +get_git_prompt() { + # Return current git branch and remote status -get_conda_env () + # Initialize git_prompt local variable + local git_prompt="" + + # Add branch + local branch=`get_git_branch` + git_prompt+="$GIT_PROMPT_BRANCH$branch" + + # Remote status + local remote_status=`get_git_remote_status` + if [[ $remote_status == "ahead" ]]; then + local remote="$GIT_PROMPT_AHEAD" + elif [[ $remote_status == "behind" ]]; then + local remote="$GIT_PROMPT_BEHIND" + elif [[ $remote_status == "noupstream" ]]; then + local remote="$GIT_PROMPT_NOUPSTREAM" + elif [[ $remote_status == "diverged" ]]; then + local remote="$GIT_PROMPT_DIVERGED" + else + local remote="" + fi + if [[ -n $remote ]]; then + git_prompt+=" $remote" + fi + + echo $git_prompt +} + +get_git_status() { + # Return git current status + + # Files status + local git_status="" + + local files_staged=`git diff --cached --numstat | wc -l` + if [[ $files_staged -ne 0 ]]; then + git_status+="$GIT_PROMPT_STAGED$files_staged" + fi + + local files_changed=`git diff --numstat | wc -l` + if [[ $files_changed -ne 0 ]]; then + git_status+="$GIT_PROMPT_CHANGED$files_changed" + fi + + local files_untracked=`git ls-files --others --exclude-standard "$(git rev-parse --show-toplevel)" | wc -l` + if [[ $files_untracked -ne 0 ]]; then + git_status+="$GIT_PROMPT_UNTRACKED$files_untracked" + fi + + local files_conflict=`git diff --name-only --diff-filter=U | wc -l` + if [[ $files_conflict -ne 0 ]]; then + git_status+="$GIT_PROMPT_CONFLICT$files_conflict" + fi + + local files_stashed=`git stash list | wc -l` + if [[ $files_stashed -ne 0 ]]; then + git_status+="$GIT_PROMPT_STASHED$files_stashed" + fi + + echo $git_status +} + + +get_conda_env() { # Determine active conda env details local env_name="" diff --git a/dotfiles/.bash/variables.sh b/dotfiles/.bash/variables.sh deleted file mode 100644 index ddf77f0..0000000 --- a/dotfiles/.bash/variables.sh +++ /dev/null @@ -1,35 +0,0 @@ -# Define variables -# ---------------- -export DICEWARE_ES="$HOME/.diceware/diceware-spanish.txt" -export GEM_HOME=$HOME/.gem -export CONDA_PREFIX=$HOME/.anaconda3 - - -# Add directories to PATH -# ----------------------- -export PATH=$HOME/bin/:$PATH -export PATH="$PATH:$(ruby -e 'print Gem.user_dir' 2> /dev/null)/bin" - - -# The following lines are default manjaro .bashrc lines -# ----------------------------------------------------- -[[ $- != *i* ]] && return - -[ -r /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion - -xhost +local:root > /dev/null 2>&1 - -complete -cf sudo - -# Bash won't get SIGWINCH if another process is in the foreground. -# Enable checkwinsize so that bash will check the terminal size when -# it regains control. #65623 -# http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11) -shopt -s checkwinsize - -shopt -s expand_aliases - -# export QT_SELECT=4 - -# Enable history appending instead of overwriting. #139609 -shopt -s histappend diff --git a/dotfiles/.bashrc b/dotfiles/.bashrc index 7e33a8e..0cb2056 100644 --- a/dotfiles/.bashrc +++ b/dotfiles/.bashrc @@ -1,67 +1,140 @@ -# -# ~/.bashrc -# -if [ -f ~/.bash/variables.sh ]; then - source ~/.bash/variables.sh +# ================== +# Bash configuration +# ================== + +# ------------- +# Load builtins +# ------------- +complete -cf sudo +shopt -s expand_aliases +shopt -s histappend # enable history appending instead of overwriting + +# Bash won't get SIGWINCH if another process is in the foreground. +# Enable checkwinsize so that bash will check the terminal size when +# it regains control. #65623 +# http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11) +shopt -s checkwinsize + + +# -------------------- +# Load bash-completion +# -------------------- +if [ -f /usr/share/bash-completion/bash_completion ]; then + source /usr/share/bash-completion/bash_completion fi -if [ -f ~/.bash/aliases.sh ]; then - source ~/.bash/aliases.sh -fi -if [ -f ~/.bash/colors.sh ]; then - source ~/.bash/colors.sh -fi +# ----------------------- +# Add directories to PATH +# ----------------------- +export PATH=$HOME/bin/:$PATH +export PATH="$PATH:$(ruby -e 'print Gem.user_dir' 2> /dev/null)/bin" -if [ -f ~/.bash/prompt.sh ]; then - # Source Tilix script for configuring VTE - # We are using the __vte_osc7 function on our set_prompt function in .bash/prompt.sh - if [[ $TILIX_ID ]]; then - source /etc/profile.d/vte.sh + +# ---------------- +# Define variables +# ---------------- +export GEM_HOME=$HOME/.gem +export CONDA_PATH=$HOME/.anaconda3 + + +# ------- +# Aliases +# ------- +alias v="nvim" +alias vim="nvim" +alias cp="cp -i" +alias ls="ls --group-directories-first --color=auto" +alias ll="ls -lh --group-directories-first --color=auto" +alias la="ls -lah --group-directories-first --color=auto" +alias grep='grep --colour=auto' +alias egrep='egrep --colour=auto' +alias fgrep='fgrep --colour=auto' +alias du="du -h -d 0" +alias open='xdg-open' +alias xc='xclip -selection clipboard' # copy to clipboard using xclip + +# Run commands in background using tmux +alias ta="tmux attach -t" +alias lab='tmux new-session -d -s lab; tmux send-keys -t lab "cd $HOME; cenv; jupyter-lab --no-browser" Enter' +alias remotelab='tmux new-session -d -s remotelab; tmux send-keys -t remotelab "ssh -N -L localhost:9999:localhost:8888 santi@soler.unsj.edu.ar" Enter' +alias serve='tmux new-session -d -s serve; tmux send-keys -t serve "livereload -p 8080 ." Enter' + +# Conda aliases +alias ca='conda activate' +alias cdtop='cd $(git rev-parse --show-toplevel)' # cd to toplevel of git repo + +# Git aliases +alias gti="git" +alias gi="git" +alias gts="git status" + +# Add an "alert" alias for long running commands. Use like so: +# sleep 10; alert +alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' + + +# ------ +# Colors +# ------ +# Load dircolors +if type -P dircolors >/dev/null ; then + if [[ -f ~/.dir_colors ]] ; then + eval $(dircolors -b ~/.dir_colors) + elif [[ -f /etc/DIR_COLORS ]] ; then + eval $(dircolors -b /etc/DIR_COLORS) fi - # Make the prompt pretty and show git branch information +fi + +# Color man pages +export LESS_TERMCAP_mb=$'\E[01;32m' +export LESS_TERMCAP_md=$'\E[01;32m' +export LESS_TERMCAP_me=$'\E[0m' +export LESS_TERMCAP_se=$'\E[0m' +export LESS_TERMCAP_so=$'\E[01;30;44m' +export LESS_TERMCAP_ue=$'\E[01;0m' +export LESS_TERMCAP_us=$'\E[01;36m' + + +# ---------------------- +# Make the prompt pretty +# ---------------------- +if [ -f ~/.bash/prompt.sh ]; then source ~/.bash/prompt.sh fi + +# -------------------------- +# Load some useful functions +# -------------------------- if [ -f ~/.bash/functions.sh ]; then source ~/.bash/functions.sh fi +# -------------------- # Initialize ssh agent +# -------------------- if [ -f ~/.ssh/agent.env ] ; then . ~/.ssh/agent.env > /dev/null if ! kill -0 $SSH_AGENT_PID > /dev/null 2>&1; then - # echo "Stale agent file found. Spawning new agent… " eval `ssh-agent | tee ~/.ssh/agent.env` - # ssh-add fi else - # echo "Starting ssh-agent" eval `ssh-agent | tee ~/.ssh/agent.env` - # ssh-add fi -# >>> conda initialize >>> -# !! Contents within this block are managed by 'conda init' !! -__conda_setup="$('$CONDA_PREFIX/bin/conda' 'shell.bash' 'hook' 2> /dev/null)" -if [ $? -eq 0 ]; then - eval "$__conda_setup" -else - if [ -f "$CONDA_PREFIX/etc/profile.d/conda.sh" ]; then - . "$CONDA_PREFIX/etc/profile.d/conda.sh" - else - export PATH="$CONDA_PREFIX/bin:$PATH" - fi -fi -unset __conda_setup -# <<< conda initialize <<< +# ---------------- +# Initialize conda +# ---------------- +# Setup and activate the conda package manager +if [ -f $CONDA_PATH/etc/profile.d/conda.sh ]; then + source "$CONDA_PATH/etc/profile.d/conda.sh" + conda activate +fi # Activate the conda default environment if [ -f $HOME/environment.yml ]; then cenv $HOME/environment.yml fi - - - diff --git a/dotfiles/.config/xfce4/terminal/terminalrc b/dotfiles/.config/xfce4/terminal/terminalrc index c532896..9610819 100644 --- a/dotfiles/.config/xfce4/terminal/terminalrc +++ b/dotfiles/.config/xfce4/terminal/terminalrc @@ -19,7 +19,7 @@ ScrollingLines=999999 ScrollingBar=TERMINAL_SCROLLBAR_NONE BackgroundDarkness=0,700000 ScrollingOnOutput=FALSE -FontName=Fira Code 9.5 +FontName=FiraCode Nerd Font 9.5 MiscBellUrgent=FALSE MiscMouseWheelZoom=TRUE MiscMiddleClickOpensUri=FALSE diff --git a/yay_packages.yml b/yay_packages.yml index 80fa1c2..62c731e 100644 --- a/yay_packages.yml +++ b/yay_packages.yml @@ -2,6 +2,7 @@ fonts: - ttf-google-fonts-git - ttf-ms-fonts - ttf-nunito + - nerd-fonts-fira-code jabref: - jabref