Bash – Clear old prompt lines in bash to save scroll space

bashpromptshellterminal

My terminal theme used to be like this,

terminal them before

But I thought the prompt wasted so much space. And later I got an idea that I could clean the prompt every time I ran a command. I was using bash, one of solution is to use the preexec_invoke_exec function.

I use the following command to clean the last prompt chars:

echo -ne "\033[1A\033[K\033[1A\033[K\033[31;1m$ \033[0m"

So that the terminal is very clean, like this,

enter image description here

But now my problem is, there will be problem if I want to use multi commands in one line, say, when I use for i in ....

Here is the full version of the function in my .bashrc,

preexec () { echo -ne "\033[1A\033[K\033[1A\033[K\033[31;1m$ \033[0m"; echo -n "$1"; echo -ne "  \033[37;2m["; echo -n "$2"; echo -ne "]\033[0m\n"; }
preexec_invoke_exec () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    local this_pwd=`pwd`; 
    preexec "$this_command" "$this_pwd"
}
trap 'preexec_invoke_exec' DEBUG

Best Answer

First preexec_invoke_exec has to be modified to prevent multiple executions of preexec. Also, modify preexec to take in account the actual number of lines in $PS1 :

preexec () { 
    # delete old prompt; one "\e[1A\e[K" per line of $PS1
    for (( i=0, l=$(echo -e $PS1 | wc -l) ; i < l ; i++ ))
    do             
        echo -ne "\e[1A\e[K"
    done
    # replacement for prompt
    echo -ne "\e[31;1m$ \e[0m"
    echo -n "$1"
    echo -ne "  \e[37;2m["
    echo -n "$2"
    echo -e "]\e[0m"
}

preexec_invoke_exec () {
    [ -n "$DONTCLEANPROMPT" ] && return
    DONTCLEANPROMPT=x
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    local this_pwd=`pwd`
    preexec "$this_command" "$this_pwd"
}

trap 'preexec_invoke_exec' DEBUG

PROMPT_COMMAND='unset DONTCLEANPROMPT'

In order for preexec to be run again, DONTCLEANPROMPT has to be either unset or set to ''. This is done with PROMPT_COMMAND, which is run just before the primary prompt is issued. Therefore preexec will be run once and only once for every command line.