19

Мне бы хотелось многострочное приглашение zsh с выровненной справа частью, которое будет выглядеть примерно так:

2.nate@host:/current/dir                                               16:00
->

Я знаю о RPROMPT в zsh, но он выровнен по правому краю напротив вашего обычного приглашения, которое находится на той же строке текста, что и вы печатаете.

Есть ли способ получить выравнивание по правому краю в первой строке многострочной командной строки? Я ищу либо директиву в переменной PS1, которая говорит «выравнивание по правому краю сейчас», либо переменную, которая для PS1, что RPROMPT для PROMPT.

Спасибо!

3 ответа3

12

Подробный ответ и пример вы найдете здесь. Идея состоит в том, чтобы написать строку перед PS1, используя обратный вызов precmd , использовать $COLUMNS и немного математики, чтобы вычислить позицию текста в правой части экрана. Знание escape-последовательностей также поможет вам с позиционированием и раскраской курсора.

Другим решением может быть использование темы от Oh My ZSH.

9

Я тоже искал это. Для меня тот факт, что прорисованные линии precmd() не перерисовываются при изменении размера или когда ^L используется для очистки экрана, был чем-то, что вызывало у меня зуд. Сейчас я использую escape-последовательности ANSI, чтобы немного переместить курсор. Хотя я подозреваю, что есть более элегантный способ их выдачи, это работает для меня:

_newline=$'\n'
_lineup=$'\e[1A'
_linedown=$'\e[1B'

PROMPT=...whatever...${_newline}...whatever...
RPROMPT=%{${_lineup}%}...whatever...%{${_linedown}%}

Помните, что руководство zsh утверждает, что% {...%} предназначено для буквенных escape-последовательностей, которые не перемещают курсор. Тем не менее, я использую их, потому что они позволяют игнорировать длину его содержимого (хотя я не мог понять, как создать escape, который перемещает курсор, используя их)

3

Вот как я настроил эту вещь только сейчас. Этот подход не требует каких-либо манипуляций с escape-последовательностями, но заставит вас иметь две разные переменные для основного приглашения: PS1 с окраской и NPS1 без.

# Here NPS1 stands for "naked PS1" and isn't a built-in shell variable. I've
# defined it myself for PS1-PS2 alignment to operate properly.
PS1='%S%F{red}[%l]%f%s %F{green}%n@%m%f %B%#%b '
NPS1='[%l] %n@%m # '
RPS1='%B%F{green}(%~)%f%b'

# Hook function which gets executed right before shell prints prompt.
function precmd() {
    local expandedPrompt="$(print -P "$NPS1")"
    local promptLength="${#expandedPrompt}"
    PS2="> "
    PS2="$(printf "%${promptLength}s" "$PS2")"
}

Обратите внимание на использование print -P для быстрого развертывания, ${#variable} для получения длины строки, хранящейся в переменной, и printf "%Nd" для заполнения слева с N пробелами. И print и printf являются встроенными командами, поэтому не должно быть никакого снижения производительности.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .