Subject: RE: bug#30938: 27.0; `dired-do-create-files' etc.: do NOT always raise error if no files

From: Drew Adams <[email-masked]>
Date: Sat, 31 Mar 2018 09:10:41 -0700 (PDT)

> > A non-interactive use case for an arbitrary command that
> > calls ` dired-get-marked-files' does not necessarily
> > have `user-error' as the right behavior for an empty set
> > of marked files.  That's all I'm saying.
> 
> I'm sorry, but you lost me.  Let me try explaining this from my POV.
> 
> First, dired-get-marked-files _can_ be invoked when no files are
> marked, without risking a user-error: it has the ARG argument for
> that.  So if your hypothetical command needs for some reason to work
> when no files are marked, it can, at least in principle.  Why your
> dired[p]-insert-subdirs didn't go that way, or at least didn't pass nil
> as ERROR, I don't understand (and I'm not sure it's related to the
> issue at hand).

Don't confuse a command that invokes `dired-get-marked-files'
with a command that invokes a command that invokes
`dired-get-marked-files'.  Their behaviors can differ (and
in the general case they do), including wrt interactive and
non-interactive use.

`diredp-insert-subdirs' inserts the subdir of the current
line, if no subdirs are marked.  If none are marked and it
is called from a non-subdir line then it _should_ raise an
error interactively (and it does).

Should it also do so non-interactively?  Why should it
decide that?  Why not let its caller do that?  When
called non-interactively it cannot (and need not) know
what is the right way to handle that case.

Imaginary command `insert-marked-subdirs-and-do-stuff'
should _not_ raise an error, and its invocation of
`diredp-insert-subdirs' should be a _no-op_, in the
same situation where invoking `diredp-insert-subdirs'
interactively would raise an error.

Code can tell `dired-get-marked-files' directly whether
it should raise an error if there are no files gathered.
What's missing is for callers of `dired-get-marked-files'
to tell it that conditionally, based on whether they are
called interactively.

Being able to do that is for the benefit of reusing a
command that calls `dired-get-marked-files' in different
ways.  It is not needed for the benefit of a command
that calls `dired-get-marked-files' directly, as that
choice is already under its control.

> It is true that dired-aux.el commands that call dired-get-marked-files
> all pass nil as ARG (and t as ERROR), but what would be the semantics
> of, say, dired-do-isearch-regexp when no files are marked?  That
> command, and all the others which call dired-get-marked-files in the
> same manner, is to do something on "all marked files", as their doc
> string clearly says.
> 
> So why do we need to allow these commands to be invoked when no files
> are marked, and expect them not to signal a user-error?

For the benefit of a function that might call them and not
want to raise that error.

The interactive case for a command that calls
`dired-get-marked-files' is completely known by that
command.  The context of a non-interactive use of the same
command is not known to it.  Its code should not prejudice
the behavior intended by its caller.

In the example of `insert-marked-subdirs-and-do-stuff', its
call to `diredp-insert-subdirs' is _not_ its main purpose,
and it is fine if there are no marked subdirs and thus none
get inserted.  For `i-m-s-a-d-s' to do its overall job, the
call to `d-i-s' needs to tolerate no subdirs being marked
and inserted, by being benign - a no-op.

Although no marked subdirs (and point not on a subdir) _is_
a user error for interactively called `d-i-s', it is _not_
an error for interactively (or not) `i-m-s-a-d-s'.

> IOW, even if dired-do-isearch-regexp and its ilk are invoked
> non-interactively, they are invoked as result of some command up the
> call-stack, so the invocation does come from the user. 

The invocation of `d-d-i-r' comes ultimately from the user,
as does the invocation of pretty much everything in Emacs.

But the intention and purpose of `d-d-i-r' can be different
- including wrt what no markings of particular files might
mean - from the intention and purpose of an upstream command
that directly or indirectly invokes `d-d-i-r'.

There is no reason to assume that interactive and
non-interactive use of a given command should have the same
behavior wrt the new `dired-get-marked-files' arg ERROR.
Such hardcoding provides no benefit and can get in the way.

> And since
> dired-do-isearch-regexp etc. are documented to act on marked files, it
> sounds appropriate to signal an error when no files are marked.

It is appropriate for _them_, i.e., when invoked interactively.
It is not necessarily appropriate for something that calls them.

> A feature which wants to allow users to get away silently in this case
> can always check whether any files are marked and avoid calling
> dired-do-isearch-regexp etc. if none are.

It shouldn't have to.  You are essentially suggesting that it
too should invoke `dired-get-marked-files'.  That shouldn't
be necessary (not to mention that it can be costly).

> That is why I asked for real-time use-cases where this gets in the
> way: your argument sounds like a general philosophical issue to me:

Call it what you like.

Your argument hasn't even been presented so far, AFAICT.
What are supporting reasons for a claim that we should
_not_ distinguish interactive from non-interactive use
for such commands and pass this along to `d-g-m-f'?

> you claim that it's "completely inappropriate" for a utility function
> to signal an error on theoretical grounds, while in reality I still
> don't see any practical problem that cannot be easily resolved.  If
> your diredp-insert-subdirs is an example of a problem, then as I said
> above, I don't understand why you couldn't just omit the last optional
> argument to dired-get-marked-files, and be done.  (And since ERROR was
> _added_ in Emacs 27, your original code should have been already
> future-proof against such changes anyway.)

See above.

The addition of optional arg ERROR was a _good_ thing.
No, no code could have taken care of this before, without
it.  Typically, point is on a file line, and when no files
are marked the command acts (purposefully) on the file of
the current line.  It is only rarely that point is in a
buffer position where the new error kicks in.

Another, more common, case where the error can kick in is
(as for the case of `diredp-insert-subdirs') when a FILTER
passed to `dired-get-marked-files' results in an empty
file list.

While it is typically a user error if nothing is marked
and point is not on any file line, it is not necessarily
an error when neither of those is the case - even for an
interactive case.  The individual command needs to decide
whether that is an error case.

Similarly, for a command B that _invokes_ such a command
A.  It is up to B to decide whether to raise an error.
If A systematically causes `d-g-m-f' to raise an error
in a context where an error makes sense for A, that can
conflict with what makes sense for B.

To me, the solution is simple: let a command that invokes
`d-g-m-f' pass non-nil ERROR when the command is called
interactively.

That just gives the command (and its author) more choice.
No reason to assume that its interactive use is the same
as its non-interactive use, including wrt its use of
`dired-get-marked-files'.