Bash提示缩短

时间:2016-05-27 22:52:32

标签: bash .bash-profile

我刚从tcsh移到bash,我特别错过了使用%c02(同时设置ellipsis)的目录缩短提示选项。< / p>

我看到PROMPT_DIRTRIM几乎做了正确的事(除了省略号,我认为),但我只在bash 3(在OS X上)。我发现this recipe elsewhere on SO缩短了总长度,因此在目录中间打破了路径名,这是我不喜欢的。

所以我想出了这个:

PROMPT_DIRTRIM=2   ## from bash4, but used here
dirtrim() 
{
    local NAME="$1" start= endelts=
    [[ "$NAME" =~ ^"$HOME"(/|$) ]] && NAME="~${NAME#$HOME}"  ## $HOME ==> ~
    IFS=/ read -ra elts <<< "$NAME";          ## split $PWD on "/"
    start=$((${#elts[@]}-${PROMPT_DIRTRIM}))  ## first element to retain
    if [ ${start} -gt 1 ]; then     
        for ((i=${start}; i<${#elts[@]}; i++)); do 
            endelts="${endelts}/${elts[$i]}"; ## concat together the trailing path
        done
        NAME="...${endelts}"
    fi
    echo "$NAME"    
}
PS1='\h:$(dirtrim "$PWD")\$ '

有效:

blackat:~$ cd ~/Library/Application\ Support/Apple
blackat:.../Application Support/Apple$

但我对bash感到陌生,并对明确的for (())循环不满意;但是,我似乎找不到任何其他方式来重新加入拆分elts数组的最后一个条目,以正确处理目录名称中的空格(例如,使用${elts[@]:${start}})。有任何提示或其他改进吗?

(顺便说一下,我认为编程问题,bash是一种编程语言......)

2 个答案:

答案 0 :(得分:3)

你可以试试这个:

if ((start > 1)); then
  name=$(IFS=/; echo .../"${elts[*]:start}")
  # If your terminal is correctly set up for unicode, you can save two character positions:
  # name=$(IFS=/; echo …/"${elts[*]:start}")
fi

请注意,在bash中,在算术上下文中,包括((...))的内部和数组下标,您只需要写出变量的名称;不需要印记。

另一种方法是

if ((start > 1)); then
  printf -v name "/%s" "${elts[@]:start}"
  name=...$name
fi

另一个解决方案,在BASH_REMATCH数组中使用正则表达式捕获而不是拆分和重新加入字符串:

dirtrim () { 
  local path="$1";
  [[ $path =~ ^"$HOME"(/.*)? ]] && path=~${BASH_REMATCH[1]};
  ((PROMPT_DIRTRIM)) &&
    [[ $path =~ ...*((/[^/]*){$PROMPT_DIRTRIM}) ]] &&
    path=…${BASH_REMATCH[1]};
  echo "$path"
}

由于算术上下文中bash评估的特殊性,((PROMPT_DIRTRIM))测试并不完全可靠。对于分发,您可能更喜欢[[ $PROMPT_DIRTRIM =~ ^[1-9][0-9]*$ ]]

之类的内容

答案 1 :(得分:1)

不是一个真正的答案,但你可能想看看mksh如何完成这个:

PS1=${| local e=$? (( e )) && REPLY+="$e|" REPLY+=${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \?)} REPLY+=@${HOSTNAME%%.*}: local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~} local m=${%d} n p=...; (( m > 0 )) || m=${#d} (( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || p= REPLY+=$p$d return $e }

不幸的是,它使用的某些扩展程序不在bash中,我相信。

麻生太郎,既然你正在切换贝壳......你考虑过fish吗?

它开箱即用,然后是一些。