* 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 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
* 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
* 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
* 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
[parent not found: <1209745744.25440.ezmlm@sunsite.dk>]
* 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
* 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: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 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: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
* 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
* 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
* 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
[parent not found: <schaefer@brasslantern.com>]
* 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
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 -- 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 -- 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 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 [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-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).