zsh-users
 help / color / mirror / code / Atom feed
* Most Recent File
@ 2021-10-23 16:15 Vin Shelton
  2021-10-23 16:43 ` Dominik Vogt
                   ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Vin Shelton @ 2021-10-23 16:15 UTC (permalink / raw)
  To: Zsh-Users List

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

I want to list the most recent file in the current directory.
    print -l -- *(-om[1,1])
works for ordinary filenames, but does not quote the output appropriately
if the filename contains spaces.  How do I quote the expression to
accommodate filenames which contain spaces?

TIA,
  Vin
--

*Never for money, always for love*

[-- Attachment #2: Type: text/html, Size: 1179 bytes --]

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

* Re: Most Recent File
  2021-10-23 16:15 Most Recent File Vin Shelton
@ 2021-10-23 16:43 ` Dominik Vogt
  2021-10-23 16:58   ` Peter Stephenson
  2021-10-23 16:47 ` david rayner
  2021-10-23 16:51 ` david rayner
  2 siblings, 1 reply; 27+ messages in thread
From: Dominik Vogt @ 2021-10-23 16:43 UTC (permalink / raw)
  To: zsh-users

On Sat, Oct 23, 2021 at 12:15:35PM -0400, Vin Shelton wrote:
> I want to list the most recent file in the current directory.
>     print -l -- *(-om[1,1])
> works for ordinary filenames, but does not quote the output appropriately
> if the filename contains spaces.  How do I quote the expression to
> accommodate filenames which contain spaces?

 # (doesn't handle newlines properly)
 $ ls -Q -- *(-om[1,1])

 # Ugly quoting with backslashes
 $ printf %q *(-om[1,1])

 # Put in variable, quote variable as needed
 $ F="$(echo *(-om[1,1]))"
 $ print -- ${(q)F}

Ciao

Dominik ^_^  ^_^

--

Dominik Vogt


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

* Re: Most Recent File
  2021-10-23 16:15 Most Recent File Vin Shelton
  2021-10-23 16:43 ` Dominik Vogt
@ 2021-10-23 16:47 ` david rayner
  2021-10-23 16:54   ` Vin Shelton
  2021-10-23 16:51 ` david rayner
  2 siblings, 1 reply; 27+ messages in thread
From: david rayner @ 2021-10-23 16:47 UTC (permalink / raw)
  To: zsh-users

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


On 23/10/2021 17:15, Vin Shelton wrote:
> print -l -- *(-om[1,1])


works for me?


touch sue\ jane.txt

print -l -- *(-om[1,1])

sue jane.txt


also

ls -l *(.om[1])

-rw-rw-r-- 1 david david 0 Oct 23 17:45 'sue jane.txt'

zzapper


[-- Attachment #2: Type: text/html, Size: 905 bytes --]

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

* Re: Most Recent File
  2021-10-23 16:15 Most Recent File Vin Shelton
  2021-10-23 16:43 ` Dominik Vogt
  2021-10-23 16:47 ` david rayner
@ 2021-10-23 16:51 ` david rayner
  2 siblings, 0 replies; 27+ messages in thread
From: david rayner @ 2021-10-23 16:51 UTC (permalink / raw)
  To: zsh-users

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

Sorry didn't read question fully!!

On 23/10/2021 17:15, Vin Shelton wrote:
> I want to list the most recent file in the current directory.
> print -l -- *(-om[1,1])
> works for ordinary filenames, but does not quote the output 
> appropriately if the filename contains spaces.  How do I quote the 
> expression to accommodate filenames which contain spaces?
>
> TIA,
>   Vin
> --
> /Never for money, always for love
> /

