zsh-users
 help / color / mirror / code / Atom feed
* Rebinding a widget within a keymap
@ 2006-07-30  6:29 ` Bart Schaefer
  2006-07-30 17:18   ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2006-07-30  6:29 UTC (permalink / raw)
  To: zsh-users

The zsh bindkey and zle commands allow one to do most things one might
want to do with keymaps, such as copying one, setting bindings, etc.
However, there isn't a straightforward way to express transformations
such as "temporarily change all keys bound to 'self-insert' to instead
be bound to 'frob'".

This leads to workarounds such as

	zle -N self-insert frob
	zle recursive-edit
	zle -A .self-insert self-insert

This is unsatisfactory, as it's sometimes difficult to guarantee that
the "zle -A" step occurs; and if it doesn't, you're left frobbing in
a context where you should be inserting.  Furthermore, this fails if
self-insert was previously replaced by yet some other widget, so to get
that handled properly it's necessary to do

	zle -A self-insert saved-self-insert
	zle -N self-insert frob
	zle recursive-edit
	zle -A saved-self-insert self-insert
	zle -D saved-self-insert

This introduces possible name clashes on saved-self-insert; e.g., it
can't be invoked again from inside recursive-edit, and every added bit
of code to repair such a problem makes the unwinding more precarious.
Automatically saving and restoring keymaps with

	bindkey -N frobber main
	zle recursive-edit -K frobber

was meant to help with this, but without doing some sort of processing
on $(bindkey -L) it's not possible to determine which keys are already
bound to self-insert and thus need rebinding in frobber, and we're back
where we started.

Having given you all that background, I'm obviously about to propose a
solution.  Here it is.

  zmodload -i zsh/zleparameter

  for k in $keymaps
  do
    if (( $+widgets[self-insert-$k] == 0 ))
    then zle -A self-insert self-insert-$k
    fi
  done

  self-insert-by-keymap() {
    if (( $+widgets[$WIDGET-$KEYMAP] == 1 ))
    then zle $WIDGET-$KEYMAP "$@"
    else zle .$WIDGET "$@"
    fi
  }
  zle -N self-insert self-insert-by-keymap

This can of course be extended to any/all other widgets; just put a loop
"for w in ${(k)widgets}" around the whole thing and replace "self-insert"
with "$w" throughout.  (It's at that point that the lack of control over
autoremoval, which I've mentioned in other threads, becomes an issue, so
if you want to go beyond self-insert you'll have to write it out yourself.)

With this in place, you should rarely need "zle -N self-insert frob" again.
Instead you do this:

	bindkey -N frobber main
	zle -N self-insert-frobber frob

Then, whenever you wish to replace self-insert with frob, change keymaps:

	zle recursive-edit -K frobber

Here's a simple example, which improves upon the caps-lock example in the
zsh manual entry for recursive-edit:

  # Assumes self-insert-by-keymap installed as self-insert!

  self-insert-ucase() {
    LBUFFER+=${(U)KEYS[-1]}
  }
  zle -N self-insert-ucase
  caps-lock() {
    bindkey -N ucase $KEYMAP
    bindkey -M ucase "$KEYS" .accept-line
    zle recursive-edit -K ucase || zle send-break
  }
  zle -N caps-lock

To turn this on, pick a key sequence (I've chosen ctrl-x shift-L) and
bind the caps-lock widget to it:

  bindkey -M main '^XL' caps-lock

An obvious extension to this scheme is to create a variant of accept-line
that notifies the caller of recursive-edit as to whether it should treat
the end of the recursive-edit as final acceptance of the buffer, so that
it's possible e.g. to execute a command without first explicitly leaving
caps-lock "mode".

The other remaining drawback to this scheme is that it can't be employed
at the topmost level of ZLE, because the value of $KEYMAP is always "main"
(or "vicmd" as a special case) at that level.

Note that for builtin widgets the "for k in $keymaps" loop is extraneous;
so it would be possible to embed this widget-name-by-keymap logic in the
C code in ZLE, thereby making it possible to insert an "override" widget
into any specific keymap simply by creating a new widget with the keymap
name appended.  Old code that uses "zle -N builtin-widget user-function"
would continue to work, but would break new code that relies on the by-
keymap technique.

-- 


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Rebinding a widget within a keymap
  2006-07-30  6:29 ` Rebinding a widget within a keymap Bart Schaefer
@ 2006-07-30 17:18   ` Peter Stephenson
  2006-07-30 17:46     ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2006-07-30 17:18 UTC (permalink / raw)
  To: zsh-users

Bart Schaefer wrote:
> Note that for builtin widgets the "for k in $keymaps" loop is extraneous;
> so it would be possible to embed this widget-name-by-keymap logic in the
> C code in ZLE, thereby making it possible to insert an "override" widget
> into any specific keymap simply by creating a new widget with the keymap
> name appended.  Old code that uses "zle -N builtin-widget user-function"
> would continue to work, but would break new code that relies on the by-
> keymap technique.

If it were done in C, I'd be tempted to use a more explicit indication
that there was (in effect) a namespace hierarchy in operation and have
the overriding widget name be $KEYMAP/$WIDGET or something like that.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Rebinding a widget within a keymap
  2006-07-30 17:18   ` Peter Stephenson
@ 2006-07-30 17:46     ` Bart Schaefer
  0 siblings, 0 replies; 66+ messages in thread
From: Bart Schaefer @ 2006-07-30 17:46 UTC (permalink / raw)
  To: Peter Stephenson, zsh-users

On Jul 30,  6:18pm, Peter Stephenson wrote:
}
} If it were done in C, I'd be tempted to use a more explicit indication
} that there was (in effect) a namespace hierarchy in operation and have
} the overriding widget name be $KEYMAP/$WIDGET or something like that.

This is not a bad plan, but it plays havoc with #autoload and #compdef,
which are going to install the function or widget under its base file
name, which obviously can't have a slash in it.  Yes, you can sort of
work around it with #compdef -K, but that's ugly.  Choosing a character
other than slash (perhaps dot?  Or does that break on Cygwin?) would
be sufficient.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Solved, but now a new twist (was: Double Evaluation Question (not in FAQ))
@ 2006-09-04  8:43 Com MN PG P E B Consultant 3
  2006-09-04 18:24 ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Com MN PG P E B Consultant 3 @ 2006-09-04  8:43 UTC (permalink / raw)
  To: zsh-users Mailinglist

> Assuming that variables are assigned in the following way:
>
>  x=abc
>  y=def
>  z='$x   $y' # Note: Single Quotes!
>
> How could I write an expression, which "evaluates" $z, in
> that it would return "abc   def"? 

Sorry, I should have read the man page in better detail before
posting this question. The solution is of course

   ${(e)z}

But now comes another twist to this problem: I found that I *also*
would like to have the resulting string to undergo tilde-expansion,
which is of course a completely different story.

That is, if I have an assignment

  x='~linus    ~steve'

Is there also a simple solution, which expands $x to the home
directories
of linus and steve, with spacing preserved?

Ronald
-- 
Ronald Fischer (phone +49-89-63676431)
mailto:mn-pg-p-e-b-consultant-3.com@siemens.com



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Solved, but now a new twist (was: Double Evaluation Question (not in FAQ))
  2006-09-04  8:43 Solved, but now a new twist (was: Double Evaluation Question (not in FAQ)) Com MN PG P E B Consultant 3
@ 2006-09-04 18:24 ` Bart Schaefer
  2006-09-07 17:53   ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2006-09-04 18:24 UTC (permalink / raw)
  To: zsh-users Mailinglist

On Sep 4, 10:43am, Com MN PG P E B Consultant 3 wrote:
}
} That is, if I have an assignment
} 
}   x='~linus    ~steve'
} 
} Is there also a simple solution, which expands $x to the home
} directories of linus and steve, with spacing preserved?

No.  Tildes are only expanded at the beginnings of words, so you
have to split the string (thus discarding the spacing, if you don't
take special care) before the home directories can be substituted.

There's a complicated solution:

setopt extendedglob
print -r ${(j//)${(s/|/)~${x/(#b)( ##)/|$match|}}}

The /(#b)( ##)/ matches a string of one or more spaces, which is
then replaced with itself ($match) surrounded by "|" (anything not
found in the strings on either side would work).  That's then split
(s/|/) on vertical bars to make an array of three words, which are
made eligible for expansion by the tilde that appears between the
closing paren and the start of the inner expansion.  Finally this is
rejoined into a single string (j//) without adding any additional
spaces between the array elements.

I'm actually a little surprised that this works -- I would have
guessed that joining with (j//) took place before tilde expansion.
But it seems to work as far back as backreferences (#b) do, so I
guess it's safe to assume it'll keep working.  (PWS, does something
need to be added to the "Rules" section under "Parameter Expansion"?)


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Solved, but now a new twist (was: Double Evaluation Question (not in FAQ))
  2006-09-04 18:24 ` Bart Schaefer
@ 2006-09-07 17:53   ` Peter Stephenson
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Stephenson @ 2006-09-07 17:53 UTC (permalink / raw)
  To: zsh-users Mailinglist

Bart Schaefer wrote:
> On Sep 4, 10:43am, Com MN PG P E B Consultant 3 wrote:
> }
> } That is, if I have an assignment
> } 
> }   x='~linus    ~steve'
> } 
> } Is there also a simple solution, which expands $x to the home
> } directories of linus and steve, with spacing preserved?
>
> There's a complicated solution:
> 
> setopt extendedglob
> print -r ${(j//)${(s/|/)~${x/(#b)( ##)/|$match|}}}
>...
> I'm actually a little surprised that this works -- I would have
> guessed that joining with (j//) took place before tilde expansion.
> But it seems to work as far back as backreferences (#b) do, so I
> guess it's safe to assume it'll keep working.  (PWS, does something
> need to be added to the "Rules" section under "Parameter Expansion"?)

I think (though I haven't checked) that it's because of the prefork() in
multsub(), which gets called for subexpressions.  This means that all
forms of $-style expansion as well as ` and ~/= expansion get handled at
each level at which a nested ${...} is processed.  Yes, this probably
ought to be documented if anyone understood it well enough.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Move command line options to start of line
@ 2006-10-06 15:07 Peter Stephenson
  2006-10-07  2:55 ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2006-10-06 15:07 UTC (permalink / raw)
  To: Zsh users list

Not sure if anybody actually needs such a thing, but the Austin group
(essentially POSIX) has been worrying about it, so I thought I'd while
away Friday afternoon by writing a zle widget (looks like Chris Johnson
had a similar idea...) Unfortunately zsh is so powerful it was trivial.

See the description at the top.

#top
# This moves an option, possibly with arguments, from before the
# cursor to immediately after the command word.
# Examples (cursor assumed to be at the end of the line):
#    ls file1 file2 -l
# -> ls -l files 1files
#
#    p4 opened -u pws
# -> p4 -u pws opened
#
# In the unlikely event that the argument of an option begins with -,
# repeated application will have the correct effect.

local -a line
integer i

line=(${(z)LBUFFER})
i=${line[(I)-*]}

(( i < 3 )) && return 1

LBUFFER="$line[1] $line[i,-1] $line[2,i-1]"
#bottom

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Move command line options to start of line
  2006-10-06 15:07 Move command line options to start of line Peter Stephenson
@ 2006-10-07  2:55 ` Bart Schaefer
  2006-10-07  6:20   ` Andrey Borzenkov
  2006-10-07 12:02   ` Peter Stephenson
  0 siblings, 2 replies; 66+ messages in thread
From: Bart Schaefer @ 2006-10-07  2:55 UTC (permalink / raw)
  To: Zsh users list

On Oct 6,  4:07pm, Peter Stephenson wrote:
}
} # This moves an option, possibly with arguments, from before the
} # cursor to immediately after the command word.

Nice, but not precisely what David Korn had in mind.  Given

zsh% ls -s file1 file2 -l

the result of the command should be

zsh% ls -s -l file1 file2

and not

zsh% ls -l -s file1 file2

I don't think this can be done without removing the trailing option and
its argument(s) from the line before finding the index of the place to
insert them again.  (Sufficiently deeply nested expansion might still
accomplish this in a single replacement.)


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Move command line options to start of line
  2006-10-07  2:55 ` Bart Schaefer
@ 2006-10-07  6:20   ` Andrey Borzenkov
  2006-10-07 12:02   ` Peter Stephenson
  1 sibling, 0 replies; 66+ messages in thread
From: Andrey Borzenkov @ 2006-10-07  6:20 UTC (permalink / raw)
  To: zsh-users

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Saturday 07 October 2006 06:55, Bart Schaefer wrote:
> On Oct 6,  4:07pm, Peter Stephenson wrote:
> }
> } # This moves an option, possibly with arguments, from before the
> } # cursor to immediately after the command word.
>
> Nice, but not precisely what David Korn had in mind.  Given
>
> zsh% ls -s file1 file2 -l
>
> the result of the command should be
>
> zsh% ls -s -l file1 file2
>
> and not
>
> zsh% ls -l -s file1 file2
>
> I don't think this can be done without removing the trailing option and
> its argument(s) from the line before finding the index of the place to
> insert them again.  (Sufficiently deeply nested expansion might still
> accomplish this in a single replacement.)

this apparently requires knowledge of arguments a given command accepts; this 
makes it rather hard to implement in general way.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)

iD8DBQFFJ0cYR6LMutpd94wRAmc8AJ9mwaNtorSYF/GGhXbxi75CFxMG4wCfbl9j
Rmqgim6+Vtwv7I11rrdEIN4=
=UlMk
-----END PGP SIGNATURE-----


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Move command line options to start of line
  2006-10-07  2:55 ` Bart Schaefer
  2006-10-07  6:20   ` Andrey Borzenkov
@ 2006-10-07 12:02   ` Peter Stephenson
  2006-10-07 12:39     ` Bart Schaefer
  1 sibling, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2006-10-07 12:02 UTC (permalink / raw)
  To: Zsh users list, pws

Bart Schaefer wrote:
> On Oct 6,  4:07pm, Peter Stephenson wrote:
> }
> } # This moves an option, possibly with arguments, from before the
> } # cursor to immediately after the command word.
> 
> Nice, but not precisely what David Korn had in mind.  Given
> 
> zsh% ls -s file1 file2 -l
> 
> the result of the command should be
> 
> zsh% ls -s -l file1 file2
> 
> and not
> 
> zsh% ls -l -s file1 file2

Why?  The option order doesn't usually matter for separate standalone
options, and if the order does matter, the function isn't going to be
able to guess which way round things have to be anyway.  I quite
deliberately did it the way I did because of options taking arguments.
Consider (example contrived on the spur of the moment, but not wholly
unrealistic):

  su -c 'rm -f .zshrc' username -l

Your way, this becomes

  su -c -l 'rm -f .zshrc' username

which is wrong.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Move command line options to start of line
  2006-10-07 12:02   ` Peter Stephenson
@ 2006-10-07 12:39     ` Bart Schaefer
  2006-10-07 17:21       ` Dan Nelson
  2006-10-07 17:36       ` Peter Stephenson
  0 siblings, 2 replies; 66+ messages in thread
From: Bart Schaefer @ 2006-10-07 12:39 UTC (permalink / raw)
  To: Zsh users list

On Oct 7,  1:02pm, Peter Stephenson wrote:
}
} > zsh% ls -s file1 file2 -l
} > 
} > the result of the command should be
} > 
} > zsh% ls -s -l file1 file2
} > 
} > and not
} > 
} > zsh% ls -l -s file1 file2
} 
} Why?

Because I didn't give a complete example.

Suppose instead that it's

zsh% ls -s *1 *3 -l

Then the result is supposed to be

zsh% ls -s -l -- *1 *3

I.e., you must know where to insert the "--" because you don't know
whether *1 is going to return something beginning with a "-", and if
you know where to put the "--" you know what to put to its left.

(Remember, I'm channeling Korn here, I don't necessarily *agree* that
this is a good idea in the first place.)

The counter-argument (Andrey's point) is that if the example is

zsh% ls -s file1 *2 -l

you don't know if file1 is an option-argument (to -s) or an operand,
so without knowing the semantics of "ls -s" you can't know where to
put the "--".

I haven't bothered disputing Korn on this; I suspect the answer is that
POSIX declares that option-arguments may appear in the same shell word
as the option, so if you cared about POSIX in the first place and you
meant "-s file1" to be a unit then you should already have been writing

zsh% ls -sfile1 *2

and now there's no ambiguity of this type:

} Consider (example contrived on the spur of the moment, but not wholly
} unrealistic):
} 
}   su -c 'rm -f .zshrc' username -l

But does

    su -c'rm -f .zshrc' username

work in a true POSIX shell?  Is it required to?


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Move command line options to start of line
  2006-10-07 12:39     ` Bart Schaefer
@ 2006-10-07 17:21       ` Dan Nelson
  2006-10-07 17:36       ` Peter Stephenson
  1 sibling, 0 replies; 66+ messages in thread
From: Dan Nelson @ 2006-10-07 17:21 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh users list

In the last episode (Oct 07), Bart Schaefer said:
> On Oct 7,  1:02pm, Peter Stephenson wrote:
> } Consider (example contrived on the spur of the moment, but not
> } wholly unrealistic):
> } 
> }   su -c 'rm -f .zshrc' username -l
> 
> But does
> 
>     su -c'rm -f .zshrc' username
> 
> work in a true POSIX shell?  Is it required to?

