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

Re: "jobs" command within substitution



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
this:

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

$ echo $jt
1:find:2:sleep

$ echo $(echo $jt)
1:find:2:sleep

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).

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.

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

function precmd {
 psvar[1]=""
 # For each key and each value in jobtexts
 for i in ${(kv)jobtexts}; do
   # Come up with a separator between psvar[1] and this text
   if [[ $sep == " " ]]; then
     sep=":"
   else
     sep=" "
   fi
   # Then tack it on to the end of psvar[1] - Removing from
   # the first space to the end of the element, if it has a space
   psvar[1]="${psvar[1]}$sep${i%% *}"
 done
 # Remove leading space we accidentally inserted
 psvar[1]=${psvar[1]# }
}

and

# Tell the prompt to reference psvar[1] (%?v == psvar[?])
PS1='micah(%1v)'

You don't even need to use prompt_subst.

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.

~Matt



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