13

I'd like to keep the bash command prompt input at the top of the screen so that outputs from older commands are pushed downwards rather than up.

How can I achieve this?

Tom Price
  • 143
  • 1
  • 7
  • 6
    So, if you `cat` a file, it would be reversed order? – chaos Jul 25 '15 at 17:50
  • Nope, but I'd want the chunks of output to be pushed downwards – Tom Price Jul 26 '15 at 09:45
  • 1
    `bash` can't do this, because `bash` doesn't even know about screen positions: it just writes to an output file. You would need a terminal emulator that knows about `bash`'s interactive prompt in order know when to reset the cursor and when to scroll the window. – chepner Mar 15 '17 at 01:54
  • Thanks @chepner, I'm revisiting this problem and your comment made me look outside of bash and start looking at the whole display stack. I want to remain within the text-based virtual consoles (i.e. no X Windows) so I'd be avoiding terminal emulators for now, but for my GUI sessions I'll certainly look into that. In case anyone comes across this question, my guess is it's to do with tty and I'm currently looking here for inspiration... https://www.linusakesson.net/programming/tty/ – Tom Price Jul 02 '19 at 06:44

1 Answers1

8

Add these lines to your .bashrc:

prompt_on_top() {
  tput cup 0 0
  tput el
  tput el1
}

pre_cmd() {
  if [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] || [ -n "$COMP_LINE" ]; then
    return
  fi
  printf "\33[2J"
}

PROMPT_COMMAND="prompt_on_top"
trap 'pre_cmd' DEBUG

bash have PROMPT_COMMAND, which hold the command will be executed before bash show prompt. Here we set it to function prompt_on_top, which use tput to set the cursor at the top of screen.

bash also have a way to execute a command before executing any command, using trap to handle signal DEBUG. Here we set it to function pre_cmd, which will clear old screen, and do nothing if we did completion (COMP_LINE is not empty) or run command in BASH_PROMPT.


There's a limitation with this approach, if command output is too long too fit in a screen, then the output will be override by prompt_on_top action. In this case, you need to pipe the output to a pager to read the whole output.

cuonglm
  • 150,973
  • 38
  • 327
  • 406
  • 1
    Thanks for your well explained answer, there's a lot for me to read up on and learn. I've tested your script, and currently it effectively wipes the old output from the screen between commands. I'd like to keep the previous outputs on the screen, below the prompt, and have it so that new outputs are inserted between the prompt and the old output, therefore pushing the old output down the screen. – Tom Price Jul 26 '15 at 13:28
  • For those coming here via a web search, this code https://github.com/swirepe/alwaysontop also "keeps your bash prompt at the top of the screen", plus a couple of other functions. Does not answer the original question though: older command outputs are deleted as with cuonglm's code. – WillC Aug 01 '18 at 18:39
  • An other drawback of this solution, is that you don't have feedback on what command was last executed. That is, `cat file` will show `file` content, but you don't get an immediate feedback of the exact command executed. Ideally the prompt would be followed with an non-expanded + expanded version of the executed command, followed with the std ouput. – psychoslave Nov 22 '18 at 15:20