Como imprimir sempre o prompt em uma nova linha e manter a entrada

4

Todos nós conhecemos este problema chato:

$ printf "abc" > some-file
$ cat some-file
abc$ 

que tende a bagunçar o prompt se for mais complexo que $ , joga fora a posição atual do cursor e parece simplesmente feio. Existem algumas soluções (por exemplo, aqui ), mas elas têm outra desvantagem: Fazer o login em uma máquina lenta sobre o ssh, você pode começar a digitar antes que o prompt seja exibido. Normalmente, sua entrada é então armazenada em buffer e exibida bem o mais rápido possível. No entanto, com a solução vinculada, a entrada é descartada.

Como faço para

  • sempre inicia o prompt em uma nova linha, esp. se a saída do último comando não terminou com uma nova linha e
  • mantém entrada não consumida já inserida durante a execução do comando anterior no buffer da linha de comando?
por Claudius 05.05.2016 / 12:29

1 resposta

2

Esta solução combina um pouco a solução da pergunta com um pequeno snippet de perl :

O código a seguir em .bashrc define duas novas funções, inject e clear_newline . O último é então chamado toda vez que um prompt tiver que ser impresso. O primeiro é chamado de dentro do último (veja comandos em linha para os detalhes):

# injects the arguments into the terminal, from the second link
function inject() {
  perl -e 'ioctl(STDIN, 0x5412, $_) for split "", join " ", @ARGV' "$@"
}
# prints a newline if the cursor is not in position 1
clear_newline() {
  local curpos # local variable to hold the cursor position
  local input  # local variable to hold entered input
  stty -echo # disable echoing
inject '
' # inject a newline to terminate entered input, '
# injects the arguments into the terminal, from the second link
function inject() {
  perl -e 'ioctl(STDIN, 0x5412, $_) for split "", join " ", @ARGV' "$@"
}
# prints a newline if the cursor is not in position 1
clear_newline() {
  local curpos # local variable to hold the cursor position
  local input  # local variable to hold entered input
  stty -echo # disable echoing
inject '
' # inject a newline to terminate entered input, '%pre%' didn't work?
  IFS='\n' read -s input # read entered input
  echo -en '3[6n'
  # ask the terminal driver to print the current cursor position
  IFS=';' read -d R -a curpos # read cursor position 
  stty echo # enable echoing
  (( curpos[1] > 1 )) && echo -e '3[7m%3[0m'
  # if cursor not in first column, print a % with inverted colours and a newline
  stty -echo # disable echoing of input to terminal again
  inject "${input}" # inject stored input
  stty echo # enable echo
}

PROMPT_COMMAND='clear_newline' # run clear_newline for every prompt
' didn't work? IFS='\n' read -s input # read entered input echo -en '3[6n' # ask the terminal driver to print the current cursor position IFS=';' read -d R -a curpos # read cursor position stty echo # enable echoing (( curpos[1] > 1 )) && echo -e '3[7m%3[0m' # if cursor not in first column, print a % with inverted colours and a newline stty -echo # disable echoing of input to terminal again inject "${input}" # inject stored input stty echo # enable echo } PROMPT_COMMAND='clear_newline' # run clear_newline for every prompt

O segundo par stty -echo/stty echo é necessário para esconder a entrada injetada; ele será impresso por bash assim que o prompt terminar.

    
por 05.05.2016 / 12:29