su isn't POSIX, but I don't think either of the above commands should
work.  -c isn't an option to su, it's an option to the shell launched
by su, so it should follow the username.  Linux's su apparently passes
-c on to the shell, but no other OSes do (and some use -c themselves).

-- 
	Dan Nelson
	dnelson@allantgroup.com


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Move command line options to start of line
  2006-10-07 12:39     ` Bart Schaefer
  2006-10-07 17:21       ` Dan Nelson
@ 2006-10-07 17:36       ` Peter Stephenson
  1 sibling, 0 replies; 66+ messages in thread
From: Peter Stephenson @ 2006-10-07 17:36 UTC (permalink / raw)
  To: Zsh users list, pws

Bart Schaefer wrote:
> Suppose instead that it's
> 
> zsh% ls -s *1 *3 -l
> 
> Then the result is supposed to be
> 
> zsh% ls -s -l -- *1 *3
> 
> I.e., you must know where to insert the "--" because you don't know
> whether *1 is going to return something beginning with a "-", and if
> you know where to put the "--" you know what to put to its left.

Aha, yes, that's a whole different ballgame, which I'm not playing.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Documentation of colon in parameter expansion
@ 2007-03-31 20:51 Miciah Dashiel Butler Masters
  2007-04-01 17:53 ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Miciah Dashiel Butler Masters @ 2007-03-31 20:51 UTC (permalink / raw)
  To: zsh-users

Hello,

I was recently trying to look up the syntax for '${NAME-WORD}'.
A search for '${NAME:-WORD}' turns up information on that syntax,
but one must look several paragraphs down to see that '${NAME-WORD}'
is also allowed and has a distinct meaning.  The string '${NAME-WORD}'
never appears in the manual.  I foolishly assumed that this meant
that the syntax is undefined.

Since the manual can be expected to be used primarily as a reference
(I personally have not read it thru in years), it seems like my
behaviour is to be expected.  Per haps the manual should have
the string '${NAME-WORD}' immediately above or below the string
'${NAME:-WORD}', and a sentence along the lines of, 'See below about
the variant of this syntax without the colon.'

Similar naturally applies to '${NAME:+WORD}', '${NAME:=WORD}', &c. I
realise that this means a fair bit of duplication, so I only offer it
as a suggestion.

Love,

-- 
Miciah Masters <miciah.masters@gmail.com> / <mdm0304@ecu.edu> /
<miciah@myrealbox.com>



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Documentation of colon in parameter expansion
  2007-03-31 20:51 Documentation of colon in parameter expansion Miciah Dashiel Butler Masters
@ 2007-04-01 17:53 ` Bart Schaefer
  2007-04-01 18:26   ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2007-04-01 17:53 UTC (permalink / raw)
  To: zsh-users

(Hmm, posting a patch on April Fools' Day might not be the best idea.
Oh, well.)

On Mar 31,  8:51pm, Miciah Dashiel Butler Masters wrote:
}
} I was recently trying to look up the syntax for '${NAME-WORD}'.
} A search for '${NAME:-WORD}' turns up information on that syntax,
} but one must look several paragraphs down to see that '${NAME-WORD}'
} is also allowed and has a distinct meaning.

Suggested patch below.  Line numbers may be off.  Is the new final
paragraph ("In any of the above ...") incorrect in some way?  It used
to only be stated for :- and :+ but I think it applies to := as well.

Index: Doc/Zsh/expn.yo
===================================================================
RCS file: /extra/cvsroot/zsh/zsh-4.0/Doc/Zsh/expn.yo,v
retrieving revision 1.22
diff -c -r1.22 expn.yo
--- expn.yo	1 Oct 2006 02:38:52 -0000	1.22
+++ expn.yo	1 Apr 2007 17:31:29 -0000
@@ -450,39 +486,39 @@
 If var(name) is the name of a set parameter `tt(1)' is substituted,
 otherwise `tt(0)' is substituted.
 )
+xitem(tt(${)var(name)tt(-)var(word)tt(}))
 item(tt(${)var(name)tt(:-)var(word)tt(}))(
-If var(name) is set and is non-null then substitute its
-value; otherwise substitute var(word). If var(name) is
-missing, substitute var(word).
-Note that you can use standard shell quoting in the var(word) value to
-selectively override the splitting done by the tt(SH_WORD_SPLIT) option
-and the tt(=) flag, but not the tt(s:)var(string)tt(:) flag.
+If var(name) is set, or in the second form is non-null, then substitute
+its value; otherwise substitute var(word).  In the second form var(name)
+may be omitted, in which case var(word) is always substituted.
 )
+xitem(tt(${)var(name)tt(PLUS())var(word)tt(}))
+item(tt(${)var(name)tt(:PLUS())var(word)tt(}))(
+If var(name) is set, or in the second form is non-null, then substitute
+var(word); otherwise substitute nothing.
+)
+xitem(tt(${)var(name)tt(=)var(word)tt(}))
 xitem(tt(${)var(name)tt(:=)var(word)tt(}))
 item(tt(${)var(name)tt(::=)var(word)tt(}))(
-In the first form, if var(name) is unset or is null then
-set it to var(word); in the second form, unconditionally
-set var(name) to var(word).  In both forms, the value of
-the parameter is then substituted.
+In the first form, if var(name) is unset then set it to var(word); in the
+second form, if var(name) is unset or null then set it to var(word); and
+in the third form, unconditionally set var(name) to var(word).  In all
+forms, the value of the parameter is then substituted.
 )
+xitem(tt(${)var(name)tt(?)var(word)tt(}))
 item(tt(${)var(name)tt(:?)var(word)tt(}))(
-If var(name) is set and is non-null then substitute
-its value; otherwise, print var(word) and exit from the shell.
-Interactive shells instead return to the prompt.
-If var(word) is omitted, then a standard message is printed.
-)
-item(tt(${)var(name)tt(:PLUS())var(word)tt(}))(
-If var(name) is set and is non-null then substitute
-var(word); otherwise substitute nothing.
-Note that you can use standard shell quoting in the var(word) value to
-selectively override the splitting done by the tt(SH_WORD_SPLIT) option
-and the tt(=) flag, but not the tt(s:)var(string)tt(:) flag.
+In the first form, if var(name) is set, or in the second form if var(name)
+is both set and non-null, then substitute its value; otherwise, print
+var(word) and exit from the shell.  Interactive shells instead return to
+the prompt.  If var(word) is omitted, then a standard message is printed.
 )
 enditem()
 
-If the colon is omitted from one of the above expressions
-containing a colon, then the shell only checks whether
-var(name) is set, not whether its value is null.
+In any of the above expressions that test a variable and substitute an
+alternate var(word), note that you can use standard shell quoting in the
+var(word) value to selectively override the splitting done by the
+tt(SH_WORD_SPLIT) option and the tt(=) flag, but not splitting by the
+tt(s:)var(string)tt(:) flag.
 
 In the following expressions, when var(name) is an array and
 the substitution is not quoted, or if the `tt((@))' flag or the


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Documentation of colon in parameter expansion
  2007-04-01 17:53 ` Bart Schaefer
@ 2007-04-01 18:26   ` Peter Stephenson
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Stephenson @ 2007-04-01 18:26 UTC (permalink / raw)
  To: zsh-users

Bart Schaefer wrote:
> Suggested patch below.  Line numbers may be off.  Is the new final
> paragraph ("In any of the above ...") incorrect in some way?  It used
> to only be stated for :- and :+ but I think it applies to := as well.

It's correct as far as I understand things.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* fg jobs info
@ 2007-09-02 15:43 Atom Smasher
  2007-09-02 17:59 ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Atom Smasher @ 2007-09-02 15:43 UTC (permalink / raw)
  To: zsh-users

hypothetical example....

% jobs
[1]    suspended  sleep 30
[2]    suspended  sleep 31
[3]    suspended  sleep 32
[4]    suspended  sleep 33
[5]  - suspended  sleep 34
[6]  + suspended  sleep 35

now, if i run 'fg' or 'fg %n', how can i make the command name (sleep xx) 
available to the shell?

why i want this: i've tweaked my ~/.zshrc file to fill in the tabs of 
mrxvt (and the windowlist in screen) with the current command name (and 
some other goodies, i'll post the rc file if there's interest). ie; i can 
quickly find the 'emacs somefile' tab (or screen) because the tab (or 
screen) says "emacs somefile". cool. but if i suspend the command, then 
bring it back with 'fg', the tab (or screen) now says "fg". not cool.

there are some hacks to get around this, but they're not pretty. i'm not 
sure if this can be done elegantly, without requesting a new feature that 
puts the ~real~ foreground command into an environment var, and/or a 4th 
argument to preexec.

unless there's a way to simulate the fg command (ie; a "-n" dry run 
argument) i think the best way to handle this (ideally) would be a 4th 
argument to preexec that contains what fg is bringing to the foreground.

any other thoughts?

thanks...


-- 
         ...atom

  ________________________
  http://atom.smasher.org/
  762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808
  -------------------------------------------------

 	"Do not wait; the time will never be 'just right.'
 	 Start where you stand, and work with whatever
 	 tools you may have at your command, and better
 	 tools will be found as you go along."
 		-- Napoleon Hill



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-02 15:43 fg jobs info Atom Smasher
@ 2007-09-02 17:59 ` Bart Schaefer
  2007-09-03  7:38   ` Stephane Chazelas
                     ` (2 more replies)
  0 siblings, 3 replies; 66+ messages in thread
From: Bart Schaefer @ 2007-09-02 17:59 UTC (permalink / raw)
  To: zsh-users

On Sep 3,  3:43am, Atom Smasher wrote:
}
} why i want this: i've tweaked my ~/.zshrc file to fill in the tabs of 
} mrxvt (and the windowlist in screen) with the current command name (and 
} some other goodies, i'll post the rc file if there's interest). ie; i can 
} quickly find the 'emacs somefile' tab (or screen) because the tab (or 
} screen) says "emacs somefile". cool. but if i suspend the command, then 
} bring it back with 'fg', the tab (or screen) now says "fg". not cool.

Have a look at the variables jobdirs, jobtexts, and jobstates in the
zsh/parameter module.  Or there's a lazier way out:

} unless there's a way to simulate the fg command (ie; a "-n" dry run 
} argument)

The "jobs" command should accept all the same job-identifier patterns
as "fg", and in recent zsh "jobs" doesn't lose track of the job list
when run in a subshell, so you can do things like

    fg() {
	# Obviously this needs error handling added, etc.
    	typeset -g fgjob=$(jobs $*)
	builtin fg $*
    }

and then stuff the title bar (or whatever) with the something parsed
out of $fgjob.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-02 17:59 ` Bart Schaefer
@ 2007-09-03  7:38   ` Stephane Chazelas
  2007-09-03 15:58     ` Bart Schaefer
  2007-09-03 16:31   ` Matthew Wozniski
  2007-09-04 11:16   ` Atom Smasher
  2 siblings, 1 reply; 66+ messages in thread
From: Stephane Chazelas @ 2007-09-03  7:38 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-users

On Sun, Sep 02, 2007 at 10:59:53AM -0700, Bart Schaefer wrote:
[...]
>     fg() {
> 	# Obviously this needs error handling added, etc.
>     	typeset -g fgjob=$(jobs $*)
> 	builtin fg $*
>     }
> 
> and then stuff the title bar (or whatever) with the something parsed
> out of $fgjob.

I'd like to point out that $* is not the right way to pass
parameters around. $* strips the empty arguments.

You want "$@" (with quotes) as with the other shells.

Also, in zsh (contrary to ksh and bash), typeset is a builtin
parsed like any other builtin, so in the typeset command above,
the command substitution will be word spit, you want:

typeset -g fgjob="$(jobs "$@")"

Or better

typeset -g fgjob
fgjob=$(jobs "$@")

not sure the typeset -g is needed there.

-- 
Stéphane


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-03  7:38   ` Stephane Chazelas
@ 2007-09-03 15:58     ` Bart Schaefer
  0 siblings, 0 replies; 66+ messages in thread
From: Bart Schaefer @ 2007-09-03 15:58 UTC (permalink / raw)
  To: zsh-users

On Sep 3,  8:38am, Stephane Chazelas wrote:
}
} I'd like to point out that $* is not the right way to pass
} parameters around. $* strips the empty arguments.

In this case that doesn't really matter because there's no sensible
reason to call "jobs" or "fg" with an empty argument.

} Also, in zsh (contrary to ksh and bash), typeset is a builtin
} parsed like any other builtin, so in the typeset command above,
} the command substitution will be word spit

You're right about that one, though.  I edited in the "typeset -g"
after writing the rest, and forgot to add the quotes.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-02 17:59 ` Bart Schaefer
  2007-09-03  7:38   ` Stephane Chazelas
@ 2007-09-03 16:31   ` Matthew Wozniski
  2007-09-04 11:16   ` Atom Smasher
  2 siblings, 0 replies; 66+ messages in thread
From: Matthew Wozniski @ 2007-09-03 16:31 UTC (permalink / raw)
  To: zsh-users

On Sun, Sep 02, 2007 at 10:59:53AM -0700, Bart Schaefer wrote:
...
> The "jobs" command should accept all the same job-identifier patterns
> as "fg", and in recent zsh "jobs" doesn't lose track of the job list
> when run in a subshell, so you can do things like
> 
>     fg() {
> 	# Obviously this needs error handling added, etc.
>     	typeset -g fgjob=$(jobs $*)
> 	builtin fg $*
>     }
> 
> and then stuff the title bar (or whatever) with the something parsed
> out of $fgjob.

In how recent a zsh?  I can't seem to get that working with 4.3.4.
Does it require a copy compiled out of the latest {CVS,SVN} HEAD?  (I
have no idea what VCS zsh uses, or the url to checkout a copy.
Forgive my ignorance.  ^_^ )

If I get a chance later, and no one beats me to the punch, I'll clean
up the code I'm using with $jobtexts and post that, for those of us
who need to use 4.3.2 or later on some machines thanks to lazy
sysadmins.

~Matt


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-02 17:59 ` Bart Schaefer
  2007-09-03  7:38   ` Stephane Chazelas
  2007-09-03 16:31   ` Matthew Wozniski
@ 2007-09-04 11:16   ` Atom Smasher
  2007-09-04 15:31     ` Bart Schaefer
  2 siblings, 1 reply; 66+ messages in thread
From: Atom Smasher @ 2007-09-04 11:16 UTC (permalink / raw)
  To: zsh-users

On Sun, 2 Sep 2007, Bart Schaefer wrote:

> Have a look at the variables jobdirs, jobtexts, and jobstates in the 
> zsh/parameter module.  Or there's a lazier way out:
=============

that seems reasonably elegant... as long as a) there's only one suspended 
job or b) jobs are only referred to by number :(

if the there's more than one job and either 1) the current job is implied 
or 2) a job is specified not by job number, things get messy.


> } unless there's a way to simulate the fg command (ie; a "-n" dry run
> } argument)
>
> The "jobs" command should accept all the same job-identifier patterns
> as "fg", and in recent zsh "jobs" doesn't lose track of the job list
> when run in a subshell, so you can do things like
==============

that doesn't seem to work in 4.3.2. i'm using versions as old as 4.2.1 so 
the foo=$(jobs) trick won't work all around, and it's hackish enough that 
it fails to inspire an upgrade.


also, here's a case where (given what i'm trying to do) i'm confident that 
anything would fail (at least partially), short of some non-trivial 
updates to zsh:

% man sh
^Z

% man zsh
^Z

% jobs
[1]  - suspended  man sh
[2]  + suspended  man zsh

% fg %1 %2



-- 
         ...atom

  ________________________
  http://atom.smasher.org/
  762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808
  -------------------------------------------------

 	"The lie can be maintained only for such time as the State can
 	 shield the people from the political, economic and/or military
 	 consequences of the lie. It thus becomes vitally important for
 	 the State to use all of its powers to repress dissent, for the
 	 truth is the mortal enemy of the lie, and thus by extension,
 	 the truth becomes the greatest enemy of the State."
 		-- Josef Goebbels




^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-04 11:16   ` Atom Smasher
@ 2007-09-04 15:31     ` Bart Schaefer
  2007-09-04 20:38       ` Peter Stephenson
                         ` (2 more replies)
  0 siblings, 3 replies; 66+ messages in thread
From: Bart Schaefer @ 2007-09-04 15:31 UTC (permalink / raw)
  To: zsh-users

On Sep 3, 12:31pm, Matthew Wozniski wrote:
} Subject: Re: fg jobs info
}
} On Sun, Sep 02, 2007 at 10:59:53AM -0700, Bart Schaefer wrote:
} ...
} > The "jobs" command should accept all the same job-identifier patterns
} > as "fg", and in recent zsh "jobs" doesn't lose track of the job list
} > when run in a subshell
} 
} In how recent a zsh?  I can't seem to get that working with 4.3.4.

You're right.  $(jobs) and (jobs) produce different output.  I thought
that because the latter worked, the former would also.

Looks to me as if there's a bug here; compare

    print $(jobs)
    (print $(jobs))

Also, although "jobs" or "jobs -l" prints out the entire jobs listing
even in subshells/pipelines/etc., "jobs %2" (for example) produces a
"no such job" error, which surprised me.  That should at least be
documented.  Try:

    sleep 40 & sleep 30 &
    jobs | cat
    jobs %1 | cat

So the easy way out is not going to work here after all.

On Sep 4, 11:16pm, Atom Smasher wrote:
}
} On Sun, 2 Sep 2007, Bart Schaefer wrote:
} 
} > Have a look at the variables jobdirs, jobtexts, and jobstates in the 
} > zsh/parameter module.  Or there's a lazier way out:
} =============
} 
} that seems reasonably elegant... as long as a) there's only one
} suspended job or b) jobs are only referred to by number :(
}
} if the there's more than one job and either 1) the current job is
} implied or 2) a job is specified not by job number, things get messy.

Not all *that* messy.  "The current job" is

    jobno=${(k)jobstates[(r)*:+:*]}

Something like "fg %fred" is

    jobno=${(k)jobstates[(r)*:?:fred*]}

And "fg %?wilma" is

    jobno=${(k)jobstates[(r)*:?:*wilma*]}

Then you just do

    fgjob="${jobtexts[$jobno]}"
    fg %$jobno

} also, here's a case where (given what i'm trying to do) i'm confident
} that anything would fail (at least partially), short of some
} non-trivial updates to zsh:
} 
} % fg %1 %2

You just have to handle that inside your "fg" function.

    fg() {
	[[ -z $1 ]] && set -- %+
        # Still ignoring all sorts of error handling here ...
	for jobspec
	do
	    case $jobspec in
	    (%<->) jobno=${jobspec#%};;
	    (%+) jobno=${(k)jobstates[(r)*:+:*]};;
	    (%-) jobno=${(k)jobstates[(r)*:-:*]};;
            # Need more quoting than shown for $jobspec below
	    (%[?]*) jobno=${(k)jobstates[(r)*:?:*${jobspec#%?}*]};;
	    (*) jobno=${(k)jobstates[(r)*:?:${jobspec#%}*]};;
	    esac
	    tab-title "$jobtexts[$jobno]"
	    builtin fg %$jobno
	done
    }

Jobs don't get renumbered as others exit, so the jobspecs that come in
are usable throughout.

The case that's going to be pretty difficult to handle is:

    % %2

(That is, bringing a job to the foreground by simply typing its job spec.
Probably need a preexec function to catch that one.)

Incidentally, yet another bug:

    % sleep 30 & sleep 50 &
    % fg %- %-
    [1]  - running    sleep 30
    fg: %3: no such job

Where did I ever ask for job 3 ?


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-04 15:31     ` Bart Schaefer
@ 2007-09-04 20:38       ` Peter Stephenson
  2007-09-04 20:45       ` Peter Stephenson
  2007-09-05  9:02       ` Atom Smasher
  2 siblings, 0 replies; 66+ messages in thread
From: Peter Stephenson @ 2007-09-04 20:38 UTC (permalink / raw)
  To: zsh-users

On Tue, 04 Sep 2007 08:31:04 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> Looks to me as if there's a bug here; compare
> 
>     print $(jobs)
>     (print $(jobs))

This is another catalogue of disasters.  Thanks for the extra work.
What's happening here is entersubsh() is being called with the MONITOR
option (job control) already unset so it doesn't know there are jobs to
save.  I've made it an extra flag to entersubsh() and taken the
opportunity to neaten the argument handling.

> Also, although "jobs" or "jobs -l" prints out the entire jobs listing
> even in subshells/pipelines/etc., "jobs %2" (for example) produces a
> "no such job" error, which surprised me.  That should at least be
> documented.  Try:
> 
>     sleep 40 & sleep 30 &
>     jobs | cat
>     jobs %1 | cat

Numbers in the saved job table aren't looked up properly.  There's
another bug that you can't refer to "thisjob" by number but that
restriction doesn't make sense once you're in a subshell that doesn't
have jobs of its own.  I'm not sure if it makes sense to have thisjob !=
-1 in subshells at all, but I've just taken the easy way out this time.

I've made sure you can only look up jobs from within a subshell for
"jobs", not fg, bg, wait, disown where they don't make sense since you
no longer have control of the job.  (Well, maybe you do, but *I* don't.)

> Incidentally, yet another bug:
> 
>     % sleep 30 & sleep 50 &
>     % fg %- %-
>     [1]  - running    sleep 30
>     fg: %3: no such job
> 
> Where did I ever ask for job 3 ?

I've never been quite sure of the handling of the prevjob variable that
remembers the job to which %- applies, but the obvious fix here is to
output the command line argument that caused the failure, not the
possibly nonsensical job number that resulted.

As we previously discussed, there is in any case a race that the job may
be gone (even long gone) by the time the subshell looks at the table,
but that's not really fixable and it's not clear it's a big issue for
the sort of use made of the saved job table.

I'll leave someone else to invent race-free tests.  In fact, tests
generally are a nice job for some philanthropist who doesn't need to
know anything about the source code.

Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.123
diff -u -r1.123 exec.c
--- Src/exec.c	31 Aug 2007 09:07:46 -0000	1.123
+++ Src/exec.c	4 Sep 2007 20:28:18 -0000
@@ -804,6 +804,105 @@
     return cn;
 }
 
+/**/
+int
+forklevel;
+
+/* Arguments to entersubsh() */
+enum {
+    /* Subshell is to be run asynchronously (else synchronously) */
+    ESUB_ASYNC = 0x01,
+    /*
+     * Perform process group and tty handling and clear the
+     * (real) job table, since it won't be any longer valid
+     */
+    ESUB_PGRP = 0x02,
+    /* Don't unset traps */
+    ESUB_KEEPTRAP = 0x04,
+    /* This is only a fake entry to a subshell */
+    ESUB_FAKE = 0x08,
+    /* Release the process group if pid is the shell's process group */
+    ESUB_REVERTPGRP = 0x10,
+    /* Don't handle the MONITOR option even if previously set */
+    ESUB_NOMONITOR = 0x20
+};
+
+/**/
+static void
+entersubsh(int flags)
+{
+    int sig, monitor;
+
+    if (!(flags & ESUB_KEEPTRAP))
+	for (sig = 0; sig < VSIGCOUNT; sig++)
+	    if (!(sigtrapped[sig] & ZSIG_FUNC))
+		unsettrap(sig);
+    monitor = isset(MONITOR);
+    if (flags & ESUB_NOMONITOR)
+	opts[MONITOR] = 0;
+    if (!isset(MONITOR)) {
+	if (flags & ESUB_ASYNC) {
+	    settrap(SIGINT, NULL, 0);
+	    settrap(SIGQUIT, NULL, 0);
+	    if (isatty(0)) {
+		close(0);
+		if (open("/dev/null", O_RDWR | O_NOCTTY)) {
+		    zerr("can't open /dev/null: %e", errno);
+		    _exit(1);
+		}
+	    }
+	}
+    } else if (thisjob != -1 && (flags & ESUB_PGRP)) {
+	if (jobtab[list_pipe_job].gleader && (list_pipe || list_pipe_child)) {
+	    if (setpgrp(0L, jobtab[list_pipe_job].gleader) == -1 ||
+		killpg(jobtab[list_pipe_job].gleader, 0) == -1) {
+		jobtab[list_pipe_job].gleader =
+		    jobtab[thisjob].gleader = (list_pipe_child ? mypgrp : getpid());
+		setpgrp(0L, jobtab[list_pipe_job].gleader);
+		if (!(flags & ESUB_ASYNC))
+		    attachtty(jobtab[thisjob].gleader);
+	    }
+	}
+	else if (!jobtab[thisjob].gleader ||
+		 setpgrp(0L, jobtab[thisjob].gleader) == -1) {
+	    jobtab[thisjob].gleader = getpid();
+	    if (list_pipe_job != thisjob &&
+		!jobtab[list_pipe_job].gleader)
+		jobtab[list_pipe_job].gleader = jobtab[thisjob].gleader;
+	    setpgrp(0L, jobtab[thisjob].gleader);
+	    if (!(flags & ESUB_ASYNC))
+		attachtty(jobtab[thisjob].gleader);
+	}
+    }
+    if (!(flags & ESUB_FAKE))
+	subsh = 1;
+    if ((flags & ESUB_REVERTPGRP) && getpid() == mypgrp)
+	release_pgrp();
+    if (SHTTY != -1) {
+	shout = NULL;
+	zclose(SHTTY);
+	SHTTY = -1;
+    }
+    if (isset(MONITOR)) {
+	signal_default(SIGTTOU);
+	signal_default(SIGTTIN);
+	signal_default(SIGTSTP);
+    }
+    if (interact) {
+	signal_default(SIGTERM);
+	if (!(sigtrapped[SIGINT] & ZSIG_IGNORED))
+	    signal_default(SIGINT);
+    }
+    if (!(sigtrapped[SIGQUIT] & ZSIG_IGNORED))
+	signal_default(SIGQUIT);
+    opts[MONITOR] = opts[USEZLE] = 0;
+    zleactive = 0;
+    if (flags & ESUB_PGRP)
+	clearjobtab(monitor);
+    get_usage();
+    forklevel = locallevel;
+}
+
 /* execute a string */
 
 /**/
@@ -1301,7 +1400,7 @@
 		    }
 		    else {
 			close(synch[0]);
-			entersubsh(Z_ASYNC, 0, 0, 0);
+			entersubsh(ESUB_ASYNC);
 			if (jobtab[list_pipe_job].procs) {
 			    if (setpgrp(0L, mypgrp = jobtab[list_pipe_job].gleader)
 				== -1) {
@@ -1413,7 +1512,8 @@
 	    } else {
 		zclose(pipes[0]);
 		close(synch[0]);
-		entersubsh(how, 2, 0, 0);
+		entersubsh(((how & Z_ASYNC) ? ESUB_ASYNC : 0)
+			   | ESUB_PGRP | ESUB_KEEPTRAP);
 		close(synch[1]);
 		execcmd(state, input, pipes[1], how, 0);
 		_exit(lastval);
@@ -2419,7 +2519,7 @@
 	  (!is_cursh && (last1 != 1 || nsigtrapped || havefiles()))))) {
 
 	pid_t pid;
-	int synch[2];
+	int synch[2], flags;
 	char dummy;
 	struct timeval bgtime;
 
@@ -2432,7 +2532,9 @@
 	    if (oautocont >= 0)
 		opts[AUTOCONTINUE] = oautocont;
 	    return;
-	} if (pid) {
+	}
+	if (pid) {
+
 	    close(synch[1]);
 	    read(synch[0], &dummy, 1);
 	    close(synch[0]);
@@ -2462,7 +2564,10 @@
 	}
 	/* pid == 0 */
 	close(synch[0]);
-	entersubsh(how, (type != WC_SUBSH) && !(how & Z_ASYNC) ? 2 : 1, 0, 0);
+	flags = ((how & Z_ASYNC) ? ESUB_ASYNC : 0) | ESUB_PGRP;
+	if ((type != WC_SUBSH) && !(how & Z_ASYNC))
+	    flags |= ESUB_KEEPTRAP;
+	entersubsh(flags);
 	close(synch[1]);
 	forked = 1;
 	if (sigtrapped[SIGINT] & ZSIG_IGNORED)
@@ -2737,10 +2842,16 @@
 	 * the current shell (including a fake exec to run a builtin then
 	 * exit) in case there is an error return.
 	 */
-	if (is_exec)
-	    entersubsh(how, (type != WC_SUBSH) ? 2 : 1, 1,
-		       (do_exec || (type >= WC_CURSH && last1 == 1)) 
-		       && !forked);
+	if (is_exec) {
+	    int flags = ((how & Z_ASYNC) ? ESUB_ASYNC : 0) |
+		ESUB_PGRP | ESUB_FAKE;
+	    if (type != WC_SUBSH)
+		flags |= ESUB_KEEPTRAP;
+	    if ((do_exec || (type >= WC_CURSH && last1 == 1)) 
+		&& !forked)
+		flags |= ESUB_REVERTPGRP;
+	    entersubsh(flags);
+	}
 	if (type >= WC_CURSH) {
 	    if (last1 == 1)
 		do_exec = 1;
@@ -3037,83 +3148,6 @@
     errno = old_errno;
 }
 
-/**/
-int
-forklevel;
-
-/**/
-static void
-entersubsh(int how, int cl, int fake, int revertpgrp)
-{
-    int sig, monitor;
-
-    if (cl != 2)
-	for (sig = 0; sig < VSIGCOUNT; sig++)
-	    if (!(sigtrapped[sig] & ZSIG_FUNC))
-		unsettrap(sig);
-    if (!(monitor = isset(MONITOR))) {
-	if (how & Z_ASYNC) {
-	    settrap(SIGINT, NULL, 0);
-	    settrap(SIGQUIT, NULL, 0);
-	    if (isatty(0)) {
-		close(0);
-		if (open("/dev/null", O_RDWR | O_NOCTTY)) {
-		    zerr("can't open /dev/null: %e", errno);
-		    _exit(1);
-		}
-	    }
-	}
-    } else if (thisjob != -1 && cl) {
-	if (jobtab[list_pipe_job].gleader && (list_pipe || list_pipe_child)) {
-	    if (setpgrp(0L, jobtab[list_pipe_job].gleader) == -1 ||
-		killpg(jobtab[list_pipe_job].gleader, 0) == -1) {
-		jobtab[list_pipe_job].gleader =
-		    jobtab[thisjob].gleader = (list_pipe_child ? mypgrp : getpid());
-		setpgrp(0L, jobtab[list_pipe_job].gleader);
-		if (how & Z_SYNC)
-		    attachtty(jobtab[thisjob].gleader);
-	    }
-	}
-	else if (!jobtab[thisjob].gleader ||
-		 setpgrp(0L, jobtab[thisjob].gleader) == -1) {
-	    jobtab[thisjob].gleader = getpid();
-	    if (list_pipe_job != thisjob &&
-		!jobtab[list_pipe_job].gleader)
-		jobtab[list_pipe_job].gleader = jobtab[thisjob].gleader;
-	    setpgrp(0L, jobtab[thisjob].gleader);
-	    if (how & Z_SYNC)
-		attachtty(jobtab[thisjob].gleader);
-	}
-    }
-    if (!fake)
-	subsh = 1;
-    if (revertpgrp && getpid() == mypgrp)
-	release_pgrp();
-    if (SHTTY != -1) {
-	shout = NULL;
-	zclose(SHTTY);
-	SHTTY = -1;
-    }
-    if (isset(MONITOR)) {
-	signal_default(SIGTTOU);
-	signal_default(SIGTTIN);
-	signal_default(SIGTSTP);
-    }
-    if (interact) {
-	signal_default(SIGTERM);
-	if (!(sigtrapped[SIGINT] & ZSIG_IGNORED))
-	    signal_default(SIGINT);
-    }
-    if (!(sigtrapped[SIGQUIT] & ZSIG_IGNORED))
-	signal_default(SIGQUIT);
-    opts[MONITOR] = opts[USEZLE] = 0;
-    zleactive = 0;
-    if (cl)
-	clearjobtab(monitor);
-    get_usage();
-    forklevel = locallevel;
-}
-
 /*
  * Close internal shell fds.
  *
@@ -3307,8 +3341,7 @@
     child_unblock();
     zclose(pipes[0]);
     redup(pipes[1], 1);
-    opts[MONITOR] = 0;
-    entersubsh(Z_SYNC, 1, 0, 0);
+    entersubsh(ESUB_PGRP|ESUB_NOMONITOR);
     cmdpush(CS_CMDSUBST);
     execode(prog, 0, 1);
     cmdpop();
@@ -3460,8 +3493,7 @@
 
     /* pid == 0 */
     redup(fd, 1);
-    opts[MONITOR] = 0;
-    entersubsh(Z_SYNC, 1, 0, 0);
+    entersubsh(ESUB_PGRP|ESUB_NOMONITOR);
     cmdpush(CS_CMDSUBST);
     execode(prog, 0, 1);
     cmdpop();
@@ -3532,7 +3564,7 @@
 	zerr("can't open %s: %e", pnam, errno);
 	_exit(1);
     }
-    entersubsh(Z_ASYNC, 1, 0, 0);
+    entersubsh(ESUB_ASYNC|ESUB_PGRP);
     redup(fd, out);
 #else /* PATH_DEV_FD */
     int pipes[2];
@@ -3558,7 +3590,7 @@
 	}
 	return pnam;
     }
-    entersubsh(Z_ASYNC, 1, 0, 0);
+    entersubsh(ESUB_ASYNC|ESUB_PGRP);
     redup(pipes[out], out);
     closem(FDT_UNUSED);   /* this closes pipes[!out] as well */
 #endif /* PATH_DEV_FD */
@@ -3602,7 +3634,7 @@
 	    addproc(pid, NULL, 1, &bgtime);
 	return pipes[!out];
     }
-    entersubsh(Z_ASYNC, 1, 0, 0);
+    entersubsh(ESUB_ASYNC|ESUB_PGRP);
     redup(pipes[out], out);
     closem(FDT_UNUSED);	/* this closes pipes[!out] as well */
     cmdpush(CS_CMDSUBST);
Index: Src/jobs.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/jobs.c,v
retrieving revision 1.58
diff -u -r1.58 jobs.c
--- Src/jobs.c	6 Jul 2007 21:52:39 -0000	1.58
+++ Src/jobs.c	4 Sep 2007 20:28:19 -0000
@@ -821,10 +821,7 @@
     int doneprint = 0;
     FILE *fout = (synch == 2) ? stdout : shout;
 
-    /*
-     * Wow, what a hack.  Did I really write this? --- pws
-     */
-    if (jn < jobtab || jn >= jobtab + jobtabsize)
+    if (oldjobtab != NULL)
 	job = jn - oldjobtab;
     else
 	job = jn - jobtab;
@@ -1286,6 +1283,7 @@
 
     if (monitor && oldmaxjob) {
 	int sz = oldmaxjob * sizeof(struct job);
+	DPUTS(oldjobtab != NULL, "BUG: saving job table twice\n");
 	oldjobtab = (struct job *)zalloc(sz);
 	memcpy(oldjobtab, jobtab, sz);
 
@@ -1473,7 +1471,16 @@
 static int
 getjob(char *s, char *prog)
 {
-    int jobnum, returnval;
+    int jobnum, returnval, mymaxjob;
+    Job myjobtab;
+
+    if (oldjobtab) {
+	myjobtab = oldjobtab;
+	mymaxjob = oldmaxjob;
+    } else {
+	myjobtab= jobtab;
+	mymaxjob = maxjob;
+    }
 
     /* if there is no %, treat as a name */
     if (*s != '%')
@@ -1502,8 +1509,15 @@
     /* a digit here means we have a job number */
     if (idigit(*s)) {
 	jobnum = atoi(s);
-	if (jobnum && jobnum <= maxjob && jobtab[jobnum].stat &&
-	    !(jobtab[jobnum].stat & STAT_SUBJOB) && jobnum != thisjob) {
+	if (jobnum && jobnum <= mymaxjob && myjobtab[jobnum].stat &&
+	    !(myjobtab[jobnum].stat & STAT_SUBJOB) &&
+	    /*
+	     * If running jobs in a subshell, we are allowed to
+	     * refer to the "current" job (it's not really the
+	     * current job in the subshell).  It's possible we
+	     * should reset thisjob to -1 on entering the subshell.
+	     */
+	    (myjobtab == oldjobtab || jobnum != thisjob)) {
 	    returnval = jobnum;
 	    goto done;
 	}
@@ -1515,10 +1529,11 @@
     if (*s == '?') {
 	struct process *pn;
 
-	for (jobnum = maxjob; jobnum >= 0; jobnum--)
-	    if (jobtab[jobnum].stat && !(jobtab[jobnum].stat & STAT_SUBJOB) &&
+	for (jobnum = mymaxjob; jobnum >= 0; jobnum--)
+	    if (myjobtab[jobnum].stat &&
+		!(myjobtab[jobnum].stat & STAT_SUBJOB) &&
 		jobnum != thisjob)
-		for (pn = jobtab[jobnum].procs; pn; pn = pn->next)
+		for (pn = myjobtab[jobnum].procs; pn; pn = pn->next)
 		    if (strstr(pn->text, s + 1)) {
 			returnval = jobnum;
 			goto done;
@@ -1772,7 +1787,7 @@
     In the default case for bg, fg and disown, the argument will be provided by
     the above routine.  We now loop over the arguments. */
     for (; (firstjob != -1) || *argv; (void)(*argv && argv++)) {
-	int stopped, ocj = thisjob;
+	int stopped, ocj = thisjob, jstat;
 
         func = ofunc;
 
@@ -1798,6 +1813,11 @@
 	    thisjob = ocj;
 	    continue;
 	}
+	if (func != BIN_JOBS && oldjobtab != NULL) {
+	    zwarnnam(name, "can't manipulate jobs in subshell");
+	    unqueue_signals();
+	    return 1;
+	}
 	/* The only type of argument allowed now is a job spec.  Check it. */
 	job = (*argv) ? getjob(*argv, name) : firstjob;
 	firstjob = -1;
@@ -1805,9 +1825,10 @@
 	    retval = 1;
 	    break;
 	}
-	if (!(jobtab[job].stat & STAT_INUSE) ||
-	    (jobtab[job].stat & STAT_NOPRINT)) {
-	    zwarnnam(name, "%%%d: no such job", job);
+	jstat = oldjobtab ? oldjobtab[job].stat : jobtab[job].stat;
+	if (!(jstat & STAT_INUSE) ||
+	    (jstat & STAT_NOPRINT)) {
+	    zwarnnam(name, "%s: no such job", *argv);
 	    unqueue_signals();
 	    return 1;
 	}
@@ -1815,7 +1836,7 @@
          * on disown), we actually do a bg and then delete the job table entry. */
 
         if (isset(AUTOCONTINUE) && func == BIN_DISOWN &&
-            jobtab[job].stat & STAT_STOPPED)
+            jstat & STAT_STOPPED)
             func = BIN_BG;
 
 	/* We have a job number.  Now decide what to do with it. */
@@ -1905,7 +1926,7 @@
 	        deletejob(jobtab + job);
 	    break;
 	case BIN_JOBS:
-	    printjob(job + jobtab, lng, 2);
+	    printjob(job + (oldjobtab ? oldjobtab : jobtab), lng, 2);
 	    break;
 	case BIN_DISOWN:
 	    if (jobtab[job].stat & STAT_STOPPED) {


-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-04 15:31     ` Bart Schaefer
  2007-09-04 20:38       ` Peter Stephenson
@ 2007-09-04 20:45       ` Peter Stephenson
  2007-09-05  9:02       ` Atom Smasher
  2 siblings, 0 replies; 66+ messages in thread
From: Peter Stephenson @ 2007-09-04 20:45 UTC (permalink / raw)
  To: zsh-users

Bart Schaefer wrote:
> The case that's going to be pretty difficult to handle is:
> 
>     % %2
> 
> (That is, bringing a job to the foreground by simply typing its job spec.
> Probably need a preexec function to catch that one.)

That's a use for the as yet unimplemented pattern aliases.  It's about
the first sensible one I've seen.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-04 15:31     ` Bart Schaefer
  2007-09-04 20:38       ` Peter Stephenson
  2007-09-04 20:45       ` Peter Stephenson
@ 2007-09-05  9:02       ` Atom Smasher
  2007-09-05  9:28         ` Peter Stephenson
  2 siblings, 1 reply; 66+ messages in thread
From: Atom Smasher @ 2007-09-05  9:02 UTC (permalink / raw)
  To: zsh-users

maybe in the process of working out the bugs, there can be some added 
functionality to add a variable that automagically returns the text of the 
fg'd job.

in the meantime, i'm keeping it (relatively) simple and assuming that i've 
only got one job at a time suspended (for me, that's a reasonable 
assumption; YMMV). my preexec runs a function (to display the command name 
in tabs, title bars, icons, etc), and part of the function is simply:

     if [ 'fg' = "${${(z)@}[1]}" ]
     then
       cmnd_name="${(vV)jobtexts}"
     fi

as far as i can tell, the worst case failure is that it will display the 
commands of more than one job. considering the lengths i'd have to go 
through to fix that, and the chances of introducing more bugs, and how 
often i have multiple jobs suspended within a shell (not very often) i 
think this is good enough, for now.

thanks...


On Tue, 4 Sep 2007, Bart Schaefer wrote:

> You're right.  $(jobs) and (jobs) produce different output.  I thought 
> that because the latter worked, the former would also.
>
> Looks to me as if there's a bug here; compare
>
>    print $(jobs)
>    (print $(jobs))
>
> Also, although "jobs" or "jobs -l" prints out the entire jobs listing
> even in subshells/pipelines/etc., "jobs %2" (for example) produces a
> "no such job" error, which surprised me.  That should at least be
> documented.  Try:
>
>    sleep 40 & sleep 30 &
>    jobs | cat
>    jobs %1 | cat
>
> So the easy way out is not going to work here after all.

~~~~~~~~~~~

> Incidentally, yet another bug:
>
>    % sleep 30 & sleep 50 &
>    % fg %- %-
>    [1]  - running    sleep 30
>    fg: %3: no such job
>
> Where did I ever ask for job 3 ?
>


-- 
         ...atom

  ________________________
  http://atom.smasher.org/
  762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808
  -------------------------------------------------

         "Human beings, who are almost unique in having the ability
          to learn from the experience of others, are also remarkable
          for their apparent disinclination to do so."
                 -- Douglas Adams, Last Chance to See


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-05  9:02       ` Atom Smasher
@ 2007-09-05  9:28         ` Peter Stephenson
  2007-09-05 11:21           ` Miek Gieben
  2007-09-05 15:30           ` Bart Schaefer
  0 siblings, 2 replies; 66+ messages in thread
From: Peter Stephenson @ 2007-09-05  9:28 UTC (permalink / raw)
  To: zsh-users

Atom Smasher wrote:
> maybe in the process of working out the bugs, there can be some added 
> functionality to add a variable that automagically returns the text of the 
> fg'd job.

That's $jobtexts.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-05  9:28         ` Peter Stephenson
@ 2007-09-05 11:21           ` Miek Gieben
  2007-09-05 11:34             ` Matthew Wozniski
                               ` (2 more replies)
  2007-09-05 15:30           ` Bart Schaefer
  1 sibling, 3 replies; 66+ messages in thread
From: Miek Gieben @ 2007-09-05 11:21 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 600 bytes --]

[On 05 Sep, @11:28, Peter Stephenson wrote in "Re: fg jobs info ..."]
> Atom Smasher wrote:
> > maybe in the process of working out the bugs, there can be some added 
> > functionality to add a variable that automagically returns the text of the 
> > fg'd job.
> 
> That's $jobtexts.

Is there a way to get the jobnumber from any of these variables. 
$jobstates includes a lot, but not the actual job number.
(I want to list the current job numbers in my prompt - if there are
any)

--
grtz,
  - Miek

  http://www.miek.nl
  PGP: 6A3C F450 6D4E 7C6B C23C  F982 258B 85CF 3880 D0F6

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-05 11:21           ` Miek Gieben
@ 2007-09-05 11:34             ` Matthew Wozniski
  2007-09-05 11:36               ` Miek Gieben
  2007-09-05 11:34             ` Atom Smasher
  2007-09-05 11:40             ` Frank Terbeck
  2 siblings, 1 reply; 66+ messages in thread
From: Matthew Wozniski @ 2007-09-05 11:34 UTC (permalink / raw)
  To: zsh-users

On Wed, Sep 05, 2007 at 01:21:41PM +0200, Miek Gieben wrote:
> Is there a way to get the jobnumber from any of these variables. 
> $jobstates includes a lot, but not the actual job number.

Sure it does.  $jobstates, and $jobtexts for that matter, is an
associative array, not a traditionally indexed array.  So, you can
just use ${(k)jobtexts} to find the current job numbers:

mastermind% sleep 50 &
[1] 26864
mastermind% sleep 100 &
[2] 26865
mastermind% sleep 20 &
[3] 26866
mastermind% kill %2
mastermind%
[2]  - terminated  sleep 100
mastermind% echo ${(k)jobstates}
1 3

~Matt


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-05 11:21           ` Miek Gieben
  2007-09-05 11:34             ` Matthew Wozniski
@ 2007-09-05 11:34             ` Atom Smasher
  2007-09-05 11:40             ` Frank Terbeck
  2 siblings, 0 replies; 66+ messages in thread
From: Atom Smasher @ 2007-09-05 11:34 UTC (permalink / raw)
  To: zsh-users

On Wed, 5 Sep 2007, Miek Gieben wrote:

> Is there a way to get the jobnumber from any of these variables. 
> $jobstates includes a lot, but not the actual job number. (I want to 
> list the current job numbers in my prompt - if there are any)
=============

${(k)jobstates}
${(k)jobtexts}


-- 
         ...atom

  ________________________
  http://atom.smasher.org/
  762A 3B98 A3C3 96C9 C6B7 582A B88D 52E4 D9F5 7808
  -------------------------------------------------

 	"The victor will never be asked if he told the truth."
 		-- Adolf Hitler



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-05 11:34             ` Matthew Wozniski
@ 2007-09-05 11:36               ` Miek Gieben
  0 siblings, 0 replies; 66+ messages in thread
From: Miek Gieben @ 2007-09-05 11:36 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 868 bytes --]

[On 05 Sep, @13:34, Matthew Wozniski wrote in "Re: fg jobs info ..."]
> On Wed, Sep 05, 2007 at 01:21:41PM +0200, Miek Gieben wrote:
> > Is there a way to get the jobnumber from any of these variables. 
> > $jobstates includes a lot, but not the actual job number.
> 
> Sure it does.  $jobstates, and $jobtexts for that matter, is an
> associative array, not a traditionally indexed array.  So, you can

ah

> just use ${(k)jobtexts} to find the current job numbers:
> 
> mastermind% sleep 50 &
> [1] 26864
> mastermind% sleep 100 &
> [2] 26865
> mastermind% sleep 20 &
> [3] 26866
> mastermind% kill %2
> mastermind%
> [2]  - terminated  sleep 100
> mastermind% echo ${(k)jobstates}
> 1 3

Thank you, this makes it very easy indeeed.


--
grtz,
  - Miek

  http://www.miek.nl
  PGP: 6A3C F450 6D4E 7C6B C23C  F982 258B 85CF 3880 D0F6

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-05 11:21           ` Miek Gieben
  2007-09-05 11:34             ` Matthew Wozniski
  2007-09-05 11:34             ` Atom Smasher
@ 2007-09-05 11:40             ` Frank Terbeck
  2007-09-05 12:18               ` Miek Gieben
  2 siblings, 1 reply; 66+ messages in thread
From: Frank Terbeck @ 2007-09-05 11:40 UTC (permalink / raw)
  To: zsh-users

Miek Gieben <miek@miek.nl>:
> [On 05 Sep, @11:28, Peter Stephenson wrote in "Re: fg jobs info ..."]
> > Atom Smasher wrote:
> > > maybe in the process of working out the bugs, there can be some added 
> > > functionality to add a variable that automagically returns the text of the 
> > > fg'd job.
> > 
> > That's $jobtexts.
> 
> Is there a way to get the jobnumber from any of these variables. 
> $jobstates includes a lot, but not the actual job number.
> (I want to list the current job numbers in my prompt - if there are
> any)

[snip]
% sleep 60 & sleep 15 & ; sleep 1 ; sleep 60 &
    (wait until 3 sleeps are in the background)
% print -l ${(kv)jobtexts}
1
sleep 60
2
sleep 15
3
sleep 60
    (wait for sleep 15 to stop)
[2]  - 17090 done       sleep 15
% print -l ${(kv)jobtexts}
1
sleep 60
3
sleep 60
[snap]

So, print ${(k)jobtexts} should give you the information you want,
I think.

Regards, Frank

-- 
In protocol design, perfection has been reached not when there is
nothing left to add, but when there is nothing left to take away.
                                                  -- RFC 1925


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-05 11:40             ` Frank Terbeck
@ 2007-09-05 12:18               ` Miek Gieben
  0 siblings, 0 replies; 66+ messages in thread
From: Miek Gieben @ 2007-09-05 12:18 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 750 bytes --]

[On 05 Sep, @13:40, Frank Terbeck wrote in "Re: fg jobs info ..."]
> Miek Gieben <miek@miek.nl>:
> > [On 05 Sep, @11:28, Peter Stephenson wrote in "Re: fg jobs info ..."]
> > > Atom Smasher wrote:
> > > > maybe in the process of working out the bugs, there can be some added 
> > > > functionality to add a variable that automagically returns the text of the 
> > > > fg'd job.
> > > 
> > > That's $jobtexts.
> > 
> > Is there a way to get the jobnumber from any of these variables. 
> > $jobstates includes a lot, but not the actual job number.
> > (I want to list the current job numbers in my prompt - if there are
> > any)
> 
> [snip]

thanks for the respones, I got what I want:
myjobs=${(pj:\,:)${(k)jobstates}}

grtz Miek

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-05  9:28         ` Peter Stephenson
  2007-09-05 11:21           ` Miek Gieben
@ 2007-09-05 15:30           ` Bart Schaefer
  2007-09-05 15:55             ` Peter Stephenson
  1 sibling, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2007-09-05 15:30 UTC (permalink / raw)
  To: zsh-users

On Sep 5, 10:28am, Peter Stephenson wrote:
}
} > add a variable that automagically returns the text of the 
} > fg'd job.
} 
} That's $jobtexts.

Well ...

$jobtexts returns the text of any/all of the jobs, by job number.

That doesn't solve the problem of knowing which job number is the job
in the foreground.

OTOH, I can't figure out how knowing that could be useful, because
when a job is in the foreground the shell is blocked in zwaitjob(),
so there's no way for it to do anything useful with the job text.

Furthermore $jobtexts never contains the text of the current job
if that job is *started* in the foreground; it only has jobs that
were at some point backgrounded or stopped (at least as far as the
user of the shell is able to tell, see previous point).

What Atom wants is the text of the job that's *about to be* in the
foreground, the instant *before* the shell hands over control of the
TTY and calls zwaitjob(), plus a hook to be able to do something
with that information.

On linux I think a better way to handle this would be to have another
process monitoring the /proc directory.  The foreground job for each
TTY is always the one where the 5th and 8th fields of /proc/<->/stat
are equal, in which case /proc/<->/cmdline gives the job text.  E.g.

  all_fg_jobs() {
    emulate -L zsh
    local -a j
    local x
    for x in /proc/<->/stat
    do
      j=( $(<$x) )
      # $j[7] is 0 for jobs having no TTY
      if (( $j[7] && $j[5] == $j[8] ))
      then print -R ${(ps:\0:)"$(</proc/$j[1]/cmdline)"}
      fi
    done
  }

I think you need to be root to map from the "tty number" represented
by $j[7] to an actual tty device name, so you'd need some meta-info to
know where to send the job text.  Probably you could parse that out of
the output of "ps $j[1]".

-- 


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: fg jobs info
  2007-09-05 15:30           ` Bart Schaefer
@ 2007-09-05 15:55             ` Peter Stephenson
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Stephenson @ 2007-09-05 15:55 UTC (permalink / raw)
  To: zsh-users

On Wed, 05 Sep 2007 08:30:00 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Sep 5, 10:28am, Peter Stephenson wrote:
> }
> } > add a variable that automagically returns the text of the 
> } > fg'd job.
> } 
> } That's $jobtexts.
> 
> Well ...
> 
> $jobtexts returns the text of any/all of the jobs, by job number.
> 
> That doesn't solve the problem of knowing which job number is the job
> in the foreground.

