titles in GNU screen

I love screen. (Though I am contemplating a migration to tmux, pending hackery)

But one thing I /hate/ is having to manually title windows.

Enter this hack (Currently only works with zsh afaik, but if you know the name of the related function for other shells let me know!)

This code is now dated- you can always retrieve the most uptodate version from richo’s zshrc

function preexec()
{ # {{{ Prexec hax
    # Potential TODO:
    # Set a variable for commands where we care about return status
    # if returnstatus and $! -> Add something to sTITLE
    reTITLE=$sTITLE
    case $1 in
        "cd"*)
            reTITLE=""
            # Clear home if we just 'cd'
            if [ "$1" = "cd" ]; then
                export t_prefix=""
                arg=$sTITLE
            else
                dir=$(echo $1 | sed -e "s/^cd //")
                if [ -e $dir/.title ]; then
                    case $dir in
                        "/"*)
                            export pdir=$dir;;
                        *)
                            export pdir=`pwd`/$dir;;
                    esac
                    # XXX Should this happen for all titles?
                    dTITLE=$(cat $dir/.title | sed $sed_r 's/[\r\n]//g')
                    export t_prefix="$dTITLE: "
                    arg=""
                fi
                if [ -n "$AUTOTAGS" -a -e $dir/.autotags ]; then
                    # TODO
                    # Store some more info about the tags, command to run and
                    # git branch, and use the stat time of the file, rather
                    # than the contents to work out timing
                    if [ $((`cat $dir/.autotags` + $TAGS_LIFETIME)) -lt `_time` ]; then
                        _time > $dir/.autotags
                        echo "Tags are mad old, regenerating."
                        b_tags $dir &|
                    fi
                fi
            fi
            ;;
        # Rails kludges
        "rails "*)
            work=`echo $1 | sed -e 's/^rails //'`
            case $work in
                "s"|"server")
                    arg="WEBRICK"
                    ;;
            esac
            ;;
        "bundle exec"*)
            arg=`echo $1 | sed -e 's/bundle exec/BE:/'`
            ;;

        "ls"*|"cp"*|"mv"*|"echo"*|"wiki"*|"screen"*|"dig"*|"rm"*|"mkdir"*|"tinfo"*)
            reTITLE=""
            return ;;

        # If we're doing it to everything, the command is more interesting than
        # the target
        *"*")
            arg=$(echo $1 | awk '{print $1}');;
        # Catch kill early
        "kill "*)
        reTITLE=""
            arg=$(echo $1 | awk '{print $NF}');;
        "ctags"*|"killall"*|"screen"*)
            return ;;
        "tmux"*)
            case $rTITLE in
                *"tmux"*)
                    ;;
                *)
                    export rTITLE="$rTITLE [tmux]"
                    urxvt_t $rTITLE
                    ;;
            esac
            ;;
        "man"*)
            arg=$1;;
        "watchr"*)
            arg="WATCHR";;
        "./deploy.sh"*)
            arg=$(echo $1 | sed $sed_r -e 's/^\.\/deploy.sh/deploy:/' -e 's/114\.111\.139\.//' -e 's|/var/www/||g');;

        # For Source control I want the whole line, I think...
        "svn"*|"git"*|"hg"*|"cvs"*)
            arg=$1;;

        #"thor"*|"_thor"*)
        #TODO Parse thor queries
        "make"*)
            arg=$(pwd | grep -o "[^/]*/[^/]*$");;

        # TODO Include host
        "cap"*)
            # hax
            #arg=$(echo $1 | grep -o "(deploy[^ ]*)");;
            arg=$(echo $1 | awk '{print $2}');;
        "ncmpc"*)
            arg=$(echo $1 | sed $sed_r -e 's/ ?-h */:/');;

        # Webby stuffs
        "lynx"*|"links"*)
            arg=$(echo $1 | sed $sed_r -e 's/^(lynx|links) (http[s]?:\/\/)?(www\.)?//' -e 's/\/.*$//');;

        "su"*)
            arg="!root!"
            export reTITLE=$sTITLE
            ;;
        "ssh"*)
            arg=$(echo $1 | awk '{print $NF}')
            # Don't care where in the local fs we are
            export t_prefix=""
            export reTITLE=$sTITLE
            ;;
        "vim"*)
            # Vim likes to play funny buggers with my terminal. Show that
            # bastage who's in charge.
            export reTITLE=$sTITLE
            # Don't bother setting a title- handles it.
            ;;
        *)
            arg=$(echo $1 | awk '{print $NF}');;
    esac

    t $arg
} # }}}

The obvious first prereq is that $INSCREEN be set. I do this with

setenv INSCREEN yes

in my screenrc.

The rest uses a feature of zsh- that you can create a preexec() function which runs after a command is submitted, but before it is executed, which then interprets the command, and sets a relevant title for screen. Note that the same control characters will set the title of many terminals (urxvt for sure) but this triggers a bug in vim, at present.

I have just dumped my function verbatim, but I feel it’ll give a good starting point to achieve many tasks, as it uses a wide variety of filters to do common tasks such as a noop, complex interpolation and dropping obvious parts of the command.

About richo

I enjoy exploring interesting concepts in weird languages. I also like hacking on all of the things.
This entry was posted in Guides, Hax and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>