Advertisement
bac0n

Expand dots to dot-dot component.

Jul 17th, 2018
579
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 3.87 KB | None | 0 0
  1. #
  2. # Expand dots to dot-dot component (~/.bash_aliases).
  3. #
  4. # https://github.com/bac0n/bash_completion
  5. #
  6. if [ -n "$PS1" ]; then
  7. cd(){
  8.     local d=${@:(-1)}
  9.     local x='' y='' z=3
  10.     while [[ ! -d $d ]] && [[ ${d:${#x}} =~ (^|/)([.]{3,})(/.*)?$ ]]; do
  11.         x=${d:0:(${#d} - ${#BASH_REMATCH[3]})}
  12.         if [[ ! -d $x ]]; then
  13.             y='..'
  14.             for ((z=3; z <= ${#BASH_REMATCH[2]}; z++)); do
  15.                 y+='/..'
  16.             done
  17.             d=${d:0:(${#d} - ${#BASH_REMATCH[0]})}${BASH_REMATCH[1]}${y}${BASH_REMATCH[3]}
  18.         fi
  19.     done
  20.     builtin pushd "$d" > /dev/null && /bin/ls --almost-all --color=auto
  21. }
  22.  
  23. cd_undo(){
  24.     if [[ ${READLINE_LINE%% *} != cd ]]; then
  25.         return
  26.     fi
  27.     local d='' x='' y='' z=0
  28.     READLINE_LINE=${READLINE_LINE%/}
  29.     d=$(rev <<< ${READLINE_LINE#* })
  30.     if [[ $d =~ (^|/)([.]{2}(/[.]{2})+)(/.*)?$ ]]; then
  31.         y=.
  32.         x=${BASH_REMATCH[2]//\/}
  33.         for ((z=0; z < (${#x} / 2); z++)); do
  34.             y+=.
  35.         done
  36.         x=${d:0:(${#d} - ${#BASH_REMATCH[0]})}
  37.         READLINE_LINE="cd $(rev <<< ${x}${BASH_REMATCH[1]}${y}${BASH_REMATCH[4]})"
  38.         READLINE_POINT=$((${#READLINE_LINE} - ${#x} - ${#BASH_REMATCH[1]}))
  39.     else
  40.         i=0
  41.         x=$((${#READLINE_LINE} - $READLINE_POINT))
  42.         while [[ ${d:$x} =~ (^|/)([.]{3,})(/.*)?$ ]]; do
  43.             x=$((${#d} - ${#BASH_REMATCH[3]}))
  44.             if (( (${#BASH_REMATCH[2]} + ${#BASH_REMATCH[3]}) == ($READLINE_POINT - 3) )); then
  45.                 continue
  46.             fi
  47.             READLINE_POINT=$((${#BASH_REMATCH[0]} - ${#BASH_REMATCH[1]} + 3))
  48.             break
  49.         done
  50.     fi
  51. }
  52.  
  53.     # bind cd undo to readline keyseq ESC ESC.
  54.     if [[ $(declare -F cd_undo) = cd_undo ]]; then
  55.         bind -r '"\e\e"'
  56.         bind -x '"\e\e"  :cd_undo'
  57.         bind -x '"\e\e\e":cd_undo'
  58.     fi
  59. fi
  60.  
  61. ##
  62.  
  63. # (/etc/bash_completion.d/cd)
  64. #
  65. # This meta-cd function observes the CDPATH variable, so that cd additionally
  66. # completes on directories under those specified in CDPATH.
  67. #
  68. _cd()
  69. {
  70.     local cur prev words cword
  71.     _init_completion || return
  72.  
  73.     local IFS=$'\n' i j k
  74.  
  75.     compopt -o filenames
  76.  
  77.     # Expand dots to dot-dot component.
  78.     local x='' y='' z=3
  79.     while [[ ! -d $cur ]] && [[ ${cur:${#x}} =~ (^|/)([.]{3,})(/.*)?$ ]]; do
  80.         if [[ -n $(compgen -d -- $cur) ]]; then
  81.             if [[ $cur == ..+(.) ]] || [[ $cur == */..+(.) ]]; then
  82.                 COMPREPLY+=("$cur/")
  83.             fi
  84.             break
  85.         fi
  86.         x="${cur:0:(${#cur}-${#BASH_REMATCH[3]})}"
  87.         if [[ ! -d $x ]]; then
  88.             y='..'
  89.             for ((z=3; z <= ${#BASH_REMATCH[2]}; z++)); do
  90.                 y+='/..'
  91.             done
  92.             cur="${cur:0:(${#cur}-${#BASH_REMATCH[0]})}${BASH_REMATCH[1]}${y}${BASH_REMATCH[3]}"
  93.         fi
  94.     done
  95.  
  96.     # Use standard dir completion if no CDPATH or parameter starts with /,
  97.     # ./ or ../
  98.     if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
  99.         _filedir -d
  100.         return
  101.     fi
  102.  
  103.     local -r mark_dirs=$(_rl_enabled mark-directories && echo y)
  104.     local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y)
  105.  
  106.     # we have a CDPATH, so loop on its contents
  107.     for i in ${CDPATH//:/$'\n'}; do
  108.         # create an array of matched subdirs
  109.         k="${#COMPREPLY[@]}"
  110.         for j in $( compgen -d -- $i/$cur ); do
  111.             if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
  112.                 j+="/"
  113.             fi
  114.             COMPREPLY[k++]=${j#$i/}
  115.         done
  116.     done
  117.  
  118.     _filedir -d
  119.  
  120.     if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
  121.         i=${COMPREPLY[0]}
  122.         if [[ "$i" == "$cur" && $i != "*/" ]]; then
  123.             COMPREPLY[0]="${i}/"
  124.         fi
  125.     fi
  126.     return
  127. }
  128.  
  129. if shopt -q cdable_vars; then
  130.     complete -v -F _cd -o nospace cd pushd
  131. else
  132.     complete -F _cd -o nospace cd pushd
  133. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement