2562 lines
		
	
	
		
			82 KiB
		
	
	
	
		
			Bash
		
	
	
	
			
		
		
	
	
			2562 lines
		
	
	
		
			82 KiB
		
	
	
	
		
			Bash
		
	
	
	
| # /etc/zsh/zshrc ou ~/.zshrc
 | ||
| # Fichier de configuration principal de zsh, lu au lancement des shells interactifs
 | ||
| # (et non des shells d'interprétation de fichier)
 | ||
| # Formation Debian GNU/Linux par Alexis de Lattre
 | ||
| # http://formation-debian.via.ecp.fr/
 | ||
| 
 | ||
| ################
 | ||
| # 1. Les alias #
 | ||
| ################
 | ||
| 
 | ||
| # Gestion du 'ls' : couleur & ne touche pas aux accents
 | ||
| alias ls='ls --classify --tabsize=0 --literal --color=auto --show-control-chars --human-readable'
 | ||
| 
 | ||
| # Copie en récursif et qui garde la date des fichiers copiés
 | ||
| #alias cp='cp -Rp'
 | ||
| alias cp='cp -R'            # **cp** copy files and directories recursively # TEST
 | ||
| 
 | ||
| # Copie distante, ajout de la récursivité tout le temps:
 | ||
| alias scp='scp -r'
 | ||
| 
 | ||
| # Demande confirmation avant d'écraser un fichier
 | ||
| alias cP='cp --interactive'
 | ||
| alias mv='mv --interactive'
 | ||
| alias rm='rm --interactive'
 | ||
| 
 | ||
| # ls shortcut {{{
 | ||
| if [ ! $(command -v eza) ]; then
 | ||
| 	## with ls {{{
 | ||
| 	alias ll='ls -l'
 | ||
| 	## Show hidden files
 | ||
| 	alias la='ll --almost-all'
 | ||
| 	## Show hidden only
 | ||
| 	alias lla='la --directory .*'
 | ||
| 	alias l.='ls --directory .*'
 | ||
| 	alias llh='ll | head'
 | ||
| 	alias llp='ll | $PAGER'
 | ||
| 	alias llw='ll | wc --lines'
 | ||
| 	## Sort by date
 | ||
| 	alias lll='ls -l -t --human-readable --reverse'
 | ||
| 	alias llll='ls -l -t --human-readable --reverse'
 | ||
| 	alias lld='ls -l --directory */ --human-readable'
 | ||
| 	alias lr='ls --recursive | grep ":$" | sed -e '\''s/:$//'\'' -e '\''s/[^-][^\/]*\//--/g'\'' -e '\''s/^/   /'\'' -e '\''s/-/|/'\'''
 | ||
| 	## }}}
 | ||
| 	## with eza (forked from exa) {{{
 | ||
| else
 | ||
| 	alias exa=eza
 | ||
| 	alias ll='eza --color=always --long --group --git'
 | ||
| 	## Show hidden files
 | ||
| 	alias la='ll --all --sort .name'
 | ||
| 	## Show hidden only
 | ||
| 	alias lla='ll --list-dirs .*'
 | ||
| 	alias l.='ls --directory .*'
 | ||
| 	alias llh='ll | head'
 | ||
| 	alias llp='ll | $PAGER'
 | ||
| 	alias llw='ll | wc --lines'
 | ||
| 	## Sort by date
 | ||
| 	alias lll='ll --sort=modified'
 | ||
| 	alias llll='ll --sort=modified'
 | ||
| 	## Give a tree of current directory
 | ||
| 	alias llt='ll --tree'
 | ||
| 	alias lld='ll --group-directories-first'
 | ||
| 	alias lr='ls --recursive | grep ":$" | sed -e '\''s/:$//'\'' -e '\''s/[^-][^\/]*\//--/g'\'' -e '\''s/^/   /'\'' -e '\''s/-/|/'\'''
 | ||
| 	## }}}
 | ||
| fi
 | ||
| # }}}
 | ||
| 
 | ||
| # cat with number on output lines
 | ||
| alias ca='cat --number'
 | ||
| # docker related
 | ||
| alias d='docker'
 | ||
| # Correct ip command
 | ||
| alias ipa='ip a'
 | ||
| # Disable because of "There is no raw‐control‐chars option" warning…
 | ||
| # less with raw character
 | ||
| #alias less='less --raw‐control‐chars'
 | ||
| #alias less='less --quiet'
 | ||
| # Call last command
 | ||
| alias pp='fc -e -'
 | ||
| # Call last command in edit mode
 | ||
| alias ppe='fc'
 | ||
| # Call last command with sudo
 | ||
| alias pps='sudo $(fc -ln -1)'
 | ||
| 
 | ||
| # fdfind
 | ||
| ## disregard vcs ignore files (.gitignore…) as homedir is a git repository…
 | ||
| alias fd='fd --no-ignore-vcs'
 | ||
| 
 | ||
| # sudo
 | ||
| ## Please consider using "Defaults      env_keep+=HOME" configuration in sudoers {{{
 | ||
| ### This is Ubuntu default behaviour.
 | ||
| ### This will allow to share user's homedir/dotfiles with root throught sudo commands
 | ||
| ## }}}
 | ||
| ## Ensure sudo can use aliases (end whitespace) {{{
 | ||
| ### `man zshall` partie Aliasing: "If the text ends with a space, the next word in the shell input is treated as though it were in command position for
 | ||
| ### purposes of alias expansion. "
 | ||
| alias s='sudo '
 | ||
| ## }}}
 | ||
| ## sudo aliases {{{
 | ||
| if [ ${USER} != "root" ]; then
 | ||
| 	alias sc='sudo systemctl '
 | ||
| 	alias scu='systemctl --user'
 | ||
| 	alias sd='sudo docker'
 | ||
| 	alias si='sudo iptables -L -vn '
 | ||
| 	alias sj='sudo journalctl '
 | ||
| 	alias sn='sudo nft list ruleset'
 | ||
| 	alias sv='sudo vi '
 | ||
| 	alias sz='sudo zsh'
 | ||
| else
 | ||
| 	alias sc='systemctl '
 | ||
| 	alias scu='systemctl --user'
 | ||
| 	alias sd='docker'
 | ||
| 	alias si='iptables -L -vn '
 | ||
| 	alias sj='journalctl '
 | ||
| 	alias sn='nft list ruleset'
 | ||
| 	alias vi='vi -S ~/.vim/vimrc '
 | ||
| 	alias sv='vi -S ~/.vim/vimrc '
 | ||
| fi
 | ||
| ## }}}
 | ||
| 
 | ||
| # Envoyer une notification via libnotify-bin (fin d'une commande, ...)
 | ||
| # Nécessite le paquet libnotify-bin
 | ||
| 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$//'\'')"'
 | ||
| 
 | ||
| # Nettoyage de l'écran
 | ||
| alias c='clear'
 | ||
| # Liste le contenu du dossier
 | ||
| alias dir='dir --color=always'
 | ||
| 
 | ||
| # Page de manuel en anglais
 | ||
| alias mane="LANG=C man "
 | ||
| 
 | ||
| # Afficher les lignes trop longues sur la ligne suivante plutot que de remplacer par un "$":
 | ||
| alias most='most -w'
 | ||
| 
 | ||
| ## System
 | ||
| # APT|Aptitude|… commands {{{
 | ||
| if [ -d /etc/apt ]; then
 | ||
|   alias acle='sudo aptitude clean'
 | ||
|   alias afil='apt-file search --'
 | ||
|   alias aful='sudo aptitude full-upgrade'
 | ||
|   alias ains='sudo aptitude install'
 | ||
|   alias alis='apt list --upgradable'
 | ||
|   alias apol='apt-cache policy'
 | ||
|   alias apur="sudo aptitude purge '~c'"
 | ||
|   alias aupd='sudo apt update'
 | ||
|   alias aupg='sudo aptitude upgrade'
 | ||
|   alias arem='sudo aptitude remove'
 | ||
|   alias apts='apt search'
 | ||
|   alias asea='aptitude search --'
 | ||
|   alias asho='aptitude show'
 | ||
|   alias aver='apt-show-versions'
 | ||
|   alias awhy='aptitude why'
 | ||
|   alias insexperimental='sudo aptitude --target-release experimental install'
 | ||
| 	alias anorepos="apt list --installed | sed --silent 's/\(.*\)\/.*,local.*/\1/p' | tr '\n' ' '"
 | ||
| fi
 | ||
| # }}}
 | ||
| # Pacman commands {{{
 | ||
| if [ -d /etc/pacman.d ]; then
 | ||
| 	alias pacle='echo "$(ls -1 /var/cache/pacman/pkg | wc --lines) packages to clean" && sudo pacman --sync --clean'
 | ||
|   alias pafil='pacman --files --regex --'
 | ||
|   alias paful='sudo pacman --sync --sysupgrade --'
 | ||
|   alias pains='sudo pacman --sync --'
 | ||
|   alias palis='pacman --query --upgrades --'
 | ||
|   alias papol='pacman --sync --info --'
 | ||
|   alias paupd='sudo pacman --sync --refresh --'
 | ||
|   alias paupg='sudo pacman --sync --'
 | ||
|   alias parem='sudo pacman --remove --'
 | ||
|   alias paremdep='sudo pacman --remove --recursive --'
 | ||
|   alias paorph='pacman --query --unrequired --deps --quiet --'
 | ||
|   alias papurge='pacman --query --unrequired --deps --quiet -- | sudo pacman --remove --recursive --nosave -- -'
 | ||
|   #alias apts='apt search'
 | ||
|   alias pasea='pacman --sync --search --'
 | ||
|   alias pasho='pacman --sync --info --'
 | ||
|   #alias awhy='aptitude why'
 | ||
| 	#alias anorepos="apt list --installed | sed --silent 's/\(.*\)\/.*,local.*/\1/p' | tr '\n' ' '"
 | ||
| fi
 | ||
| # }}}
 | ||
| # Yay commands for AUR − Archlinux User Repository {{{
 | ||
| if command -v yay > /dev/null; then
 | ||
|   alias yains='yay --sync --'
 | ||
|   alias yalis='yay --query --upgrades --'
 | ||
|   alias yapol='yay --sync --info --'
 | ||
|   #alias apts='apt search'
 | ||
|   alias yasea='yay --sync --search --'
 | ||
|   alias yasho='yay --sync --info --'
 | ||
|   #alias awhy='aptitude why'
 | ||
| 	#alias anorepos="apt list --installed | sed --silent 's/\(.*\)\/.*,local.*/\1/p' | tr '\n' ' '"
 | ||
| fi
 | ||
| # }}}
 | ||
| 
 | ||
| # Filter pending mail by date
 | ||
| alias maildate='sudo mailq |grep "^[A-F0-9]" |sort -k5n -k6n'
 | ||
| 
 | ||
| # Grep aliases {{{
 | ||
| alias grep='grep --color=always --ignore-case '
 | ||
| alias gerp='grep --ignore-case'
 | ||
| alias Grep='\grep '
 | ||
| alias gdpkg='dpkg --list | grep --extended-regexp -- '
 | ||
| alias gmount='mount | grep --extended-regexp -- '
 | ||
| alias gdf='df | grep --extended-regexp -- '
 | ||
| # }}}
 | ||
| 
 | ||
| # Espace disque
 | ||
| alias df='df --block-size=1K --print-type --human-readable'
 | ||
| alias dus='du --total --human-readable | sort --human-numeric-sort'
 | ||
| alias dua='du --all --total --human-readable  | sort --human-numeric-sort'
 | ||
| alias ncdu='gdu'
 | ||
| 
 | ||
| # Gestion des processus:
 | ||
| # Si htop n'est pas installé sur la machine:
 | ||
| if [ ! -f "`which htop`" ]; then
 | ||
|   alias htop=top
 | ||
| fi
 | ||
| 
 | ||
| # Qu'est-ce qui consomme de la mémoire vive sur le système
 | ||
| alias wotgobblemem='ps -o time,ppid,pid,nice,pcpu,pmem,user,comm -A | sort --numeric-sort --key=6 | tail -15'
 | ||
| 
 | ||
| # ps aliases
 | ||
| alias px='ps faux|grep --invert-match -- grep|grep --extended-regexp --ignore-case --regexp=VSZ -e '
 | ||
| ## ps with fzf
 | ||
| alias fpx="ps -ef | fzf --bind 'ctrl-r:reload(ps -ef)' --header 'Press CTRL-R to reload' --header-lines=1 --color fg:188,bg:233,hl:103,fg+:222,bg+:234,hl+:104"
 | ||
| alias pxf="ps -ef | fzf --bind 'ctrl-r:reload(ps -ef)' --header 'Press CTRL-R to reload' --header-lines=1 --color fg:188,bg:233,hl:103,fg+:222,bg+:234,hl+:104"
 | ||
| ## ps last entries with watch|tail|grep
 | ||
| alias wps="watch \"ps faux | tail --lines=30 -- | grep --invert-match --extended-regexp '(tail|ps faux|grep)' --\""
 | ||
| alias psw="watch \"ps faux | tail --lines=30 -- | grep --invert-match --extended-regexp '(tail|ps faux|grep)' --\""
 | ||
| 
 | ||
| # Décompression
 | ||
| alias untargz='tar --gzip --extract --verbose -f'
 | ||
| alias untarbz2='tar --bzip2 --extract --verbose -f'
 | ||
| 
 | ||
| # Terminal multiplexer
 | ||
| alias ta='tmux a || tmux'
 | ||
| alias td='tmux detach'
 | ||
| 
 | ||
| # Send the content of a file to a privatebin
 | ||
| # Needs cpaste or any other Third party clients for PrivateBin
 | ||
| # https://github.com/PrivateBin/PrivateBin/wiki/Third-party-clients
 | ||
| alias pbin='~/repos/cpaste/cpaste --sourcecode --expire 1week --file '
 | ||
| 
 | ||
| ## Git aliases − Try to prefix with 'gg' {{{
 | ||
| ### Get status of the repo
 | ||
| alias ggstatus='git status'
 | ||
| ### Show differences between changes and index and ensure to display colors even with a pipe
 | ||
| alias ggdiff='git diff --color=always'
 | ||
| ### Show differences between changes and index WITHOUT any colors
 | ||
| alias ggnocolordiff='git diff --color=never'
 | ||
| ### Show only words/characters differences
 | ||
| alias ggwdiff='git diff --color-words=. --patience'
 | ||
| ### Add changes to index
 | ||
| alias ggadd='git add'
 | ||
| ### Restore changes to be committed
 | ||
| alias ggrestore='git restore --staged'
 | ||
| ### Remove files from the index
 | ||
| alias ggrm='git rm'
 | ||
| ### Move or rename file
 | ||
| alias ggmv='git mv'
 | ||
| ### Cancel changes
 | ||
| alias ggcheckout='git checkout --'
 | ||
