Вызов кода: средство сокращения пути Bash - PullRequest
21 голосов
/ 17 августа 2010

Я реализовал средство сокращения пути для включения bash в переменную среды PS1, которая сокращает рабочий каталог до чего-то более компактного, но все же описательного.Мне любопытно, какие еще идеи могут существовать.

Вот проблема:

Создайте функцию 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\] '

с «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, но не скомпилированные программы на Си или аналогичные.Другими словами: внешние исходные файлы не допускаются, код должен быть встроенным.Кратчайшая версия выигрывает.Длина тела функции bash (и вызываемых подфункций) рассчитывает, означает:

_sub_helper() {
  # this counts
}
_dir_chomp() {
  # these characters count (between { and })
  _sub_helper "foobar" # _sub_helper body counts, too
}

Ответы [ 4 ]

12 голосов
/ 17 августа 2010

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[*]}"
}

В целях тестирования я предполагаю, что вопрос означает, что текущий пользователь - "user1".

Примечание: Bash 4 имеет переменную PROMPT_DIRTRIM, которая сокращает экранирование \w в PS1, сохраняя количество подкаталогов в соответствии с его значением и заменяя остальные на ...

/$ PROMPT_DIRTRIM=2
/$ echo $PS1
\w\$
/$ pwd
/
/$ cd /usr/share/doc/bash
.../doc/bash$
8 голосов
/ 17 августа 2010

Этот символ приблизительно на 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
}
1 голос
/ 17 августа 2010

Это было мое собственное решение, когда у меня была идея для этого испытания.На самом деле вдохновение пришло из блога Джолексы .

. Итак, реализация рубина в удобочитаемой формефункция bash:

_dir_chomp() {
  ruby -e'a="'$1'".gsub(%r{^'$HOME'},"~");b,a=a,a.gsub(%r{/(\.?[^/.])[^/]+(/.*)},"/\\1\\2")while(a.length>'$2')&&(b!=a);print a'
}
0 голосов
/ 20 сентября 2014

Вот так я сокращаю свое приглашение bash с полным путем в заголовке заголовка (работает с версии 3.0):

_PS1P=('' '..')
PROMPT_COMMAND='_PS1L=${#DIRSTACK[0]} _PS1D=${DIRSTACK[0]}'
PS1='\[\e]2;\h:\w\a\]\h ${_PS1P[$_PS1L>36]}${_PS1D:$_PS1L>36?-34:0} \$ '

Этот метод требует очень низкой загрузки ЦП.

...