Title and Hardstatus

Here are functions to set the title and hardstatus of an XTerm or of GNU Screen to 'zsh' and the current directory, respectively, when the prompt is displayed, and to the command name and rest of the command line, respectively, when a command is executed:

function title {
  if [[ $TERM == "screen" ]]; then
    # Use these two for GNU Screen:
    print -nR $'\033k'$1$'\033'\\

    print -nR $'\033]0;'$2$'\a'
  elif [[ $TERM == "xterm" || $TERM == "rxvt" ]]; then
    # Use this one instead for XTerms:
    print -nR $'\033]0;'$*$'\a'
  fi
}
  
function precmd {
  title zsh "$PWD"
}
  
function preexec {
  emulate -L zsh
  local -a cmd; cmd=(${(z)1})
  title $cmd[1]:t "$cmd[2,-1]"
}

This line from my .screenrc lets me see this fancy hardstatus:

caption always "%3n %t%? (%u)%?%?: %h%?"

This version of preexec from a post by Bart Schaefer on zsh-workers handles job control, eg. so that entering 'fg' sets the title and hardstatus to the command line of the program that is resumed, not to 'fg'.

Warning: Resuming a job with the full command line will fail, so eg. 'fg %less\ some_file' will fail while 'fg %less' will work. If you can fix this, that would be groovy.

Bart:

I've made the groovy edits:
preexec() {
  emulate -L zsh
  local -a cmd; cmd=(${(z)1})             # Re-parse the command line
  
  # Construct a command that will output the desired job number.
  case $cmd[1] in
      fg)
        if (( $#cmd == 1 )); then
          # No arguments, must find the current job
          cmd=(builtin jobs -l %+)
        else
          # Replace the command name, ignore extra args.
          cmd=(builtin jobs -l ${(Q)cmd[2]})
        fi;;
       %*) cmd=(builtin jobs -l ${(Q)cmd[1]});; # Same as "else" above
       exec) shift cmd;& # If the command is 'exec', drop that, because
          # we'd rather just see the command that is being
          # exec'd. Note the ;& to fall through.
       *)  title $cmd[1]:t "$cmd[2,-1]"    # Not resuming a job,
          return;;                        # so we're all done
      esac
  
  local -A jt; jt=(${(kv)jobtexts})       # Copy jobtexts for subshell
  
  # Run the command, read its output, and look up the jobtext.
  # Could parse $rest here, but $jobtexts (via $jt) is easier.
  $cmd >>(read num rest
          cmd=(${(z)${(e):-\$jt$num}})
          title $cmd[1]:t "$cmd[2,-1]") 2>/dev/null
}

madduck:

This produces an ugly leading space on all messages from zsh… like:
cirrus:~>
 new mail in 'debian'.

I can't find the source though…

madduck:

My problem, I call
function precmd() {
  title zsh "$IDENTITY:$(print -P %~)"
}
precmd

in .zshrc. Change that:

- precmd
+ title "$IDENTITY:$(print -P %~)"

fixes it.

ninja:

You can also use screen string escapes in the hardstatus if you use ^E (\005) as the escape character, e.g.:
"%{^[]0;screen ^En (^Et) ^G%}"

Also, screen window titling is as complex an affair as prompting, e.g.:

print -nRP $'\033k%(!.#\[.)'$1$'%'$\(\(20\-${#1}\)\)$'< ..<'${${2:+${${${@[${#${@}}]##/*/}/#/ }:-}}//\"/}$'%(!.\].)\033'\\
 
examples/hardstatus.txt · Last modified: 2010/01/05 09:20 (external edit)