It's easy and probably useful to make it possible to look up jobs in the
special variables by non-numeric arguments, as below.  You only get normal
job numbers back out when scanning keys, however.

> OTOH, I can't figure out how knowing that could be useful, because
> when a job is in the foreground the shell is blocked in zwaitjob(),
> so there's no way for it to do anything useful with the job text.

It doesn't fix this, however.

Index: Doc/Zsh/mod_parameter.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_parameter.yo,v
retrieving revision 1.7
diff -u -r1.7 mod_parameter.yo
--- Doc/Zsh/mod_parameter.yo	17 Sep 2006 19:28:46 -0000	1.7
+++ Doc/Zsh/mod_parameter.yo	5 Sep 2007 15:51:19 -0000
@@ -124,11 +124,19 @@
 item(tt(jobdirs))(
 This associative array maps job numbers to the directories from which the
 job was started (which may not be the current directory of the job).
+
+The keys of the associative arrays are usually valid job numbers,
+and these are the values output with, for example, tt(${(k)jobdirs}).
+Non-numeric job references may be used when looking up a value;
+for example, tt(${jobdirs[%+]}) refers to the current job.
 )
 vindex(jobtexts)
 item(tt(jobtexts))(
 This associative array maps job numbers to the texts of the command lines
 that were used to start the jobs.
+
+Handling of the keys of the associative array is as described for
+tt(jobdirs) above.
 )
 vindex(jobstates)
 item(tt(jobstates))(
@@ -142,6 +150,9 @@
 otherwise. This is followed by one `var(pid)tt(=)var(state)' for every
 process in the job. The var(pid)s are, of course, the process IDs and
 the var(state) describes the state of that process.
+
+Handling of the keys of the associative array is as described for
+tt(jobdirs) above.
 )
 vindex(nameddirs)
 item(tt(nameddirs))(
Index: Src/jobs.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/jobs.c,v
retrieving revision 1.59
diff -u -r1.59 jobs.c
--- Src/jobs.c	4 Sep 2007 20:43:52 -0000	1.59
+++ Src/jobs.c	5 Sep 2007 15:51:20 -0000
@@ -1468,8 +1468,8 @@
  * to a job number.                                             */
 
 /**/
-static int
-getjob(char *s, char *prog)
+mod_export int
+getjob(const char *s, const char *prog)
 {
     int jobnum, returnval, mymaxjob;
     Job myjobtab;
@@ -1489,7 +1489,8 @@
     /* "%%", "%+" and "%" all represent the current job */
     if (*s == '%' || *s == '+' || !*s) {
 	if (curjob == -1) {
-	    zwarnnam(prog, "no current job");
+	    if (prog)
+		zwarnnam(prog, "no current job");
 	    returnval = -1;
 	    goto done;
 	}
@@ -1499,7 +1500,8 @@
     /* "%-" represents the previous job */
     if (*s == '-') {
 	if (prevjob == -1) {
-	    zwarnnam(prog, "no previous job");
+	    if (prog)
+		zwarnnam(prog, "no previous job");
 	    returnval = -1;
 	    goto done;
 	}
@@ -1521,7 +1523,8 @@
 	    returnval = jobnum;
 	    goto done;
 	}
-	zwarnnam(prog, "%%%s: no such job", s);
+	if (prog)
+	    zwarnnam(prog, "%%%s: no such job", s);
 	returnval = -1;
 	goto done;
     }
@@ -1538,7 +1541,8 @@
 			returnval = jobnum;
 			goto done;
 		    }
-	zwarnnam(prog, "job not found: %s", s);
+	if (prog)
+	    zwarnnam(prog, "job not found: %s", s);
 	returnval = -1;
 	goto done;
     }
@@ -2299,7 +2303,7 @@
 
 /**/
 int
-findjobnam(char *s)
+findjobnam(const char *s)
 {
     int jobnum;
 
Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.166
diff -u -r1.166 utils.c
--- Src/utils.c	30 Aug 2007 15:18:25 -0000	1.166
+++ Src/utils.c	5 Sep 2007 15:51:22 -0000
@@ -5017,7 +5017,7 @@
 
 /**/
 mod_export int
-strpfx(char *s, char *t)
+strpfx(const char *s, const char *t)
 {
     while (*s && *s == *t)
 	s++, t++;
Index: Src/Modules/parameter.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v
retrieving revision 1.44
diff -u -r1.44 parameter.c
--- Src/Modules/parameter.c	6 Jul 2007 21:52:40 -0000	1.44
+++ Src/Modules/parameter.c	5 Sep 2007 15:51:23 -0000
@@ -1007,13 +1007,18 @@
 {
     Param pm = NULL;
     int job;
+    char *pend;
 
     pm = (Param) hcalloc(sizeof(struct param));
     pm->node.nam = dupstring(name);
     pm->node.flags = PM_SCALAR | PM_READONLY;
     pm->gsu.s = &nullsetscalar_gsu;
 
-    if ((job = atoi(name)) >= 1 && job <= maxjob &&
+    job = strtod(name, &pend);
+    /* Non-numeric keys are looked up by job name */
+    if (*pend)
+	job = getjob(name, NULL);
+    if (job >= 1 && job <= maxjob &&
 	jobtab[job].stat && jobtab[job].procs &&
 	!(jobtab[job].stat & STAT_NOPRINT))
 	pm->u.str = pmjobtext(job);
@@ -1104,13 +1109,17 @@
 {
     Param pm = NULL;
     int job;
+    char *pend;
 
     pm = (Param) hcalloc(sizeof(struct param));
     pm->node.nam = dupstring(name);
     pm->node.flags = PM_SCALAR | PM_READONLY;
     pm->gsu.s = &nullsetscalar_gsu;
 
-    if ((job = atoi(name)) >= 1 && job <= maxjob &&
+    job = strtod(name, &pend);
+    if (*pend)
+	job = getjob(name, NULL);
+    if (job >= 1 && job <= maxjob &&
 	jobtab[job].stat && jobtab[job].procs &&
 	!(jobtab[job].stat & STAT_NOPRINT))
 	pm->u.str = pmjobstate(job);
@@ -1166,13 +1175,17 @@
 {
     Param pm = NULL;
     int job;
+    char *pend;
 
     pm = (Param) hcalloc(sizeof(struct param));
     pm->node.nam = dupstring(name);
     pm->node.flags = PM_SCALAR | PM_READONLY;
     pm->gsu.s = &nullsetscalar_gsu;
 
-    if ((job = atoi(name)) >= 1 && job <= maxjob &&
+    job = strtod(name, &pend);
+    if (*pend)
+	job = getjob(name, NULL);
+    if (job >= 1 && job <= maxjob &&
 	jobtab[job].stat && jobtab[job].procs &&
 	!(jobtab[job].stat & STAT_NOPRINT))
 	pm->u.str = pmjobdir(job);



.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* preexec hook: possible enhancement?
@ 2007-09-05 16:34 Matthew Wozniski
  2007-09-05 17:14 ` Bart Schaefer
  2007-09-05 19:32 ` Stephane Chazelas
  0 siblings, 2 replies; 66+ messages in thread
From: Matthew Wozniski @ 2007-09-05 16:34 UTC (permalink / raw)
  To: zsh-users

While we're on the topic of using the preexec hook to set the
titlebar, I'd like to bounce something off the list and see if 1) it's
possible and 2) people would consider it useful.  So, would it be
possible and/or useful to have the preexec hook (or some other, new
hook) fire once for each pipeline in the current command, rather
than just once using the entire current line?

For instance, if one were to type
% xterm ; echo google.com | xargs w3m ; gnome-terminal
could a hook be inserted to fire once with "xterm", once with "echo 
google.com | xargs w3m", and once with "gnome-terminal" passed to it,
rather than just once with
"xterm ; echo google.com | xargs w3m ; gnome-terminal" passed to it?

It's by no means a necessary feature, and I don't know if others would
even find it useful, but I think it would be pretty cool to watch the
titlebar change as we moved from one pipeline to the next.

~Matt


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: preexec hook: possible enhancement?
  2007-09-05 16:34 preexec hook: possible enhancement? Matthew Wozniski
@ 2007-09-05 17:14 ` Bart Schaefer
  2007-09-05 19:05   ` Peter Stephenson
  2007-09-05 19:32 ` Stephane Chazelas
  1 sibling, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2007-09-05 17:14 UTC (permalink / raw)
  To: zsh-users

On Sep 5, 12:34pm, Matthew Wozniski wrote:
}
} While we're on the topic of using the preexec hook to set the
} titlebar, I'd like to bounce something off the list and see if 1) it's
} possible and 2) people would consider it useful.  So, would it be
} possible and/or useful to have the preexec hook (or some other, new
} hook) fire once for each pipeline in the current command, rather
} than just once using the entire current line?

