Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: "jobs" command within substitution

Matt Wozniski wrote:
On 3/8/07, Micah Cowan wrote:
Matt Wozniski wrote:
> On 3/8/07, Micah Cowan wrote:
>> Hello, all. This is my first post to this group.
>> I scoured the manpages and list archives, but could not find the answer
>> I seek.
>> My question, in a nutshell, is: How can I effectively use the "jobs"
>> builtin command in producing the interactive prompt?
> Rather than trying to parse the output of the 'jobs' command, you
> might find yourself better suited by manipulating the variables
> $jobdirs, $jobstates, and $jobtexts.  You correctly identified the
> problem that you're hitting - $(jobs) is running in a subshell that
> doesn't have any jobs in its job table.  I agree, however, that (jobs)
> should also be blank, since it's also running in a subshell.  If,
> however, you're dead-set on parsing the output of 'jobs', you could
> use a syntax like 'jobs > >(read jobtext; echo $jobtext)', which is a
> clever way to run jobs in the current shell and do the parsing in a
> subshell via process substitution.

Myself, I'd prefer to see both subshells produce the same output as the
"current shell", as bash, pdksh and ksh do. However, dash goes the other
way and makes ( jobs ) emit nothing (for all its claims of being a POSIX
shell, though, dash is fairly broken in some respects, such as broken
arithmetic expansion and lack of a line-editor [which POSIX requires]).
I'd be interested in seeing what the OpenGroup committee has to say
about it, since the standard is far from clear on the subject.

I was not familiar with the variables you mention above. However, I'm
not sure they solve the problem, as yet again, invoking them within a
command-substitution will produce no information. The same problem would
be true of using the other syntax you describe: I still have no
available means to run the commands every time the prompt is issued,
apart from within command substitution, which will kill the job-state
info. Is there any way to get what I want executing in the "current" shell?

Also, had you meant to post this reply to the list? It appears to have
been sent to me only.

Yes, of course, I had meant to send it to the list.  My mistake.
*sheepish grin*.  So, you're right - the special variable $jobtexts
wouldn't match up in the subshell, but you could do something like

$ function precmd {
export jt=""
for i in ${(kv)jobtexts}; jt="$jt:${i%% *}"

$ echo $jt

$ echo $(echo $jt)

And then you have a not-special, not-array version of jobtexts
exported into the environment of subshells that you can manipulate
however you want - and it even lets you remove the ugly dependence on
awk.  ;-)

(precmd is a function that gets called every time the editor is about
to display a prompt, FYI).

precmd looks to be /exactly/ what I was looking for, then. I'll I was so focused on the bashism, that I was searching and re-searching the special parameters, rather than special functions. Thanks!

Using jobtexts, etc is probably preferable to using the "jobs" output anyway, since zsh's appears to have a non-standard format (splitting a single job across lines), which will make my life more difficult. It's also probably more precise.

I probably won't lose the awk dependency, though, since the awk script also does some clean-up on the command names, and I'll probably add support for displaying the /arguments/ to certain commands (such as vim), or an alert color for some commands (sudo).

Like I said, though - even though this should take no effort
whatsoever to do with zsh - no more than 5 lines or so - it would be
difficult to maintain compatibility with bash.

Eh, I've managed pretty well so far. Where I can't rely on common syntax, I can test for the shell (as you can see by my spamming of the shell namespace with vars like PJOBS_ZSH). I'm aiming for compliance with as many shells will provide me with a hook to the prompt, and are reasonably POSIX-compliant.

The best way I can think of to do what you want, off the top of my
head, is the following:

<solution snipped>

That'll make a great reference. I'll need to complicate it a bit what with my use of terminal escape sequences (tput output) and whatnot, but that makes a great start.

Frankly, I'd just make your script check for ZSH right off the bat and
do it the simple way, leaving the complicated stuff for shells that
don't give you an elegant solution.

Yeah, I'm already doing that (it's just that the zsh-specific solution doesn't work). I already have to cater specifically to bash (PROMPT_COMMAND), and even the set of shells that will let me hook in via prompt substitution each have their unique ways of telling the line-editor to ignore the invisible terminal escape sequences I use for coloring.

Thanks very much for the help. For some reason, I simply couldn't find precmd or the job* vars on my own.

Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...

Messages sorted by: Reverse Date, Date, Thread, Author