zsh-workers
 help / color / mirror / code / Atom feed
From: "Bart Schaefer" <schaefer@candle.brasslantern.com>
To: "Glenn F. Maynard" <glennm@mediaone.net>, zsh-workers@sunsite.auc.dk
Subject: Re: xterm title/screen title+hardstatus
Date: Wed, 22 Nov 2000 08:11:41 +0000	[thread overview]
Message-ID: <1001122081141.ZM11237@candle.brasslantern.com> (raw)
In-Reply-To: <20001121145838.A2755@h0040333b7dc3.ne.mediaone.net>

On Nov 21,  2:58pm, Glenn F. Maynard wrote:
}
} My objective is to display exactly what was typed in the titlebar (parsed
} somewhat: the first word, the command, is placed in the title; the remainder,
} if anything, is placed in the hardstatus line.)

I hate to rain on your parade, but you haven't even begun to address all
the possible problems here.  What do you do about the AUTO_FG option?  What
is "the command" in something like:

zsh% ( print look, I am a subshell ; sleep 60 ; echo goodbye ) &

(Your function, and mine below, will put "(" in the title bar for that.)

How meaningful is your hardstatus line when you run several commands in
a pipeline?  What about redirections?  (Did you know that you can write
`2>/dev/null foo bar' in place of `foo bar 2>/dev/null'?)  What about
`fg %2 %3 %5'?  (Brings multiple jobs to the foreground in succession.)

(OK, maybe I did like raining, just a little.  One solution would be to
forget about putting one word in the title, and instead put a truncated
prefix of the entire command line there.)

Anyway, here's a preexec to do what your patches and precmd did, without
having to hack on the zsh source.

    # Helper function to output the title escapes
    title() {
	print -nR $'\033k'$1$'\033'\\
	print -nR $'\033_'$2$'\033'\\
    }

    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 $cmd[2])
		fi;;
	    %*) cmd=(builtin jobs -l $cmd[1]);;	# Same as "else" above
	    *)  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
    }

Probably the oddest bit of that is ${(z)${(e):-\$jt$num}} ... $num will be
a string such as "[3]", so \$jt$num is $jt[3], which evaluated with (e) is
the desired job text, which is then parsed with (z).

Some other commentary:

} preexec appears to receive the original, unparsed input command (including
} whitespace)--except that escapes are parsed, so a command like
} echo "Hello\nThere\n"; contains two real newlines, not the character
} sequence "\n".

No, escapes of that sort are not parsed before calling preexec.  It's your
`echo -n' that's turning those "\n" into newlines.  That's why I used
`print -Rn' instead, in the `title' function above.

} Currently, I've added a variable expansion parameter: if FOO=%vi, then
} ${(J)FOO} expands to the job number.

That was a creative approach, but I don't think it's the best way.  An
option to the `jobs' command to have it stick its output in a parameter,
like the `stat' command from the zsh/stat module does, would probably be
much better.

} Other problems I've had: Whitespace stripping was rather tricky; I'm sure
} there's a better way to do it.  The (z) (split) expansion command has very
} strange behavior: it splits on spaces if there's more than one word; if
} there's only one word, it splits it into an array of single characters.

Nope, that's not what's happening.  Subscripts on zsh parameters always
behave that way:  If the parameter is a string, the subscript indexes it
by characters, and if it's an array, it indexes by array elements.

When you do this:

	spl=${(z)cmd}

The type of `spl' is a string if ${(z)cmd} is a string, or an array if
${(z)cmd} is an array.  It just happens that when $cmd has only one word,
${(z)cmd} is a string, and otherwise it's an array.  That's probably not
intentional -- most likely (z) should always return a (maybe one-element)
array.  However, you can (and should) force `spl' to always be an array,
by using parens like this:

	spl=( ${(z)cmd} )

} preexec() {
} 	local cmd spl pnum lhs rhs
} 	cmd=$@

This is unneccesary; preexec always gets exactly one argument (the whole
command line, unparsed).

} 	spl=${(z)cmd}
} 	if [[ ${#spl} == ${#cmd} ]] then
} 		# it was split into an array of chars

Oh, really?  Try `echo 1 2 3'.

} 	# strip off any path from lhs
} 	lhs=${lhs:t}
} 	# is this a command which restarts an existing job?
} 	# lhs "fg"
} 	if [[ $lhs == "fg" ]] then
} 		pnum=${(J)rhs}
} 		preexec ${jobtexts[$pnum]}

This recursive call is a lot of work just to get those two `echo's.

} precmd() {
} 	echo -n '\033kzsh\033\\\033_'$PWD'\033'\\
} }

This, of course, is still necessary with my preexec above.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


  parent reply	other threads:[~2000-11-22  8:12 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-11-21 19:58 Glenn F. Maynard
2000-11-22  6:52 ` Andrej Borsenkow
2000-11-22  8:11 ` Bart Schaefer [this message]
2000-11-23  5:35   ` Glenn F. Maynard
2000-11-27 12:42 Sven Wischnowsky
2000-11-27 16:26 ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1001122081141.ZM11237@candle.brasslantern.com \
    --to=schaefer@candle.brasslantern.com \
    --cc=glennm@mediaone.net \
    --cc=zsh-workers@sunsite.auc.dk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).