The TRAPDEBUG function is called at these points in the execution,
if you "setopt DEBUG_BEFORE_CMD".  However, I don't remember offhand
whether it's possible to access the command text that is about to be
executed.  The documentation for TRAPDEBUG is pretty sparse.

(Also DEBUG_BEFORE_CMD requires a very recent zsh version.)


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: preexec hook: possible enhancement?
  2007-09-05 17:14 ` Bart Schaefer
@ 2007-09-05 19:05   ` Peter Stephenson
  2007-09-05 21:11     ` Matthew Wozniski
  2007-09-08 17:20     ` Bart Schaefer
  0 siblings, 2 replies; 66+ messages in thread
From: Peter Stephenson @ 2007-09-05 19:05 UTC (permalink / raw)
  To: zsh-users

Bart Schaefer wrote:
> On Sep 5, 12:34pm, Matthew Wozniski wrote:
> }
> } While we're on the topic of using the preexec hook to set the
> } titlebar, I'd like to bounce something off the list and see if 1) it's
> } possible and 2) people would consider it useful.  So, would it be
> } possible and/or useful to have the preexec hook (or some other, new
> } hook) fire once for each pipeline in the current command, rather
> } than just once using the entire current line?
> 
> The TRAPDEBUG function is called at these points in the execution,
> if you "setopt DEBUG_BEFORE_CMD".  However, I don't remember offhand
> whether it's possible to access the command text that is about to be
> executed.  The documentation for TRAPDEBUG is pretty sparse.
> 
> (Also DEBUG_BEFORE_CMD requires a very recent zsh version.)

I doubt if there's much joy there... debug traps are called before/after
every command, including in precmd and preexec, so probably far too
often.  (They're for debugging, right?)  The only argument to a
TRAPDEBUG function is the signal number, which is meaningless in this
case anyway.  The older stuff like this ksh import doesn't tend to be
tightly enough defined to be useful interactively.

The idea of a hook between pipelines is actually rather different from
preexec and precmd; those get run around the time the shell fetches the
line for editing, rather than in the middle of execution.  Running
something after every pipeline would have to dig its mitts into into the
execution tree, which is why Bart suggested debug traps.

It doesn't look like there's a clean way to do this.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: preexec hook: possible enhancement?
  2007-09-05 16:34 preexec hook: possible enhancement? Matthew Wozniski
  2007-09-05 17:14 ` Bart Schaefer
@ 2007-09-05 19:32 ` Stephane Chazelas
  1 sibling, 0 replies; 66+ messages in thread
From: Stephane Chazelas @ 2007-09-05 19:32 UTC (permalink / raw)
  To: Matthew Wozniski; +Cc: zsh-users

On Wed, Sep 05, 2007 at 12:34:17PM -0400, Matthew Wozniski wrote:
> While we're on the topic of using the preexec hook to set the
> titlebar, I'd like to bounce something off the list and see if 1) it's
> possible and 2) people would consider it useful.  So, would it be
> possible and/or useful to have the preexec hook (or some other, new
> hook) fire once for each pipeline in the current command, rather
> than just once using the entire current line?
> 
> For instance, if one were to type
> % xterm ; echo google.com | xargs w3m ; gnome-terminal
> could a hook be inserted to fire once with "xterm", once with "echo 
> google.com | xargs w3m", and once with "gnome-terminal" passed to it,
> rather than just once with
> "xterm ; echo google.com | xargs w3m ; gnome-terminal" passed to it?
> 
> It's by no means a necessary feature, and I don't know if others would
> even find it useful, but I think it would be pretty cool to watch the
> titlebar change as we moved from one pipeline to the next.
[...]

Hi Matthew,

You can probably do that already with the DEBUG trap or
TRAPDEBUG() 

-- 
Stéphane


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: preexec hook: possible enhancement?
  2007-09-05 19:05   ` Peter Stephenson
@ 2007-09-05 21:11     ` Matthew Wozniski
  2007-09-08 17:20     ` Bart Schaefer
  1 sibling, 0 replies; 66+ messages in thread
From: Matthew Wozniski @ 2007-09-05 21:11 UTC (permalink / raw)
  To: zsh-users

On Wed, Sep 05, 2007 at 08:05:38PM +0100, Peter Stephenson wrote:
> Bart Schaefer wrote:
> > 
> > The TRAPDEBUG function is called at these points in the execution,
> > if you "setopt DEBUG_BEFORE_CMD".  However, I don't remember offhand
> > whether it's possible to access the command text that is about to be
> > executed.  The documentation for TRAPDEBUG is pretty sparse.
> > 
> > (Also DEBUG_BEFORE_CMD requires a very recent zsh version.)
> 
> I doubt if there's much joy there... debug traps are called before/after
> every command, including in precmd and preexec, so probably far too
> often.  (They're for debugging, right?)  The only argument to a
> TRAPDEBUG function is the signal number, which is meaningless in this
> case anyway.  The older stuff like this ksh import doesn't tend to be
> tightly enough defined to be useful interactively.

Yeah, that's what I gathered.  Since there doesn't seem to be a way to
get the text of the currently executing command from the debug trap,
nor to even tell if the currently executing was entered interactively,
I don't see any reasonable way to proceed down that road.
 
> The idea of a hook between pipelines is actually rather different from
> preexec and precmd; those get run around the time the shell fetches the
> line for editing, rather than in the middle of execution.  Running
> something after every pipeline would have to dig its mitts into into the
> execution tree, which is why Bart suggested debug traps.

I had a feeling it wouldn't be easy, but maintained a bit of hope that
somewhere along the line there was a function being called that was
both called for every command in an interactive pipeline and knew the
full text of the command it was being called for.  zsh's source is
still a bit scary for me, so I figured I should ask.
 
> It doesn't look like there's a clean way to do this.

Thanks for the input PWS.  :)

~Matt


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: preexec hook: possible enhancement?
  2007-09-05 19:05   ` Peter Stephenson
  2007-09-05 21:11     ` Matthew Wozniski
@ 2007-09-08 17:20     ` Bart Schaefer
  1 sibling, 0 replies; 66+ messages in thread
From: Bart Schaefer @ 2007-09-08 17:20 UTC (permalink / raw)
  To: zsh-users

On Sep 5,  8:05pm, Peter Stephenson wrote:
}
} I doubt if there's much joy there... debug traps are called before/after
} every command, including in precmd and preexec, so probably far too
} often.

My thought was to create a TRAPDEBUG function in preexec, and delete it
again in precmd.  Or at least set/clear a variable in those places so
that the function can become an effective no-op when not executing a
pipeline from zle.

} The only argument to a TRAPDEBUG function is the signal number, which
} is meaningless in this case anyway.

I think you mean the *line* number?  What signal's number would it be?

(The argument passed to TRAPDEBUG ought to be documented somewhere, but
is not as far as I can tell.)

