5

I want to set the Xterm window title to switch between two states:

  • When a command is running, show the command name (e.g. "less")
  • When no command is running, show the current path (e.g. "src")

I can create an Xterm window title with the current path with:

$ export PROMPT_COMMAND='echo -ne "\033]0;`basename ${PWD}`\007"'

And I can show the current running command by adding a trap statement to .bashrc:

$ trap 'echo -ne "\033]0;$BASH_COMMAND\007"' DEBUG

But I'm not able to automatically switch between the two. Is it possible?

EDIT: @terdon shows a solution that works in a regular xterm, that's cool! But I failed to mention that I use the MacOSX Terminal.app. That shows still shows "bash" instead of the current path when no command is running. With a little tinkering I figured out how to solve this.

neu242
  • 1,738
  • 2
    Aren't all details already included in Display command in xterm titlebar? – manatwork Sep 20 '13 at 08:41
  • Cool, that's half the solution solved. But how do I display the current path if $BASH_COMMAND == "bash"? – neu242 Sep 20 '13 at 09:26
  • Not sure where is your dilemma. Your PROMPT_COMMAND displays the current directory when no command runs and the accepted answer of the linked question displays the current command while one is running. – manatwork Sep 20 '13 at 09:39
  • Might be of help: http://unix.stackexchange.com/questions/14113/is-it-possible-to-set-gnome-terminals-title-to-userhost-for-whatever-host-i – Boris Burkov Sep 20 '13 at 09:53
  • @manatwork: If use the trap example in .bashrc, I always have the current command in the title (including bash if no command is running). If I use PROMPT_COMMAND, I always have the path. I only want to display the current path if no command is running. – neu242 Sep 20 '13 at 10:06

2 Answers2

3

You can do this if you use a function that checks whether $BASH_COMMAND is set and prints your CWD if it is not. Add these lines to your ~/.bashrc:

trap 'echo -ne "\033]0;$BASH_COMMAND\007"' DEBUG
function show_name(){ 
    if [[ -n "$BASH_COMMAND" ]]; 
    then 
    echo -en "\033]0;`pwd`\007"; 
    else 
    echo -en "\033]0;$BASH_COMMAND\007"; 
    fi 
}
export PROMPT_COMMAND='show_name'

This will cause your terminal's name to be the currently running command (if there is one) or your current directory if there is not. Bear in mind that this will result in a slightly schizophrenic terminal if you run a long loop that runs a command many times. Try it with while true; do echo foo; done for example.

If you are using zsh this is much easier to achieve (source) and it handles loops correctly:

case $TERM in
    xterm*)
      preexec () {
        print -Pn "\e]0;$*\a"
      }
    ;;
esac
terdon
  • 242,166
  • 1
    Thanks, but that still just shows me "bash" (and not the current path) when no command is running... EDIT: Ah! It works in a plain xterm, but not in the MacOSX Terminal. Need to investigate. – neu242 Sep 24 '13 at 06:31
2

I realized that the MacOSX Terminal.app doesn't read .bashrc. With some help on how to extract the first word of a string and a little tinkering, I tweaked @terdon's great answer by adding the following to .bash_profile:

trap 'echo -ne "\033]0;${BASH_COMMAND%% *}\007"' DEBUG

function show_name { 
    if [[ -n "$BASH_COMMAND" ]]; then
      echo -en "\033]0;`basename ${PWD}`\007"
    fi 
}
export PROMPT_COMMAND='show_name'

Voila! It works like a charm.

neu242
  • 1,738
  • 2
    Ah yes, I missed the OSX tag. For some reason they decided to make all shells login shells. – terdon Sep 24 '13 at 15:06
  • The correct solution should be to have the .bash_profile source the .bashrc when interactive so login shells also interpret the shell customization file (the fact that bash doesn't do that by itself is a misdesign that has to be worked around). Here, your PROMPT_COMMAND is exported, but not your show_name or trap, so it won't work properly in non-login shells. – Stéphane Chazelas Dec 03 '15 at 09:56