Вопрос по – Длина счета видимой пользователем строки для приглашения zsh

14

Я хотел бы поставить свой текущийgit перейдите в мой многострочный ZSH. Однако это портит две строки - мне бы хотелось, чтобы они выстроились в очередь.

<code>
┌─([email protected]:s000)─[master *]────────────────
───(~  )─┐  
└─(127:15:44)──                       ──(Sat,May12)─┘
</code>

должно быть:

<code>
┌─([email protected]:s000)─[master *]─────────(~  )─┐  
└─(127:15:44)──                       ──(Sat,May12)─┘
</code>

git ветка схвачена изoh-my-zsh функция,git_prompt_info(), что дает мне ветку, грязный статус и кучу быстрых выходов, чтобы красиво раскрасить вещи.

Как рассчитать символы, которые будутvisibly вставлен в подсказку ZSH - не escape-последовательности подсказки?

Ваш Ответ

2   ответа
11

что экранированная подсказка строка хранится в переменнойFOO, это будет считать только видимые пользователем символы:

                                                                                                                                
FOO=$(git_prompt_info)                                                                                                                     
local zero='%([BSUbfksu]|([FK]|){*})'
FOOLENGTH=${#${(S%%)FOO//$~zero/}} 

Это происходит отэто.zshrc.

Этогрубы объяснение того, почему это работает, свободно цитируяman zshexpn, разделPARAMETER EXPANSION. Я не уверен на 100% в деталях, поэтому, если вы используете это для разработки собственного эквивалента, прочитайте соответствующийman zshall разделы.

Работа с линииFOOLENGTH=${#${(S%%)FOO//$~zero/}} у нас есть несколько битов. Идя изнутри:

$~zero:~ гарантирует, чтоzero, который мы определили как'%([BSUbfksu]|([FB]|){*})', рассматривается как шаблон, а не как простая строка.

${(S%%)FOO//$~zero/}: Это соответствует${name//pattern/repl}:

Замените максимально возможное совпадение шаблона при расширении имени параметра на строку repl

Обратите внимание, что у нас нетrepl; мы заменяем максимально длинное совпадениеpattern ни с чем, тем самым удаляя его.
(S%%)FOO проводит расширение наFOO с несколькими установленными флагами. Я не совсем слежу за этим.

${#${(S%%)FOO//$~zero/}}: ${#spec} подставит длину в символах результата подстановкиspec, еслиspec это замена. В нашем случаеspec является результатом замены${(S%%)FOO//$~zero/}; так что это в основном возвращает длину символов в результате регулярного выраженияs/zero// наFOO, гдеzero шаблон выше.

И да, все(*)лаги @ описаны в разделе РАСШИРЕНИЕ ПАРАМЕТРАman zshexpn. ZyX
(S) делает сопоставление нежадным, превращая «максимально возможное совпадение» в «максимально короткое совпадение» (без него{*} в шаблоне превратится как%F{blue}%M%F{yellow}%#%f в просто%#, в то время как это должно превратить это в%M%#),(%%) выполняет быстрое раскрытие строки в соответствии с параметрами PROMPT_ *. Примечание: этого метода следует избегать, если строка PROMPT содержит команду с некоторыми побочными эффектами: например, если вы хотите использовать ее для подсчета частоты, с которой отображается подсказка. Большую часть времени вы не будете страдать от этого. ZyX
@ ZyX Спасибо. Я видел объяснениеS вzshexpn страница, но не был уверен, как это вписалось. simont
Не работает с форматированием даты, как%D{%a %b %d, %I:%M:%S%P} dbkaplun
@ beardtree Правда. Но строка, возвращаемая этим форматом даты, не будет включать специфичные для приглашения символы (например, цветовые коды). Вы можете посчитать это используяdate='%D{%a %b %d, %I:%M:%S%P}', length=${#${date}}}. simont
2

как это сделать с помощью встроенных команд zsh, но информацию о цвете можно удалить с помощью sed (как описано в документации @Во):

sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"

например

plain_str=$(git_prompt_info | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g")

, Который удалит все escape-последовательности из строки. Длина теперь просто:

echo $#plain_str
@ beardtree: спасибо за предложенное изменение. Thor

Похожие вопросы