The following appears to work for me; the command is printed only if it
runs for at least 1 second, which seems reasonable.  Obviously this is
pretty expensive -- the shell has the information this is digging out of
/proc/*/stat, it just doesn't put it anywhere that TRAPDEBUG can get it.

    find_fg_job() {
      emulate -L zsh
      local x j t
      reply=()

      # Find the TTY of the current shell
      j=( $(</proc/$$/stat) )
      t=$j[7]

      # Return if no TTY
      (( $t )) || return 1

      # Find any other job in the foreground on this TTY
      for x in /proc/<->/stat
      do
        j=()

        # Process might exit between glob and file read,
        # so suppress error messages ...
        j=( $(<$x) ) 2>/dev/null
        # ... and skip this if we can't read it
        (( $#j )) || continue

        # This test skips any sub-shell intermediaries
        [[ $j[2] == "(zsh)" ]] && continue

        # Not this shell and on this TTY and in foreground
        if (( $j[5] != $$ && $j[7] == $t && $j[5] == $j[8] ))
        then
          reply=( ${(ps:\0:)"$(</proc/$j[1]/cmdline)"} )
          return 0
        fi
      done
      return 1
    }

    print_fg_job() {
      find_fg_job || return
      print -u2 "$reply"	# REPLACE THIS WITH TAB TITLE CHANGE
    }

    setopt DEBUG_BEFORE_CMD
    TRAPDEBUG() {
      if [[ -n $DEBUG_FG ]] 
      then
        # Background and disown to suppress job control
        { sleep 1; print_fg_job } &!
      fi
    }

    preexec() { DEBUG_FG="$*" }
    precmd() {
      unset DEBUG_FG
      print -u2 "$0"		# REPLACE THIS WITH TAB TITLE CHANGE
    }


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Zsh hangs sometimes?
       [not found] <1209745744.25440.ezmlm@sunsite.dk>
@ 2008-05-02 17:39 ` Kamil Jońca
  2008-05-02 22:44   ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: Kamil Jońca @ 2008-05-02 17:39 UTC (permalink / raw)
  To: zsh-users

I have some maildirs and some mails (files with mails are) duplicated.
(But I don't want to pass them through formail -D)
I wrote script to find duplicates:

==============================
export IFS="
" ;find -type d -not -name cur -not -name tmp -not -name new -not -name "." -not -name ".." | while read q ; do echo $q ; find "$q" -maxdepth 2 -type f |while read w ; do  find "$q" -maxdepth 2 -type f |while read e ; do if [[ "$w" < "$e" ]] ; then ; if cmp -s "$w" "$e" ; then echo "$w" "$e" identical ; fi ; fi ; done;done;done

==============================
And sometimes this hangs :( 
there's not child processes.

Moreover if I put loops in the subshells (ie. |( while read q ; ....|(while read w ... ) ...) )
then everthings luks good.
Am I missing something?
zsh 4.3.6 (i686-pc-linux-gnu)
Debian GNU/Linux lenny/sid
Linux alfa.kjonca 2.6.25+1 #2 PREEMPT Tue Apr 29 12:44:38 CEST 2008 i686 GNU/Linux

KJ


PS. I know about O(n^2) comparisions between files.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Zsh hangs sometimes?
  2008-05-02 17:39 ` Zsh hangs sometimes? Kamil Jońca
@ 2008-05-02 22:44   ` Peter Stephenson
  2008-05-03 11:35     ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2008-05-02 22:44 UTC (permalink / raw)
  To: Kamil Jońca; +Cc: zsh-users

On Fri, 2 May 2008 19:39:43 +0200
Kamil Jońca <kjonca@poczta.onet.pl> wrote:
> And sometimes this hangs :( 
> there's not child processes.

OK, as you already know this isn't a very good way of doing things
but it does tickle a bug and I've managed to get it to happen.

With a bit of luck, I think this fixes it.  On attaching to the
shell I happened to notice that there were two jobs in the job table
with the same process number.  One was marked as done, and the other
wasn't:  the shell was waiting for the second job to finish.
Further probing confirmed my suspicion that the shell had decided
to fish out the PID for a job that was already done and mark it
as, well, even more well done.  So the newly done job never got
cleared and the shell waited for it for ever.  This would only happen if
you had lots and lots and lots of processes so that there was a chance
that the process numbers would wrap before an entry in the table was
cleared (an essentially random process depending on when children
died)---not something that happens with most programmes.

The fix is not to fish out jobs that are already done.  I think the use
of findproc() is restricted to occasions when you've just found out, or
want to find out, something new about a process and hence ignoring those
attached to done and dusted jobs is OK.

I've tidied up zhandler() because the comments were all over the place
and I took against the way a goto in a for loop was written, and I've
tidied up the STAT_ definitions because I can't do powers of two in my
head well enough.  The only actual fix is the new test in the first hunk,
so you can ignore the rest until I commit it.

I'm extremely relieved this wasn't a horrible race.

Index: Src/jobs.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/jobs.c,v
retrieving revision 1.62
diff -u -r1.62 jobs.c
--- Src/jobs.c	25 Mar 2008 18:17:08 -0000	1.62
+++ Src/jobs.c	2 May 2008 22:33:14 -0000
@@ -153,6 +153,15 @@
 
     for (i = 1; i <= maxjob; i++)
     {
+	/*
+	 * We are only interested in jobs with processes still
+	 * marked as live.  Careful in case there's an identical
+	 * process number in a job we haven't quite got around
+	 * to deleting.
+	 */
+	if (jobtab[i].stat & STAT_DONE)
+	    continue;
+
 	for (pn = aux ? jobtab[i].auxprocs : jobtab[i].procs;
 	     pn; pn = pn->next)
 	    if (pn->pid == pid) {
Index: Src/signals.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/signals.c,v
retrieving revision 1.45
diff -u -r1.45 signals.c
--- Src/signals.c	1 May 2007 09:35:05 -0000	1.45
+++ Src/signals.c	2 May 2008 22:33:14 -0000
@@ -408,15 +408,21 @@
     signal_process(sig);
  
     sigfillset(&newmask);
-    oldmask = signal_block(newmask);        /* Block all signals temporarily           */
+    /* Block all signals temporarily           */
+    oldmask = signal_block(newmask);
  
 #if defined(NO_SIGNAL_BLOCKING)
-    do_jump = suspend_longjmp;              /* do we need to longjmp to signal_suspend */
-    suspend_longjmp = 0;                    /* In case a SIGCHLD somehow arrives       */
-
-    if (sig == SIGCHLD) {                   /* Traps can cause nested signal_suspend()  */
-        if (do_jump)
-            jump_to = suspend_jmp_buf;      /* Copy suspend_jmp_buf                    */
+    /* do we need to longjmp to signal_suspend */
+    do_jump = suspend_longjmp;
+    /* In case a SIGCHLD somehow arrives       */
+    suspend_longjmp = 0;
+
+    /* Traps can cause nested signal_suspend()  */
+    if (sig == SIGCHLD) {
+        if (do_jump) {
+	    /* Copy suspend_jmp_buf                    */
+            jump_to = suspend_jmp_buf;
+	}
     }
 #endif
 
@@ -425,30 +431,36 @@
         int temp_rear = ++queue_rear % MAX_QUEUE_SIZE;
 
 	DPUTS(temp_rear == queue_front, "BUG: signal queue full");
-        if (temp_rear != queue_front) { /* Make sure it's not full (extremely unlikely) */
-            queue_rear = temp_rear;                  /* ok, not full, so add to queue   */
-            signal_queue[queue_rear] = sig;          /* save signal caught              */
-            signal_mask_queue[queue_rear] = oldmask; /* save current signal mask        */
+	/* Make sure it's not full (extremely unlikely) */
+        if (temp_rear != queue_front) {
+	    /* ok, not full, so add to queue   */
+            queue_rear = temp_rear;
+	    /* save signal caught              */
+            signal_queue[queue_rear] = sig;
+	    /* save current signal mask        */
+            signal_mask_queue[queue_rear] = oldmask;
         }
         signal_reset(sig);
         return;
     }
  
-    signal_setmask(oldmask);          /* Reset signal mask, signal traps ok now */
+    /* Reset signal mask, signal traps ok now */
+    signal_setmask(oldmask);
  
     switch (sig) {
     case SIGCHLD:
 
 	/* keep WAITING until no more child processes to reap */
-	for (;;)
-	  cont: {
-            int old_errno = errno; /* save the errno, since WAIT may change it */
+	for (;;) {
+	    /* save the errno, since WAIT may change it */
+	    int old_errno = errno;
 	    int status;
 	    Job jn;
 	    Process pn;
-            pid_t pid;
+	    pid_t pid;
 	    pid_t *procsubpid = &cmdoutpid;
 	    int *procsubval = &cmdoutval;
+	    int cont = 0;
 	    struct execstack *es = exstack;
 
 	    /*
@@ -471,8 +483,8 @@
 # endif
 #endif
 
-            if (!pid)  /* no more children to reap */
-                break;
+	    if (!pid)  /* no more children to reap */
+		break;
 
 	    /* check if child returned was from process substitution */
 	    for (;;) {
@@ -483,7 +495,8 @@
 		    else
 			*procsubval = WEXITSTATUS(status);
 		    get_usage();
-		    goto cont;
+		    cont = 1;
+		    break;
 		}
 		if (!es)
 		    break;
@@ -491,16 +504,22 @@
 		procsubval = &es->cmdoutval;
 		es = es->next;
 	    }
+	    if (cont)
+		continue;
 
 	    /* check for WAIT error */
-            if (pid == -1) {
-                if (errno != ECHILD)
-                    zerr("wait failed: %e", errno);
-                errno = old_errno;    /* WAIT changed errno, so restore the original */
-                break;
-            }
+	    if (pid == -1) {
+		if (errno != ECHILD)
+		    zerr("wait failed: %e", errno);
+		/* WAIT changed errno, so restore the original */
+		errno = old_errno;
+		break;
+	    }
 
-	    /* Find the process and job containing this pid and update it. */
+	    /*
+	     * Find the process and job containing this pid and
+	     * update it.
+	     */
 	    if (findproc(pid, &jn, &pn, 0)) {
 #if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE)
 		struct timezone dummy_tz;
@@ -517,11 +536,12 @@
 	    } else {
 		/* If not found, update the shell record of time spent by
 		 * children in sub processes anyway:  otherwise, this
-		 * will get added on to the next found process that terminates.
+		 * will get added on to the next found process that
+		 * terminates.
 		 */
 		get_usage();
 	    }
-        }
+	}
         break;
  
     case SIGHUP:
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.128
diff -u -r1.128 zsh.h
--- Src/zsh.h	29 Apr 2008 17:19:26 -0000	1.128
+++ Src/zsh.h	2 May 2008 22:33:14 -0000
@@ -857,24 +857,24 @@
     struct ttyinfo *ty;		/* the modes specified by STTY       */
 };
 
-#define STAT_CHANGED	(1<<0)	/* status changed and not reported      */
-#define STAT_STOPPED	(1<<1)	/* all procs stopped or exited          */
-#define STAT_TIMED	(1<<2)	/* job is being timed                   */
-#define STAT_DONE	(1<<3)	/* job is done                          */
-#define STAT_LOCKED	(1<<4)	/* shell is finished creating this job, */
-                                /*   may be deleted from job table      */
-#define STAT_NOPRINT	(1<<5)	/* job was killed internally,           */
-                                /*   we don't want to show that         */
-#define STAT_INUSE	(1<<6)	/* this job entry is in use             */
-#define STAT_SUPERJOB	(1<<7)	/* job has a subjob                     */
-#define STAT_SUBJOB	(1<<8)	/* job is a subjob                      */
-#define STAT_WASSUPER   (1<<9)  /* was a super-job, sub-job needs to be */
-				/* deleted */
-#define STAT_CURSH	(1<<10)	/* last command is in current shell     */
-#define STAT_NOSTTY	(1<<11)	/* the tty settings are not inherited   */
-				/* from this job when it exits.         */
-#define STAT_ATTACH	(1<<12)	/* delay reattaching shell to tty       */
-#define STAT_SUBLEADER  (1<<13) /* is super-job, but leader is sub-shell */
+#define STAT_CHANGED	(0x0001) /* status changed and not reported      */
+#define STAT_STOPPED	(0x0002) /* all procs stopped or exited          */
+#define STAT_TIMED	(0x0004) /* job is being timed                   */
+#define STAT_DONE	(0x0008) /* job is done                          */
+#define STAT_LOCKED	(0x0010) /* shell is finished creating this job, */
+                                 /*   may be deleted from job table      */
+#define STAT_NOPRINT	(0x0020) /* job was killed internally,           */
+                                 /*   we don't want to show that         */
+#define STAT_INUSE	(0x0040) /* this job entry is in use             */
+#define STAT_SUPERJOB	(0x0080) /* job has a subjob                     */
+#define STAT_SUBJOB	(0x0100) /* job is a subjob                      */
+#define STAT_WASSUPER   (0x0200) /* was a super-job, sub-job needs to be */
+				 /* deleted */
+#define STAT_CURSH	(0x0400) /* last command is in current shell     */
+#define STAT_NOSTTY	(0x0800) /* the tty settings are not inherited   */
+				 /* from this job when it exits.         */
+#define STAT_ATTACH	(0x1000) /* delay reattaching shell to tty       */
+#define STAT_SUBLEADER  (0x2000) /* is super-job, but leader is sub-shell */
 
 #define SP_RUNNING -1		/* fake status for jobs currently running */
 


-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Zsh hangs sometimes?
  2008-05-02 22:44   ` Peter Stephenson
@ 2008-05-03 11:35     ` Bart Schaefer
  2008-05-04 12:13       ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2008-05-03 11:35 UTC (permalink / raw)
  To: zsh-users

On May 2, 11:44pm, Peter Stephenson wrote:
}
} This would only happen if you had lots and lots and lots of processes
} so that there was a chance that the process numbers would wrap before
} an entry in the table was cleared

Indeed, that's a lot of processes.  I don't think I've ever managed to
create that situation intentionally, and certainly not without putting
the machine into serious memory thrash.

} I've tidied up zhandler() because the comments were all over the place
} and I took against the way a goto in a for loop was written

"Took against"?  That's a turn of phrase I'd never encountered before.
I must be spending too much time on the west side of the Atlantic.

} and I've tidied up the STAT_ definitions because I can't do powers of
} two in my head well enough.

Interesting.  Not interesting that you can't do powers of two, but
interesting that your reaction to not being able to do powers of two
is to write out longhand the powers of two, rather than let the compiler
figure it out by use of shift operators.  All my professors back in
college would have said the Right Thing is what was there before, in
which you can see plainly exactly which bit-position is set rather than
having to convert hex to binary in your head, and in which you can add
the next bit-position without having to first work out the next power.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Zsh hangs sometimes?
  2008-05-03 11:35     ` Bart Schaefer
@ 2008-05-04 12:13       ` Peter Stephenson
  2008-05-04 17:00         ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2008-05-04 12:13 UTC (permalink / raw)
  To: zsh-users

Bart Schaefer wrote:
> } and I've tidied up the STAT_ definitions because I can't do powers of
> } two in my head well enough.
> 
> Interesting.  Not interesting that you can't do powers of two, but
> interesting that your reaction to not being able to do powers of two
> is to write out longhand the powers of two, rather than let the compiler
> figure it out by use of shift operators.  All my professors back in
> college would have said the Right Thing is what was there before, in
> which you can see plainly exactly which bit-position is set rather than
> having to convert hex to binary in your head, and in which you can add
> the next bit-position without having to first work out the next power.

Can I suggest your professors were either very weird or (more likely)
didn't do much real programming?  You're suggesting (i) that they
couldn't see from

#define THIS_DEFINITION 0x0080

that the next one is obviously

#define THAT_DEFINITION 0x0100

which I don't believe (ii) that they are happy when debugging, given a
set of bits 0x09e1 (or whatever), to deduce that this includes (1<<11),
(1<<8), (1<<7), (1<<6), (1<<5) and (1<<0)?  In that case, please could
they do more zsh debugging, because given 0x09e1 I need definitions that
separate out into 0x0800, 0x0100, 0x0080, 0x0040, 0x0020 and 0x0001 so
that I can work out what the flags are.  I wrote the latter ones out
straight away but had to think for a long time about the former ones.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Zsh hangs sometimes?
  2008-05-04 12:13       ` Peter Stephenson
@ 2008-05-04 17:00         ` Bart Schaefer
  2008-05-04 18:14           ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2008-05-04 17:00 UTC (permalink / raw)
  To: zsh-users

On May 4,  1:13pm, Peter Stephenson wrote:
}
} Can I suggest your professors were either very weird or (more likely)
} didn't do much real programming?

Emphasis on source maintainability rather than on ease of debugging.

} set of bits 0x09e1 (or whatever), to deduce that this includes (1<<11),
} (1<<8), (1<<7), (1<<6), (1<<5) and (1<<0)?

If it's a bitmask, you should be asking the debugger to print it in
binary rather than hex, so you can see the individual 100111100001.
In 0x09e1 you still have to compute that "e" is ... er ... gimme a
moment ... 8+4+2.

I think perhaps your programming of BlueTooth drivers has you thinking
more naturally in hex.  It's quite true that my professors did little
if any device driver programming.

Actually given that this is C, some of my professors probably would
have advocated using a bitfield struct, so your earlier point is not
without merit. :-)


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Zsh hangs sometimes?
  2008-05-04 17:00         ` Bart Schaefer
@ 2008-05-04 18:14           ` Peter Stephenson
  2008-05-04 20:00             ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2008-05-04 18:14 UTC (permalink / raw)
  To: zsh-users

Bart Schaefer wrote:
> } set of bits 0x09e1 (or whatever), to deduce that this includes (1<<11),
> } (1<<8), (1<<7), (1<<6), (1<<5) and (1<<0)?
> 
> If it's a bitmask, you should be asking the debugger to print it in
> binary rather than hex, so you can see the individual 100111100001.

Hmm... the first thing I do with that is group it as 1001 1110 0001,
otherwise I can't count it.  So I end up with something that looks like
hex anyway.  But in that form it's six and two threes (which you don't
say in California, either; I'm told it's probably a Tyneside
peculiarity) whether I turn it into hex or count within the groups of
four.

