Как получить длинные командные строки для переноса на следующую строку?

Что-то, что я заметил в Ubuntu в течение долгого времени, меня расстраивало, когда я набираю команду в командной строке, которая становится длиннее (шире) ширины терминала, вместо переноса на новую строку, она возвращается к столбец 1 в той же строке и начинает перезаписывать начало моей командной строки. (На самом деле она не перезаписывает действительную команду, но визуально она перезаписывает отображаемый текст).

Трудно объяснить, не видя этого, но, скажем, мой терминал был 20 символов в ширину (мой больше похож на 120 символов - но для примера), и я хочу повторить английский алфавит. Что я печатаю это:

echo abcdefghijklmnopqrstuvwxyz

Но как выглядит мой терминал перед нажатием клавиши:

pqrstuvwxyzghijklmno

Когда я нажимаю войти, это эхо

abcdefghijklmnopqrstuvwxyz

поэтому я знаю, что команда была получена правильно. Это просто обернуло мое печатание после "о" и началось с той же строки.

Что бы я ожидал, если бы я набрал эту команду на терминале шириной всего 20 символов, это было бы так:

echo abcdefghijklmno
pqrstuvwxyz

Справочная информация: я использую bash в качестве оболочки, и у меня есть эта строка в моем ~/.bashrc:

set -o vi

чтобы иметь возможность перемещаться по командной строке с помощью команд VI. В настоящее время я использую сервер Ubuntu 10.10 и подключаюсь к серверу с помощью Putty.

В любой другой среде, в которой я работал, если я наберу длинную командную строку, она добавит новую строку под строкой, над которой я работаю, когда моя команда становится длиннее, чем ширина терминала, и когда я продолжаю печатать, я вижу свою команду на 2 разные строки. Но насколько я помню, используя Ubuntu, мои длинные команды занимают только одну строку.

Это также происходит, когда я возвращаюсь к предыдущим командам в истории (я нажимаю клавишу Esc, затем "K", чтобы вернуться к предыдущим командам) - когда я получаю предыдущую команду, длина которой была больше ширины терминала, командная строка получает покалеченный, и я не могу сказать, где я в команде.

Единственный обходной путь, который я нашел, чтобы увидеть всю длинную команду, - это нажать "Esc-V", которая открывает текущую команду в редакторе VI.

Я не думаю, что у меня есть что-то странное в моем файле.bashrc. Я закомментировал строку "set -o vi", и у меня все еще была проблема.

Я скачал свежую копию Putty и не внес никаких изменений в конфигурацию - я просто набрал имя хоста для подключения, и у меня все еще есть проблема, поэтому я не думаю, что это что-то с Putty (если мне не нужно внести некоторые изменения в конфигурацию)

У кого-нибудь еще была такая проблема, и может кто-нибудь придумать, как ее исправить?

редактировать

Это был мой файл.bashrc. Я скопировал один и тот же профиль с машины на машину, и я использовал специальные символы в моем $PS1, которые каким-то образом выбрасывают его. Теперь я придерживаюсь стандартных переменных bash для моего $PS1.

Спасибо @ændrük за подсказку.bashrc!

... Конец редактирования...

8 ответов

Решение

Убедитесь, что все непечатаемые байты в вашем PS1 содержатся в \[ \], В противном случае, bash посчитает их по длине подсказки. Он использует длину приглашения, чтобы определить, когда переносить строку.

Например, здесь bash считает подсказку шириной 19 столбцов, тогда как подсказка, отображаемая терминалом, имеет ширину всего 10 столбцов (My prompt написано на голубом, и > написано в цвете по умолчанию):

PS1='\e[36mMy prompt\e[0m>'         # bash count: 19, actual: 10

в то время как здесь он только подсчитывает приглашение как 10 столбцов шириной, потому что игнорирует байты между специальным \[ а также \] ускользает:

PS1='\[\e[36m\]My prompt\[\e[0m\]>' # bash count: 10, actual: 10

Для хорошей практики используйте tput генерировать экранирование терминала, а не жестко их кодировать:

cyan=$(tput setaf 6) # \e[36m
reset=$(tput sgr0)   # \e[0m
PS1='\[$cyan\]My prompt\[$reset\]>'

См. http://mywiki.wooledge.org/BashFAQ/053, а также http://wiki.bash-hackers.org/scripting/terminalcodes для получения дополнительной информации о tput,

Я полагаю, вы настроили PS1 с цветами, верно?

Просто убедитесь, что у вас есть \[ внутри вашего PS1 цитата, предшествующая вашему набору цветов

Например:

PS1='\[\e[0;32m\u@\w/:\[\e[m '

У меня была похожая проблема, и я наконец нашел простое решение.

Добавьте следующую строку в ваш .bashrc файл:

COLUMNS=250

Затем введите source ~/.bashrc чтобы получить желаемый эффект.

Чтобы сделать PS1, нужно добавить следующую строку:

stty columns 1000

Например,

stty columns 1000
PS1='\[\e[0;32m\u@\w/:[\e[m '

однако это влияет на другие команды Unix, такие как ls и man.

У меня была та же проблема с настраиваемым цветным приглашением, хотя я содержал цветовые коды в \[ а также \] разделители. Оказывается, что у bash есть проблемы с отображением цветов внутри функции. Я просто использовал переменные для моего приглашения, и хотя мой.bashrc немного менее элегантен, теперь все работает хорошо.

У меня была эта проблема при подключении в tmux. Проблема была в том, что у меня был ipython сессия в фоновом режиме (ctrl + z) и это как-то сломало перенос строки. Как только я это прекратил (fg, ctrl+d+d) мой терминал начал работать нормально

Поэтому проверяйте, не остановились ли интерактивные подсказки.

\[ а также \] не работает для меня Я думаю, что-то отличалось в том, как я генерировал приглашение (из внешней программы), или потому что мое приглашение было "динамическим".

Прочитав это, я обнаружил, что вы можете избежать цветовых кодов с помощью 0x01 а также 0x02 байт.

Например, я использую специальную версию Chalk и оборачиваю цвета, используя это:

const Chalk = require('@nasc/chalk');

const chalk = new Chalk.constructor({
  wrapper: {
    pre: '\1',
    post: '\2',
  }
});

Так что у меня возникла та же проблема с небольшим поворотом, и я подумал, что тоже поделюсь своим решением, просто чтобы добавить свой маленький нюанс:D

Мой начальный PS1 был

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$"

Проблема была в том, что я пытался изменить заголовок своего терминала, а также командную строку. Я сделал это, добавив \[\033]0;\]Title\a к переменной PS1.

Так что теперь мой PS1 был:

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[\033]0;\]Title\a"

Это испортило мне черту. Наконец-то я понял, что bash не нравится \a в конце. Чтобы обойти это, я поместил заголовок в переменную, которая, казалось, исправила это.

TITLE="\033]0;Title\a"
PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[$TITLE\]"
Другие вопросы по тегам