From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5710 invoked by alias); 16 Aug 2011 06:05:17 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 16251 Received: (qmail 19589 invoked from network); 16 Aug 2011 06:05:14 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received-SPF: none (ns1.primenet.com.au: domain at closedmail.com does not designate permitted sender hosts) From: Bart Schaefer Message-id: <110815230507.ZM3115@torch.brasslantern.com> Date: Mon, 15 Aug 2011 23:05:07 -0700 X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-users@zsh.org Subject: Prompt theme: Show the original job text after foregrounding MIME-version: 1.0 Content-type: text/plain; charset=us-ascii For years I've been using a two-line prompt that displays the previous command and its exit status (represented by highlighting) in the first of the two lines. You may have seen this as "prompt bart" in the theme system distributed with zsh. In that theme, the previous command is extracted from the history like so: zmodload zsh/parameter psvar[7]="$history[$[HISTCMD-1]]" A few days ago I had backgrounded a command. I brought it into the foreground again, after which it exited with a nonzero status. This left [fg] in reverse video in the upper line of my prompt; not very informative. It occurred to me that it might be possible to recover the text of the command that was foregrounded, so that I could easily see what actual command had failed -- and in fact it was even easier than I expected. The doc for the zsh/parameter module describes the jobdirs, jobtexts, and jobstates associative arrays thusly: The keys of the associative arrays are usually valid job numbers, and these are the values output with, for example, ${(k)jobdirs}. Non-numeric job references may be used when looking up a value; for example, ${jobdirs[%+]} refers to the current job. What this means is that anything you can pass to the "jobs" command to identify a job, can be used as a key in any of these associations. So the text of the job that will be resumed by fg is given by $jobtexts[%+] With that, it's possible to write a preexec function that recognizes the "fg" command and looks up the job text for the command that is about to be resumed. This can then be stashed in a variable for use by precmd when it builds the next prompt; or it can be poked into the window title bar, etc. There are still a few gotchas -- compound commands are annoying to interpret even with ${(z)...} to handle the syntax, and multiple jobs can be resumed by a single fg -- but a function that handles all the common cases is not hard to write. See prompt_bart_preexec below. Also handling "wait" is left as an exercise. I can't remember the last time I used "wait" in an interactive shell except when testing a zsh bugfix, so this doesn't seem like a significant omission. --- current/Functions/Prompts/prompt_bart_setup 2009-05-12 08:14:11.000000000 -0700 +++ Functions/Prompts/prompt_bart_setup 2011-08-15 21:50:05.000000000 -0700 @@ -67,15 +67,38 @@ } integer PSCOL=1 +typeset PSCMD= + +prompt_bart_preexec () { + setopt localoptions noxtrace noksharrays unset + local -a cmd; cmd=( ${(z)3} ) + if [[ $cmd[1] = fg ]] + then + shift cmd + cmd[1]=${cmd[1]:-%+} + fi + if [[ $#cmd -eq 1 && $cmd[1] = %* ]] + then + PSCMD=$jobtexts[$cmd[1]] + elif [[ -o autoresume && -n $jobtexts[%?$2] ]] + then + PSCMD=$jobtexts[%?$2] + else + PSCMD=$2 + fi + return 0 +} prompt_bart_precmd () { setopt localoptions noxtrace noksharrays unset local zero='%([BSUbfksu]|[FB]{*})' escape colno lineno + : "${PSCMD:=$history[$[HISTCMD-1]]}" # Default to history text + # Using psvar here protects against unwanted promptsubst expansions. - psvar[7]="$history[$[HISTCMD-1]]" # Use history text, not just number - psvar[8]='' # No padding until we compute it + psvar[7]="$PSCMD" + psvar[8]='' # No padding until we compute it psvar[9]=() typeset -g PSCOL @@ -153,6 +176,7 @@ repeat 1 case "$1:l" in (off|disable) add-zsh-hook -D precmd "prompt_*_precmd" + add-zsh-hook -D preexec "prompt_*_preexec" functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_bart_winch}" [[ $prompt_theme[1] = bart ]] && PS1=${${(f)PS1}[-1]} return 1 @@ -182,6 +206,7 @@ # Paste our special commands into precmd and TRAPWINCH add-zsh-hook precmd prompt_bart_precmd + add-zsh-hook preexec prompt_bart_preexec functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_bart_winch} prompt_bart_winch"