* view onto command pipeline? @ 2022-07-16 16:15 Anthony Heading 2022-07-16 21:30 ` Bart Schaefer 0 siblings, 1 reply; 15+ messages in thread From: Anthony Heading @ 2022-07-16 16:15 UTC (permalink / raw) To: zsh-users I'm trying to wrap 'git' in a shell function to better anticipate when I want colour output. Which is probably something like "when run from the command line and outputting to a tty or piped a pager, but not when piped to anything else". The condition seems to make this difficuult post-shell; while most (all?) of the coloured command support an isatty() test, the traditional ways of commandeering that with pty pairs or LD_PRELOAD or whatever seem no use by themselves without knowing more about the pipeline. I vaguely built a solution by ferreting about in /proc and using lsof to follow the stdout chain to identify a pager, but that feels misguided. Is there a zsh way to solve this? Perhaps just by pattern matching on the command buffer to see if it has "| less" toward the end? I couldn't find any shell variables that show the current pipeline string, also found history appears to be written too late to introspect that? I'd be fine to wrap the pager as well, if there is any way to convey some flag backwards up the pipeline... but I think by the time that is evaluated everything is running totally concurrently in different subshells, so probably that can't work. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-16 16:15 view onto command pipeline? Anthony Heading @ 2022-07-16 21:30 ` Bart Schaefer 2022-07-20 11:23 ` Anthony Heading 0 siblings, 1 reply; 15+ messages in thread From: Bart Schaefer @ 2022-07-16 21:30 UTC (permalink / raw) To: Anthony Heading; +Cc: Zsh Users On Sat, Jul 16, 2022 at 9:16 AM Anthony Heading <ajrh@ajrh.net> wrote: > > I'm trying to wrap 'git' in a shell function to better anticipate when I want colour output. Which is probably something like "when run from the command line and outputting to a tty or piped a pager, but not when piped to anything else". > > Is there a zsh way to solve this? Perhaps just by pattern matching on the command buffer to see if it has "| less" toward the end? I couldn't find any shell variables that show the current pipeline string [...] You need to look at the preexec hook. Something like gitpaged_hook() { emulate -L zsh -o extendedglob local -a match mbegin mend if [[ $3 = (#b)git*\|[[:space:]]##(more|less)[[:space:]]#* ]]; then export GITPAGED=$match[1] else unset GITPAGED fi } autoload add-zsh-hook add-zsh-hook preexec gitpaged_hook gitwrapper() { if [[ -o interactive ]]; then if [[ -t 1 ]]; then # Interactive terminal elif [[ -n $GITPAGED ]]; then # piped to a pager else # other pipeline or file output fi else # not interactive fi } ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-16 21:30 ` Bart Schaefer @ 2022-07-20 11:23 ` Anthony Heading 2022-07-20 11:37 ` Dominik Vogt 2022-07-20 19:27 ` Phil Pennock 0 siblings, 2 replies; 15+ messages in thread From: Anthony Heading @ 2022-07-20 11:23 UTC (permalink / raw) To: Bart Schaefer; +Cc: Zsh Users On Sat, Jul 16, 2022, at 5:30 PM, Bart Schaefer wrote: > You need to look at the preexec hook. Ah, many thanks Bart! Much appreciated. Don't know how I missed that. For the record, I used just the following, and it works great. git () { local opts=() if [[ -o interactive && ( -t 1 || -n $pager ) ]] then opts=(-c color.ui=always) fi command git $opts $@ } ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-20 11:23 ` Anthony Heading @ 2022-07-20 11:37 ` Dominik Vogt 2022-07-20 12:22 ` Vincent Bernat 2022-07-21 0:15 ` Anthony Heading 2022-07-20 19:27 ` Phil Pennock 1 sibling, 2 replies; 15+ messages in thread From: Dominik Vogt @ 2022-07-20 11:37 UTC (permalink / raw) To: zsh-users On Wed, Jul 20, 2022 at 07:23:46AM -0400, Anthony Heading wrote: > local opts=() > if [[ -o interactive && ( -t 1 || -n $pager ) ]] > then > opts=(-c color.ui=always) > fi > command git $opts $@ For proper handling of whitecpace in options and arguments: command git "${opts[@]}" "$@" Otherwise, if you have, say, files "a", "b" and "a b", $ git commit "a b" Would commit a and b but not "a b" if the $@ is not quoted. As a rule of thumb, _never_ use unquoted variables in shell scripts. Ciao Dominik ^_^ ^_^ -- Dominik Vogt ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-20 11:37 ` Dominik Vogt @ 2022-07-20 12:22 ` Vincent Bernat 2022-07-20 12:35 ` Dominik Vogt 2022-07-21 0:15 ` Anthony Heading 1 sibling, 1 reply; 15+ messages in thread From: Vincent Bernat @ 2022-07-20 12:22 UTC (permalink / raw) To: zsh-users On 2022-07-20 13:37, Dominik Vogt wrote: > On Wed, Jul 20, 2022 at 07:23:46AM -0400, Anthony Heading wrote: >> local opts=() >> if [[ -o interactive && ( -t 1 || -n $pager ) ]] >> then >> opts=(-c color.ui=always) >> fi >> command git $opts $@ > > For proper handling of whitecpace in options and arguments: > > command git "${opts[@]}" "$@" > > Otherwise, if you have, say, files "a", "b" and "a b", > > $ git commit "a b" > > Would commit a and b but not "a b" if the $@ is not quoted. As a > rule of thumb, _never_ use unquoted variables in shell scripts. I don't think this is true for Zsh. 14:21 ❱ f() { print -l $@ } 14:21 ❱ f a b a b 14:21 ❱ f "a b" a b ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-20 12:22 ` Vincent Bernat @ 2022-07-20 12:35 ` Dominik Vogt 2022-07-20 19:07 ` Lawrence Velázquez 0 siblings, 1 reply; 15+ messages in thread From: Dominik Vogt @ 2022-07-20 12:35 UTC (permalink / raw) To: zsh-users On Wed, Jul 20, 2022 at 02:22:21PM +0200, Vincent Bernat wrote: > On 2022-07-20 13:37, Dominik Vogt wrote: > > On Wed, Jul 20, 2022 at 07:23:46AM -0400, Anthony Heading wrote: > > > local opts=() > > > if [[ -o interactive && ( -t 1 || -n $pager ) ]] > > > then > > > opts=(-c color.ui=always) > > > fi > > > command git $opts $@ > > > > For proper handling of whitecpace in options and arguments: > > > > command git "${opts[@]}" "$@" > > > > Otherwise, if you have, say, files "a", "b" and "a b", > > > > $ git commit "a b" > > > > Would commit a and b but not "a b" if the $@ is not quoted. As a > > rule of thumb, _never_ use unquoted variables in shell scripts. > > I don't think this is true for Zsh. > > 14:21 ??? f() { print -l $@ } > 14:21 ??? f a b > a > b > 14:21 ??? f "a b" > a b Depends on shell options: $ function xls () { command ls $@ } $ setopt shwordsplit $ xls "a b" ls: cannot access 'a': No such file or directory ls: cannot access 'b': No such file or directory $ unsetopt shwordsplit $ xls "a b" 'a b' Ciao Dominik ^_^ ^_^ -- Dominik Vogt ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-20 12:35 ` Dominik Vogt @ 2022-07-20 19:07 ` Lawrence Velázquez 0 siblings, 0 replies; 15+ messages in thread From: Lawrence Velázquez @ 2022-07-20 19:07 UTC (permalink / raw) To: Dominik Vogt; +Cc: zsh-users On Wed, Jul 20, 2022, at 8:35 AM, Dominik Vogt wrote: > On Wed, Jul 20, 2022 at 02:22:21PM +0200, Vincent Bernat wrote: >> On 2022-07-20 13:37, Dominik Vogt wrote: >> > For proper handling of whitecpace in options and arguments: >> > >> > command git "${opts[@]}" "$@" >> > >> > Otherwise, if you have, say, files "a", "b" and "a b", >> > >> > $ git commit "a b" >> > >> > Would commit a and b but not "a b" if the $@ is not quoted. As a >> > rule of thumb, _never_ use unquoted variables in shell scripts. >> >> I don't think this is true for Zsh. > > Depends on shell options: Additionally, without quoting empty words are removed. % foo= % bar=(a '' 'b c') % printf '<%s>' "$foo" "$bar[@]"; echo <><a><><b c> % printf '<%s>' $foo $bar[@]; echo <a><b c> Whether or not this is desirable is up to the application. -- vq ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-20 11:37 ` Dominik Vogt 2022-07-20 12:22 ` Vincent Bernat @ 2022-07-21 0:15 ` Anthony Heading 2022-07-21 1:35 ` Lawrence Velázquez 1 sibling, 1 reply; 15+ messages in thread From: Anthony Heading @ 2022-07-21 0:15 UTC (permalink / raw) To: zsh-users On Wed, Jul 20, 2022, at 7:37 AM, Dominik Vogt wrote: > command git "${opts[@]}" "$@" > As a rule of thumb, _never_ use unquoted variables in shell scripts That's a very unequivocal rule-of-thumb then :-). For me, zsh's word-splitting rule is one of its best features, and I think anyone who turns it off deserves all their pain! Agree quoting $@ makes sense here since this is a wrapper, but I find more often dropping empty arguments is often very helpful after splits and suchlike. But as to "${opts[@]}"... Just too ugly to do that all the time, no? Instead, use zsh's awesome sticky emulation: emulate zsh -c 'autoload -Uz ~/my-zsh-funcs/*' Very helpful for insulating the risks of unexpected option settings, and makes it safe to use unquoted variables. As a rule of thumb, at least :-) ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-21 0:15 ` Anthony Heading @ 2022-07-21 1:35 ` Lawrence Velázquez 2022-07-21 2:11 ` Anthony Heading 0 siblings, 1 reply; 15+ messages in thread From: Lawrence Velázquez @ 2022-07-21 1:35 UTC (permalink / raw) To: Anthony Heading; +Cc: zsh-users On Wed, Jul 20, 2022, at 8:15 PM, Anthony Heading wrote: > Agree > quoting $@ makes sense here since this is a wrapper, but I find more > often dropping empty > arguments is often very helpful after splits and suchlike. > > But as to "${opts[@]}"... Just too ugly to do that all the time, no? > Instead, use > zsh's awesome sticky emulation: > > emulate zsh -c 'autoload -Uz ~/my-zsh-funcs/*' Leaving $opts[@] unquoted still elides empty elements in this context; that behavior is not limited to $@. (If this is what you actually want, go for it. Just don't think that fiddling with options has an effect.) > Very helpful for insulating the risks of unexpected option settings, > and makes it > safe to use unquoted variables. As a rule of thumb, at least :-) It's better to run ''emulate -L zsh'' inside the function itself (or localize and [un]set options individually as desired) to achieve a known state, rather than relying on a specific method of invocation. -- vq ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-21 1:35 ` Lawrence Velázquez @ 2022-07-21 2:11 ` Anthony Heading 2022-07-21 3:15 ` Lawrence Velázquez ` (2 more replies) 0 siblings, 3 replies; 15+ messages in thread From: Anthony Heading @ 2022-07-21 2:11 UTC (permalink / raw) To: zsh-users On Wed, Jul 20, 2022, at 9:35 PM, Lawrence Velázquez wrote: > On Wed, Jul 20, 2022, at 8:15 PM, Anthony Heading wrote: >> Agree >> quoting $@ makes sense here since this is a wrapper, but I find more >> often dropping empty >> arguments is often very helpful after splits and suchlike. >> >> But as to "${opts[@]}"... Just too ugly to do that all the time, no? >> Instead, use >> zsh's awesome sticky emulation: >> >> emulate zsh -c 'autoload -Uz ~/my-zsh-funcs/*' > > Leaving $opts[@] unquoted still elides empty elements in this > context; that behavior is not limited to $@. (If this is what you > actually want, go for it. Just don't think that fiddling with > options has an effect.) > Yes indeed! Though recall the context here was a *fixed* *literal* array: opts=(-c color.ui=always) command git $opts "$@" Quoting "$@" agreed, but writing "${opts[@]}" instead here seems a little bit like self-flagellation, no? > It's better to run ''emulate -L zsh'' inside the function itself > (or localize and [un]set options individually as desired) to achieve > a known state, rather than relying on a specific method of invocation. Oh, interesting! why is that? Certainly want to get the most stable state. I do vaguely remember tricky corner cases being discussed on zsh-workers maybe decades ago, but it seems to work great now. And, unless I picked up this autoload idiom from the mailing list, I think it's from the man pages somewhere. If you're advising that it's sub-optimal, should it be removed or caveated in the documentation? ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-21 2:11 ` Anthony Heading @ 2022-07-21 3:15 ` Lawrence Velázquez 2022-07-21 6:43 ` Dominik Vogt 2022-08-04 21:12 ` Felipe Contreras 2 siblings, 0 replies; 15+ messages in thread From: Lawrence Velázquez @ 2022-07-21 3:15 UTC (permalink / raw) To: Anthony Heading; +Cc: zsh-users On Wed, Jul 20, 2022, at 10:11 PM, Anthony Heading wrote: > On Wed, Jul 20, 2022, at 9:35 PM, Lawrence Velázquez wrote: >> Leaving $opts[@] unquoted still elides empty elements in this >> context; that behavior is not limited to $@. (If this is what you >> actually want, go for it. Just don't think that fiddling with >> options has an effect.) >> > > Yes indeed! Though recall the context here was a *fixed* *literal* array: > opts=(-c color.ui=always) > command git $opts "$@" > > Quoting "$@" agreed, but writing "${opts[@]}" instead here seems > a little bit like self-flagellation, no? Sure, it doesn't matter for this particular case. I didn't notice that you were hardcoding the array contents. >> It's better to run ''emulate -L zsh'' inside the function itself >> (or localize and [un]set options individually as desired) to achieve >> a known state, rather than relying on a specific method of invocation. > > Oh, interesting! why is that? Certainly want to get the most > stable state. I do vaguely remember tricky corner cases being discussed > on zsh-workers maybe decades ago, but it seems to work great now. > And, unless I picked up this autoload idiom from the mailing list, > I think it's from the man pages somewhere. If you're advising that > it's sub-optimal, should it be removed or caveated in the documentation? I assume you're referring to this (https://zsh.sourceforge.io/Doc/Release/Shell-Builtin-Commands.html#index-autoload): Note that the autoload command makes no attempt to ensure the shell options set during the loading or execution of the file have any particular value. For this, the emulate command can be used: emulate zsh -c 'autoload -Uz func' arranges that when func is loaded the shell is in native zsh emulation, and this emulation is also applied when func is run. I'm not saying there's anything incorrect here. I imagine it's useful if you're using functions written by others that break due to options you've set or unset in your own environment. What I'm saying is that if you are writing your own functions, you should try to write them so they proactively establish whatever state they require, instead of punting that responsibility to the caller. (This is just common sense.) If you need many options to have their zsh-native default values, then it generally suffices to call emulate -L zsh at the beginning of the function. -- vq ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-21 2:11 ` Anthony Heading 2022-07-21 3:15 ` Lawrence Velázquez @ 2022-07-21 6:43 ` Dominik Vogt 2022-08-04 21:12 ` Felipe Contreras 2 siblings, 0 replies; 15+ messages in thread From: Dominik Vogt @ 2022-07-21 6:43 UTC (permalink / raw) To: zsh-users On Wed, Jul 20, 2022 at 10:11:45PM -0400, Anthony Heading wrote: > On Wed, Jul 20, 2022, at 9:35 PM, Lawrence Velázquez wrote: > > On Wed, Jul 20, 2022, at 8:15 PM, Anthony Heading wrote: > >> Agree > >> quoting $@ makes sense here since this is a wrapper, but I find more > >> often dropping empty > >> arguments is often very helpful after splits and suchlike. > >> > >> But as to "${opts[@]}"... Just too ugly to do that all the time, no? > >> Instead, use > >> zsh's awesome sticky emulation: > >> > >> emulate zsh -c 'autoload -Uz ~/my-zsh-funcs/*' > > > > Leaving $opts[@] unquoted still elides empty elements in this > > context; that behavior is not limited to $@. (If this is what you > > actually want, go for it. Just don't think that fiddling with > > options has an effect.) > > > > Yes indeed! Though recall the context here was a *fixed* *literal* array: > opts=(-c color.ui=always) > command git $opts "$@" > > Quoting "$@" agreed, but writing "${opts[@]}" instead here seems > a little bit like self-flagellation, no? No. Who guarantees that this array is not modified later during a potential rewrite of the function? Of course it's stupid, but I've seen people automate their checkins in a script with an empty commit message. I write production quality shell scripts with various shells as part of my job. People _always_ forget to quote their variables. Make a habit of it and you're safe. Ciao Dominik ^_^ ^_^ -- Dominik Vogt ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-21 2:11 ` Anthony Heading 2022-07-21 3:15 ` Lawrence Velázquez 2022-07-21 6:43 ` Dominik Vogt @ 2022-08-04 21:12 ` Felipe Contreras 2 siblings, 0 replies; 15+ messages in thread From: Felipe Contreras @ 2022-08-04 21:12 UTC (permalink / raw) To: Anthony Heading; +Cc: zsh-users On Wed, Jul 20, 2022 at 9:12 PM Anthony Heading <ajrh@ajrh.net> wrote: > > On Wed, Jul 20, 2022, at 9:35 PM, Lawrence Velázquez wrote: > > On Wed, Jul 20, 2022, at 8:15 PM, Anthony Heading wrote: > >> Agree > >> quoting $@ makes sense here since this is a wrapper, but I find more > >> often dropping empty > >> arguments is often very helpful after splits and suchlike. > >> > >> But as to "${opts[@]}"... Just too ugly to do that all the time, no? > >> Instead, use > >> zsh's awesome sticky emulation: > >> > >> emulate zsh -c 'autoload -Uz ~/my-zsh-funcs/*' > > > > Leaving $opts[@] unquoted still elides empty elements in this > > context; that behavior is not limited to $@. (If this is what you > > actually want, go for it. Just don't think that fiddling with > > options has an effect.) > > > > Yes indeed! Though recall the context here was a *fixed* *literal* array: > opts=(-c color.ui=always) > command git $opts "$@" > > Quoting "$@" agreed, but writing "${opts[@]}" instead here seems > a little bit like self-flagellation, no? Why not simply use git existing functionality? GIT_CONFIG_PARAMETERS="'color.ui=always'" -- Felipe Contreras ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-20 11:23 ` Anthony Heading 2022-07-20 11:37 ` Dominik Vogt @ 2022-07-20 19:27 ` Phil Pennock 2022-07-21 0:18 ` Anthony Heading 1 sibling, 1 reply; 15+ messages in thread From: Phil Pennock @ 2022-07-20 19:27 UTC (permalink / raw) To: zsh-users On 2022-07-20 at 07:23 -0400, Anthony Heading wrote: > On Sat, Jul 16, 2022, at 5:30 PM, Bart Schaefer wrote: > > You need to look at the preexec hook. > > Ah, many thanks Bart! Much appreciated. Don't know how I missed that. > > For the record, I used just the following, and it works great. > > git () { > local opts=() > if [[ -o interactive && ( -t 1 || -n $pager ) ]] > then > opts=(-c color.ui=always) > fi > command git $opts $@ > } So, "if invoked from shell, use color if stdout is a tty, otherwise don't". Since ancient Git (1.8.4) automatic-based-on-tty is the default, so you'll need `git config --global color.ui false` run to populate your gitconfig file to disable color normally. The shell wrapping is simply: function git { command git -c color.ui=auto "$@" } and only define this for interactive shells, so in .zshrc or the like, not .zshenv. -Phil ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: view onto command pipeline? 2022-07-20 19:27 ` Phil Pennock @ 2022-07-21 0:18 ` Anthony Heading 0 siblings, 0 replies; 15+ messages in thread From: Anthony Heading @ 2022-07-21 0:18 UTC (permalink / raw) To: zsh-users On Wed, Jul 20, 2022, at 3:27 PM, Phil Pennock wrote: > function git { command git -c color.ui=auto "$@" } Maybe you missed the clever bit that Bart helped with? As far as I know, these 'auto' settings can only detect a tty, they can't detect a pipe that happens to feed a tty. Hence the panoply of command-line options and environment variables that Unix color needs. I had been wondering about OS support to create a more standard mechanism, but it seems impossible? A fcntl(F_TTY) flag bit that can be set on a pipe to hint that it should be treated like a tty would seem like a start, but maybe nothing short of an end-to-end handshake negotiation along the pipeline is going to work, and then maybe that's not Unix any more. Obviously yes git has an automatic pager option, probably as another workaround for this, but personally I just want to type '| less', invariant to whether I'm running git diff or plain diff. For the same reason agree the -t 1 test might be redundant for the default git config, but not for all other commands or scenarios. ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2022-08-04 21:14 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-07-16 16:15 view onto command pipeline? Anthony Heading 2022-07-16 21:30 ` Bart Schaefer 2022-07-20 11:23 ` Anthony Heading 2022-07-20 11:37 ` Dominik Vogt 2022-07-20 12:22 ` Vincent Bernat 2022-07-20 12:35 ` Dominik Vogt 2022-07-20 19:07 ` Lawrence Velázquez 2022-07-21 0:15 ` Anthony Heading 2022-07-21 1:35 ` Lawrence Velázquez 2022-07-21 2:11 ` Anthony Heading 2022-07-21 3:15 ` Lawrence Velázquez 2022-07-21 6:43 ` Dominik Vogt 2022-08-04 21:12 ` Felipe Contreras 2022-07-20 19:27 ` Phil Pennock 2022-07-21 0:18 ` Anthony Heading
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).