paperlined.org
project_proposals > 2012-03-19__shell_hilight_STDIN
document updated 12 years ago, on Mar 20, 2012
# Cause all STDIN to be hilighted.

# To use this, source it from your ~/.bashrc.

# To change the color that your STDIN text is displayed in, add an ANSI code to the end of your
# prompt.
#
# Example:
#           export PS1='\[\033[0m\]\u@\h:\w\$ \[\033[102;30m\]'


# This was inspired by http://www.twistedmatrix.com/users/glyph/preexec.bash.txt
#                      http://superuser.com/questions/175799



# BUGS:
#       - bleeding happens when:
#               - Ctrl-L is used to clear the screen
#               - you backspace
#               - you do a syntax error (for example, open a single-quote, but don't close it)



function trap_install () {
    # *BOTH* of these options need to be set for the DEBUG trap to be invoked
    # in ( ) subshells.  This smells like a bug in bash to me.  The null stderr
    # redirections are to quiet errors on bash2.05 (i.e. OSX's default shell)
    # where the options can't be set, and it's impossible to inherit the trap
    # into subshells.

    set -o functrace > /dev/null 2>&1
    shopt -s extdebug > /dev/null 2>&1

    # Finally, install the actual traps.
    #PROMPT_COMMAND="${PROMPT_COMMAND};preexec_invoke_cmd"
    PROMPT_COMMAND="preexec_invoke_cmd"
    trap 'preexec_invoke_exec' DEBUG
}



# This function is installed as the PROMPT_COMMAND; it is invoked before each
# interactive prompt display.  It sets a variable to indicate that the prompt
# was just displayed, to allow the DEBUG trap, below, to know that the next
# command is likely interactive.
function preexec_invoke_cmd () {
    preexec_interactive_mode="yes"
}


# This function is installed as the DEBUG trap.  It is invoked before each
# interactive prompt display.  Its purpose is to inspect the current
# environment to attempt to detect if the current command is being invoked
# interactively, and invoke 'preexec' if so.
function preexec_invoke_exec () {
    # We're in the middle of tab-completion.  Don't do anything.
    if [[ -n "$COMP_LINE" ]]; then return; fi

    echo -ne '\033[0m'
    return

    if [[ -z "$preexec_interactive_mode" ]]
    then
        # We're doing something related to displaying the prompt.  Let the
        # prompt set the title instead of me.
        return
    else
        # If we're in a subshell, then the prompt won't be re-displayed to put
        # us back into interactive mode, so let's not set the variable back.
        # In other words, if you have a subshell like
        #   (sleep 1; sleep 2)
        # You want to see the 'sleep 2' as a set_command_title as well.
        if [[ 0 -eq "$BASH_SUBSHELL" ]]
        then
            preexec_interactive_mode=""
        fi
    fi
    if [[ "preexec_invoke_cmd" == "$BASH_COMMAND" ]]
    then
        # Sadly, there's no cleaner way to detect two prompts being displayed
        # one after another.  This makes it important that PROMPT_COMMAND
        # remain set _exactly_ as below in preexec_install.  Let's switch back
        # out of interactive mode and not trace any of the commands run in
        # precmd.

        # Given their buggy interaction between BASH_COMMAND and debug traps,
        # versions of bash prior to 3.1 can't detect this at all.
        preexec_interactive_mode=""
        return
    fi

    # If none of the previous checks have earlied out of this function, then
    # the command is in fact interactive, and this is the equivlant point of zsh's preexec.
    echo -en '\033[0m'
}





trap_install