| ### Print lines matching a pattern
 | ||
| alias ggrep='git grep --color --line-number --perl-regexp'
 | ||
| alias gggrep='git grep --color --line-number --perl-regexp'
 | ||
| ### Show commit logs
 | ||
| alias gglog="git log --graph --full-history --all --color --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'"
 | ||
| ### Show last 20 commits with graph
 | ||
| alias gglg="git --no-pager log --graph --pretty=tformat:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%an %ar)%Creset' -20"
 | ||
| ### Show all commits with graph
 | ||
| alias ggllg="git log --graph --pretty=tformat:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%an %ar)%Creset'"
 | ||
| ### Display all commits/changes of a file
 | ||
| alias ggchanges="git log --follow --perl-regexp --"
 | ||
| 
 | ||
| ### Commands that might require a valid gpg-agent
 | ||
| #### Download any new commits
 | ||
| alias ggpull='load-gpg-agent && git pull'
 | ||
| #### Commit changes
 | ||
| alias ggco='load-gpg-agent && git commit'
 | ||
| alias ggcommit='load-gpg-agent && git commit'
 | ||
| #### Amend changes
 | ||
| alias ggamend='load-gpg-agent && git commit --amend'
 | ||
| #### Update remote repository
 | ||
| alias ggpush='load-gpg-agent && git push'
 | ||
| ## }}}
 | ||
| 
 | ||
| # Lister les fichiers de configuration inutiles
 | ||
| alias purge='grep-status --no-field-names --show-field=Package --field=Status config-files'
 | ||
| 
 | ||
| ## Piped alias
 | ||
| alias -g H='| head'
 | ||
| alias -g T='tail --follow'
 | ||
| alias -g G='| grep --invert-match grep -- | grep --extended-regexp'
 | ||
| alias -g L='| less'
 | ||
| alias -g M="| most"
 | ||
| alias -g S="| sort"
 | ||
| alias -g V="| vimmanpager"
 | ||
| alias -g W="| wc --lines"
 | ||
| alias -g X="| xclip -selection clipboard"
 | ||
| alias -g TM="| tmux load-buffer -- -"
 | ||
| alias -g B="&|"
 | ||
| alias -g HL="--help"
 | ||
| alias -g MM="2>&1 | most"
 | ||
| alias -g LL="2>&1 | less"
 | ||
| alias -g CA="2>&1 | cat --show-all"
 | ||
| alias -g NE="2> /dev/null"
 | ||
| alias -g NUL="> /dev/null 2>&1"
 | ||
| 
 | ||
| ## Affichage de l'historique
 | ||
| if [ "$PAGER" = "most" ]; then
 | ||
|   # En commencant par la fin avec most (bidouillage, on est pas sensé avoir):
 | ||
|   alias hist="fc -El 0 | most +$HISTSIZE"
 | ||
|   # Une fois dans un fichier avec most, la touche 'B' permet d'aller à la fin du fichier
 | ||
| else
 | ||
|   # En commencant par la fin avec less:
 | ||
|   alias hist="fc -El 0 | $PAGER +G"
 | ||
|   #alias hist="less +G ~/.zsh/history"
 | ||
| fi
 | ||
| alias ghist='fc -El 0 | grep --'
 | ||
| 
 | ||
| ## Gestion des répertoires
 | ||
| alias u='cd ..'
 | ||
| alias cd..='cd ..'
 | ||
| alias ..='cd ..'
 | ||
| alias ...='cd ../..'
 | ||
| alias ....='cd ../../..'
 | ||
| # Revenir dans le dossier dans lequel on se trouvait précédemment
 | ||
| alias cd-='cd -'
 | ||
| alias uu='cd -'
 | ||
| alias uuu='cd -2'
 | ||
| # Afficher la pile des dossiers:
 | ||
| alias dirs='dirs -v'
 | ||
| # Créer les répertoires précédents si ils n'existent pas
 | ||
| alias mkdir='mkdir --parents'
 | ||
| # Affiche l'arborescence du répertoire courant
 | ||
| #alias tree="find . | sed 's/[^/]*\//|   /g;s/| *\([^| ]\)/+--- \1/'"
 | ||
| #La commande tree "basique" fait ça très bien ...
 | ||
| 
 | ||
| # Affiche la variable $PATH ligne par ligne
 | ||
| alias path='printf %s $PATH | tr ":" "\n"'
 | ||
| 
 | ||
| # Edite le dernier fichier d'un dossier
 | ||
| ## Fonctionement:
 | ||
| ## (. correspond au fichier
 | ||
| ## om les classent par date de modification
 | ||
| ## [1] choisit le premier
 | ||
| ##  désactive les options GLOB_DOTS
 | ||
| alias vil='vi *(.om[1]^D)'
 | ||
| # Lancer vi pour qu'il ne conserve aucune trace du fichier
 | ||
| ## Faire précéder la commande d'un espace empêche l'enregistrement dans l'historique du shell
 | ||
| alias vnb='vi -n "+set noundofile" "+set nobackup"'
 | ||
| 
 | ||
| # Différence entre deux fichiers
 | ||
| alias diff='colordiff -u'
 | ||
| alias diffs='\diff --side-by-side'
 | ||
| 
 | ||
| # Recherche toutes les occurences de l'arguments passé en paramètre dans l'historique des commandes
 | ||
| alias param='fc -l 0 | grep --'
 | ||
| 
 | ||
| # Multimédia
 | ||
| ##Extraire la piste audio d'un .avi
 | ||
| alias avi2wav='mplayer -vc dummy -vo null -ao pcm:file=video.wav'
 | ||
| ##Modifie la bar de progression du gestionnaire de téléchargement Axel
 | ||
| alias axel='axel -a --num-connection=20'
 | ||
| ## List video file's subtitles
 | ||
| alias ff.list.subs='ffprobe -loglevel error -select_streams s -show_entries stream=index:stream_tags=language -of csv=p=0'
 | ||
| ## List video file's audio stream
 | ||
| alias ff.list.audio='ffprobe -loglevel error -select_streams a -show_entries stream=index:stream_tags=language -of csv=p=0'
 | ||
| 
 | ||
| # Calculatrice en ligne de commande
 | ||
| alias caltos='bc'
 | ||
| 
 | ||
| #alias df='df --human-readable'
 | ||
| #alias du='du --human-readable'
 | ||
| alias m='mutt -y'
 | ||
| alias md='mkdir'
 | ||
| alias rd='rmdir'
 | ||
| 
 | ||
| #Internet
 | ||
| ## Minimal webserver from current directory and available at http://IP.AD.RE.SS:8002
 | ||
| ## See : https://docs.python.org/3/library/http.server.html
 | ||
| alias httpserv="python3 -m http.server -b $(ip route get 1 | awk '{print $(NF-2);exit}') 8002"
 | ||
| ## Minimal webserver with upload option and storage in dedicated directory
 | ||
| alias httpup="mkdir --parent -- /tmp/http.upload.directory && cd -- /tmp/http.upload.directory && python3 ${HOME}/bin/upload-http-server.py --listen $(ip route get 1 | awk '{print $(NF-2);exit}') --port 8004"
 | ||
| 
 | ||
| ## Limite l'envoi à 3 requêtes pour ping
 | ||
| alias ping="ping -c 3"
 | ||
| alias ping6="ping6 -c 3"
 | ||
| 
 | ||
| ## JOSM
 | ||
| alias josm="java -jar -Xmx2048M /opt/josm-tested.jar"
 | ||
| 
 | ||
| # Khard
 | ||
| alias kemail='khard email'
 | ||
| alias kmail='khard email'
 | ||
| alias kphone='khard phone'
 | ||
| alias ktel='khard phone'
 | ||
| 
 | ||
| # SSH {{{
 | ||
| #########
 | ||
| 
 | ||
| # Load ssh-agent with a fix socket path {{{
 | ||
| ## This function can be used :
 | ||
| ##   1. in zlogin (for a new shell)
 | ||
| ##   2. with recossh alias to load a new ssh-agent
 | ||
| function load-ssh-agent() {
 | ||
| 	# If a ssh-key is available
 | ||
| 	if find "${HOME}/.ssh" -maxdepth 1 -type f -iname "id_*" | grep --quiet -- .; then
 | ||
| 		## If ssh-agent is not already launched
 | ||
| 		if ! ps -x | grep --invert-match -- grep | grep --fixed-strings --quiet -- "ssh-agent -a ${SSH_AGENT_SOCK}"; then
 | ||
| 			### Remove any previous socket and environment files
 | ||
| 			rm --force -- "${SSH_AGENT_SOCK}" "${SSH_AGENT_ENV}"
 | ||
| 			### Start ssh-agent with a specified socket path
 | ||
| 			###   AND store informations in a file
 | ||
| 			ssh-agent -a "${SSH_AGENT_SOCK}" > "${SSH_AGENT_ENV}"
 | ||
| 		fi
 | ||
| 		## Load content of ssh-agent environment file
 | ||
| 		source "${SSH_AGENT_ENV}"
 | ||
| 	fi
 | ||
| }
 | ||
| # }}}
 | ||
| # Add ed25519 ssh-key to ssh-agent {{{
 | ||
| function load-ssh-ed25519() {
 | ||
| 	# If a ED25519 ssh-key is available
 | ||
| 	#   AND not already loaded in ssh-agent
 | ||
| 	if [ -f "${SSH_ED25519_KEY}" ] &&
 | ||
| 		! ssh-add -l | grep --quiet --ignore-case -- "(ed25519)"; then
 | ||
| 			ssh-add "${SSH_ED25519_KEY}"
 | ||
| 	fi
 | ||
| }
 | ||
| # }}}
 | ||
| # Add rsa ssh-key to ssh-agent {{{
 | ||
| function load-ssh-rsa() {
 | ||
| 	# If a RSA ssh-key is available
 | ||
| 	#   AND not already loaded in ssh-agent
 | ||
| 	if [ -f "${SSH_RSA_KEY}" ] &&
 | ||
| 	   ! ssh-add -l | grep --quiet --ignore-case -- "(rsa)"; then
 | ||
| 		ssh-add "${SSH_RSA_KEY}"
 | ||
| 	fi
 | ||
| }
 | ||
| # }}}
 | ||
| # Clear old entries in known_hosts {{{
 | ||
