Есть ли команда, чтобы заставить bash напечатать новую строку приглашения и перерисовать текущую строку?

237
Ari Sweedler

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

$ slowcmd & $ cmd_output █ 
  • Перед моим курсором нет строки подсказки.
  • и slowcmdможет быть любой медленной командой (о вещах, которые я пробовал, я только что сказал alias slowcmd='sleep 1 && echo cmd_output')

В то время как я хотел бы что-то вроде этого:

$ slowcmd && redrawPromptString & $ cmd_output $ █ 

Где после вывода команды для меня выводится новая строка подсказки.

Что я могу сделать, чтобы сделать redrawPromptStringто, что я хочу? Я пытался clear, kill $$чтобы послать ^Cк терминалу, и, наконец, printf "^C"(конечно, не работает). Я бегу Баш. (GNU bash, версия 3.2.57).

1
Для `redrawPromptString`, как насчет` printf '$' `? dsstorefile1 6 лет назад 0
Мой PS1 цветной и использует экранированные от обратной косой черты специальные символы - например, `\ @` для того времени. (Но да, это подходящий обходной путь для любого здравомыслящего человека, который не заботится о том, чтобы получить именно то, что он хочет ...) Ахаха, но на самом деле, я ненавижу не иметь возможности делать то, что я хочу из-за невежества! Из-за отсутствия поддержки в программе, которую я использую? Конечно (пока). Но по незнанию? Мне это не нравится Я буду гуглить и составлять переполнения и буду спрашивать всех, кто, по-моему, может сейчас, пока коровы не вернутся домой. Ari Sweedler 6 лет назад 0
Почему бы не использовать отдельный, выделенный для терминала `slowcmd`? Используйте терминальный мультиплексор, такой как `tmux`, создайте новое окно и запустите там` slowcmd`, пока вы можете переключиться обратно на работающий терминал и продолжить свою работу. Alex 6 лет назад 1
@ Алекс Я также могу открыть новую вкладку в iTerm. Я не спрашиваю, как получить контроль над моим терминалом, выполняя команды, которые занимают некоторое время, потому что я уже знаю, как это сделать. И если бы я задал такой вопрос, меня бы по праву опровергли. Нет, я не ищу эвристику, я ищу решение Ari Sweedler 6 лет назад 0

2 ответа на вопрос

1
RalfFriedl

Если вы нажмете Ctrl+L, он будет частично делать то, что вы хотите. Он будет перерисовывать текущую строку, включая все, что вы набрали до этой точки, включая позицию курсора, но он очистит экран, поэтому ваш предыдущий вывод будет потерян (или в случае окна терминала в буфере прокрутки). С другой стороны, вы хотели попробовать clear, так что, возможно, это не проблема.

Да, `clear` и` ^ L` не делают то, что я хочу. Я хочу, чтобы команда финишировала, чтобы создать новое приглашение, поэтому мне не нужно ничего делать вручную. Должен быть способ! Я использовал `^ C` или` ^ L` или просто "`, они все _work_. Но я делаю неоптимальную вещь из-за невежества и ненавижу это! Ari Sweedler 6 лет назад 0
Вы не получите новое приглашение, потому что приглашение уже распечатано. Но вы можете использовать `set -b`, чтобы оболочка немедленно напечатала` [1] + Done`, и ваш курсор окажется на новой строке. Вы также можете `поймать`` SIGCHLD` и использовать его для печати нового приглашения, но вам нужно будет выяснить, был ли завершен фоновый процесс. RalfFriedl 6 лет назад 1
1
Kamil Maciorowski

Используйте redraw-current-lineфункцию bindвстроенного. Сначала проверьте, если это уже связано, может быть:

bind -q redraw-current-line 

Я никогда не видел его привязанным по умолчанию, поэтому вам, вероятно, придется связать его. Выберите комбинацию клавиш, скажем, Ctrl+ Y. Проверьте, не занято ли уже:

bind -p | grep -F '"\C-y' 

Пустой вывод означает, что комбинация не используется. Если так, давайте свяжемся redraw-current-lineс этим:

bind "\C-y":redraw-current-line 

Теперь, когда фоновый процесс мешает вашей командной строке, нажмите Ctrl+ Y. Затем ваша подсказка будет перерисована вместе с любой командой, которую вы только что частично набрали (если она есть), так что вы можете продолжить, как будто ничего не произошло.

Чтобы сделать привязку постоянной, вы можете добавить вышеуказанную команду к вашей ~/.bashrc, но не добавляйте . Правильный подход заключается в изменении ~/.inputrc(для пользователя) или /etc/inputrc(для всей системы). Таким образом, любая программа, которая использует readline(3)библиотеку, будет подчиняться. Строка для добавления в любой файл выглядит следующим образом:

"\C-y":redraw-current-line 

Но если вы создаете ~/.inputrcзаново, убедитесь, что в первой строке написано $include /etc/inputrc. Это потому, что до этого момента readlineиспользовался /etc/inputrcи, возможно, ваш рабочий процесс зависит от того, что находится в этом файле. Отныне библиотека будет использовать ~/.inputrcвместо вас; строка также $include /etc/inputrcвыполняет синтаксический анализ общесистемного файла.

Для получения дополнительной информации см help bindи man 3 readline.

Я использовал `" \ Cc "`, который отправляет символ `INTR` в соответствии с` stty`, и заставляет все входные данные быть отброшенными и сценарий подсказки должен быть представлен снова. Но `redraw-current-line` это именно то, что я искал! Это не теряет мой текущий ввод или историю экрана. Я не хочу быть жадным, но знаете ли вы какие-либо команды CLI, которые могут вызывать функцию `Readline`? Ari Sweedler 6 лет назад 0
+1 за подробное объяснение `bind` тоже. Найти супер документацию по нему очень сложно. У Man bash есть хорошие вещи под командой Shell Builtin Commands (если вы можете найти их через все это). Для всех, кто читает, эта [ссылка] (https://www.computerhope.com/unix/bash/bind.htm) предназначена только для `bind`, и я нашел ее гораздо более дружественной для новичков. Ari Sweedler 6 лет назад 0

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