> In 0x09e1 you still have to compute that "e" is ... er ... gimme a
> moment ... 8+4+2.
> 
> I think perhaps your programming of BlueTooth drivers has you thinking
> more naturally in hex.

You're quite right that I tend to think down at the lowest levels, but
actually in firmware terms rather than driver terms.  I'm used to things
like

enum fiddly_analogue_radio_bits {
  ANA_TWEAK_FOR_THE_STUFF_IN_THAT_OTHER_WOTSIT_LVL_MASK = 0x0f00
};

and bitmasks don't naturally lend themselves to individual powers of
two.  (See the new definitions for colour attributes in zsh.h for
examples.)

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Zsh hangs sometimes?
  2008-05-04 18:14           ` Peter Stephenson
@ 2008-05-04 20:00             ` Bart Schaefer
  2008-05-05 11:54               ` Aaron Davies
  0 siblings, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2008-05-04 20:00 UTC (permalink / raw)
  To: zsh-users

On May 4,  7:14pm, Peter Stephenson wrote:
}
} But in that form it's six and two threes (which you don't
} say in California, either; I'm told it's probably a Tyneside
} peculiarity)

"Six of one and half a dozen of the other."

(Personally I've been known to say "six dozen of one and half a gross
of the other" to see just how confused someone might get.)

As long as you don't start writing in rhyming slang, we're good.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Zsh hangs sometimes?
  2008-05-04 20:00             ` Bart Schaefer
@ 2008-05-05 11:54               ` Aaron Davies
  0 siblings, 0 replies; 66+ messages in thread
From: Aaron Davies @ 2008-05-05 11:54 UTC (permalink / raw)
  To: zsh-users

On Sun, May 4, 2008 at 4:00 PM, Bart Schaefer <schaefer@brasslantern.com> wrote:

> On May 4,  7:14pm, Peter Stephenson wrote:
>  }
>  } But in that form it's six and two threes (which you don't
>  } say in California, either; I'm told it's probably a Tyneside
>  } peculiarity)
>
>  "Six of one and half a dozen of the other."
>
>  (Personally I've been known to say "six dozen of one and half a gross
>  of the other" to see just how confused someone might get.)
>
>  As long as you don't start writing in rhyming slang, we're good.

reminds me of "always dot your j's and cross your x's".
-- 
Aaron Davies
aaron.davies@gmail.com


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Synchronous vs. Asynchronous
@ 2010-08-20 15:35 Bart Schaefer
  2010-08-20 15:45 ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2010-08-20 15:35 UTC (permalink / raw)
  To: zsh-users

I just occured to me that when the zsh manual describes something as
"asynchronous" it means not synchronous with respect to the parent zsh,
e.g., that the shell will not wait for it.  That is distinct from
whether it is [not] synchronous with respect to other commands in the
same syntactic construct.

So if we're going to cause zsh to wait for >(...), we should change the
description in the documentation to no longer say "asynchronous".


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Synchronous vs. Asynchronous
  2010-08-20 15:35 Synchronous vs. Asynchronous Bart Schaefer
@ 2010-08-20 15:45 ` Peter Stephenson
  2010-08-20 17:36   ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2010-08-20 15:45 UTC (permalink / raw)
  To: zsh-users

On Fri, 20 Aug 2010 08:35:01 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> I just occured to me that when the zsh manual describes something as
> "asynchronous" it means not synchronous with respect to the parent
> zsh, e.g., that the shell will not wait for it.  That is distinct from
> whether it is [not] synchronous with respect to other commands in the
> same syntactic construct.
> 
> So if we're going to cause zsh to wait for >(...), we should change
> the description in the documentation to no longer say "asynchronous".

Actually, I think it already does that, except in the case of a builtin not
run inside { ... }, and that isn't one of the current set of changes (it's
hard because current-shell job processing is a mess, because it's hellish
difficult deciding what the job actually consists of), so the documentation
is already out of date.

The latest set of changes, which I need to review further, affect (i)
whether a signal is forwarded to the >(...) process (ii) whether that
process is attached to the foreground terminal so it gets a ^C.  There's no
extra waiting.

My big remaining worry is whether the >(...) could think it's in the
foreground when it's actually in the background after the patch in the
second subthread.

-- 
Peter Stephenson <pws@csr.com>            Software Engineer
Tel: +44 (0)1223 692070                   Cambridge Silicon Radio Limited
Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, UK


Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Synchronous vs. Asynchronous
  2010-08-20 15:45 ` Peter Stephenson
@ 2010-08-20 17:36   ` Bart Schaefer
  2010-08-21 18:41     ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2010-08-20 17:36 UTC (permalink / raw)
  To: zsh-users

On Aug 20,  4:45pm, Peter Stephenson wrote:
}
} > So if we're going to cause zsh to wait for >(...), we should change
} > the description in the documentation to no longer say "asynchronous".
} 
} Actually, I think it already does that, except in the case of a builtin not
} run inside { ... }

Based on Vincent's description, it's an external command not run inside
{ ... } for which it becomes asynchronous.  Any builtin, including any
command in { ... }, does make it synchronous.

(All of this begs the question of what happens with <(...), but that's
less likely to be noticed by anyone.)

} My big remaining worry is whether the >(...) could think it's in the
} foreground when it's actually in the background after the patch in the
} second subthread.

Yes, mine too.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Synchronous vs. Asynchronous
  2010-08-20 17:36   ` Bart Schaefer
@ 2010-08-21 18:41     ` Peter Stephenson
  2010-08-21 22:31       ` Vincent Lefevre
  2010-08-22  5:42       ` Bart Schaefer
  0 siblings, 2 replies; 66+ messages in thread
From: Peter Stephenson @ 2010-08-21 18:41 UTC (permalink / raw)
  To: zsh-users

On Fri, 20 Aug 2010 10:36:38 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Aug 20,  4:45pm, Peter Stephenson wrote:
> } My big remaining worry is whether the >(...) could think it's in the
> } foreground when it's actually in the background after the patch in the
> } second subthread.
> 
> Yes, mine too.

I think that's not a problem in the case of redirection, and I should
have known... as already described in the manual, the reason
"external_command > >(blah)" apparently executes "blah" asynchronously
is because it forks "external_command" before starting the process
substitution.  (Casual visitors should remember that the difference
between starting a process in the background and the foreground is
essentially that the shell doesn't wait for the former; the sequence of
starting processes is otherwise the same, though the jiggery pokery with
terminal handling is different.)  So there's no chance of >(blah)
grabbing the terminal when it shouldn't because it's already associated
with a job that's disconnected from the terminal; it's basically the
same case as starting a new command in a list of commands that's been
forked to the background.  (If it tried to talk to the terminal, having
already been forked, the job would be stopped by SIGTTIN, so you'd find
out straight away --- I think that would indicate in this case that the
logic was screwy rather than what we were trying to do was wrong,
however.)  The change I made simply means it grabs the terminal when it
should, which is when it's in the foreground and there was no fork,
which is exactly what we need to make it get ^C.

People who read the zsh source code for fun(*) may be confused because
prefork() documents process substitutions as happening at that point.
That's the case of >(...) as an ordinary(**) command line argument, not
redirection.  It turns out this is different enough that the change
doesn't have any effect:

cat >(sleep 100)

is uninterruptible, while

cat <(sleep 100)

is interruptible but the sleep doesn't get killed.  Both these are true
with and without the ESUB_ASYNC change (unless I'm even more confused
than I think I am).

I think the difference must be because with >(...) we add the PID to our
job table of things to wait for, whereas with <(...) we don't (see
getproc() in exec.c).  (My best guess as to why is that in the case of
<(...) it will get SIGPIPE if the reader of the file goes away, so it
will go away of its own accord, though I'm not at all sure that's
guaranteed in all circumstances; although it may just be a hack to make
it interruptible for all i know.)  Then presumably with >(...) we have
the same problem that the process isn't attached to a suitable job to
allow it to get the ^C but the shell still waits for it to finish (as it
was created before forking the main command it's there in the job
table).

I'm tempted to back off the change for non-redirection process
substitution and attack that separately, and commit the remaining
shebang.


Another piece of unfinished business is the reference to "asynchronous"
process substitutions.  This is replaced by some circumlocution below.


(*) "people who read the zsh source code for fun": This reminds me of
those scenes where Krusty the Clown, standing up performing before an
audience, makes a joke, and the only thing you can hear on the soundtrack
in response is someone coughing at the back of the hall.

(**) "the case of >(...) as an ordinary command line argument": This
reminds of a sketch I can vaguely remember of a gorilla travelling on
the Tube (London Underground to overseas visitors) and everyone ignoring
it.  It might have been Monty Python.  Or I might just have invented it.


(The book of the Collected Zsh Mailing List Posts On Process Management
will soon be published by Fantasy Press, price several thousand dead
brain cells.)


Index: Doc/Zsh/expn.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/expn.yo,v
retrieving revision 1.117
diff -p -u -r1.117 expn.yo
--- Doc/Zsh/expn.yo	13 Jun 2010 15:59:59 -0000	1.117
+++ Doc/Zsh/expn.yo	21 Aug 2010 17:45:19 -0000
@@ -390,7 +390,8 @@ Process substitutions may be used follow
 case, the substitution must appear with no trailing string.
 
 In the case of the tt(<) or tt(>) forms, the shell runs the commands in
-var(list) asynchronously.  If the system supports the tt(/dev/fd)
+var(list) as a subprocess of the job executing the shell command line.
+If the system supports the tt(/dev/fd)
 mechanism, the command argument is the name of the device file
 corresponding to a file descriptor; otherwise, if the system supports named
 pipes (FIFOs), the command argument will be a named pipe.  If the form with
@@ -456,7 +457,7 @@ version of the example above:
 example(tt(paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR()) tt(> >LPAR())var(process)tt(RPAR()))
 
 (note that no tt(MULTIOS) are involved), var(process) will be run
-asynchronously.  The workaround is:
+asynchronously as far as the parent shell is concerned.  The workaround is:
 
 example(tt({ paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR() }) tt(> >LPAR())var(process)tt(RPAR()))
 

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Synchronous vs. Asynchronous
  2010-08-21 18:41     ` Peter Stephenson
@ 2010-08-21 22:31       ` Vincent Lefevre
  2010-08-22  5:02         ` Bart Schaefer
  2010-08-22  5:42       ` Bart Schaefer
  1 sibling, 1 reply; 66+ messages in thread
From: Vincent Lefevre @ 2010-08-21 22:31 UTC (permalink / raw)
  To: zsh-users

I've noticed differences between Mac OS X Tiger and GNU/Linux (Debian).

On 2010-08-21 19:41:22 +0100, Peter Stephenson wrote:
> cat >(sleep 100)
> 
> is uninterruptible, while
[...]

Under Mac OS X, I get:

prunille% cat >(sleep 100)
cat: /dev/fd/31: Permission denied
^C^C^C^C^C^C^C^C

^C^C^C^C^C^C^C
prunille%

Under Linux:

xvii% cat >(sleep 100)
^C^C^C^C^C

Both are uninterruptible, but I get an error under Mac OS X.
Now...

prunille% printf "a%s\n" {1..9} >>(while read s; do sleep 1; echo $s; done)
a1
a2
a3
^Ca4
^C^C^Ca5
^C^C^Ca6
^C^Ca7
a8
a9
prunille%

is uninterruptible, but not under Linux:

xvii% printf "a%s\n" {1..9} >>(while read s; do sleep 1; echo $s; done)
a1
a2
a3
^C%
xvii% a4
a5
a6
a7
a8
a9

xvii%

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Synchronous vs. Asynchronous
  2010-08-21 22:31       ` Vincent Lefevre
@ 2010-08-22  5:02         ` Bart Schaefer
  0 siblings, 0 replies; 66+ messages in thread
From: Bart Schaefer @ 2010-08-22  5:02 UTC (permalink / raw)
  To: zsh-users

On Aug 22, 12:31am, Vincent Lefevre wrote:
}
} Under Mac OS X, I get:
} 
} prunille% cat >(sleep 100)
} cat: /dev/fd/31: Permission denied

I'm pretty sure PWS meant >>(sleep 100); cat is going to try to read
from its filename argument, and >(...) is opening a write-only socket,
so what's more surprising is that it doesn't give an error elsewhere.

macadamia[502] ls -l >(sleep 100)
prw-rw----  0 schaefer  staff  0 Aug 21 21:47 /dev/fd/12|

} Under Linux:
} 
} xvii% cat >(sleep 100)
} ^C^C^C^C^C

torch[594] ls -l >(sleep 10)
l-wx------  1 schaefer schaefer 64 Aug 21 21:52 /proc/self/fd/12 -> pipe:[1059569]

Seems like "cat" should have complained about a read-only file there, I
wonder why it doesn't.  Oh:

torch[599] ls -Ll >(sleep 10)                                          4.2.0
prw-------  1 schaefer schaefer 0 Aug 21 21:55 /proc/self/fd/12|

So the pipe to which /dev/fd/12 points behaves as readable on Linux.

} prunille% printf "a%s\n" {1..9} >>(while read s; do sleep 1; echo $s; done)
} a1
} a2
} a3
} ^Ca4
} ^C^C^Ca5
} ^C^C^Ca6
} ^C^Ca7
} a8
} a9
} prunille%
} 
} is uninterruptible

Hmm, under 4.3.9 that's interruptible on MacOS:

macadamia[505] printf "a%s\n" {1..9} >>(while read s; do sleep 1; echo $s; done)
a1
a2
a3
^C%
macadamia[506] a4
a5
a6
a7
a8
a9

With the latest CVS, it is not interruptible.  I'm not sure which change
would have brought that on.


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Synchronous vs. Asynchronous
  2010-08-21 18:41     ` Peter Stephenson
  2010-08-21 22:31       ` Vincent Lefevre
@ 2010-08-22  5:42       ` Bart Schaefer
  2010-08-22 17:53         ` Peter Stephenson
  1 sibling, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2010-08-22  5:42 UTC (permalink / raw)
  To: zsh-users

On Aug 21,  7:41pm, Peter Stephenson wrote:
}
} "external_command > >(blah)" apparently executes "blah" asynchronously
} is because it forks "external_command" before starting the process
} substitution.

Ah, I should have thought of that.

} So there's no chance of >(blah) grabbing the terminal when it
} shouldn't because it's already associated with a job that's
} disconnected from the terminal [...]
} (If it tried to talk to the terminal, having
} already been forked, the job would be stopped by SIGTTIN, so you'd find
} out straight away --- I think that would indicate in this case that the
} logic was screwy rather than what we were trying to do was wrong,
} however.)

Hm.

schaefer<515> /bin/echo >>(tty 0<&1)
/dev/ttys001
schaefer<520> /bin/echo >>(cat 0<&1)
cat: stdin: Input/output error

In neither case is there a SIGTTIN, so there's something wrong with this
analysis.  Nevertheless ...

} The change I made simply means it grabs the terminal when it
} should, which is when it's in the foreground and there was no fork

... that seem likely correct, because withOUT your patch:

schaefer<525> : >>(trap "print Nyah nyah" TTIN; cat 0<&1)
cat: stdin: Interrupted system call
Nyah nyah

Without the trap, I get a silently stopped process with no way to bring
it to the foreground, which becomes a zombie if I SIGTERM it.  So there
definitely is an argument for having *something* wait for those process
substitutions.

} That's the case of >(...) as an ordinary(**) command line argument

Oops, just misconstrued this in my response to Vincent.

} I think the difference must be because with >(...) we add the PID to our
} job table of things to wait for

I'm not sure that's true.

schaefer<537> : >(trap "print Nyah nyah" TTIN; cat 0<&1) 
cat: stdin: Interrupted system call
Nyah nyah

Here again, if I omit the trap then I end up with a zombie cat.  (That
sounds like a line from a low-budget horror flick.)  Nothing's waiting.

} I'm tempted to back off the change for non-redirection process
} substitution and attack that separately, and commit the remaining
} shebang.

I tentatively agree, but confess I've lost precise track of what the
end result is.

} (**) "the case of >(...) as an ordinary command line argument": This
} reminds of a sketch I can vaguely remember of a gorilla travelling on
} the Tube (London Underground to overseas visitors) and everyone ignoring
} it.  It might have been Monty Python.  Or I might just have invented it.

About 3:30 into this:  http://www.youtube.com/watch?v=Px_4JxrIVHc


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: Synchronous vs. Asynchronous
  2010-08-22  5:42       ` Bart Schaefer
@ 2010-08-22 17:53         ` Peter Stephenson
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Stephenson @ 2010-08-22 17:53 UTC (permalink / raw)
  To: zsh-users

Bart Schaefer wrote:
> schaefer<515> /bin/echo >>(tty 0<&1)
> /dev/ttys001
> schaefer<520> /bin/echo >>(cat 0<&1)
> cat: stdin: Input/output error
> 
> In neither case is there a SIGTTIN, so there's something wrong with this
> analysis.

Nothing's in the background here.  The point of the change affecting
>>(...) is that both processes are treated as foreground processes, so
that both get ^C.  So there's nothing to get SIGTTIN.

I'll try to commit what I've got before I go on holiday on Tuesday.

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 66+ messages in thread

