代码挑战:Bash提示路径缩短

hur*_*n77 21 bash prompt path

我实现了一个包含在PS1环境变量中的bash快速路径缩短器,它将工作目录缩短为更紧凑但仍然具有描述性的东西.我很好奇其他想法可能存在.

这是挑战:

创建一个bash函数_dir_chomp,可以像这样包含在PS1中(插入换行符以便于阅读):

PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] $(
  _dir_chomp "$(pwd)" 20
)\[\033[01;37m\]$(parse_git_branch)\[\033[01;34m\] \$\[\033[00m\] '
Run Code Online (Sandbox Code Playgroud)

"20"是最大长度的参数,作为软限制.这些是例子:

  1. /usr/portage/media-plugins/banshee-community-extensions/files/u/p/m/b/files
  2. /home/user1/media/video/music/live-sets成为~/m/v/m/live-sets(注意〜字符作为$ HOME的替代)
  3. /home/user2/media 不会改变(不超过20个限额)
  4. /home/user1/this-is-a-very-long-path-name-with-more-than-20-chars成为~/this-is-a-very-long-path-name-with-more-than-20-chars(最后一个组件保持不变:软限制)
  5. /home/user1/src变成~/src($ HOME总是缩短)
  6. /home/user1/.kde4/share/config/kresources变成~/.k/s/c/kresources(注意保留前缀点)

当前用户是user1.

它允许调用外部口译一样awk,perl,ruby,python但没有编译C程序或类似.换句话说:不允许使用外部源文件,代码必须是内联的.最短版本获胜.bash函数体的长度(和称为子函数)计数,表示:

_sub_helper() {
  # this counts
}
_dir_chomp() {
  # these characters count (between { and })
  _sub_helper "foobar" # _sub_helper body counts, too
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*ce. 12

Pure Bash:

_dir_chomp () {
    local IFS=/ c=1 n d
    local p=(${1/#$HOME/\~}) r=${p[*]}
    local s=${#r}
    while ((s>$2&&c<${#p[*]}-1))
    do
        d=${p[c]}
        n=1;[[ $d = .* ]]&&n=2
        ((s-=${#d}-n))
        p[c++]=${d:0:n}
    done
    echo "${p[*]}"
}
Run Code Online (Sandbox Code Playgroud)

出于测试目的,我假设问题意味着当前用户是"user1".

注意:Bash 4有一个变量PROMPT_DIRTRIM,通过根据其值保留子目录的数量并用其替换其余的来缩短\w转义.PS1...

/$ PROMPT_DIRTRIM=2
/$ echo $PS1
\w\$
/$ pwd
/
/$ cd /usr/share/doc/bash
.../doc/bash$
Run Code Online (Sandbox Code Playgroud)


Pau*_*ce. 8

这个字符比我的其他答案短20个左右:

_dir_chomp () {
    local p=${1/#$HOME/\~} b s
    s=${#p}
    while [[ $p != "${p//\/}" ]]&&(($s>$2))
    do
        p=${p#/}
        [[ $p =~ \.?. ]]
        b=$b/${BASH_REMATCH[0]}
        p=${p#*/}
        ((s=${#b}+${#p}))
    done
    echo ${b/\/~/\~}${b+/}$p
}
Run Code Online (Sandbox Code Playgroud)