| function clearsshkey() {
 | ||
| 	sed -i "${1}d" ~/.ssh/known_hosts
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # recossh will:
 | ||
| #  (re)load ssh-agent informations
 | ||
| #  run the previous ssh command
 | ||
| alias recossh='load-ssh-agent &&
 | ||
| 	$(fc -lr 4900 | \grep --max-count=1 --extended-regexp "[0-9]{1,4}  ssh " | cut --delimiter=" " --fields=4-)'
 | ||
| 
 | ||
| # For development and tests
 | ||
| alias sshdev='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=accept-new'
 | ||
| alias sshdev-copy-id='ssh-copy-id -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=accept-new'
 | ||
| alias scpdev='scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=accept-new'
 | ||
| 
 | ||
| # }}}
 | ||
| 
 | ||
| # GPG {{{
 | ||
| #########
 | ||
| 
 | ||
| # (re)Load gpg-agent {{{
 | ||
| ## This function can be used :
 | ||
| ##   1. with aliases (git commit,…)
 | ||
| function load-gpg-agent() {
 | ||
| 	## If a gpg key is available
 | ||
| 	if [ -f "${GPG_PRIV_KEY}" ]; then
 | ||
| 		## Remove any previous test file
 | ||
| 		rm --force -- "${GPG_TEST_FILE}"
 | ||
| 		## Run a gpg command on the test file
 | ||
| 		gpg --quiet --for-your-eyes-only --decrypt "${GPG_TEST_FILE}.gpg" > /dev/null
 | ||
| 	fi
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # }}}
 | ||
| 
 | ||
| # Taskwarrior {{{
 | ||
| ## Aliases
 | ||
| alias t="task"
 | ||
| ### Most recent tasks first
 | ||
| alias tarecent="task simple limit:page"
 | ||
| alias taold="task oldest limit:page"
 | ||
| ### All pending tasks
 | ||
| alias tapending="task rc._forcecolor:on +PENDING all | less"
 | ||
| ### Filter by tag
 | ||
| alias tawork="task rc._forcecolor:on +work | head"
 | ||
| alias taperso="task rc._forcecolor:on +perso | head"
 | ||
| alias tarm=tadel
 | ||
| 
 | ||
| ## Functions
 | ||
| ## search in pending tasks by task's name (case INsensitive) {{{
 | ||
| function tase() {
 | ||
| 	local search=""
 | ||
| 	for i; do; search="$search /$i/"; done;
 | ||
| 	task rc.search.case.sensitive:no +PENDING $search all || return 0
 | ||
| }
 | ||
| ## }}}
 | ||
| ## search in pending tasks by task's name (case SENSITIVE) {{{
 | ||
| function tasec() {
 | ||
| 	local search=""
 | ||
| 	for i; do; search="$search /$i/"; done;
 | ||
| 	task $search +PENDING all || return 0
 | ||
| }
 | ||
| ## }}}
 | ||
| ## search in all tasks by task's name (case INsensitive) {{{
 | ||
| function tall() {
 | ||
| 	local search=""
 | ||
| 	for i; do; search="$search /$i/"; done;
 | ||
| 	task rc.search.case.sensitive:no $search all || return 0
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Delete a task {{{
 | ||
| function tadel() {
 | ||
| 	local tadel_task_id
 | ||
| 	local tadel_task_desc
 | ||
| 	local tadel_confirmation
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	if [ "${#}" -eq 1 ]; then
 | ||
| 		## Get the first arg as task ID
 | ||
| 		tadel_task_id="${1}"
 | ||
| 	else
 | ||
| 		## If no argument or more than one
 | ||
| 		## Ask the user to choose an ID in the 20 more recents tasks {{{
 | ||
| 		task newest limit:20 || return 0
 | ||
| 
 | ||
| 		printf '%b' "Enter the ${MAGENTAB}ID${RESET} of the task to remove : "
 | ||
| 		read -r tadel_task_id
 | ||
| 		## }}}
 | ||
| 	fi
 | ||
| 
 | ||
| 	# If no task with this ID exists, exit function {{{
 | ||
| 	if ! task "${tadel_task_id}" | grep --quiet -- "^ID *${tadel_task_id}"; then
 | ||
| 		printf '%b' "No available task with ${REDB}${tadel_task_id}${RESET} ID."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	# Get task's description
 | ||
| 	tadel_task_desc=$(task "${tadel_task_id}" | sed --quiet "s/^Description *\(.*\)/\1/p")
 | ||
| 
 | ||
| 	printf '%b' "Delete the task \"${MAGENTAB}${tadel_task_id} − ${tadel_task_desc}${RESET}\" [Y/n] ? "
 | ||
| 	read -r tadel_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${tadel_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 		task rc.confirmation:no "${tadel_task_id}" delete
 | ||
| 		printf '%b' "\"${MAGENTAB}${tadel_task_id} − ${tadel_task_desc}${RESET}\" task was removed.\n"
 | ||
| 	fi
 | ||
| 
 | ||
| 	# Also offer to purge this task
 | ||
| 	tapurge "${tadel_task_desc}"
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Mark a task as done {{{
 | ||
| function tadone() {
 | ||
| 	local tadone_task_regexp
 | ||
| 	local tadone_task_id
 | ||
| 	local tadone_task_desc
 | ||
| 	local tadone_confirmation
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		## If no argument
 | ||
| 		## Ask the user to choose a task description from the last week Timewarrior activities {{{
 | ||
| 		timew summary :week :ids || return 0
 | ||
| 
 | ||
| 		printf '%b' "Enter the ${MAGENTAB}a pattern${RESET} matching the expected task to mark as complete : "
 | ||
| 		read -r tadone_task_regexp
 | ||
| 	else
 | ||
| 		## Merge all args into one var
 | ||
| 		tadone_task_regexp="${*}"
 | ||
| 		## }}}
 | ||
| 	fi
 | ||
| 
 | ||
| 	#printf '%b' "Pattern to search a task is ${REDB}${tadone_task_regexp}${RESET}.\n"
 | ||
| 	tadone_task_id=$(task "${tadone_task_regexp}" simpleid | grep --after-context=2 -- ID | tail --lines=1 || return 0)
 | ||
| 
 | ||
| 	# If no task with this ID exists, exit function {{{
 | ||
| 	if [ -z "${tadone_task_id}" ]; then
 | ||
| 		printf '%b' "No available task with ${REDB}${tadone_task_regexp}${RESET} pattern."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	# Get task's description
 | ||
| 	tadone_task_desc=$(task "${tadone_task_id}" | sed --quiet "s/^Description *\(.*\)/\1/p")
 | ||
| 
 | ||
| 	printf '%b' "Mark the task \"${MAGENTAB}${tadone_task_id} − ${tadone_task_desc}${RESET}\" as done [Y/n] ? "
 | ||
| 	read -r tadone_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${tadone_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 		task "${tadone_task_id}" done
 | ||
| 		printf '%b' "\"${MAGENTAB}${tadone_task_id} − ${tadone_task_desc}${RESET}\" task is now complete."
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Purge an old task {{{
 | ||
| function tapurge() {
 | ||
| 	local tapurge_task_regexp
 | ||
| 	local tapurge_task_desc
 | ||
| 	local tapurge_confirmation
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		## If no argument
 | ||
| 		## Ask the user to choose a task description from the deleted tasks list {{{
 | ||
| 		task all status:deleted || return 0
 | ||
| 
 | ||
| 		printf '%b' "Enter few ${MAGENTAB}words matching the description${RESET} of the expected task to purge : "
 | ||
| 		read -r tapurge_task_regexp
 | ||
| 	else
 | ||
| 		## Merge all args into one var
 | ||
| 		tapurge_task_regexp="${*}"
 | ||
| 		## }}}
 | ||
| 	fi
 | ||
| 
 | ||
| 	tapurge_task_desc=$(task "${tapurge_task_regexp}" simpledeleted | grep --after-context=2 -- "^Description" | tail --lines=1 || return 0)
 | ||
| 
 | ||
| 	# If no task with this Description exists, exit function {{{
 | ||
| 	if [ -z "${tapurge_task_desc}" ]; then
 | ||
| 		printf '%b' "No available task with ${REDB}${tapurge_task_regexp}${RESET} pattern."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	printf '%b' "Completly purge the task \"${MAGENTAB}${tapurge_task_desc}${RESET}\" [Y/n] ? "
 | ||
| 	read -r tapurge_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${tapurge_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 		task rc.confirmation:no "${tapurge_task_desc}" purge
 | ||
| 		printf '%b' "\"${MAGENTAB}${tapurge_task_desc}${RESET}\" was purged."
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Take note for a task {{{
 | ||
| function tanote() {
 | ||
| 	local tanote_task_regexp
 | ||
| 	local tanote_task_id
 | ||
| 	local tanote_task_desc
 | ||
| 	local tanote_confirmation
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		## If no argument
 | ||
| 		## Ask the user to choose a task description from the recent tasks {{{
 | ||
| 		task simple limit:page || return 0
 | ||
| 
 | ||
| 		printf '%b' "Enter ${MAGENTAB}a pattern${RESET} matching the expected task that need notes : "
 | ||
| 		read -r tanote_task_regexp
 | ||
| 	else
 | ||
| 		## Merge all args into one var
 | ||
| 		tanote_task_regexp="${*}"
 | ||
| 		## }}}
 | ||
| 	fi
 | ||
| 
 | ||
| 	tanote_task_id=$(task "${tanote_task_regexp}" simpleid | grep --after-context=2 -- ID | tail --lines=1 || return 0)
 | ||
| 
 | ||
| 	# If no task with this ID exists, exit function {{{
 | ||
| 	if [ -z "${tanote_task_id}" ]; then
 | ||
| 		printf '%b' "No available task with ${REDB}${tanote_task_regexp}${RESET} pattern."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	# Get task's description
 | ||
| 	tanote_task_desc=$(task "${tanote_task_id}" | sed --quiet "s/^Description *\(.*\)/\1/p")
 | ||
| 
 | ||
| 	printf '%b' "Add notes to \"${MAGENTAB}${tanote_task_id} − ${tanote_task_desc}${RESET}\" task [Y/n] ? "
 | ||
| 	read -r tanote_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${tanote_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 		task note "${tanote_task_id}"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| 
 | ||
| ## Completion {{{
 | ||
| zstyle ':completion:*:*:task:*' verbose yes
 | ||
| zstyle ':completion:*:*:task:*:descriptions' format '%U%B%d%b%u'
 | ||
| zstyle ':completion:*:*:task:*' group-name ''
 | ||
| ## }}}
 | ||
| # }}}
 | ||
| # Timewarrior {{{
 | ||
| ## Aliases
 | ||
| alias tid="tiday"
 | ||
| alias tiw="tiweek"
 | ||
| alias tim="timonth"
 | ||
| alias timv="timove"
 | ||
| alias tiresize="tiduration"
 | ||
| 
 | ||
| ## Functions
 | ||
| ## Display tasks of today {{{
 | ||
| function tiday() {
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		timew summary :day :ids || return 0
 | ||
| 	else
 | ||
| 		timew summary :day :ids "${*}" || return 0
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Display tasks of last day {{{
 | ||
| function tilastday() {
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		timew summary :yesterday :ids || return 0
 | ||
| 	else
 | ||
| 		timew summary :yesterday :ids "${*}" || return 0
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Display tasks of this week {{{
 | ||
| function tiweek() {
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		timew summary :week :ids || return 0
 | ||
| 	else
 | ||
| 		timew summary :week :ids "${*}" || return 0
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Display tasks of last week {{{
 | ||
| function tilastweek() {
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		timew summary :lastweek :ids || return 0
 | ||
| 	else
 | ||
| 		timew summary :lastweek :ids "${*}" || return 0
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Display tasks of this month {{{
 | ||
| function timonth() {
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		timew summary :month :ids || return 0
 | ||
| 	else
 | ||
| 		timew summary :month :ids "${*}" || return 0
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Display tasks of last month {{{
 | ||
| function tilastmonth() {
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		timew summary :lastmonth :ids || return 0
 | ||
| 	else
 | ||
| 		timew summary :lastmonth :ids "${*}" || return 0
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Display tasks of this year {{{
 | ||
| function tiyear() {
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		timew summary :year :ids || return 0
 | ||
| 	else
 | ||
| 		timew summary :year :ids "${*}" || return 0
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Display tasks of last year {{{
 | ||
| function tilastyear() {
 | ||
| 	if [ "${#}" -eq 0 ]; then
 | ||
| 		timew summary :lastyear :ids || return 0
 | ||
| 	else
 | ||
| 		timew summary :lastyear :ids "${*}" || return 0
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Double spent time on a task {{{
 | ||
| ## "double" cause by default my tasks runs for 25 minutes
 | ||
| function tidouble() {
 | ||
| 	# Default duration time to add to a task
 | ||
| 	local tidouble_extra_time="25mins"
 | ||
| 	local tidouble_task_id
 | ||
| 	local tidouble_confirmation
 | ||
| 	local tidouble_task_desc
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	if [ "${#}" -eq 1 ]; then
 | ||
| 		## Get the first arg as task ID
 | ||
| 		tidouble_task_id="${1}"
 | ||
| 	else
 | ||
| 		## If no argument or more than one
 | ||
| 		## Ask the user to choose an ID in tasks from the yesterday {{{
 | ||
| 		timew summary from yesterday :ids || return 0
 | ||
| 
 | ||
| 		printf '%b' "Enter the ${MAGENTAB}ID${RESET} of the task to double spent time should be doubled : "
 | ||
| 		read -r tidouble_task_id
 | ||
| 		## }}}
 | ||
| 	fi
 | ||
| 
 | ||
| 	# If no task with this ID exists, exit function {{{
 | ||
| 	if ! timew summary :year :ids | grep --quiet -- " @${tidouble_task_id} "; then
 | ||
| 		printf '%b' "No available task in the last year with ${REDB}${tidouble_task_id}${RESET} ID."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	# Get task's description from all task of this year
 | ||
| 	tidouble_task_desc=$(timew summary :year :ids | sed --quiet "s/.*@\(${tidouble_task_id} .*\)/\1/p" | sed 's/   */ − /g')
 | ||
| 
 | ||
| 	printf '%b' "Add ${tidouble_extra_time} to \"${MAGENTAB}${tidouble_task_desc}${RESET}\" [Y/n] ? "
 | ||
| 	read -r tidouble_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${tidouble_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 		timew lengthen @"${tidouble_task_id}" "${tidouble_extra_time}" || return 0
 | ||
| 		timew split @"${tidouble_task_id}" || return 0
 | ||
| 		printf '%b' "${tidouble_extra_time} were added to \"${MAGENTAB}${tidouble_task_desc}${RESET}\" task."
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Delete a time tracking {{{
 | ||
| function tirm() {
 | ||
| 	local tirm_task_id
 | ||
| 	local tirm_task_desc
 | ||
| 	local tirm_confirmation
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	if [ "${#}" -eq 1 ]; then
 | ||
| 		## Get the first arg as task ID
 | ||
| 		tirm_task_id="${1}"
 | ||
| 	else
 | ||
| 		## If no argument or more than one
 | ||
| 		## Ask the user to choose an ID in tasks from the yesterday {{{
 | ||
| 		timew summary from yesterday :ids || return 0
 | ||
| 
 | ||
| 		printf '%b' "Enter the ${MAGENTAB}ID${RESET} of the task to delete : "
 | ||
| 		read -r tirm_task_id
 | ||
| 		## }}}
 | ||
| 	fi
 | ||
| 
 | ||
| 	# If no task with this ID exists, exit function {{{
 | ||
| 	if ! timew summary :year :ids | grep --quiet -- " @${tirm_task_id} "; then
 | ||
| 		printf '%b' "No available task in the last year with ${REDB}${tirm_task_id}${RESET} ID."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	# Get task's description from all task of this year
 | ||
| 	tirm_task_desc=$(timew summary :year :ids | sed --quiet "s/.*@\(${tirm_task_id} .*\)/\1/p" | sed 's/   */ − /g')
 | ||
| 
 | ||
| 	printf '%b' "Delete to \"${MAGENTAB}${tirm_task_desc}${RESET}\" [Y/n] ? "
 | ||
| 	read -r tirm_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${tirm_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 		timew delete @"${tirm_task_id}" || return 0
 | ||
| 		printf '%b' "${tirm_task_desc} was deleted"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Modify the start of a time tracking {{{
 | ||
| function tistart() {
 | ||
| 
 | ||
| 	# Define new_start empty by default
 | ||
| 	local tistart_time_new_start=""
 | ||
| 	local tistart_time_id
 | ||
| 	local tistart_time_desc
 | ||
| 	local tistart_time_start_day
 | ||
| 	local tistart_confirmation
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	case "${#}" in
 | ||
| 		1 )
 | ||
| 			## Get the first arg as time ID
 | ||
| 			tistart_time_id="${1}"
 | ||
| 			;;
 | ||
| 		2 )
 | ||
| 			## Get the first arg as time ID
 | ||
| 			tistart_time_id="${1}"
 | ||
| 
 | ||
| 			## Get the second arg as new start time for this track
 | ||
| 			tistart_time_new_start="${2}"
 | ||
| 			;;
 | ||
| 		* )
 | ||
| 			## Ask the user to choose an ID in time tracking from the yesterday {{{
 | ||
| 			timew summary from yesterday :ids || return 0
 | ||
| 
 | ||
| 			printf '%b' "Enter the ${MAGENTAB}ID${RESET} of the time tracking to modify : "
 | ||
| 			read -r tistart_time_id
 | ||
| 			## }}}
 | ||
| 			;;
 | ||
| 	esac
 | ||
| 
 | ||
| 	# If no time tracking exists with this ID, exit function {{{
 | ||
| 	if ! timew summary :year :ids | grep --quiet -- " @${tistart_time_id} "; then
 | ||
| 		printf '%b' "No available time tracking in the last year with ${REDB}${tistart_time_id}${RESET} ID."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	# Get time tracking's description from all time tracking of this year
 | ||
| 	tistart_time_desc=$(timew summary :year :ids | sed --quiet "s/.*@\(${tistart_time_id} .*\)/\1/p" | sed 's/   */ − /g')
 | ||
| 
 | ||
| 	# Get time tracking's start day from all time tracking
 | ||
| 	tistart_time_start_day=$(timew export | sed --quiet --regexp-extended "s/^\{\"id\":${tistart_time_id},\"start\":\"([0-9]{4})([0-9]{2})([0-9]{2})T.*end.*/\1-\2-\3/p")
 | ||
| 
 | ||
| 	# Check or ask for new start time {{{
 | ||
| 	if [ -z "${tistart_time_new_start}" ]; then
 | ||
| 			printf '%b' "Enter the ${MAGENTAB}new start time${RESET} (or new date 'YYYY-MM-DD${REDB}T${RESET}HH:MM:SS'; default day is ${tistart_time_start_day}) for this time tracking : "
 | ||
| 			read -r tistart_time_new_start
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	printf '%b' "Change start time of \"${MAGENTAB}${tistart_time_desc}${RESET}\" to ${REDB}=> ${tistart_time_new_start} <=${RESET} [Y/n] ? "
 | ||
| 	read -r tistart_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${tistart_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 		## If the new start time entered by user contains a "T" (user enter a dateTtime)
 | ||
| 		if printf -- '%s' "${tistart_time_new_start}" | grep --quiet -- "T"; then
 | ||
| 			printf '%b' "start time of ${tistart_time_desc} is now ${tistart_time_new_start}."
 | ||
| 			timew modify start @"${tistart_time_id}" "${tistart_time_new_start}" || return 0
 | ||
| 		else
 | ||
| 			printf '%b' "start time of ${tistart_time_desc} is now ${tistart_time_start_day}T${tistart_time_new_start}."
 | ||
| 			timew modify start @"${tistart_time_id}" "${tistart_time_start_day}T${tistart_time_new_start}" || return 0
 | ||
| 		fi
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Modify the end of a time tracking {{{
 | ||
| function tiend() {
 | ||
| 
 | ||
| 	# Define new_end empty by default
 | ||
| 	local tiend_time_new_end=""
 | ||
| 	local tiend_time_id
 | ||
| 	local tiend_time_new_end
 | ||
| 	local tiend_time_desc
 | ||
| 	local tiend_time_start_day
 | ||
| 	local tiend_confirmation
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	case "${#}" in
 | ||
| 		1 )
 | ||
| 			## Get the first arg as time ID
 | ||
| 			tiend_time_id="${1}"
 | ||
| 			;;
 | ||
| 		2 )
 | ||
| 			## Get the first arg as time ID
 | ||
| 			tiend_time_id="${1}"
 | ||
| 
 | ||
| 			## Get the second arg as new end time for this track
 | ||
| 			tiend_time_new_end="${2}"
 | ||
| 			;;
 | ||
| 		* )
 | ||
| 			## Ask the user to choose an ID in time tracking from the yesterday {{{
 | ||
| 			timew summary from yesterday :ids || return 0
 | ||
| 
 | ||
| 			printf '%b' "Enter the ${MAGENTAB}ID${RESET} of the time tracking to modify : "
 | ||
| 			read -r tiend_time_id
 | ||
| 			## }}}
 | ||
| 			;;
 | ||
| 	esac
 | ||
| 
 | ||
| 	# If no time tracking exists with this ID, exit function {{{
 | ||
| 	if ! timew summary :year :ids | grep --quiet -- " @${tiend_time_id} "; then
 | ||
| 		printf '%b' "No available time tracking in the last year with ${REDB}${tiend_time_id}${RESET} ID."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	# Get time tracking's description from all time tracking of this year
 | ||
| 	tiend_time_desc=$(timew summary :year :ids | sed --quiet "s/.*@\(${tiend_time_id} .*\)/\1/p" | sed 's/   */ − /g')
 | ||
| 
 | ||
| 	# Get time tracking's start day from all time tracking
 | ||
| 	tiend_time_start_day=$(timew export | sed --quiet --regexp-extended "s/^\{\"id\":${tiend_time_id},\"start\":\"([0-9]{4})([0-9]{2})([0-9]{2})T.*end.*/\1-\2-\3/p")
 | ||
| 
 | ||
| 	# Check or ask for new end time {{{
 | ||
| 	if [ -z "${tiend_time_new_end}" ]; then
 | ||
| 			printf '%b' "Enter the ${MAGENTAB}new end time${RESET} (or new date 'YYYY-MM-DD${REDB}T${RESET}HH:MM:SS'; default day is ${tiend_time_start_day}) for this time tracking : "
 | ||
| 			read -r tiend_time_new_end
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	printf '%b' "Change end time of \"${MAGENTAB}${tiend_time_desc}${RESET}\" to ${REDB}=> ${tiend_time_new_end} <=${RESET} [Y/n] ? "
 | ||
| 	read -r tiend_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${tiend_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 		## If the new end time entered by user contains a "T" (user enter a dateTtime)
 | ||
| 		if printf -- '%s' "${tiend_time_new_end}" | grep --quiet -- "T"; then
 | ||
| 			timew modify end @"${tiend_time_id}" "${tiend_time_new_end}" || return 0
 | ||
| 			printf '%b' "End time of ${tiend_time_desc} is now ${tiend_time_new_end}."
 | ||
| 		else
 | ||
| 			timew modify end @"${tiend_time_id}" "${tiend_time_start_day}T${tiend_time_new_end}" || return 0
 | ||
| 			printf '%b' "End time of ${tiend_time_desc} is now ${tiend_time_start_day}T${tiend_time_new_end}."
 | ||
| 		fi
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Modify the duration of a time tracking {{{
 | ||
| function tiduration() {
 | ||
| 
 | ||
| 	# Define new_duration empty by default
 | ||
| 	local tiduration_time_new_duration=""
 | ||
| 	local tiduration_time_id
 | ||
| 	local tiduration_time_new_duration
 | ||
| 	local tiduration_time_desc
 | ||
| 	local tiduration_confirmation
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	case "${#}" in
 | ||
| 		1 )
 | ||
| 			## Get the first arg as time ID
 | ||
| 			tiduration_time_id="${1}"
 | ||
| 			;;
 | ||
| 		2 )
 | ||
| 			## Get the first arg as time ID
 | ||
| 			tiduration_time_id="${1}"
 | ||
| 
 | ||
| 			## Get the second arg as new end time for this track
 | ||
| 			tiduration_time_new_duration="${2}"
 | ||
| 			;;
 | ||
| 		* )
 | ||
| 			## Ask the user to choose an ID in time tracking from the yesterday {{{
 | ||
| 			timew summary from yesterday :ids || return 0
 | ||
| 
 | ||
| 			printf '%b' "Enter the ${MAGENTAB}ID${RESET} of the time tracking to modify : "
 | ||
| 			read -r tiduration_time_id
 | ||
| 			## }}}
 | ||
| 			;;
 | ||
| 	esac
 | ||
| 
 | ||
| 	# If no time tracking exists with this ID, exit function {{{
 | ||
| 	if ! timew summary :year :ids | grep --quiet -- " @${tiduration_time_id} "; then
 | ||
| 		printf '%b' "No available time tracking in the last year with ${REDB}${tiduration_time_id}${RESET} ID."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	# Get time tracking's description from all time tracking of this year
 | ||
| 	tiduration_time_desc=$(timew summary :year :ids | sed --quiet "s/.*@\(${tiduration_time_id} .*\)/\1/p" | sed 's/   */ − /g')
 | ||
| 
 | ||
| 	# Check or ask for new end time {{{
 | ||
| 	if [ -z "${tiduration_time_new_duration}" ]; then
 | ||
| 			printf '%b' "Enter the ${MAGENTAB}new duration${RESET} (eg. 25mins, 1hour…) for this time tracking : "
 | ||
| 			read -r tiduration_time_new_duration
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	printf '%b' "Change duration of \"${MAGENTAB}${tiduration_time_desc}${RESET}\" to ${REDB}=> ${tiduration_time_new_duration} <=${RESET} [Y/n] ? "
 | ||
| 	read -r tiduration_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${tiduration_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 		timew resize @"${tiduration_time_id}" "${tiduration_time_new_duration}" || return 0
 | ||
| 		printf '%b' "Duration of ${tiduration_time_desc} is now ${tiduration_time_new_duration}."
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Move a time tracking {{{
 | ||
| function timove() {
 | ||
| 
 | ||
| 	# Define new_start empty by default
 | ||
| 	local timove_time_new_start=""
 | ||
| 	local timove_time_id
 | ||
| 	local timove_time_new_start
 | ||
| 	local timove_time_desc
 | ||
| 	local timove_time_start_day
 | ||
| 	local timove_confirmation
 | ||
| 
 | ||
| 	# Verify argument
 | ||
| 	case "${#}" in
 | ||
| 		1 )
 | ||
| 			## Get the first arg as task ID
 | ||
| 			timove_time_id="${1}"
 | ||
| 			;;
 | ||
| 		2 )
 | ||
| 			## Get the first arg as task ID
 | ||
| 			timove_time_id="${1}"
 | ||
| 
 | ||
| 			## Get the second arg as new start time for the task
 | ||
| 			timove_time_new_start="${2}"
 | ||
| 			;;
 | ||
| 		* )
 | ||
| 			## Ask the user to choose an ID in tasks from the yesterday {{{
 | ||
| 			timew summary from yesterday :ids || return 0
 | ||
| 
 | ||
| 			printf '%b' "Enter the ${MAGENTAB}ID${RESET} of the task to move : "
 | ||
| 			read -r timove_time_id
 | ||
| 			## }}}
 | ||
| 			;;
 | ||
| 	esac
 | ||
| 
 | ||
| 	# If no task with this ID exists in the last month, exit function {{{
 | ||
| 	if ! timew summary :month :ids | grep --quiet -- " @${timove_time_id} "; then
 | ||
| 		printf '%b' "No available task in the last month with ${REDB}${timove_time_id}${RESET} ID."
 | ||
| 		return 1
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	# Get task's description from all task of this month
 | ||
| 	timove_time_desc=$(timew summary :month :ids | sed --quiet "s/.*@\(${timove_time_id} .*\)/\1/p" | sed 's/   */ − /g')
 | ||
| 
 | ||
| 	# Get time tracking's start day from all time tracking
 | ||
| 	timove_time_start_day=$(timew export | sed --quiet --regexp-extended "s/^\{\"id\":${timove_time_id},\"start\":\"([0-9]{4})([0-9]{2})([0-9]{2})T.*end.*/\1-\2-\3/p")
 | ||
| 
 | ||
| 	# Check or ask for new start time {{{
 | ||
| 	if [ -z "${timove_time_new_start}" ]; then
 | ||
| 			printf '%b' "Enter the ${MAGENTAB}new start time${RESET} (or new date 'YYYY-MM-DD${REDB}T${RESET}HH:MM:SS'; default day is ${timove_time_start_day}) for this task : "
 | ||
| 			read -r timove_time_new_start
 | ||
| 	fi
 | ||
| 	# }}}
 | ||
| 
 | ||
| 	printf '%b' "Move \"${MAGENTAB}${timove_time_desc}${RESET}\" to ${REDB}=> ${timove_time_new_start} <=${RESET} [Y/n] ? "
 | ||
| 	read -r timove_confirmation
 | ||
| 
 | ||
| 	# Check confirmation
 | ||
| 	if printf -- '%s' "${timove_confirmation:=y}" | grep --quiet --word-regexp -- "y"; then
 | ||
| 
 | ||
| 		## If the new start time entered by user contains a "T" (user enter a dateTtime)
 | ||
| 		if printf -- '%s' "${timove_time_new_start}" | grep --quiet -- "T"; then
 | ||
| 			timew move @"${timove_time_id}" "${timove_time_new_start}" || return 0
 | ||
| 			printf '%b' "${timove_time_desc} was moved to ${timove_time_new_start}."
 | ||
| 		else
 | ||
| 			timew move @"${timove_time_id}" "${timove_time_start_day}T${timove_time_new_start}" || return 0
 | ||
| 			printf '%b' "start time of ${timove_time_desc} is now ${timove_time_start_day}T${timove_time_new_start}."
 | ||
| 		fi
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| 
 | ||
| # }}}
 | ||
| 
 | ||
| # DebOps {{{
 | ||
| ## Source DebOps user environment file {{{
 | ||
| if [ -f "${HOME}/.config/debops/environment" ]; then
 | ||
| 	source "${HOME}/.config/debops/environment"
 | ||
| fi
 | ||
| ## }}}
 | ||
| ## Direct access to DebOps's directories
 | ||
| alias dero="cd ${DEBOPS_VENV_ROLES:-/dev/null}"
 | ||
| alias deplay="cd ${DEBOPS_VENV_PLAYBOOKS:-/dev/null}"
 | ||
| 
 | ||
| ## Apply full config to a define host(s)/group(s) {{{
 | ||
| function debhost() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		debops run site --limit "${ANS_HOST}"
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Apply a role to a define host(s)/group(s) {{{
 | ||
| function debrole() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		debops run site --limit "${ANS_HOST}" --tags "role::${1:-/dev/null}"
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Apply the role from a service to a define host(s)/group(s) {{{
 | ||
| function debserv() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		debops run service/"${1:-/dev/null}" --limit "${ANS_HOST}" --tags "role::${1:-/dev/null}"
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Apply a role from a service to a define host(s)/group(s) {{{
 | ||
| function debservice() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		debops run service/"${1:-/dev/null}" --limit "${ANS_HOST}"
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Apply a playbook to a define host(s)/group(s) {{{
 | ||
| function debplay() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		if [ ! ${2} ]; then
 | ||
| 			debops run "${1:-/dev/null}" --limit "${ANS_HOST}"
 | ||
| 		else
 | ||
| 			debops run "${1:-/dev/null}" --limit "${ANS_HOST}" --tags "role::${2:-/dev/null}"
 | ||
| 		fi
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| 
 | ||
| ## Check full config to a define host(s)/group(s) {{{
 | ||
| function debchost() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		debops check site --limit "${ANS_HOST}"
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Check a role to a define host(s)/group(s) {{{
 | ||
| function debcrole() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		debops check site --limit "${ANS_HOST}" --tags "role::${1:-/dev/null}"
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Check the role from a service to a define host(s)/group(s) {{{
 | ||
| function debcserv() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		debops check service/"${1:-/dev/null}" --limit "${ANS_HOST}" --tags "role::${1:-/dev/null}"
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Check a role from a service to a define host(s)/group(s) {{{
 | ||
| function debcservice() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		debops check service/"${1:-/dev/null}" --limit "${ANS_HOST}"
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| ## Check a playbook to a define host(s)/group(s) {{{
 | ||
| function debcplay() {
 | ||
| 	if [ ${ANS_HOST} ]; then
 | ||
| 		if [ ! ${2} ]; then
 | ||
| 			debops run "${1:-/dev/null}" --limit "${ANS_HOST}"
 | ||
| 		else
 | ||
| 			debops run "${1:-/dev/null}" --limit "${ANS_HOST}" --tags "role::${2:-/dev/null}"
 | ||
| 		fi
 | ||
| 	else
 | ||
| 		printf '%b' "${MAGENTA}ANS_HOST${RESET} vars is ${REDB}not${RESET} define !\n"
 | ||
| 	fi
 | ||
| }
 | ||
| ## }}}
 | ||
| # }}}
 | ||
| # Web apps {{{
 | ||
| # Get weather
 | ||
| function meteo {
 | ||
| 	if command -v curl > /dev/null; then
 | ||
| 		curl http://fr.wttr.in/${*}
 | ||
| 	elif command -v wget > /dev/null; then
 | ||
| 		wget --quiet --output-document=- http://wttr.in/${*}
 | ||
| 	else
 | ||
| 		printf '%b' "Please ${REDB}install one of this tools :${RESET} curl or wget.\n"
 | ||
| 	fi
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| #######################################
 | ||
| #Ouverture d'un programme en fonction
 | ||
| #de l'extension du fichier
 | ||
| #######################################
 | ||
| alias -s txt='$PAGER '
 | ||
| alias -s odt='libreoffice --writer '
 | ||
| alias -s rtf='libreoffice --writer '
 | ||
| alias -s doc='libreoffice --writer '
 | ||
| alias -s docx='libreoffice --writer '
 | ||
| alias -s ods='libreoffice --calc '
 | ||
| alias -s xls='libreoffice --calc '
 | ||
| alias -s html=$BROWSER
 | ||
| alias -s org=$BROWSER
 | ||
| alias -s php=$BROWSER
 | ||
| alias -s com=$BROWSER
 | ||
| alias -s net=$BROWSER
 | ||
| alias -s png='mirage '
 | ||
| alias -s jpg='mirage '
 | ||
| alias -s gif='mirage '
 | ||
| alias -s mp4='smplayer '
 | ||
| alias -s avi='smplayer '
 | ||
| alias -s flv='smplayer '
 | ||
| alias -s log='tail --follow'
 | ||
| alias -s conf='vim '
 | ||
| alias -s gz='gunzip '
 | ||
| alias -s bz2='bzip2'
 | ||
| 
 | ||
| 
 | ||
| #######################################
 | ||
| # Raccourcis pour les dossier
 | ||
| # Pour y accéder, faire ~NOM_DU_RACCOURCIS
 | ||
| #######################################
 | ||
| hash -d apt="/etc/apt"
 | ||
| hash -d zsh="/etc/zsh"
 | ||
| hash -d dl="/media/udata/download/"
 | ||
| hash -d sid="/media/udata/config_debian"
 | ||
| hash -d smb="/etc/samba/"
 | ||
| 
 | ||
| 
 | ||
| # Inutile mais fun :p
 | ||
| ##Affiche le calendrier et le jour courant en couleur
 | ||
| #alias ccal='var=$(cal -m); echo "${var/$(date +%-d)/$(echo -e "\033[1;31m$(date +%-d)\033[0m")}"'
 | ||
| alias ccal='var=$(cal); echo "${var/$(date +%-d)/$(echo -e "\033[1;31m$(date +%-d)\033[0m")}"'
 | ||
| 
 | ||
| ##Commande utilisant cowsay (ou PONYSAY!!) pour afficher un message
 | ||
| function bonjour() {
 | ||
|   local MIN_TIME=$(date +%M)
 | ||
|   local MODULO_MIN=$(($MIN_TIME % 2))
 | ||
|   if [ $(command -v bash_quote) ] && [ $(command -v cowsay) ]; then
 | ||
|     if [ $MODULO_MIN -eq 0 ]; then
 | ||
|       #echo Bonjour $USER, nous sommes le `date +"%A %e %B %Y"`, et il est : `date +"%H"` h `date +"%M"` | cowsay -f $(/bin/ls /usr/share/cowsay/cows -1 | head -n $(expr $$$(date +%s) % $(ls /usr/share/cowsay/cows | wc -w) + 1) | tail -n 1)
 | ||
| 			# Random cow
 | ||
|       command bash_quote | cowsay -f $(find /usr/share/cow* -type f -iname "*.cow" | sort --random-sort | head --lines=1)
 | ||
|     else
 | ||
|       #echo Bonjour $USER, nous sommes le `date +"%A %e %B %Y"`, et il est : `date +"%H"` h `date +"%M"` | ponythink
 | ||
|       command bash_quote | ponythink
 | ||
|     fi
 | ||
|   else
 | ||
|     printf '%b' "${WHITEB}bonjour function${RESET}: One of the prerequesites is unavailable.\nFor bash_quote please see: https://git.101010.fr/dotfiles-gardouille/scripts/blob/master/bash_quote\n"
 | ||
|   fi
 | ||
| }
 | ||
| 
 | ||
| ##Affiche quelques statistiques à propos de l'ordinateur
 | ||
| alias stat_sys="echo ' ' && uname --all && echo ' '&& uptime &&echo ' '&& df && echo ' '"
 | ||
| 
 | ||
| #####################################
 | ||
| #####FONCTIONS
 | ||
| ######################################
 | ||
| 
 | ||
| ## Verrouiller le shell avec vlock
 | ||
| #function TRAPALRM() { vlock }
 | ||
| 
 | ||
| ##Cree le repertoire et va dedans
 | ||
| function mkcd() {
 | ||
|   mkdir -- $1 && cd $_
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| #liste les alias et functions
 | ||
| function listalias(){
 | ||
|   cat /etc/zsh/zshrc | egrep "alias|function" | grep --invert-match "^#" -- | $PAGER
 | ||
| }
 | ||
| 
 | ||
| # Get real address behind a shorten URL {{{
 | ||
| # Require a function because the given argument need to be passed to curl
 | ||
| function unshorten()
 | ||
| {
 | ||
| 	curl --silent https://unshorten.me/s/"${1-}"
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # Get public IP address {{{
 | ||
| function ippub()
 | ||
| {
 | ||
|   #curl ifconfig.me
 | ||
|   #wget http://checkip.dyndns.org/ -O - -o /dev/null | cut -d" " -f 6 | cut -d\< -f 1
 | ||
|   dig +short myip.opendns.com @resolver1.opendns.com
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # Get all private IP addresses {{{
 | ||
| function ippriv()
 | ||
| {
 | ||
|   for interface in $(find /sys/class/net/ ! -name lo -type l -printf "%f\n" | sort);
 | ||
|   do
 | ||
|     local IP_INTER=$(ip a s ${interface}|grep "inet "|awk '{print $2}')
 | ||
|     printf '%b' "${WHITEB}${interface}${RESET}: ${IP_INTER}\n"
 | ||
|   done
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # Get main private IP adress {{{
 | ||
| function ipmain()
 | ||
| {
 | ||
| 	ip route get 1 | awk '{print $(NF-2);exit}'
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # Test if a network connection is available
 | ||
| function is_network()
 | ||
| {
 | ||
|   for path_interface in $(find /sys/class/net/ ! -name lo -type l);
 | ||
|   do
 | ||
|     local IS_UP=$(grep 1 ${path_interface}/carrier)
 | ||
|     if [ ${IS_UP} ]; then
 | ||
|       return 0
 | ||
|     fi
 | ||
|   done
 | ||
|   printf '%b' "${REDB}Not Online${RESET}\n"
 | ||
|   return 1
 | ||
| }
 | ||
| 
 | ||
| #Renomme les fichiers en minuscule
 | ||
| function lowercase()
 | ||
| {
 | ||
|   for file in *; do
 | ||
|     local filename=${file##*/}
 | ||
|     case "$filename" in
 | ||
|       */*) local dirname==${file%/*} ;;
 | ||
|       *) local dirname=.;;
 | ||
|     esac
 | ||
|     local nf=$(printf $filename | tr A-Z a-z)
 | ||
|     local newname="${dirname}/${nf}"
 | ||
|     if [ "$nf" != "$filename" ]; then
 | ||
|       mv "$file" "$newname"
 | ||
|       printf 'lowercase: %s --> %s\n' ${file} ${newname}
 | ||
|     else
 | ||
|       printf 'lowercase %s not changed\n' ${file}
 | ||
|     fi
 | ||
|   done
 | ||
| }
 | ||
| 
 | ||
| ##Capture d'écran
 | ||
| function printscreen()
 | ||
| {
 | ||
|   scrot --select --exec 'gimp $f ; rm --recursive --force -- $f'
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| ## Latex:
 | ||
| ##Redéfinition de pdflatex:
 | ||
| # La commande pdflatex est exécutée deux fois pour permettre la construction de l'index
 | ||
| function pdflatex()
 | ||
| {
 | ||
|   # On récupère le nom du fichier sans l'extension
 | ||
|   local file_name="${1:r}"
 | ||
|   # Le fichier avec l'extension pdf
 | ||
|   local pdf="${file_name}.pdf"
 | ||
|   # Dossier temporaire
 | ||
|   local temp_dir="temp"
 | ||
| 
 | ||
|   # On supprime le fichier pdf si il est présent
 | ||
|   if [ -f "${pdf}" ]; then
 | ||
|     rm --recursive --force -- "${pdf}"
 | ||
|   fi
 | ||
| 
 | ||
|   # Si le répertoire temporaire n'existe pas, on le crée
 | ||
|   if [ ! -d "${temp_dir}" ]; then
 | ||
|     mkdir "${temp_dir}"
 | ||
|   fi
 | ||
| 
 | ||
|   # On exécute la commande pour créer le pdf
 | ||
|   /usr/bin/pdflatex -output-directory ${temp_dir} $1
 | ||
|   /usr/bin/pdflatex -output-directory ${temp_dir} $1
 | ||
| 
 | ||
|   # On place le fichier pdf qui est dans le répertoire temporaire dans le répertoire courant
 | ||
|   mv --force -- "${temp_dir}"/*.pdf .
 | ||
| }
 | ||
| 
 | ||
| #Éteint un pc sous windows à distance
 | ||
| #Nécessite le paquet samba-common
 | ||
| # Arguments:
 | ||
| #  ${1}: l'ip de la machine
 | ||
| #  ${2}: le nom d'utilisateur
 | ||
| #  ${3}: le mot de passe de l'utilisateur
 | ||
| function eteint()
 | ||
| {
 | ||
|   net rpc shutdown -f -I $1 -U $2%$3 -t 10 -C "Arrêt en cours..."
 | ||
| }
 | ||
| 
 | ||
| # Calculatrice en ligne de commande
 | ||
| function calc()
 | ||
| {
 | ||
|   echo "${1}" | bc -l
 | ||
| }
 | ||
| 
 | ||
| # Afficher le code retour de la commande précédente
 | ||
| function cmd_status {
 | ||
|   local exit_code=$?            # exit code of command
 | ||
|   local count=$(jobs | wc --lines)   # no. of background jobs
 | ||
| 
 | ||
|   # Report no. of background jobs if >0
 | ||
|   if [ $count -gt 0 ]; then
 | ||
|     echo -n " %{$fg[cyan]%}⎇ %j "
 | ||
|   fi
 | ||
| 
 | ||
|   # Report exit code
 | ||
|   if [ $exit_code -ne 0 ]; then
 | ||
|     echo -n "%{$fg[yellow]%}%?%{$fg[red]%} ✖%{$reset_color%}"
 | ||
|   else
 | ||
|     echo -n "%{$fg[green]%}✔%{$reset_color%}"
 | ||
|   fi
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| # Affiche un rappel des raccourcis pour se déplacer dans vim
 | ||
| function rappel_vim()
 | ||
| {
 | ||
|   echo "\
 | ||
| ##########################################
 | ||
| # Rappel basique pour VIM
 | ||
| ##########################################
 | ||
| # Déplacements basiques :
 | ||
| H       pour se déplacer vers la gauche
 | ||
| J       pour se déplacer vers le bas
 | ||
| K       pour se déplacer vers la droite
 | ||
| L       pour se déplacer vers la droite
 | ||
| 
 | ||
| # Déplacements avancés sur une ligne :
 | ||
| e       pour aller à la fin du mot suivant
 | ||
| w  pour aller au début du mot suivant
 | ||
| b       pour aller à la fin du mot précédent
 | ||
| 0       pour aller en début de ligne
 | ||
| $       pour aller en fin de ligne
 | ||
| ^       pour aller au premier caractère de la ligne qui n'est pas un espace ni une tabulation
 | ||
| f<c>    pour aller jusqu'au caractère <c> vers l'avant
 | ||
| 3f<c>  pour aller jusqu'à la 3ème occurence du caractère <c> vers l'avant
 | ||
| F<c>    pour aller jusqu'au caractère <c> vers l'arrière
 | ||
| nF<c>  pour aller jusqu'à la nème occurence du caractère <c> vers l'arrière
 | ||
| t<c>    pour aller jusqu'au caractère <c> vers l'avant en s'arrêtant avant
 | ||
| T<c>    pour aller jusqu'au caractère <c> vers l'arrière en s'arrêtant avant
 | ||
| 
 | ||
| # Déplacement dans le document :
 | ||
| gg      pour aller au début du document
 | ||
| G       pour aller à la fin du document
 | ||
| nG      pour aller à la ligne <n>
 | ||
| :<n>    pour aller à la ligne <n>
 | ||
| %  pour aller à la parenthèse (acollade, crochet) correspondant
 | ||
| 
 | ||
| # Copier/coller avancé
 | ||
| \"ayy   Copier la ligne courante dans le buffer \"a\"
 | ||
| \"5byy  Copier les 5 lignes sous le curseur dans le buffer \"b\"
 | ||
| <MODE_VISUEL>\"ey   Copier les lignes sélectionnées dans le buffer \"e\"
 | ||
| 
 | ||
| # undo & redo
 | ||
| u        pour annuler pour annuler la dernière modification
 | ||
| CTRL+R  pour refaire la dernière modification
 | ||
| 
 | ||
| # Gestion du texte
 | ||
| ~       pour inverser la casse du texte sélectionné
 | ||
| # Supprimer le texte du curseur à la fin de la ligne
 | ||
| <mode commande> d$
 | ||
| <mode insertion> CTRL-o D
 | ||
| # Supprimer le texte du curseur au début de la ligne
 | ||
| <mode commande> d^
 | ||
| " | $PAGER
 | ||
| }
 | ||
| 
 | ||
| # Affiche un rappel des raccourcis pour se déplacer dans vim
 | ||
| function rappel_vim_avance()
 | ||
| {
 | ||
|   echo "\
 | ||
| ##########################################
 | ||
| # Utilisation un peu plus avancée de VIM
 | ||
| ##########################################
 | ||
| # nom fichier
 | ||
| # Avec par exemple un fichier qui s'appelle fichier.tex dans /home/limax/Documents/
 | ||
| 
 | ||
| # est le nom du fichier en cours
 | ||
| :!echo % (renvoie /Documents/fichier.tex )
 | ||
| :!echo %:r (renvoie /Documents/fichier )
 | ||
| :!echo %:e (renvoie tex )
 | ||
| :!echo %:t (renvoie fichier.tex )
 | ||
| :!echo %:p (renvoie /home/limax/Documents/fichier.tex )
 | ||
| :!echo %:t (renvoie fichier.tex )
 | ||
| :!echo %:h (renvoie Documents)
 | ||
| # Par exemple pour ouvrir le pdf avec lesspipe
 | ||
| :!lesspipe %:r.pdf
 | ||
| 
 | ||
| # Indentation
 | ||
| # Pour réindenter du texte:
 | ||
| mode visuel
 | ||
| - sélectionner toutes les lignes à indenter correctement
 | ||
| touche \"=\"
 | ||
| # Pour décaler plusieurs lignes de plusieurs tabulations:
 | ||
| mode visuel
 | ||
| - sélectionner toutes les lignes à décaler
 | ||
| :>>>
 | ||
| 
 | ||
| # Commande
 | ||
| # Pour exécuter une seule commande à partir du mode insertion
 | ||
| <mode insertion> CTRL-o suivi de la commande à exécuter
 | ||
| 
 | ||
| # Code touche
 | ||
| # Pour afficher le code clavier d'une touche spéciale en mode insertion:
 | ||
| <mode insertion> CTRL-V
 | ||
| # Pour afficher le code interne d'une touche spéciale:
 | ||
| <mode insertion> CTRL-K
 | ||
| # Pour obtenir le code ascii d'un caractère:
 | ||
| ga
 | ||
| 
 | ||
| # Plier/déplier
 | ||
| zm  Plier tout le document sur un niveau de plus
 | ||
| zr  Déplier tout le document sur un niveau de plus
 | ||
| zc  Plier un bloc/fonction/class
 | ||
| zo  Déplier un bloc/fonction/class
 | ||
| 
 | ||
| 
 | ||
| " | $PAGER
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| # Affiche un rappel pour l'édition de fichier Latex
 | ||
| function rappel_latex()
 | ||
| {
 | ||
|   echo "\
 | ||
| -\\/-           Permet d'afficher -- et non un tiret cadratin
 | ||
| Ligne vide      Permet un retour à la ligne entre deux textes
 | ||
| \\ldots         Affiche correctement \"...\"
 | ||
| 
 | ||
| 
 | ||
| # itemize
 | ||
| Mettre un \\vspace{0.5cm} après une liste?
 | ||
| Laisser une ligne vide après une commande root dans une liste?
 | ||
| 
 | ||
| # À faire
 | ||
| Ajouter un style pour les notes d'informations
 | ||
| Ajouter un style pour les notes importantes
 | ||
| 
 | ||
| 
 | ||
| " |  $PAGER
 | ||
| }
 | ||
| 
 | ||
| ## Vérifier les logins et logouts de tous les comptes incluant le mien.
 | ||
| watch=all
 | ||
| # Vérifie toutes les 30 secondes
 | ||
| logcheck=30
 | ||
| # Change le format de watch pour quelques chose avec plus d'informations
 | ||
| #  %n = username, %M = hostname, %a = action, %l = tty, %T = time,
 | ||
| #  %W = date
 | ||
| WATCHFMT="%n from %M has %a tty%l at %T %W"
 | ||
| 
 | ||
| 
 | ||
| # Crypte le fichier passer en paramètre en utilisant le certificat public
 | ||
| #   de l'utilisateur.
 | ||
| # Arguments:
 | ||
| #  ${1}: fichier à crypter
 | ||
| #  ${2}:
 | ||
| function crypt()
 | ||
| {
 | ||
|   openssl smime -encrypt -aes128 -in ${1} -out .${1}.ls ~/.openssl/mycert.crt
 | ||
| }
 | ||
| 
 | ||
| # Décrypte le fichier passer en paramètre en fonction de la clef ssl de
 | ||
| #   l'utilisateur et trouve la ligne contenant le mot rechercher par l'user
 | ||
| # Arguments:
 | ||
| #  ${1}: le fichier à décrypter
 | ||
| #  ${2}: le paramètre rechercher dans le fichier
 | ||
| function getpdw()
 | ||
| {
 | ||
|   openssl smime -decrypt -in ${1} -inkey ~/.openssl/mykey.key | grep ${2}
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| # Décrypte le fichier passer en paramètre en fonction de la clef ssl de
 | ||
| #   l'utilisateur et le fichier de sorti est le second paramètre
 | ||
| # Arguments:
 | ||
| #  ${1}: le fichier à décrypter
 | ||
| #  ${2}: le fichier de sorti
 | ||
| function decrypt()
 | ||
| {
 | ||
|   openssl smime -decrypt -in ${1} -out ${2} -inkey ~/.openssl/mykey.key
 | ||
| }
 | ||
| 
 | ||
| ################################################
 | ||
| # 2. Prompt et définition des touches basiques #
 | ||
| ################################################
 | ||
| 
 | ||
| # Prompt couleur (la couleur n'est pas la même pour le root et
 | ||
| # pour les simples utilisateurs)
 | ||
| # Définition des couleurs:
 | ||
| bleu_clair="[36;1m"
 | ||
| bleu_fonce="[34;1m"
 | ||
| rouge="[31m"
 | ||
| jaune="[33m"
 | ||
| blanc="[37m"
 | ||
| vert="[32m"
 | ||
| couleur_normale="[0m"
 | ||
| # Définition du texte du prompt
 | ||
| heure="%{$bleu_clair%}%T"
 | ||
| user="%{$bleu_fonce%}%n"
 | ||
| user_root="%{$rouge%}%n"
 | ||
| at="%{$jaune%}@"
 | ||
| host="%{$blanc%}%m"
 | ||
| repertoire_courant="%{$vert%}%c"
 | ||
| repertoire_absolu="%{$vert%}%d"
 | ||
| # Chemin du répertoire courant en relatif à ~
 | ||
| repertoire_relatif="%{$vert%}%~"
 | ||
| root="%{$jaune%}%#"
 | ||
| noroot="%{$jaune%}%%"
 | ||
| normal="%{$couleur_normale%}"
 | ||
| # Définition du prompt
 | ||
| if [ "`id -u`" -eq 0 ]; then ## Root
 | ||
|   export PS1="$heure $user_root$at$host $repertoire_courant$root $normal"
 | ||
| #  export PS1="%{$bleu_clair%T %{$rouge%n%{$jaune@%{$blanc%m %{$vert%c%{$jaune%#%{[0m%} "
 | ||
| else ## Simple utilisateur
 | ||
|   export PS1="$heure $host $repertoire_courant$noroot $normal"
 | ||
| fi
 | ||
| 
 | ||
| # Prise en charge des touches [début], [fin] et autres
 | ||
| typeset -A key
 | ||
| 
 | ||
| key[Home]=${terminfo[khome]}
 | ||
| key[End]=${terminfo[kend]}
 | ||
| key[Insert]=${terminfo[kich1]}
 | ||
| key[Delete]=${terminfo[kdch1]}
 | ||
| key[Up]=${terminfo[kcuu1]}
 | ||
| key[Down]=${terminfo[kcud1]}
 | ||
| key[Left]=${terminfo[kcub1]}
 | ||
| key[Right]=${terminfo[kcuf1]}
 | ||
| key[PageUp]=${terminfo[kpp]}
 | ||
| key[PageDown]=${terminfo[knp]}
 | ||
| 
 | ||
| [[ -n "${key[Home]}"    ]]  && bindkey  "${key[Home]}"    beginning-of-line
 | ||
| [[ -n "${key[End]}"     ]]  && bindkey  "${key[End]}"     end-of-line
 | ||
| [[ -n "${key[Insert]}"  ]]  && bindkey  "${key[Insert]}"  overwrite-mode
 | ||
| [[ -n "${key[Delete]}"  ]]  && bindkey  "${key[Delete]}"  delete-char
 | ||
| [[ -n "${key[Up]}"      ]]  && bindkey  "${key[Up]}"      up-line-or-history
 | ||
| [[ -n "${key[Down]}"    ]]  && bindkey  "${key[Down]}"    down-line-or-history
 | ||
| [[ -n "${key[Left]}"    ]]  && bindkey  "${key[Left]}"    backward-char
 | ||
| [[ -n "${key[Right]}"   ]]  && bindkey  "${key[Right]}"   forward-char
 | ||
| [[ -n "${key[PageUp]}"   ]] && bindkey  "${key[PageUp]}"   history-beginning-search-backward
 | ||
| [[ -n "${key[PageDown]}" ]] && bindkey  "${key[PageDown]}" history-beginning-search-forward
 | ||
| 
 | ||
| # ctrl+← and ctrl+→ issue
 | ||
| bindkey "^[[1;5C" vi-forward-word-end
 | ||
| bindkey "^[[1;5D" backward-word
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| # Titre de la fenêtre d'un xterm
 | ||
| case $TERM in
 | ||
|    xterm*)
 | ||
|        precmd () {print -Pn "\e]0;%n@%m: %~\a"}
 | ||
|        ;;
 | ||
| esac
 | ||
| 
 | ||
| # Gestion de la couleur pour 'ls' (exportation de LS_COLORS)
 | ||
| # First, use vivid {{{
 | ||
| if [ $(command -v vivid) ]; then
 | ||
| 	#export LS_COLORS="$(vivid generate dracula)"
 | ||
| 	export LS_COLORS="$(vivid generate one-light)"
 | ||
| # }}}
 | ||
| # Second, use dircolors {{{
 | ||
| elif [ -x /usr/bin/dircolors ]
 | ||
| then
 | ||
|   if [ -r ~/.dir_colors ]
 | ||
|   then
 | ||
|     eval "`dircolors ~/.dir_colors`"
 | ||
|   elif [ -r /etc/dir_colors ]
 | ||
|   then
 | ||
|     eval "`dircolors /etc/dir_colors`"
 | ||
|   else
 | ||
|     eval "`dircolors`"
 | ||
|   fi
 | ||
| fi
 | ||
| # }}}
 | ||
| 
 | ||
| #######################################
 | ||
| # 3. Comportement ligne de commandes  #
 | ||
| #######################################
 | ||
| # La ligne de commande dans zsh peut fonctionner suivant différents schémas (options).
 | ||
| # Les principaux que je vais utiliser sont fait pour la ligne de commande dans zhs se
 | ||
| #   comporte à la vim. Il y a donc un mode commande/normal et un mode insertion.
 | ||
| 
 | ||
| # Afficher le mode courant dans le prompt de droite (normal|insertion)
 | ||
| function zle-line-init zle-keymap-select {
 | ||
|   RPS1="$(cmd_status) ${${KEYMAP/vicmd/-CMD-}/(main|viins)/-INS-}"
 | ||
|   RPS2=$RPS1
 | ||
|   zle reset-prompt
 | ||
| }
 | ||
| 
 | ||
| # easy color names in this config
 | ||
| autoload -U colors && colors
 | ||
| 
 | ||
| # Chargement des keymaps
 | ||
| zle -N zle-line-init
 | ||
| zle -N zle-keymap-select
 | ||
| 
 | ||
| ### Raccourcis communs à tous les modes
 | ||
| autoload -U   edit-command-line
 | ||
| zle -N        edit-command-line
 | ||
| bindkey           ''      edit-command-line                     # Ouvrir la commande actuelle dans l'éditeur
 | ||
| bindkey           ''      history-incremental-search-backward   # Recherche incrémentale qui monte dans l'historique
 | ||
| #bindkey           ''      history-incremental-search-forward    # Recherche incrémentale qui descend dans l'historique
 | ||
| 
 | ||
| ### Raccourcis spécifiques au mode insertion
 | ||
| bindkey -M viins  ''      beginning-of-line                     # Début de ligne
 | ||
| bindkey -M viins  ''      vi-forward-blank-word-end             # Fin du mot courant
 | ||
| #bindkey -M viins  ''      vi-forward-blank-word                 # Début du mot suivant
 | ||
| bindkey -M viins  ''      vi-backward-word                      # Début du mot précédent
 | ||
| bindkey -M viins  ''      vi-find-prev-char                     # Rechercher la précédente occurence d'une lettre
 | ||
| #bindkey -M viins  ' ;'     vi-repeat-find                        # Aller à la prochaine occurence de la lettre recherchée
 | ||
| 
 | ||
| ### Raccourcis spécifiques au mode commande
 | ||
| # Le mode commande dispose déjà de la plupart d'un fonctionnement très semblable
 | ||
| #   au mode normal de vim. Seul problème pour le moment, l'absence d'un mode visuel.
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| ###########################################
 | ||
| # 4. Options de zsh (cf 'man zshoptions') #
 | ||
| ###########################################
 | ||
| 
 | ||
| # Je ne veux JAMAIS de beeps
 | ||
| unsetopt beep
 | ||
| unsetopt hist_beep
 | ||
| unsetopt list_beep
 | ||
| 
 | ||
| # Redirection de la sortie:
 | ||
| # >| doit être utilisés pour pouvoir écraser un fichier déjà existant ;
 | ||
| # le fichier ne sera pas écrasé avec '>'
 | ||
| unsetopt clobber
 | ||
| 
 | ||
| # Ctrl+D est équivalent à 'logout'
 | ||
| unsetopt ignore_eof
 | ||
| 
 | ||
| # Affiche le code de sortie si différent de '0'
 | ||
| setopt print_exit_value
 | ||
| 
 | ||
| # Demande confirmation pour 'rm *'
 | ||
| unsetopt rm_star_silent
 | ||
| # Attend 10 secondes avant d'exécuter une commande rm qui contient un * (asterisk).
 | ||
| setopt rmstarwait
 | ||
| 
 | ||
| # Correction orthographique des commandes
 | ||
| # Désactivé car, contrairement à ce que dit le "man", il essaye de
 | ||
| # corriger les commandes avant de les hasher
 | ||
| setopt correct
 | ||
| # Si on utilise des jokers dans une liste d'arguments, retire les jokers
 | ||
| # qui ne correspondent à rien au lieu de donner une erreur
 | ||
| setopt nullglob
 | ||
| 
 | ||
| # Désactivé le raccourcis '='
 | ||
| # Par défaut, `ls -l =vim` indiquera l'emplacement de vim.
 | ||
| # =vim équivaut à `which vim`
 | ||
| #setopt noequals
 | ||
| 
 | ||
| ## Activation des fonctions internes de ZSH:
 | ||
| # Liste des fonctions disponibles:
 | ||
| #zcalc : une calculatrice (plus besoin de bc ou autres expr)
 | ||
| #zargs : un super xargs
 | ||
| #zmv : une commande permettant de faire du renommage/déplaçage en masse de fichiers.
 | ||
| #zftp : un client ftp natif
 | ||
| autoload -U zfinit
 | ||
| zfinit
 | ||
| 
 | ||
| # Les jobs qui tournent en tâche de fond sont nicé à '0'
 | ||
| unsetopt bg_nice
 | ||
| # N'envoie pas de "HUP" aux jobs qui tourent quand le shell se ferme
 | ||
| unsetopt hup
 | ||
| 
 | ||
| # Lancer le manuel en se placant sur une commande et en faisant {ESC,ALT}+{H,h}
 | ||
| autoload -U run-help
 | ||
| 
 | ||
| ## Gestion de la pile des dossiers:
 | ||
| # Taille maximale de la pile placé dans zshenv
 | ||
| # L'exécution de "cd" met le répertoire d'où l'on vient sur la pile
 | ||
| setopt auto_pushd
 | ||
| # Ignore les doublons dans la pile
 | ||
| setopt pushd_ignore_dups
 | ||
| # N'affiche pas la pile après un "pushd" ou "popd"
 | ||
| setopt pushd_silent
 | ||
| # Inverse l'action de cd +1 et cd +1
 | ||
| setopt pushdminus
 | ||
| # "pushd" sans argument = "pushd $HOME"
 | ||
| setopt pushd_to_home
 | ||
| ## Pour bien utiliser la pile:
 | ||
| # `dirs` va afficher la pile
 | ||
| # `cd -NUMÉRO` ira dans le dossier correspondant au numéro du dossier dans la pile
 | ||
| 
 | ||
| ## Dirstack
 | ||
| DIRSTACKSIZE=20
 | ||
| setopt autopushd pushdsilent pushdtohome
 | ||
| ## Remove duplicate entries
 | ||
| setopt pushdignoredups
 | ||
| ## This reverts the +/- operators.
 | ||
| setopt pushdminus
 | ||
| 
 | ||
| #DIRSTACKFILE="$HOME/.zsh/cache/dirs"
 | ||
| #if [[ -f $DIRSTACKFILE ]] && [[ $#dirstack -eq 0 ]]; then
 | ||
|   #dirstack=( ${(f)"$(< $DIRSTACKFILE)"} )
 | ||
|   #[[ -d $dirstack[1] ]] && cd $dirstack[1]
 | ||
| #fi
 | ||
| 
 | ||
| #chpwd() {
 | ||
|   #print -l $PWD ${(u)dirstack} >> $DIRSTACKFILE
 | ||
| #}
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| ###################################
 | ||
| ###### Options de complétion ######
 | ||
| ###################################
 | ||
| 
 | ||
| # Schémas de complétion
 | ||
| 
 | ||
| # - Schéma A :
 | ||
| # 1ère tabulation : complète jusqu'au bout de la partie commune
 | ||
| # 2ème tabulation : propose une liste de choix
 | ||
| # 3ème tabulation : complète avec le 1er item de la liste
 | ||
| # 4ème tabulation : complète avec le 2ème item de la liste, etc...
 | ||
| # -> c'est le schéma de complétion par défaut de zsh.
 | ||
| 
 | ||
| # Schéma B :
 | ||
| # 1ère tabulation : propose une liste de choix et complète avec le 1er item
 | ||
| #                   de la liste
 | ||
| # 2ème tabulation : complète avec le 2ème item de la liste, etc...
 | ||
| # Si vous voulez ce schéma, décommentez la ligne suivante :
 | ||
| #setopt menu_complete
 | ||
| 
 | ||
| # Schéma C :
 | ||
| # 1ère tabulation : complète jusqu'au bout de la partie commune et
 | ||
| #                   propose une liste de choix
 | ||
| # 2ème tabulation : complète avec le 1er item de la liste
 | ||
| # 3ème tabulation : complète avec le 2ème item de la liste, etc...
 | ||
| # Ce schéma est le meilleur à mon goût !
 | ||
| # Si vous voulez ce schéma, décommentez la ligne suivante :
 | ||
| unsetopt list_ambiguous
 | ||
| 
 | ||
| # Quand le dernier caractère d'une complétion est '/' et que l'on
 | ||
| # tape 'espace' après, le '/' est effacé
 | ||
| setopt auto_remove_slash
 | ||
| # Ne fait pas de complétion sur les fichiers et répertoires cachés
 | ||
| unsetopt glob_dots
 | ||
| 
 | ||
| # Traite les liens symboliques comme il faut
 | ||
| setopt chase_links
 | ||
| 
 | ||
| # Quand l'utilisateur commence sa commande par '!' pour faire de la
 | ||
| # complétion historique, il n'exécute pas la commande immédiatement
 | ||
| # mais il écrit la commande dans le prompt
 | ||
| setopt hist_verify
 | ||
| # Si la commande est invalide mais correspond au nom d'un sous-répertoire
 | ||
| # exécuter 'cd sous-répertoire'
 | ||
| setopt auto_cd
 | ||
| 
 | ||
| 
 | ||
| ###############################################
 | ||
| # 5. Paramètres de l'historique des commandes #
 | ||
| ###############################################
 | ||
| 
 | ||
| # Définition des variables
 | ||
| SAVEHIST=5000
 | ||
| HISTSIZE=5000
 | ||
| HISTFILE=$HOME/.zsh/history
 | ||
| #export TIMEFMT="%E"
 | ||
| 
 | ||
| export SAVEHIST HISTSIZE HISTFILE
 | ||
| 
 | ||
| # Toutes les sessions zsh partage le même historique
 | ||
| #setopt SHARE_HISTORY
 | ||
| 
 | ||
| # Ajoute l'historique à la fin de l'ancien fichier
 | ||
| #setopt append_history
 | ||
| 
 | ||
| # Chaque ligne est ajoutée dans l'historique à mesure qu'elle est tapée
 | ||
| setopt inc_append_history
 | ||
| 
 | ||
| # Ne stocke pas une ligne dans l'historique si elle est identique à la
 | ||
| # précédente
 | ||
| setopt hist_ignore_dups
 | ||
| 
 | ||
| # Supprime les  répétitions dans le fichier  d'historique, ne conservant
 | ||
| # que la dernière occurrence ajoutée
 | ||
| #setopt hist_ignore_all_dups
 | ||
| 
 | ||
| # Supprime les répétitions dans l'historique lorsqu'il est plein, mais
 | ||
| # pas avant
 | ||
| setopt hist_expire_dups_first
 | ||
| 
 | ||
| # N'enregistre  pas plus d'une fois  une même ligne, quelles  que soient
 | ||
| # les options fixées pour la session courante
 | ||
| #setopt hist_save_no_dups
 | ||
| 
 | ||
| # La recherche dans  l'historique avec l'éditeur de commandes de zsh ne
 | ||
| # montre  pas  une même  ligne  plus  d'une fois,  même  si  elle a  été
 | ||
| # enregistrée plusieurs fois
 | ||
| setopt hist_find_no_dups
 | ||
| 
 | ||
| # Affichage de la date du début de la commande et sa durée (depuis epoch)
 | ||
| # Culture time: epoch: 1er janvier 1970
 | ||
| setopt extended_history
 | ||
| 
 | ||
| # Ne pas enregistrer les commandes précédées d'un espace:
 | ||
| setopt hist_ignore_space
 | ||
| 
 | ||
| ###########################################
 | ||
| # 6. Complétion des options des commandes #
 | ||
| ###########################################
 | ||
| 
 | ||
| zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}'
 | ||
| zstyle ':completion:*' max-errors 3 numeric
 | ||
| zstyle ':completion:*' use-compctl false
 | ||
| 
 | ||
| ## Pour la liste des processus que l'on peut kill, avec un menu et couleur
 | ||
| zstyle ':completion:*:*:*:*:processes' menu yes select
 | ||
| #zstyle ':completion:*:*:*:*:processes' force-list always
 | ||
| zstyle ':completion:*:processes' command 'ps -fau$USER'
 | ||
| zstyle ':completion:*:*:kill:*:processes' list-colors "=(#b) #([0-9]#)*=36=31"
 | ||
| 
 | ||
| ## Pour éviter de reproposer un argument déjà utiliser dans la commande lors de la complétion
 | ||
| zstyle ':completion:*:(rm|mv|cp|ls|scp):*' ignore-line yes
 | ||
| 
 | ||
| ## cd ne sélectionnera pas le dossier courant lorsqu'il devra remonter d'un dossier
 | ||
| # cd ../<TAB> ne proposera pas le dossier courant par exemple.
 | ||
| zstyle ':completion:*:cd:*' ignore-parents parent pwd
 | ||
| 
 | ||
| ## Pour la liste des fichiers qu'on peut ouvrir avec vim
 | ||
| zstyle ':completion:*:*:vim:*' menu yes select
 | ||
| ## Mettre en cache les résultats de l'auto-complétion car certaines fonctions sont lentes (apt, dpkg, ...)
 | ||
| # Ne pas hésiter à faire un petit aptitude install <TAB> et de lister tous les résultats possibles une première fois, histoire d'avoir tous les paquets en cache (~600ko), ça vaut le coup!
 | ||
| zstyle ':completion:*' use-cache on
 | ||
| zstyle ':completion:*' cache-path ~/.zsh/cache
 | ||
| 
 | ||
| ## Ajout des couleurs pour la complétion
 | ||
| zmodload -i zsh/complist
 | ||
| zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
 | ||
| 
 | ||
| ## Complétion de la commande cd avec les répertoires locaux puis ceux de la variable CDPATH
 | ||
| zstyle ':completion:*:*:cd:*' tag-order local-directories path-directories
 | ||
| 
 | ||
| ## Complétion des commandes ssh avec le contenu du fichier ~/.ssh/config et le contenu de host
 | ||
| #local HOSTS
 | ||
| #[[ -f ~/.ssh/config ]] && HOSTS=(`sed --quiet \'s/^Host \(.*\)/\1/p\' ~/.ssh/config`)
 | ||
| #if [ -f ~/.ssh/config ]; then
 | ||
| #HOSTS=(`grep ^Host ~/.ssh/config | sed s/Host\ // | egrep -v ‘^\*$’`)
 | ||
| #fi
 | ||
| #zstyle ':completion:*:(ssh|scp|sftp|sshfs):*' hosts ${HOSTS}
 | ||
| zstyle ':completion:*:hosts' hosts off
 | ||
| 
 | ||
| # Complétions pour certains programmes en fonction des extensions
 | ||
| zstyle ':completion:*:*:vlc:*' file-patterns '*.(mkv|MKV|avi|AVI|flv|FLV|mp4|MP4|webm|WEBM|mov|MOV|flac|FLAC|mp3|MP3|ogg|OGG|ogv|OGV|wmv|WMV)\ *(-/):directories'
 | ||
| 
 | ||
| ## Ajout de la complétion pour plusieurs fonctions:
 | ||
| autoload -U compinit
 | ||
| autoload -U zutil
 | ||
| autoload -U complist
 | ||
| # Activation
 | ||
| compinit
 | ||
| 
 | ||
| 
 | ||
| ###########################################
 | ||
| # 7. Création des fichiers et répertoires #
 | ||
| ###########################################
 | ||
| # Dossier .zsh dans le répertoire personnel
 | ||
| if [ ! -d ~/.zsh ]; then
 | ||
|   mkdir ~/.zsh
 | ||
| fi
 | ||
| 
 | ||
| # Fichier contenant l'historique pour chaque utilisateur
 | ||
| if [ ! -f ~/.zsh/history ]; then
 | ||
|   touch ~/.zsh/history
 | ||
| fi
 | ||
| 
 | ||
| # Dossier contenant le cache pour chaque utilisateur
 | ||
| if [ ! -d ~/.zsh/cache ]; then
 | ||
|   mkdir ~/.zsh/cache
 | ||
| fi
 | ||
| 
 | ||
| 
 | ||
| ###########################################
 | ||
| ############## 8. Globbing ################
 | ||
| ###########################################
 | ||
| 
 | ||
| # Activation du globbing étendu
 | ||
| setopt extendedglob
 | ||
| ## '^' inverse la pattern qui suit.
 | ||
| # Exemple:
 | ||
| # `ls ^*.log` listera tous les fichiers exceptés *.log
 | ||
| 
 | ||
| 
 | ||
| ###########################################
 | ||
| ############### 9. Modules ################
 | ||
| ###########################################
 | ||
| 
 | ||
| ## IF fzf AVAILABLE
 | ||
| if [ -d ~/.fzf ]; then
 | ||
| 
 | ||
| ## If local fzf bin is available use it in priority
 | ||
| if [[ ! "$PATH" == *"${HOME}"/.fzf/bin* ]]; then
 | ||
| 	export PATH="${HOME}/.fzf/bin:${PATH}"
 | ||
| fi
 | ||
| 
 | ||
| if [ -f ~/bin/fd ]; then
 | ||
| 	export FZF_DEFAULT_COMMAND='fd --type f'
 | ||
| fi
 | ||
| 
 | ||
| autoload is-at-least
 | ||
| if is-at-least 0.29.0 $(fzf --version); then
 | ||
| 	export FZF_DEFAULT_OPTS="--cycle --multi --select-1 --bind 'change:first,shift-tab:down,tab:up'"
 | ||
| else
 | ||
| 	## change:first is unknown in FZF before 0.29.0
 | ||
| 	export FZF_DEFAULT_OPTS="--cycle --multi --select-1 --bind 'tab:down,shift-tab:up'"
 | ||
| fi
 | ||
| 
 | ||
| # Auto-completion
 | ||
| # ---------------
 | ||
| [[ $- == *i* ]] && source "${HOME}/.fzf/shell/completion.zsh" 2> /dev/null
 | ||
| 
 | ||
| # Key bindings
 | ||
| # ------------
 | ||
| source "${HOME}/.fzf/shell/key-bindings.zsh"
 | ||
| 
 | ||
| # ff - cd to selected directory exclude hidden directories and their content {{{
 | ||
| # Search with find (fd|fdfind overkill the CPU for few benefits on small tree)
 | ||
| # Check for symlinked directories too
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Display a preview tree of the directory
 | ||
| # Move to the selected directory
 | ||
| function ff() {
 | ||
| 	local dir
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		dir=$(find -L . -xtype d -not -path "*/.*" | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 2 {} | head --lines=20' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		dir=$(find -L . -xtype d -not -path "*/.*" | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 2 {} | head --lines=20' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	cd -- "${dir}"
 | ||
| }
 | ||
| # }}}
 | ||
| # ffh - cd to selected directory (hidden only) {{{
 | ||
| # Search with find (fd|fdfind overkill the CPU for few benefits on small tree)
 | ||
| # Check for symlinked directories too
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Display a preview tree of the directory
 | ||
| # Move to the selected directory
 | ||
| function ffh() {
 | ||
| 	local dir
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		dir=$(find -L . -xtype d -path "*/.*" | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 2 {} | head --lines=20' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		dir=$(find -L . -xtype d -path "*/.*" | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 2 {} | head --lines=20' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	cd -- "${dir}"
 | ||
| }
 | ||
| # }}}
 | ||
| # ffa - cd to any directory from / {{{
 | ||
| # Search with fd (fdfind is perfect to search on /)
 | ||
| # Check for symlinked directories too
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Display a preview tree of the directory
 | ||
| # Move to the selected directory
 | ||
| function ffa() {
 | ||
| 	local dir
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		dir=$(fd -uu --search-path / --type d --type symlink --follow | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 1 {} | head --lines=20' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		dir=$(fd -uu --search-path / --type d --type symlink --follow | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 1 {} | head --lines=20' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	cd -- "${dir}"
 | ||
| }
 | ||
| # }}}
 | ||
| # ffu - cd to selected parent directory {{{
 | ||
| function ffu() {
 | ||
| 	local declare dirs=()
 | ||
| 	local dir
 | ||
| 
 | ||
| 	## Function to list parents of the given directory {{{
 | ||
| 	get_parent_dirs() {
 | ||
| 		if [[ -d "${1}" ]]; then dirs+=("$1"); else return; fi
 | ||
| 		if [[ "${1}" == '/' ]]; then
 | ||
| 			for _dir in "${dirs[@]}"; do echo $_dir; done
 | ||
| 		else
 | ||
| 			get_parent_dirs $(dirname "${1}")
 | ||
| 		fi
 | ||
| 	}
 | ||
| 	## }}}
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		dir=$(get_parent_dirs $(realpath "${PWD}") | fzf --prompt='cd> ' --tac --height=50% --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		dir=$(get_parent_dirs $(realpath "${PWD}") | fzf --prompt='cd> ' --tac --height=50% --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	cd -- "${dir}"
 | ||
| }
 | ||
| # }}}
 | ||
| # fff - cd to the directory of the selected file {{{
 | ||
| # Search with fd (after few tests, fdfind is fareway better than find… even on small tree)
 | ||
| # Check for symlinked files too
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Display a directory preview tree of the selected file with eza
 | ||
| # Move to the directory of the selected file
 | ||
| function fff() {
 | ||
| 	local file
 | ||
| 	local dir
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		file=$(fd -uu --type file --type symlink --follow | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 2 $(dirname {}) | head --lines=20' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		file=$(fd -uu --type file --type symlink --follow | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 2 $(dirname {}) | head --lines=20' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	dir=$(dirname "${file}")
 | ||
| 	cd -- "${dir}"
 | ||
| }
 | ||
| # }}}
 | ||
| # cf - fuzzy cd from anywhere {{{
 | ||
| # Search with fd (fdfind is perfect to search on /)
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Display a directory preview tree of the selected file with eza
 | ||
| # Move to the directory of the selected file
 | ||
| function cf() {
 | ||
| 	local file
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		file=$(fd -uu --search-path / --follow | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 1 $(dirname {}) | head --lines=20' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		file=$(fd -uu --search-path / --follow | fzf --prompt='cd> ' --height=50% --preview 'eza --tree --level 1 $(dirname {}) | head --lines=20' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	if [[ -n "${file}" ]]
 | ||
| 	then
 | ||
| 		if [[ -d "${file}" ]]
 | ||
| 		then
 | ||
| 			### If it's a directory, cd
 | ||
| 			cd -- "${file}"
 | ||
| 		else
 | ||
| 			### If it's a file, cd to the directory
 | ||
| 			cd -- "${file:h}"
 | ||
| 		fi
 | ||
| 	fi
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # v - fuzzy open file with vi from current directory {{{
 | ||
| # Search with fd (fdfind is perfect to search more than ~200k files)
 | ||
| # Check for symlinked files too
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Display the 50 first lines of the selected file with bat (batcat)
 | ||
| # Move to the directory of the selected file
 | ||
| # Open the selected file with vi
 | ||
| function v() {
 | ||
| 	local files
 | ||
| 	local dir
 | ||
| 	local file
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		files=$(fd -uu --type file --type symlink --follow | fzf --prompt='vi> ' --preview 'bat --color=always --line-range 0:50 {}' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		files=$(fd -uu --type file --type symlink --follow | fzf --prompt='vi> ' --preview 'bat --color=always --line-range 0:50 {}' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	## Move to the directory and open the file {{{
 | ||
| 	if [[ -n "${files}" ]]
 | ||
| 	then
 | ||
| 		dir=$(dirname "${files}")
 | ||
| 		### Change directory only if not already in the expected dir
 | ||
| 		test $(realpath "${dir}") != $(realpath .) && cd -- "${dir}"
 | ||
| 		file=$(basename "${files}")
 | ||
| 		vi -- "${file}"
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # pdf − fuzzy open PDF file with "${PDF_VIEWER}" from current directory {{{
 | ||
| # Search with fd (fdfind is better than find with a pattern)
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Display a preview of selected file with lesspipe
 | ||
| # Move to the directory of the selected file
 | ||
| # Open the selected file with "${PDF_VIEWER}"
 | ||
| function pdf() {
 | ||
| 	local files
 | ||
| 	local dir
 | ||
| 	local file
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.pdf$" | fzf --prompt='pdf> ' --preview 'lesspipe {} | less' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.pdf$" | fzf --prompt='pdf> ' --preview 'lesspipe {} | less' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	## Move to the directory and open the file {{{
 | ||
| 	if [[ -n $files ]]
 | ||
| 	then
 | ||
| 		dir=$(dirname "${files}")
 | ||
| 		### Change directory only if not already in the expected dir
 | ||
| 		test $(realpath "${dir}") != $(realpath .) && cd -- "${dir}"
 | ||
| 		file=$(basename "${files}")
 | ||
| 		"${PDF_VIEWER}" -- "${file}"
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| }
 | ||
| # }}}
 | ||
| # pdfe − fuzzy open PDF file with evince from current directory {{{
 | ||
| # Search with fd (fdfind is better than find with a pattern)
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Display a preview of selected file with lesspipe
 | ||
| # Move to the directory of the selected file
 | ||
| # Open the selected file with evince (default rollback to "${PDF_VIEWER}")
 | ||
| function pdfe() {
 | ||
| 	local files
 | ||
| 	local dir
 | ||
| 	local file
 | ||
| 	local evince_bin
 | ||
| 
 | ||
| 	## If evince is available {{{
 | ||
| 	if [ $(command -v evince) ]; then
 | ||
| 		evince_bin=$(command -v evince)
 | ||
| 	else
 | ||
| 		evince_bin="${PDF_VIEWER}"
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.pdf$" | fzf --prompt='pdf> ' --preview 'lesspipe {} | less' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.pdf$" | fzf --prompt='pdf> ' --preview 'lesspipe {} | less' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	## Move to the directory and open the file {{{
 | ||
| 	if [[ -n $files ]]
 | ||
| 	then
 | ||
| 		dir=$(dirname "${files}")
 | ||
| 		cd "${dir}"
 | ||
| 		file=$(basename "${files}")
 | ||
| 		"${evince_bin}" -- "${file}"
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| }
 | ||
| # }}}
 | ||
| # pdfz - fuzzy open with zathura from current directory {{{
 | ||
| # Search with fd (fdfind is better than find with a pattern)
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Display a preview of selected file with lesspipe
 | ||
| # Move to the directory of the selected file
 | ||
| # Open the selected file with zathura (default rollback to "${PDF_VIEWER}")
 | ||
| function pdfz() {
 | ||
| 	local files
 | ||
| 	local dir
 | ||
| 	local file
 | ||
| 	local zathura_bin
 | ||
| 
 | ||
| 	## If zathura is available {{{
 | ||
| 	if [ $(command -v zathura) ]; then
 | ||
| 		zathura_bin=$(command -v zathura)
 | ||
| 	else
 | ||
| 		zathura_bin="${PDF_VIEWER}"
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.pdf$" | fzf --prompt='pdf> ' --preview 'lesspipe {} | less' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.pdf$" | fzf --prompt='pdf> ' --preview 'lesspipe {} | less' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	## Move to the directory and open the file {{{
 | ||
| 	if [[ -n $files ]]
 | ||
| 	then
 | ||
| 		dir=$(dirname "${files}")
 | ||
| 		cd "${dir}"
 | ||
| 		file=$(basename "${files}")
 | ||
| 		"${zathura_bin}" -- "${file}"
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # odt − fuzzy open text document file with LibreOffice from current directory {{{
 | ||
| # Search with fd (fdfind is better than find with a pattern)
 | ||
| # Search for odt|rtf|doc|docx files
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Move to the directory of the selected file
 | ||
| # Open the selected file with libreoffice --writer
 | ||
| function odt() {
 | ||
| 	local files
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.(odt|rtf|doc|docx)" | fzf --prompt='odt> ' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.(odt|rtf|doc|docx)" | fzf --prompt='odt> ' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	## Move to the directory and open the file {{{
 | ||
| 	if [[ -n $files ]]
 | ||
| 	then
 | ||
| 		dir=$(dirname "${files}")
 | ||
| 		### Change directory only if not already in the expected dir
 | ||
| 		test $(realpath "${dir}") != $(realpath .) && cd -- "${dir}"
 | ||
| 		file=$(basename "${files}")
 | ||
| 		command libreoffice --writer "${file}" &
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| }
 | ||
| # }}}
 | ||
| # ods − fuzzy open calc document file with LibreOffice from current directory {{{
 | ||
| # Search with fd (fdfind is better than find with a pattern)
 | ||
| # Search for ods|xls|xlsx files
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Move to the directory of the selected file
 | ||
| # Open the selected file with libreoffice --calc
 | ||
| function ods() {
 | ||
| 	local files
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.(ods|xls|xlsx)" | fzf --prompt='ods> ' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.(ods|xls|xlsx)" | fzf --prompt='ods> ' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	## Move to the directory and open the file {{{
 | ||
| 	if [[ -n $files ]]
 | ||
| 	then
 | ||
| 		dir=$(dirname "${files}")
 | ||
| 		### Change directory only if not already in the expected dir
 | ||
| 		test $(realpath "${dir}") != $(realpath .) && cd -- "${dir}"
 | ||
| 		file=$(basename "${files}")
 | ||
| 		command libreoffice --calc "${file}" &
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| }
 | ||
| # }}}
 | ||
| # odp − fuzzy open presentation document file with LibreOffice from current directory {{{
 | ||
| # Search with fd (fdfind is better than find with a pattern)
 | ||
| # Search for odp|ppt|pptx files
 | ||
| # Allow to give arguments to prefill fzf request
 | ||
| # Move to the directory of the selected file
 | ||
| # Open the selected file with libreoffice --impress
 | ||
| function odp() {
 | ||
| 	local files
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -eq "0" ]; then
 | ||
| 		## Default command without args
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.(odp|ppt|pptx)" | fzf --prompt='odp> ' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "\.(odp|ppt|pptx)" | fzf --prompt='odp> ' --no-multi "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	## Move to the directory and open the file {{{
 | ||
| 	if [[ -n $files ]]
 | ||
| 	then
 | ||
| 		dir=$(dirname "${files}")
 | ||
| 		### Change directory only if not already in the expected dir
 | ||
| 		test $(realpath "${dir}") != $(realpath .) && cd -- "${dir}"
 | ||
| 		file=$(basename "${files}")
 | ||
| 		command libreoffice --impress "${file}" &
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # fopen − fuzzy open file with xdg-open from current directory {{{
 | ||
| # Search with fd (fdfind is better than find with a pattern)
 | ||
| # Use first argument as fd pattern
 | ||
| # Other arguments will prefill fzf request
 | ||
| # Move to the directory of the selected file
 | ||
| # Open the selected file with xdg-open
 | ||
| function fopen() {
 | ||
| 	local files
 | ||
| 
 | ||
| 	## Manage argument {{{
 | ||
| 	if [ "${#}" -le "1" ]; then
 | ||
| 		## Default command with one argument or default value
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "${1:-.}" | fzf --prompt='open> ' --no-multi) &&
 | ||
| 	else
 | ||
| 		## If at least one argument was given, add it to fzf query
 | ||
| 		files=$(fd --unrestricted --type file --type symlink --follow "${1:-.}" | fzf --prompt='open> ' --no-multi --query "${*} ") &&
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| 
 | ||
| 	## Move to the directory and open the file {{{
 | ||
| 	if [[ -n $files ]]
 | ||
| 	then
 | ||
| 		dir=$(dirname "${files}")
 | ||
| 		### Change directory only if not already in the expected dir
 | ||
| 		test $(realpath "${dir}") != $(realpath .) && cd -- "${dir}"
 | ||
| 		file=$(basename "${files}")
 | ||
| 		command xdg-open "${file}" &
 | ||
| 	fi
 | ||
| 	## }}}
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # dexec − Docker exec in a running container {{{
 | ||
| # Display Docker running containers
 | ||
| # Allow to specify the shell (default to bash)
 | ||
| function dexec() {
 | ||
| 	local images_name
 | ||
| 	local container_name
 | ||
| 	local container_id
 | ||
| 
 | ||
| 	images_name=$(docker container ls --format "table {{.Image}}\t {{.RunningFor}}\t {{.Ports}}\t {{.Names}}" | fzf --prompt='docker> ' --tac )
 | ||
| 
 | ||
| 	## Extract container_name from the selected line
 | ||
| 	container_name=$(printf '%b' "${images_name}" | awk '{ print $NF }')
 | ||
| 	## Get container_id from the selected container_name
 | ||
| 	container_id=$(docker container ls --quiet --filter=name="${container_name}")
 | ||
| 
 | ||
| 	printf "%b\n" "Try to enter to Docker container (named : ${container_name})"
 | ||
| 	docker exec --interactive --tty -- "${container_id:-/dev/null}" "${1:-bash}"
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| # passf − Edit pass's passwords {{{
 | ||
| # Display existing files in ~/.password-store without .gpg extension
 | ||
| # https://www.passwordstore.org/
 | ||
| function passf() {
 | ||
| 	local pass_files
 | ||
| 
 | ||
| 	pass_file=$(find ~/.password-store -type f -iname "*.gpg" -printf "%P\n" | sed 's/\(.*\)\.gpg$/\1/' | fzf --prompt='pass > ' )
 | ||
| 
 | ||
| 	pass edit "${pass_file:-/dev/null}"
 | ||
| }
 | ||
| # }}}
 | ||
| 
 | ||
| fi
 | ||
| ## ENDIF fzf AVAILABLE
 | ||
| 
 | ||
| # }}}
 | ||
| # zsh-syntax-highlighting {{{
 | ||
| ## Activate if plugin is available
 | ||
| [ -f ~/repos/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ] && source ~/repos/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
 | ||
| 
 | ||
| ## Additionnal highlighters
 | ||
| ### The order is important. Put **regexp** before **main** to prioritize
 | ||
| ###  the double quotation marks
 | ||
| ZSH_HIGHLIGHT_HIGHLIGHTERS=(regexp main brackets pattern)
 | ||
| ### Dangerous commands
 | ||
| ZSH_HIGHLIGHT_PATTERNS+=('rm -rf ' 'fg=white,bold,bg=black')
 | ||
| ZSH_HIGHLIGHT_PATTERNS+=('sudo ' 'fg=white,bold,bg=red')
 | ||
| ### CLI
 | ||
| ZSH_HIGHLIGHT_REGEXP+=('\ \-[^- ]+' 'fg=202') # short args in orange (-l)
 | ||
| ZSH_HIGHLIGHT_REGEXP+=('\ \--[^ ]+' 'fg=214') # long args in light orange (--all)
 | ||
| ### Taskwarrior
 | ||
| ZSH_HIGHLIGHT_REGEXP+=('\ \+[^ ]+' 'fg=202') # tags in orange (+txt)
 | ||
| ZSH_HIGHLIGHT_REGEXP+=('[^ ]+\:' 'fg=135')   # metadata in purple (project:)
 | ||
| ZSH_HIGHLIGHT_REGEXP+=('\ \_[^ ]+' 'fg=32')  # subcommands in blue (_command)
 | ||
| # }}}
 |