* mailcap configuration in zsh can't open .bk files
@ 2013-08-30  1:12 vinurs
  2013-08-30  2:59 ` Phil Pennock
  0 siblings, 1 reply; 66+ messages in thread
From: vinurs @ 2013-08-30  1:12 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 453 bytes --]

Hi all,
I wrote
application/pdf; vinurs-pdf %s ;
in my .mailcap file, vinurs-pdf is a function that can open pdf files;

In zsh configuration file:
# MIME system
autoload -U zsh-mime-setup
zsh-mime-setup

then in zsh, I can open pdf files, but ,when I mv test.pdf to test.pdf.bk,
It can not be opened.
I use file --mime-type test.pdf.bk, It shows:
test.pdf.bk: application/pdf

Why this happens? How can I configure that zsh can open test.pdf.bk files.

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: mailcap configuration in zsh can't open .bk files
  2013-08-30  1:12 mailcap configuration in zsh can't open .bk files vinurs
@ 2013-08-30  2:59 ` Phil Pennock
  2013-08-30  3:27   ` shawn wilson
  2013-08-30  8:29   ` Peter Stephenson
  0 siblings, 2 replies; 66+ messages in thread
From: Phil Pennock @ 2013-08-30  2:59 UTC (permalink / raw)
  To: vinurs; +Cc: zsh-users

On 2013-08-30 at 09:12 +0800, vinurs wrote:
> then in zsh, I can open pdf files, but ,when I mv test.pdf to test.pdf.bk,
> It can not be opened.
> I use file --mime-type test.pdf.bk, It shows:
> test.pdf.bk: application/pdf

The `file` command looks inside the content of a file and uses a complex
set of rules to try to figure out what sort of file it is.

The normal approach of MIME handling on Unix is to use the filename
extension to figure out the type of file.  There are *two* files of
interest: `mailcap` files say what to do with a MIME type, `mime.types`
files say what MIME type should be assumed for a given extension.

The pathnames to these files and other information can be found in the
zshcontrib(1) manual-page:

    % man zshcontrib

and search for "MIME FUNCTIONS".

-Phil


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: mailcap configuration in zsh can't open .bk files
  2013-08-30  2:59 ` Phil Pennock
@ 2013-08-30  3:27   ` shawn wilson
  2013-08-30  8:29   ` Peter Stephenson
  1 sibling, 0 replies; 66+ messages in thread
From: shawn wilson @ 2013-08-30  3:27 UTC (permalink / raw)
  To: vinurs, Zsh Users

[-- Attachment #1: Type: text/plain, Size: 1018 bytes --]

Magic isn't 100% anyway. It's best to use extensions unless you're doing
forensics.


On Thu, Aug 29, 2013 at 10:59 PM, Phil Pennock <
zsh-workers+phil.pennock@spodhuis.org> wrote:

> On 2013-08-30 at 09:12 +0800, vinurs wrote:
> > then in zsh, I can open pdf files, but ,when I mv test.pdf to
> test.pdf.bk,
> > It can not be opened.
> > I use file --mime-type test.pdf.bk, It shows:
> > test.pdf.bk: application/pdf
>
> The `file` command looks inside the content of a file and uses a complex
> set of rules to try to figure out what sort of file it is.
>
> The normal approach of MIME handling on Unix is to use the filename
> extension to figure out the type of file.  There are *two* files of
> interest: `mailcap` files say what to do with a MIME type, `mime.types`
> files say what MIME type should be assumed for a given extension.
>
> The pathnames to these files and other information can be found in the
> zshcontrib(1) manual-page:
>
>     % man zshcontrib
>
> and search for "MIME FUNCTIONS".
>
> -Phil
>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: mailcap configuration in zsh can't open .bk files
  2013-08-30  2:59 ` Phil Pennock
  2013-08-30  3:27   ` shawn wilson
@ 2013-08-30  8:29   ` Peter Stephenson
  2013-08-30 17:10     ` Bart Schaefer
  1 sibling, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2013-08-30  8:29 UTC (permalink / raw)
  To: Phil Pennock, zsh-users

On Thu, 29 Aug 2013 19:59:18 -0700
Phil Pennock <zsh-workers+phil.pennock@spodhuis.org> wrote:
> On 2013-08-30 at 09:12 +0800, vinurs wrote:
> > then in zsh, I can open pdf files, but ,when I mv test.pdf to test.pdf.bk,
> > It can not be opened.
> > I use file --mime-type test.pdf.bk, It shows:
> > test.pdf.bk: application/pdf
> 
> The `file` command looks inside the content of a file and uses a complex
> set of rules to try to figure out what sort of file it is.
> 
> The normal approach of MIME handling on Unix is to use the filename
> extension to figure out the type of file.  There are *two* files of
> interest: `mailcap` files say what to do with a MIME type, `mime.types`
> files say what MIME type should be assumed for a given extension.

Hmm... the zsh-mime-setup script is smart enough to get this right if
you specify pdf.bk in ~/.mime.types, e.g.

application/pdf pdf pdf.bk

but unfortunately the main shell isn't:  given the suffix alias pdf.bk,
it only looks for the .bk suffix, so the MIME handler isn't started.
This is probably fixable, although I'm not sure if it's strictly a bug.

If you were able to use a special suffix for this case, e.g. pdf_bk, it
would all work.

pws


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: mailcap configuration in zsh can't open .bk files
  2013-08-30  8:29   ` Peter Stephenson
@ 2013-08-30 17:10     ` Bart Schaefer
  2013-09-01 17:11       ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: Bart Schaefer @ 2013-08-30 17:10 UTC (permalink / raw)
  To: zsh-users

On Aug 30,  9:29am, Peter Stephenson wrote:
}
} Hmm... the zsh-mime-setup script is smart enough to get this right if
} you specify pdf.bk in ~/.mime.types, e.g.
} 
} application/pdf pdf pdf.bk
} 
} but unfortunately the main shell isn't:  given the suffix alias pdf.bk,
} it only looks for the .bk suffix, so the MIME handler isn't started.

The documentation would imply that it is therefore sufficient to put the
pdf.pk rule in ~/.mime.types, run zsh-mime-setup, and then add

    alias -s bk=zsh-mime-handler

Quote from the doc:

    ... Alternatively, if no handling
   for .gz on its own is needed, simply adding the command

       alias -s gz=zsh-mime-handler

    to the initialisation code is sufficient; .gz will not be handled
    on its own, but may be in combination with other suffixes.

Is this not accurate, or am I misinterpreting it somehow?


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: mailcap configuration in zsh can't open .bk files
  2013-08-30 17:10     ` Bart Schaefer
@ 2013-09-01 17:11       ` Peter Stephenson
  2013-09-02  1:28         ` vinurs
  0 siblings, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2013-09-01 17:11 UTC (permalink / raw)
  To: zsh-users

Bart Schaefer wrote:
> On Aug 30,  9:29am, Peter Stephenson wrote:
> }
> } Hmm... the zsh-mime-setup script is smart enough to get this right if
> } you specify pdf.bk in ~/.mime.types, e.g.
> } 
> } application/pdf pdf pdf.bk
> } 
> } but unfortunately the main shell isn't:  given the suffix alias pdf.bk,
> } it only looks for the .bk suffix, so the MIME handler isn't started.
> 
> The documentation would imply that it is therefore sufficient to put the
> pdf.pk rule in ~/.mime.types, run zsh-mime-setup, and then add
> 
>     alias -s bk=zsh-mime-handler

That should work, too, since zsh-mime-handler doesn't care how it gets
started, only the file name passed to it; what won't work is leaving it
to zsh-mime-setup which will only add the alias for pdf.bk.

I guess alternatively we could make it add a suffix alias for bk if
there isn't one.

pws


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: mailcap configuration in zsh can't open .bk files
  2013-09-01 17:11       ` Peter Stephenson
@ 2013-09-02  1:28         ` vinurs
  2013-09-02 13:46           ` Peter Stephenson
  0 siblings, 1 reply; 66+ messages in thread
From: vinurs @ 2013-09-02  1:28 UTC (permalink / raw)
  To: zsh-users

[-- Attachment #1: Type: text/plain, Size: 1092 bytes --]

It's not intelligent deciding filetype by suffix only, I'd like to write
functions to open flles using 'file --mime-type'
Thanks all


2013/9/2 Peter Stephenson <p.w.stephenson@ntlworld.com>

> Bart Schaefer wrote:
> > On Aug 30,  9:29am, Peter Stephenson wrote:
> > }
> > } Hmm... the zsh-mime-setup script is smart enough to get this right if
> > } you specify pdf.bk in ~/.mime.types, e.g.
> > }
> > } application/pdf pdf pdf.bk
> > }
> > } but unfortunately the main shell isn't:  given the suffix alias pdf.bk,
> > } it only looks for the .bk suffix, so the MIME handler isn't started.
> >
> > The documentation would imply that it is therefore sufficient to put the
> > pdf.pk rule in ~/.mime.types, run zsh-mime-setup, and then add
> >
> >     alias -s bk=zsh-mime-handler
>
> That should work, too, since zsh-mime-handler doesn't care how it gets
> started, only the file name passed to it; what won't work is leaving it
> to zsh-mime-setup which will only add the alias for pdf.bk.
>
> I guess alternatively we could make it add a suffix alias for bk if
> there isn't one.
>
> pws
>

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: mailcap configuration in zsh can't open .bk files
  2013-09-02  1:28         ` vinurs
@ 2013-09-02 13:46           ` Peter Stephenson
  2013-09-02 17:45             ` Bart Schaefer
  0 siblings, 1 reply; 66+ messages in thread
From: Peter Stephenson @ 2013-09-02 13:46 UTC (permalink / raw)
  To: zsh-users

On Mon, 02 Sep 2013 09:28:26 +0800
vinurs <haiyuan.vinurs@gmail.com> wrote:
> It's not intelligent deciding filetype by suffix only, I'd like to write
> functions to open flles using 'file --mime-type'

You're on your own here -- the zsh system isn't going to do this --- and
it looks like you've got problems.  The shell allows you to define a
command to handle other commands that aren't found, but it doesn't allow
you define a command to handle other errors, in particular "permission
denied", which is what you'd get if you tried to "execute" a
non-executable file that wasn't aliased by one means or another.

Your best bet might be to do it in ZLE as a zle-line-finish hook.  It's
going to be a bit of a guess, but if you determine that the word in
command position is a file but isn't executable, then you've got the
basis for something workable.  You'd then need to insert the handler
back in the command line at the start of BUFFER.

I haven't tried the following, so there may be trivial bugs, but you
ought to be able to whip it into shape with enough effort.


zle-line-finish() {
  local REPLY REPLY2 handler
  local -a reply
  autoload -Uz split-shell-arguments
  split-shell-arguments

  local fname=$reply[1]

  # Tests here could be a bit more stringent
  if [[ -n $fname && -f $fname && ! -x $fname ]]; then
    # Should replace the case with a look-up similar to zsh-mime-handler
    # but based on type not suffix.
    case ${$(file --mime-type $fname)##*:} in
      # HERE: match types, e.g.
      (application/pdf)
      handler=okular
      ;;
    esac
  fi

  # HERE: cleverness for backgrounding, etc, also similar to
  # zsh-mime-handler.
  if [[ -n $handler ]]; then
    BUFFER="$handler $BUFFER"
  fi
}
zle -N zle-line-finish


pws


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: mailcap configuration in zsh can't open .bk files
  2013-09-02 13:46           ` Peter Stephenson
@ 2013-09-02 17:45             ` Bart Schaefer
  0 siblings, 0 replies; 66+ messages in thread
From: Bart Schaefer @ 2013-09-02 17:45 UTC (permalink / raw)
  To: zsh-users

On Sep 2,  2:46pm, Peter Stephenson wrote:
}
} On Mon, 02 Sep 2013 09:28:26 +0800
} vinurs <haiyuan.vinurs@gmail.com> wrote:
} > It's not intelligent deciding filetype by suffix only, I'd like to write
} > functions to open flles using 'file --mime-type'
} 
} You're on your own here -- the zsh system isn't going to do this --- and
} it looks like you've got problems.  The shell allows you to define a
} command to handle other commands that aren't found, but it doesn't allow
} you define a command to handle other errors, in particular "permission
} denied", which is what you'd get if you tried to "execute" a
} non-executable file that wasn't aliased by one means or another.

If "." is not in $path and the filename is relative to $PWD, then the
error will in fact be command not found, so there might be some room to
address this in the not-found handler.

} Your best bet might be to do it in ZLE as a zle-line-finish hook.

Note that this doesn't work for complex commands, e.g., loops or "if"
constructs, unless you always use newline as the separator so that a
ZLE line ends after every simple command within the complex one.  In
some places the shell syntax makes this impossible, and history recall
won't work because the whole complex command is recalled as a single
multi-line buffer.

You might be better off creating a function or alias with a short name
and get in the habit of typing that yourself ahead of any file name you
want MIME-interpreted.

If the zle-line-finish hook is sufficient, then:

}   # HERE: cleverness for backgrounding, etc, also similar to
}   # zsh-mime-handler.
}   if [[ -n $handler ]]; then
}     BUFFER="$handler $BUFFER"
}   fi

Another possibility, to avoid inserting $handler into the buffer and
thus into the shell history, would be something like

    alias $fname="unalias $fname && $handler $fname"

This would invoke the current $handler every time upon history recall,
even if the defined handler changes between calls.


^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2013-09-02 17:45 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-20 15:35 Synchronous vs. Asynchronous Bart Schaefer
2010-08-20 15:45 ` Peter Stephenson
2010-08-20 17:36   ` Bart Schaefer
2010-08-21 18:41     ` Peter Stephenson
2010-08-21 22:31       ` Vincent Lefevre
2010-08-22  5:02         ` Bart Schaefer
2010-08-22  5:42       ` Bart Schaefer
2010-08-22 17:53         ` Peter Stephenson
  -- strict thread matches above, loose matches on Subject: below --
2013-08-30  1:12 mailcap configuration in zsh can't open .bk files vinurs
2013-08-30  2:59 ` Phil Pennock
2013-08-30  3:27   ` shawn wilson
2013-08-30  8:29   ` Peter Stephenson
2013-08-30 17:10     ` Bart Schaefer
2013-09-01 17:11       ` Peter Stephenson
2013-09-02  1:28         ` vinurs
2013-09-02 13:46           ` Peter Stephenson
2013-09-02 17:45             ` Bart Schaefer
     [not found] <1209745744.25440.ezmlm@sunsite.dk>
2008-05-02 17:39 ` Zsh hangs sometimes? Kamil Jońca
2008-05-02 22:44   ` Peter Stephenson
2008-05-03 11:35     ` Bart Schaefer
2008-05-04 12:13       ` Peter Stephenson
2008-05-04 17:00         ` Bart Schaefer
2008-05-04 18:14           ` Peter Stephenson
2008-05-04 20:00             ` Bart Schaefer
2008-05-05 11:54               ` Aaron Davies
2007-09-05 16:34 preexec hook: possible enhancement? Matthew Wozniski
2007-09-05 17:14 ` Bart Schaefer
2007-09-05 19:05   ` Peter Stephenson
2007-09-05 21:11     ` Matthew Wozniski
2007-09-08 17:20     ` Bart Schaefer
2007-09-05 19:32 ` Stephane Chazelas
2007-09-02 15:43 fg jobs info Atom Smasher
2007-09-02 17:59 ` Bart Schaefer
2007-09-03  7:38   ` Stephane Chazelas
2007-09-03 15:58     ` Bart Schaefer
2007-09-03 16:31   ` Matthew Wozniski
2007-09-04 11:16   ` Atom Smasher
2007-09-04 15:31     ` Bart Schaefer
2007-09-04 20:38       ` Peter Stephenson
2007-09-04 20:45       ` Peter Stephenson
2007-09-05  9:02       ` Atom Smasher
2007-09-05  9:28         ` Peter Stephenson
2007-09-05 11:21           ` Miek Gieben
2007-09-05 11:34             ` Matthew Wozniski
2007-09-05 11:36               ` Miek Gieben
2007-09-05 11:34             ` Atom Smasher
2007-09-05 11:40             ` Frank Terbeck
2007-09-05 12:18               ` Miek Gieben
2007-09-05 15:30           ` Bart Schaefer
2007-09-05 15:55             ` Peter Stephenson
2007-03-31 20:51 Documentation of colon in parameter expansion Miciah Dashiel Butler Masters
2007-04-01 17:53 ` Bart Schaefer
2007-04-01 18:26   ` Peter Stephenson
2006-10-06 15:07 Move command line options to start of line Peter Stephenson
2006-10-07  2:55 ` Bart Schaefer
2006-10-07  6:20   ` Andrey Borzenkov
2006-10-07 12:02   ` Peter Stephenson
2006-10-07 12:39     ` Bart Schaefer
2006-10-07 17:21       ` Dan Nelson
2006-10-07 17:36       ` Peter Stephenson
2006-09-04  8:43 Solved, but now a new twist (was: Double Evaluation Question (not in FAQ)) Com MN PG P E B Consultant 3
2006-09-04 18:24 ` Bart Schaefer
2006-09-07 17:53   ` Peter Stephenson
     [not found] <schaefer@brasslantern.com>
2006-07-30  6:29 ` Rebinding a widget within a keymap Bart Schaefer
2006-07-30 17:18   ` Peter Stephenson
2006-07-30 17:46     ` Bart Schaefer

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