# /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|dpkg|… 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' ' '" alias gdpkg='dpkg --list | grep --extended-regexp -- ' 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' ' '" alias gpackage='pacman --query --search -- | grep --extended-regexp -- ' 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 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 mutt='neomutt' alias m='neomutt' 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 pour aller jusqu'au caractère vers l'avant 3f pour aller jusqu'à la 3ème occurence du caractère vers l'avant F pour aller jusqu'au caractère vers l'arrière nF pour aller jusqu'à la nème occurence du caractère vers l'arrière t pour aller jusqu'au caractère vers l'avant en s'arrêtant avant T pour aller jusqu'au caractère 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 : pour aller à la ligne % 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\" \"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 d$ CTRL-o D # Supprimer le texte du curseur au début de la ligne 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 CTRL-o suivi de la commande à exécuter # Code touche # Pour afficher le code clavier d'une touche spéciale en mode insertion: CTRL-V # Pour afficher le code interne d'une touche spéciale: 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%#%{%} " 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 ../ 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 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 local fzf bin is available use it in priority if [[ ! "$PATH" == *"${HOME}"/.fzf/bin* ]]; then export PATH="${HOME}/.fzf/bin:${PATH}" fi ## IF fzf is AVAILABLE if [ $(command -v fzf) ]; then ## IF fd is AVAILABLE {{{ if [ -f ~/bin/fd ] || [ -f /bin/fd ] || [ -f /usr/bin/fd ]; then export FZF_DEFAULT_COMMAND='fd --type f' fi ## }}} autoload is-at-least # FZF_DEFAULT_OPTS according to fzf version {{{ 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 # ------------ test -f "${HOME}/.fzf/shell/key-bindings.zsh" && source "${HOME}/.fzf/shell/key-bindings.zsh" test -f "/usr/share/fzf/key-bindings.zsh" && source "/usr/share/fzf/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 is 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) # }}}