[-- Attachment #2: Type: text/html, Size: 2008 bytes --]

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

* Re: Most Recent File
  2021-10-23 16:47 ` david rayner
@ 2021-10-23 16:54   ` Vin Shelton
  0 siblings, 0 replies; 27+ messages in thread
From: Vin Shelton @ 2021-10-23 16:54 UTC (permalink / raw)
  To: david rayner; +Cc: Zsh-Users List

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

Yes, but the spaces aren't quoted, so the output can't be used in another
command.

On Sat, Oct 23, 2021 at 12:48 PM david rayner <david@rayninfo.co.uk> wrote:

>
> On 23/10/2021 17:15, Vin Shelton wrote:
>
>   print -l -- *(-om[1,1])
>
>
> works for me?
>
>
> touch sue\ jane.txt
>
> print -l -- *(-om[1,1])
>
> sue jane.txt
>
>
> also
>
> ls -l *(.om[1])
>
> -rw-rw-r-- 1 david david 0 Oct 23 17:45 'sue jane.txt'
>
> zzapper
>

[-- Attachment #2: Type: text/html, Size: 1272 bytes --]

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

* Re: Most Recent File
  2021-10-23 16:43 ` Dominik Vogt
@ 2021-10-23 16:58   ` Peter Stephenson
  2021-10-23 17:24     ` Dominik Vogt
  0 siblings, 1 reply; 27+ messages in thread
From: Peter Stephenson @ 2021-10-23 16:58 UTC (permalink / raw)
  To: zsh-users

On Sat, 2021-10-23 at 17:43 +0100, Dominik Vogt wrote:
> On Sat, Oct 23, 2021 at 12:15:35PM -0400, Vin Shelton wrote:
> > I want to list the most recent file in the current directory.
> >     print -l -- *(-om[1,1])
> > works for ordinary filenames, but does not quote the output appropriately
> > if the filename contains spaces.  How do I quote the expression to
> > accommodate filenames which contain spaces?
> 
>  # Put in variable, quote variable as needed
>  $ F="$(echo *(-om[1,1]))"
>  $ print -- ${(q)F}

An array would be neater since you get globbing for free... it also
extends more naturally if you need multiple files (print -l then handles
those on multiple lines, though there are other ways there).

f=(*(-om[1,1]))
print -l -- ${(q)f}

You get the choice of type of quoting here by changing the (q) to its
various relatives.

pws



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

* Re: Most Recent File
  2021-10-23 16:58   ` Peter Stephenson
@ 2021-10-23 17:24     ` Dominik Vogt
  2021-10-23 17:32       ` Peter Stephenson
  0 siblings, 1 reply; 27+ messages in thread
From: Dominik Vogt @ 2021-10-23 17:24 UTC (permalink / raw)
  To: zsh-users

On Sat, Oct 23, 2021 at 05:58:28PM +0100, Peter Stephenson wrote:
> f=(*(-om[1,1]))
> print -l -- ${(q)f}

Hmmmm

  # filename with newline:
  $ touch "c
  d"
  $ f=(c*d)
  $ echo "${(q)f}"
  c$'
  'd

Why does the value contain a '$'?

Ciao

Dominik ^_^  ^_^

--

Dominik Vogt


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

* Re: Most Recent File
  2021-10-23 17:24     ` Dominik Vogt
@ 2021-10-23 17:32       ` Peter Stephenson
  2021-10-23 18:39         ` Bart Schaefer
  2021-10-23 19:07         ` Vin Shelton
  0 siblings, 2 replies; 27+ messages in thread
From: Peter Stephenson @ 2021-10-23 17:32 UTC (permalink / raw)
  To: zsh-users

On Sat, 2021-10-23 at 18:24 +0100, Dominik Vogt wrote:
> On Sat, Oct 23, 2021 at 05:58:28PM +0100, Peter Stephenson wrote:
> > f=(*(-om[1,1]))
> > print -l -- ${(q)f}
> 
> Hmmmm
> 
>   # filename with newline:
>   $ touch "c
>   d"
>   $ f=(c*d)
>   $ echo "${(q)f}"
>   c$'
>   'd
> 
> Why does the value contain a '$'?

The $'...' form of quoting is a special one which can be used to quote
things that can't be quoted by backslashes.  In this case, that's a
newline.  Actually, a normal '<newline>' would work here, but $'...'
quoting is used for consistency with cases where that wouldn't work.  If
you try it, you'll see it does indeed do the right thing.

pws



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

* Re: Most Recent File
  2021-10-23 17:32       ` Peter Stephenson
@ 2021-10-23 18:39         ` Bart Schaefer
  2021-10-23 19:07         ` Vin Shelton
  1 sibling, 0 replies; 27+ messages in thread
From: Bart Schaefer @ 2021-10-23 18:39 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh Users

On Sat, Oct 23, 2021 at 10:32 AM Peter Stephenson
<p.w.stephenson@ntlworld.com> wrote:
>
> >   $ echo "${(q)f}"
> >   c$'
> >   'd
> >
> > Why does the value contain a '$'?
>
> The $'...' form of quoting is a special one

Also:

% printf "%s\n" "${(q)f}"
c$'\n'c

'Twas echo changed the \n to an actual newline.


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

* Re: Most Recent File
  2021-10-23 17:32       ` Peter Stephenson
  2021-10-23 18:39         ` Bart Schaefer
@ 2021-10-23 19:07         ` Vin Shelton
  2021-10-23 19:26           ` Bart Schaefer
  1 sibling, 1 reply; 27+ messages in thread
From: Vin Shelton @ 2021-10-23 19:07 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh-Users List

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

Thanks. I had attempted to strip away unnecessary complexity from my
problem, but I now see that was a mistake. I have a function, recent:

# Print the names of the most recent files in the specified directory.
# Usage: recent [count [file_pattern]]] [directory]
#               count defaults to 1
#               file_pattern defaults to *
#               directory defaults to the current directory.


local dir=
if [[ $# -gt 2 ]]; then
  if [[ ! -d "$3" ]]; then
    print -u2 "$0: directory \"$3\" does not exist."
    return 1
  fi
  [[ $3 != '.' ]] && dir="$3"/
fi

print -l -- ${dir}${~2:-*}(-om[1,${1:-1}])


So far, so good.  recent 3 ==>

zsh/
Any Given Sunday.mkv
TheEnglishPatient.mkv

BUT ls -ld $( recent 3 ) ==>

/usr/bin/ls: cannot access 'Any': No such file or directory
/usr/bin/ls: cannot access 'Given': No such file or directory
/usr/bin/ls: cannot access 'Sunday.mkv': No such file or directory
-rw-r--r-- 1 acs acs 727146010 Oct 22 15:52 TheEnglishPatient.mkv
drwxr-xr-x 3 acs acs      3488 Oct 23 12:20 zsh/

I would like to make the second example work.  I don't particularly care
how the first example looks.  Do I really have to use an external command
(like `printf') to make this work?

  - Vin

[-- Attachment #2: Type: text/html, Size: 4372 bytes --]

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

* Re: Most Recent File
  2021-10-23 19:07         ` Vin Shelton
@ 2021-10-23 19:26           ` Bart Schaefer
  2021-10-23 20:43             ` Vin Shelton
  0 siblings, 1 reply; 27+ messages in thread
From: Bart Schaefer @ 2021-10-23 19:26 UTC (permalink / raw)
  To: Vin Shelton; +Cc: Peter Stephenson, Zsh-Users List

On Sat, Oct 23, 2021 at 12:08 PM Vin Shelton <acs@alumni.princeton.edu> wrote:
>
> print -l -- ${dir}${~2:-*}(-om[1,${1:-1}])

You're still missing any of the (q) options on those expansions.

The easiest thing to do here is something like

local recent=( ${dir}${~2:-*}(-om[1,${1:-1}]) )
print -lr -- ${(@q-)recent}

It's important to add the quoting after any globbing but before you
print the result.

> Do I really have to use an external command (like `printf') to make this work?

printf is a zsh builtin, for some years now.  But as long as you add
quoting and do not use echo, you should be OK.


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

* Re: Most Recent File
  2021-10-23 19:26           ` Bart Schaefer
@ 2021-10-23 20:43             ` Vin Shelton
  2021-10-23 20:56               ` Pier Paolo Grassi
  0 siblings, 1 reply; 27+ messages in thread
From: Vin Shelton @ 2021-10-23 20:43 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Peter Stephenson, Zsh-Users List

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

Thanks, (I had tried the (q) and the extra assignment after pws suggested
it) but no luck:

zsh -f

nuc2% function recent {
function> local dir=
if [[ $# -gt 2 ]]; then
  if [[ ! -d "$3" ]]; then
    print -u2 "$0: directory \"$3\" does not exist."
    return 1
  fi
  [[ $3 != '.' ]] && dir="$3"/
fi

local f=( ${dir}${~2:-*}(-om[1,${1:-1}]) )
print -lr -- ${(@q-)f}
}
nuc2% recent 3
zsh
'Any Given Sunday.mkv'
TheEnglishPatient.mkv
nuc2% \ls -ld $(recent 3)
ls: cannot access "'Any": No such file or directory
ls: cannot access 'Given': No such file or directory
ls: cannot access "Sunday.mkv'": No such file or directory
-rw-r--r-- 1 acs acs 727146010 Oct 22 15:52  TheEnglishPatient.mkv
drwxr-xr-x 3 acs acs      3488 Oct 23 12:20  zsh


What am I doing wrong?  Does quoting not work correctly in captured output?

I appreciate knowing that printf is builtin; thanks.  Sorry I missed that.

 - Vin


On Sat, Oct 23, 2021 at 3:26 PM Bart Schaefer <schaefer@brasslantern.com>
wrote:

> On Sat, Oct 23, 2021 at 12:08 PM Vin Shelton <acs@alumni.princeton.edu>
> wrote:
> >
> > print -l -- ${dir}${~2:-*}(-om[1,${1:-1}])
>
> You're still missing any of the (q) options on those expansions.
>
> The easiest thing to do here is something like
>
> local recent=( ${dir}${~2:-*}(-om[1,${1:-1}]) )
> print -lr -- ${(@q-)recent}
>
> It's important to add the quoting after any globbing but before you
> print the result.
>
> > Do I really have to use an external command (like `printf') to make this
> work?
>
> printf is a zsh builtin, for some years now.  But as long as you add
> quoting and do not use echo, you should be OK.
>

[-- Attachment #2: Type: text/html, Size: 4999 bytes --]

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

* Re: Most Recent File
  2021-10-23 20:43             ` Vin Shelton
@ 2021-10-23 20:56               ` Pier Paolo Grassi
  2021-10-23 22:42                 ` Bart Schaefer
  0 siblings, 1 reply; 27+ messages in thread
From: Pier Paolo Grassi @ 2021-10-23 20:56 UTC (permalink / raw)
  To: Vin Shelton; +Cc: Bart Schaefer, Peter Stephenson, Zsh-Users List

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

I think to use it that way you should remove the quoting:

print -lr -- ${(@)f}

and use it like this:

ls "${(f)$recent 3)}"

to have the output of recent to be split at newlines and treated as
separate arguments
would be nice not to have to write all this boilerplate though (I use
global aliases for that)
hope someone will show a better/simpler way

Pier Paolo Grassi


Il giorno sab 23 ott 2021 alle ore 22:44 Vin Shelton <
acs@alumni.princeton.edu> ha scritto:

> Thanks, (I had tried the (q) and the extra assignment after pws suggested
> it) but no luck:
>
> zsh -f
>
> nuc2% function recent {
> function> local dir=
> if [[ $# -gt 2 ]]; then
>   if [[ ! -d "$3" ]]; then
>     print -u2 "$0: directory \"$3\" does not exist."
>     return 1
>   fi
>   [[ $3 != '.' ]] && dir="$3"/
> fi
>
> local f=( ${dir}${~2:-*}(-om[1,${1:-1}]) )
> print -lr -- ${(@q-)f}
> }
> nuc2% recent 3
> zsh
> 'Any Given Sunday.mkv'
> TheEnglishPatient.mkv
> nuc2% \ls -ld $(recent 3)
> ls: cannot access "'Any": No such file or directory
> ls: cannot access 'Given': No such file or directory
> ls: cannot access "Sunday.mkv'": No such file or directory
> -rw-r--r-- 1 acs acs 727146010 Oct 22 15:52  TheEnglishPatient.mkv
> drwxr-xr-x 3 acs acs      3488 Oct 23 12:20  zsh
>
>
> What am I doing wrong?  Does quoting not work correctly in captured output?
>
> I appreciate knowing that printf is builtin; thanks.  Sorry I missed that.
>
>  - Vin
>
>
> On Sat, Oct 23, 2021 at 3:26 PM Bart Schaefer <schaefer@brasslantern.com>
> wrote:
>
>> On Sat, Oct 23, 2021 at 12:08 PM Vin Shelton <acs@alumni.princeton.edu>
>> wrote:
>> >
>> > print -l -- ${dir}${~2:-*}(-om[1,${1:-1}])
>>
>> You're still missing any of the (q) options on those expansions.
>>
>> The easiest thing to do here is something like
>>
>> local recent=( ${dir}${~2:-*}(-om[1,${1:-1}]) )
>> print -lr -- ${(@q-)recent}
>>
>> It's important to add the quoting after any globbing but before you
>> print the result.
>>
>> > Do I really have to use an external command (like `printf') to make
>> this work?
>>
>> printf is a zsh builtin, for some years now.  But as long as you add
>> quoting and do not use echo, you should be OK.
>>
>

[-- Attachment #2: Type: text/html, Size: 6341 bytes --]

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

* Re: Most Recent File
  2021-10-23 20:56               ` Pier Paolo Grassi
@ 2021-10-23 22:42                 ` Bart Schaefer
  2021-10-24  0:24                   ` Pier Paolo Grassi
  0 siblings, 1 reply; 27+ messages in thread
From: Bart Schaefer @ 2021-10-23 22:42 UTC (permalink / raw)
  To: Pier Paolo Grassi; +Cc: Vin Shelton, Peter Stephenson, Zsh-Users List

On Sat, Oct 23, 2021 at 1:57 PM Pier Paolo Grassi <pierpaolog@gmail.com> wrote:
>
> and use it like this:
>
> ls "${(f)$recent 3)}"

That doesn't work because if one of the file names has a newline in
it, (f) will split it into two words.  (Also I think you left out an
open paren.)

print -lr -- ${(q)f}

and then

eval ls -ld $(recent 3)

seems to be the closest thing.

> Il giorno sab 23 ott 2021 alle ore 22:44 Vin Shelton <acs@alumni.princeton.edu> ha scritto:
>>
>> What am I doing wrong?  Does quoting not work correctly in captured output?

The trouble is that "ls" doesn't interpret the quoting, when $(...)
preserves it.  So you have to emit the quotes in a form that the shell
can interpret, and then use "eval" to make that happen.

For extra safety, you could use ${(qqqq)f} instead.


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

* Re: Most Recent File
  2021-10-23 22:42                 ` Bart Schaefer
@ 2021-10-24  0:24                   ` Pier Paolo Grassi
  2021-10-24  0:32                     ` Paul
  2021-10-24  1:37                     ` Most Recent File Dominik Vogt
  0 siblings, 2 replies; 27+ messages in thread
From: Pier Paolo Grassi @ 2021-10-24  0:24 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Vin Shelton, Peter Stephenson, Zsh-Users List

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

>That doesn't work because if one of the file names has a newline in
>it, (f) will split it into two words.  (Also I think you left out an
>open paren.)

sorry about that, I haven't ever considered newlines in filenames, since I
wouldn't put them in the first place. Of course that's not to say that
cannot happen anyway, of course.
And yes, it should have been:

ls "${(f)$(recent 3)}"

thanks for catching that

Pier Paolo Grassi


Il giorno dom 24 ott 2021 alle ore 00:42 Bart Schaefer <
schaefer@brasslantern.com> ha scritto:

> On Sat, Oct 23, 2021 at 1:57 PM Pier Paolo Grassi <pierpaolog@gmail.com>
> wrote:
> >
> > and use it like this:
> >
> > ls "${(f)$recent 3)}"
>
> That doesn't work because if one of the file names has a newline in
> it, (f) will split it into two words.  (Also I think you left out an
> open paren.)
>
> print -lr -- ${(q)f}
>
> and then
>
> eval ls -ld $(recent 3)
>
> seems to be the closest thing.
>
> > Il giorno sab 23 ott 2021 alle ore 22:44 Vin Shelton <
> acs@alumni.princeton.edu> ha scritto:
> >>
> >> What am I doing wrong?  Does quoting not work correctly in captured
> output?
>
> The trouble is that "ls" doesn't interpret the quoting, when $(...)
> preserves it.  So you have to emit the quotes in a form that the shell
> can interpret, and then use "eval" to make that happen.
>
> For extra safety, you could use ${(qqqq)f} instead.
>

[-- Attachment #2: Type: text/html, Size: 2284 bytes --]

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

* Re: Most Recent File
  2021-10-24  0:24                   ` Pier Paolo Grassi
@ 2021-10-24  0:32                     ` Paul
  2021-10-24  1:45                       ` Dominik Vogt
  2021-10-24  1:37                     ` Most Recent File Dominik Vogt
  1 sibling, 1 reply; 27+ messages in thread
From: Paul @ 2021-10-24  0:32 UTC (permalink / raw)
  To: Pier Paolo Grassi, Bart Schaefer
  Cc: Vin Shelton, Peter Stephenson, Zsh-Users List

Fundamentally, you're dealing with a limitation of Zsh (and almost all
other shells): There is no way to "return" a list from a function.

$( ) captures stdout, which is a *stream*, not inherently a list or any
other structure. Using $( ) means you have to serialize your data, even
if only by putting NULs between each element:

	recent(){
		local l=( *(om[1,$1]) )
		print -rn ${(pj:\0:)l}
	}
	ls -ld -- "${(0)$(recent 3)}"

There's an alternate convention in shell programming where results are
instead saved in a parameter, either of the user's choosing, or
sometimes hardcoded as 'reply'.

	recent(){
		# Use $reply if no parameter name given
		typeset -ga "${2:=reply}"
		set -A "$2" *(om[1,$1])
	}
	recent 3 files; ls -ld $files

This way, there's no serialization, forking, or reading and writing to
pipes.


On Sat Oct 23, 2021 at 7:24 PM CDT, Pier Paolo Grassi wrote:
> >That doesn't work because if one of the file names has a newline in
> >it, (f) will split it into two words.  (Also I think you left out an
> >open paren.)
>
> sorry about that, I haven't ever considered newlines in filenames, since
> I
> wouldn't put them in the first place. Of course that's not to say that
> cannot happen anyway, of course.
> And yes, it should have been:
>
> ls "${(f)$(recent 3)}"
>
> thanks for catching that
>
> Pier Paolo Grassi
>
>
> Il giorno dom 24 ott 2021 alle ore 00:42 Bart Schaefer <
> schaefer@brasslantern.com> ha scritto:
>
> > On Sat, Oct 23, 2021 at 1:57 PM Pier Paolo Grassi <pierpaolog@gmail.com>
> > wrote:
> > >
> > > and use it like this:
> > >
> > > ls "${(f)$recent 3)}"
> >
> > That doesn't work because if one of the file names has a newline in
> > it, (f) will split it into two words.  (Also I think you left out an
> > open paren.)
> >
> > print -lr -- ${(q)f}
> >
> > and then
> >
> > eval ls -ld $(recent 3)
> >
> > seems to be the closest thing.
> >
> > > Il giorno sab 23 ott 2021 alle ore 22:44 Vin Shelton <
> > acs@alumni.princeton.edu> ha scritto:
> > >>
> > >> What am I doing wrong?  Does quoting not work correctly in captured
> > output?
> >
> > The trouble is that "ls" doesn't interpret the quoting, when $(...)
> > preserves it.  So you have to emit the quotes in a form that the shell
> > can interpret, and then use "eval" to make that happen.
> >
> > For extra safety, you could use ${(qqqq)f} instead.
> >



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

* Re: Most Recent File
  2021-10-24  0:24                   ` Pier Paolo Grassi
  2021-10-24  0:32                     ` Paul
@ 2021-10-24  1:37                     ` Dominik Vogt
  1 sibling, 0 replies; 27+ messages in thread
From: Dominik Vogt @ 2021-10-24  1:37 UTC (permalink / raw)
  To: zsh-users

On Sun, Oct 24, 2021 at 02:24:04AM +0200, Pier Paolo Grassi wrote:
> >That doesn't work because if one of the file names has a newline in
> >it, (f) will split it into two words.  (Also I think you left out an
> >open paren.)
>
> sorry about that, I haven't ever considered newlines in filenames, since I
> wouldn't put them in the first place.

Maybe just stop putting spaces in filenames.  Unix systems are
cluttered with scripts and other programs that cannot handle
whitespace, asterisks, hyphens, semicola and other charaters with
a special shell or program meaning anyway.  (The vast majority of
people forget to put variables in double quotes in their scripts.)
Passing funny file names to programs is asking for trouble.  In
the worst case it can destroy or compromise your system.

You could try this solution where the most recent entries are
automatically put into an array (needs some work to deal with *
matching nothing):

  precmd () { __recent=( *(-om) ) }
  $ ls -- "${(@)__recent[1,3]}"

Or if it's only about ls, you could write a function "ls-recent"
that implements the logic.

The suggestions with "eval" or automatic unquoting of values may
be a path to disaster.

Ciao

Dominik ^_^  ^_^

--

Dominik Vogt


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

* Re: Most Recent File
  2021-10-24  0:32                     ` Paul
@ 2021-10-24  1:45                       ` Dominik Vogt
  2021-10-24  7:22                         ` Roman Perepelitsa
  0 siblings, 1 reply; 27+ messages in thread
From: Dominik Vogt @ 2021-10-24  1:45 UTC (permalink / raw)
  To: zsh-users

On Sat, Oct 23, 2021 at 07:32:09PM -0500, Paul wrote:
> 	recent(){
> 		# Use $reply if no parameter name given
> 		typeset -ga "${2:=reply}"
> 		set -A "$2" *(om[1,$1])
> 	}

> 	recent 3 files; ls -ld $files
                               ^^^^^^

  ls -ld -- "${files[@]}"

Ciao

Dominik ^_^  ^_^

--

Dominik Vogt


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

* Re: Most Recent File
  2021-10-24  1:45                       ` Dominik Vogt
@ 2021-10-24  7:22                         ` Roman Perepelitsa
  2021-10-25 19:45                           ` Disabling null elision (was: Re: Most Recent File) Daniel Shahaf
  0 siblings, 1 reply; 27+ messages in thread
From: Roman Perepelitsa @ 2021-10-24  7:22 UTC (permalink / raw)
  To: dominik.vogt, Zsh Users

On Sun, Oct 24, 2021 at 3:48 AM Dominik Vogt <dominik.vogt@gmx.de> wrote:
>
> On Sat, Oct 23, 2021 at 07:32:09PM -0500, Paul wrote:
> >       recent(){
> >               # Use $reply if no parameter name given
> >               typeset -ga "${2:=reply}"
> >               set -A "$2" *(om[1,$1])
> >       }
>
> >       recent 3 files; ls -ld $files
>                                ^^^^^^
>
>   ls -ld -- "${files[@]}"

The "--" is a good addition but the other suggested changes only make
a difference if KSH_ARRAYS or SH_WORD_SPLIT is set. Neither is set in
native mode and few zsh users set them.

It's one of the nice things about zsh that you can use the shorter
$foo and $#foo instead of "${foo[@]}" and ${#foo[@]}. I wish there was
an option to disable null elision with a corresponding expansion flag
to turn it on similar to no_sh_word_split and ${(=)name}

Roman.


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

* Disabling null elision (was: Re: Most Recent File)
  2021-10-24  7:22                         ` Roman Perepelitsa
@ 2021-10-25 19:45                           ` Daniel Shahaf
  2021-10-25 20:02                             ` Roman Perepelitsa
  2021-10-25 20:05                             ` Bart Schaefer
  0 siblings, 2 replies; 27+ messages in thread
From: Daniel Shahaf @ 2021-10-25 19:45 UTC (permalink / raw)
  To: Zsh Users; +Cc: Roman Perepelitsa

Roman Perepelitsa wrote on Sun, Oct 24, 2021 at 09:22:46 +0200:
> > It's one of the nice things about zsh that you can use the shorter
> $foo and $#foo instead of "${foo[@]}" and ${#foo[@]}. I wish there was
> an option to disable null elision with a corresponding expansion flag
> to turn it on similar to no_sh_word_split and ${(=)name}

I'm in two minds about this.

On the one hand, null elision breaks the principle of least surprise —
both in reference to other programming languages, and in reference to
SH_WORD_SPLIT's default behaviour being the unlike-Bourne-shell
behaviour.

On the other hand, making it on by default would be backwards
incompatible, and making it off by default would mean there's yet
another syntax-changing option for everyone to keep in mind when they
review random autoloaded functions' code.

All in all, perhaps this is a change to keep in mind for 6.0 (deferring
it to a major version due to the incompatibility).

Thoughts?

Cheers,

Daniel


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

* Re: Disabling null elision (was: Re: Most Recent File)
  2021-10-25 19:45                           ` Disabling null elision (was: Re: Most Recent File) Daniel Shahaf
@ 2021-10-25 20:02                             ` Roman Perepelitsa
  2021-10-25 20:41                               ` Daniel Shahaf
  2021-10-25 20:05                             ` Bart Schaefer
  1 sibling, 1 reply; 27+ messages in thread
From: Roman Perepelitsa @ 2021-10-25 20:02 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh Users

On Mon, Oct 25, 2021 at 9:45 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Roman Perepelitsa wrote on Sun, Oct 24, 2021 at 09:22:46 +0200:
> > > It's one of the nice things about zsh that you can use the shorter
> > $foo and $#foo instead of "${foo[@]}" and ${#foo[@]}. I wish there was
> > an option to disable null elision with a corresponding expansion flag
> > to turn it on similar to no_sh_word_split and ${(=)name}
>
> I'm in two minds about this.
>
> On the one hand, null elision breaks the principle of least surprise —
> both in reference to other programming languages, and in reference to
> SH_WORD_SPLIT's default behaviour being the unlike-Bourne-shell
> behaviour.
>
> On the other hand, making it on by default would be backwards
> incompatible, and making it off by default would mean there's yet
> another syntax-changing option for everyone to keep in mind when they
> review random autoloaded functions' code.

How about a two-step approach with the possibility of stopping after the first?

Step 1: Add an option to disable null elision. Off by default.
Step 2: Make this option the default in native mode.

I would be 99% satisfied with step 1. I would be less satisfied if
step 2 was implemented because I hate when my scripts break. Granted,
even step 1 will break "plugins" that attempt to work with any options
but at least it won't break executable scripts. It's also nice that
this option would affect parsing, only evaluation, so it won't be
necessary to care about it when defining functions.

I do get your point about the difficulty of reading plugins when you
have to keep in mind all possible options that the code can be
evaluated with (how many plugins work with no_glob? mine don't). I
still think it's worth it to have *this* option. Dropping all those
quotes would remove noise from code and make comprehension easier. I
realise that few users would benefit from this. Not many write zsh
scripts to begin with and a small number of those would enable a new
option.

Roman.


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

* Re: Disabling null elision (was: Re: Most Recent File)
  2021-10-25 19:45                           ` Disabling null elision (was: Re: Most Recent File) Daniel Shahaf
  2021-10-25 20:02                             ` Roman Perepelitsa
@ 2021-10-25 20:05                             ` Bart Schaefer
  1 sibling, 0 replies; 27+ messages in thread
From: Bart Schaefer @ 2021-10-25 20:05 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh Users, Roman Perepelitsa

On Mon, Oct 25, 2021 at 12:45 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Roman Perepelitsa wrote on Sun, Oct 24, 2021 at 09:22:46 +0200:
> > > It's one of the nice things about zsh that you can use the shorter
> > $foo and $#foo instead of "${foo[@]}" and ${#foo[@]}. I wish there was
> > an option to disable null elision with a corresponding expansion flag
> > to turn it on similar to no_sh_word_split and ${(=)name}

Note there isn't a ${(=)name}, it's just $=name or ${=name}.

> On the one hand, null elision breaks the principle of least surprise

This is another one of those where it depends on who is being surprised.

A person coming from csh would not be surprised by null-elision and in
fact would be surprised by the opposite.

> On the other hand, making it on by default would be backwards
> incompatible, and making it off by default would mean there's yet
> another syntax-changing option for everyone to keep in mind

If we ignore the global option and focus on expansion flags, this
becomes much less problematic; we could add a flag with this semantic
... but if you're going to need a flag, you might as well need double
quotes as well.


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

* Re: Disabling null elision (was: Re: Most Recent File)
  2021-10-25 20:02                             ` Roman Perepelitsa
@ 2021-10-25 20:41                               ` Daniel Shahaf
  2021-10-25 21:00                                 ` Ray Andrews
                                                   ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Daniel Shahaf @ 2021-10-25 20:41 UTC (permalink / raw)
  To: zsh-users

Roman Perepelitsa wrote on Mon, 25 Oct 2021 20:02 +00:00:
> I would be 99% satisfied with step 1. I would be less satisfied if
> step 2 was implemented because I hate when my scripts break. Granted,
> even step 1 will break "plugins" that attempt to work with any options
> but at least it won't break executable scripts.

In addition to these two categories, there's also plugins that set
non-default options explicitly for their own use, and users who do
that in their zshrc's and then post usage questions that don't start
with a «zsh -f».

> It's also nice that this option would affect parsing, only evaluation,
> so it won't be necessary to care about it when defining functions.

How so?  If a function f is written under the assumption null elision is
disabled, but is run with null elision enabled, then it would silently
do the wrong thing, rather than, say, error out.

I don't see why a function's caller should decide whether the callee
should or shouldn't elide nulls.  I think the function's author should
make that decision.

> I do get your point about the difficulty of reading plugins when you
> have to keep in mind all possible options that the code can be
> evaluated with (how many plugins work with no_glob? mine don't).

Writing plugins that are meant to be sourced by others is a pain, not
only because of options but also because of aliases.  Having some
way to provide packaged code to others in a way that the code will
run under predictable syntax would be nice… but that's yet another
thread.  (E.g., perhaps the new behaviour should be triggered by magic
bytes at the top of the sourced file.  Or perhaps we should start
adding some directory under ~ to the default fpath, e.g., ~/.local/share/zsh
[plus or minus XDG base dirs support])

> I still think it's worth it to have *this* option. Dropping all those
> quotes would remove noise from code and make comprehension easier. I
> realise that few users would benefit from this. Not many write zsh
> scripts to begin with and a small number of those would enable a new
> option.

Yeah.  I assume that if we make this change, then once the
incompatibility wave is past us (i.e., once everyone has made their code
Y2k compliant, so to speak), the resulting language would be more
intuitive — just like it's more intuitive with NO_SH_WORD_SPLIT than
with sh's word splitting behaviour.

Well, why not push an implementation to a branch?  If you've got the
tuits, of course.

Cheers,

Daniel


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

* Re: Disabling null elision (was: Re: Most Recent File)
  2021-10-25 20:41                               ` Daniel Shahaf
@ 2021-10-25 21:00                                 ` Ray Andrews
  2021-10-25 21:09                                   ` Bart Schaefer
  2021-10-25 21:05                                 ` Bart Schaefer
  2021-10-25 21:20                                 ` Roman Perepelitsa
  2 siblings, 1 reply; 27+ messages in thread
From: Ray Andrews @ 2021-10-25 21:00 UTC (permalink / raw)
  To: zsh-users

On 2021-10-25 1:41 p.m., Daniel Shahaf wrote:
> Yeah. I assume that if we make this change, then once the
> incompatibility wave is past us (i.e., once everyone has made their code
> Y2k compliant, so to speak), the resulting language would be more
> intuitive — just like it's more intuitive with NO_SH_WORD_SPLIT than
> with sh's word splitting behaviour.
>
> Well, why not push an implementation to a branch?  If you've got the
> tuits, of course.
But wouldn't such a thing be enabled via some option, so that nothing 
changes unless you explicitly activate it?  I have the same assumption 
regarding my various bitches and complaints -- some option enables the 
change so that nothing is different out of the box.




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

* Re: Disabling null elision (was: Re: Most Recent File)
  2021-10-25 20:41                               ` Daniel Shahaf
  2021-10-25 21:00                                 ` Ray Andrews
@ 2021-10-25 21:05                                 ` Bart Schaefer
  2021-10-25 21:20                                 ` Roman Perepelitsa
  2 siblings, 0 replies; 27+ messages in thread
From: Bart Schaefer @ 2021-10-25 21:05 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh Users

On Mon, Oct 25, 2021 at 1:41 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> I don't see why a function's caller should decide whether the callee
> should or shouldn't elide nulls.  I think the function's author should
> make that decision. [...]  Having some
> way to provide packaged code to others in a way that the code will
> run under predictable syntax would be nice…

Isn't that what

emulate zsh [options] -c 'autoload -U packagebootstrapper'

is for?  Yeah, some syntactic sugar would be nice (e.g., it's a pain
to have to quote the argument of the -c option, rather than [say]
using a code block in braces).

Anyway, we haven't yet explored all the ramifications of changing null
elision.  What effect does it have on $(...) in an array context, for
example?  Any?


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

* Re: Disabling null elision (was: Re: Most Recent File)
  2021-10-25 21:00                                 ` Ray Andrews
@ 2021-10-25 21:09                                   ` Bart Schaefer
  0 siblings, 0 replies; 27+ messages in thread
From: Bart Schaefer @ 2021-10-25 21:09 UTC (permalink / raw)
  To: Ray Andrews; +Cc: Zsh Users

On Mon, Oct 25, 2021 at 2:01 PM Ray Andrews <rayandrews@eastlink.ca> wrote:
>
> But wouldn't such a thing be enabled via some option, so that nothing
> changes unless you explicitly activate it?

The discussion at the point where you jumped in is about how long we
have to wait before making it the default so you'd no longer
explicitly activate it.

Traditionally the answer would be "forever".  The last attempt to do
it differently resulted in the dead zsh 2.5 fork (I hope I'm
remembering that number correctly, it's been a really long time.)


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

* Re: Disabling null elision (was: Re: Most Recent File)
  2021-10-25 20:41                               ` Daniel Shahaf
  2021-10-25 21:00                                 ` Ray Andrews
  2021-10-25 21:05                                 ` Bart Schaefer
@ 2021-10-25 21:20                                 ` Roman Perepelitsa
  2 siblings, 0 replies; 27+ messages in thread
From: Roman Perepelitsa @ 2021-10-25 21:20 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh Users

On Mon, Oct 25, 2021 at 10:42 PM Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>
> Roman Perepelitsa wrote on Mon, 25 Oct 2021 20:02 +00:00:
>
> > It's also nice that this option would affect parsing, only evaluation,
> > so it won't be necessary to care about it when defining functions.
>
> How so?

Some options can be set within a function for the function to work as
the author has intended. For example, extended_glob.

    function foo() {
      emulate -L zsh -o extended_glob
      # can extended-glob here to one's heart's content
      [[ $1 == a## ]]
    }

Other options must be set when the function is defined. For example,
brace_expand.

    # if brace_expand is unset here, bar is screwed
    unset brace_expand  # bwa-ha-ha

    function bar() {
      emulate -L zsh -o brace_expand  # this won't help
      typeset var{1,2,3}=42
    }

    setopt brace_expand  # this won't help either
    bar  # oh no!

Options of the second kind cause more grief.

As Bar says, autoload -Uz is key when it comes to loading plugins and
sourcing is a losing game (I learned this from Bart earlier).
Sometimes you still have to have a function in a plugin that must run
with user options but at least that's just for evaluation and not for
parsing.

Roman.


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

end of thread, other threads:[~2021-10-25 21:22 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-23 16:15 Most Recent File Vin Shelton
2021-10-23 16:43 ` Dominik Vogt
2021-10-23 16:58   ` Peter Stephenson
2021-10-23 17:24     ` Dominik Vogt
2021-10-23 17:32       ` Peter Stephenson
2021-10-23 18:39         ` Bart Schaefer
2021-10-23 19:07         ` Vin Shelton
2021-10-23 19:26           ` Bart Schaefer
2021-10-23 20:43             ` Vin Shelton
2021-10-23 20:56               ` Pier Paolo Grassi
2021-10-23 22:42                 ` Bart Schaefer
2021-10-24  0:24                   ` Pier Paolo Grassi
2021-10-24  0:32                     ` Paul
2021-10-24  1:45                       ` Dominik Vogt
2021-10-24  7:22                         ` Roman Perepelitsa
2021-10-25 19:45                           ` Disabling null elision (was: Re: Most Recent File) Daniel Shahaf
2021-10-25 20:02                             ` Roman Perepelitsa
2021-10-25 20:41                               ` Daniel Shahaf
2021-10-25 21:00                                 ` Ray Andrews
2021-10-25 21:09                                   ` Bart Schaefer
2021-10-25 21:05                                 ` Bart Schaefer
2021-10-25 21:20                                 ` Roman Perepelitsa
2021-10-25 20:05                             ` Bart Schaefer
2021-10-24  1:37                     ` Most Recent File Dominik Vogt
2021-10-23 16:47 ` david rayner
2021-10-23 16:54   ` Vin Shelton
2021-10-23 16:51 ` david rayner

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