Subject: bug#76023: closed (Re: bug#76023: 31.0.50; Observed behavior for substitute-in-file-name different from the doc string)

From: [email-masked] (GNU bug Tracking System)
Date: Tue, 04 Feb 2025 14:13:02 +0000

Your bug report

#76023: 31.0.50; Observed behavior for substitute-in-file-name different from the doc string

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
76023: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=76023
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#76023: 31.0.50; Observed behavior for substitute-in-file-name different from the doc string
From: Eli Zaretskii <[email-masked]>
To: arthur miller <[email-masked]>
Cc: [email-masked]
Date: Tue, 04 Feb 2025 16:11:45 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

> From: arthur miller <[email-masked]>
> CC: "[email-masked]" <[email-masked]>
> Date: Tue, 4 Feb 2025 06:25:21 +0000
> 
> > primitives that accept file names support both flavors of slashes.
> > Example:
> >
> >   (file-name-nondirectory "d:\\foo/bar\\baz")
> >    => "baz"
> 
> I know, I have implemented most of them in CL by now, and discovered they 
> work so. They also all emit out Emacs canonical namestrings; it is only those
> two that don't (if I haven't missed some). It is easy and cheap to make them to
> emit path in the same form as the rest. I first thought not to hack them, but I
> did since I was anyway looking at the code. In the case of substitute-in-file-name,
> it is just to call dostounix_filename on the result:

First, dostounix_filename can only be called safely after the file
name was converted to UTF-8, so it is not safe with unibyte
(undecoded) file names, something that happens during a short period
of startup.  So inserting it requires some auditing.

More importantly, I would hesitate making such changes in such old and
stable functions.

> And in file-name-concat is just to check the last written char for an argument:

file-name-concat is specifically intended to work unlike
expand-file-name, and just concatenate the parts and nothing else.  So
it only caters to backslashes vs forward slashes where it needs to
determine whether or not to add a slash, but otherwise it leaves it to
the caller to format the file-name parts as they see fit.  So I think
it would be a mistake to add such transformations to that function.

> > So the only case where a Lisp program will fail for such file names is
> > if that Lisp program manually analyzes the file name, instead of using
> > Emacs primitives.  In which case I'd say the Lisp program has a bug.
> 
> Depends on. People are creative when writing programs and puting Emacs to
> different use these days. But it is not so much about what is wrong or correct
> usage, it is more about the principle of least surprise and having uniform
> behavior for the api.

IME, people get surprised about quite a few aspects of file names,
their handling on different systems, and in particular on MS-Windows.
So my warm advice to everyone is not to invent their own code that
handles file names, but rely on Emacs primitives instead.

> > But we digress, I think?
> 
> You can close the bug, I understand why do you say it is not a bug. Thank you
> for the patience and helping me to understand it.

Closing.

> Also if you add a short sentence that says "if an expansion results in an
> absolute path, part of the file name before the expansion is discarded" it wont
> hurt. Or somthing in that line. It is a little bit arcane function that does
> some more than described in the doc string.

That's the part which talks about "//", it just is worded in a way
that has only Posix filesystems in mind.  I guess it won't do any harm
to make that more general; done.

> > And why is that a problem?  (Of course, one should almost never use
> > file-name-concat, it exists for a small number of very special cases;
> > everything else should use expand-file-name.)
> 
> How should I know it is meant to be for a special cases?

You are not supposed to know about that function at all ;-)

> There is nothing about
> special cases in docs. :) You have to document stuff. I write everywhere that
> Emacs is *the* best documented Lisp in existence. 

Emacs has the best documentation where documentation is contributed.

> To note, expand-file-name always returns absolute file name. If someone
> would like to construct a relative path programmatically than perhaps that
> function is more apropriate?

They should use expand-file-name followed by file-relative-name.

> I don't know if that is a realistic use-case
> but I can imagine it would be useful in that scenario.

It is indeed a real-life scenario, and it is covered in the manual.

Subject: 31.0.50; Observed behavior for substitute-in-file-name different from the doc string
From: arthur miller <[email-masked]>
To: "[email-masked]" <[email-masked]>
Date: Mon, 3 Feb 2025 03:12:39 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

According to docstring, text ending with '/~' should be descarded through
the slash. Does not happen:

(substitute-in-file-name "some-string/~$HOME") => some-string/~C:\Users\arthur

However:

(substitute-in-file-name "some-string~/$HOME") => C:\Users\arthur

Which seems to be the promised effect. I guess it was a typo in
the doc string and the code comment, otherwise it is a bug in the
implementation. '//' works as advertised, so I guess it is just a typo in
the doc string.

Furthermore, I find it a bit arcane, or at least unnexpected that I get
a native namestring, instead of Emacs path, since other functions in the
fileo.c return Emacs internal (unix-like) namestrings (thus far I have
tested them).

(substitute-in-file-name "some-string~/$HOME/test") => C:\Users\arthu/test

It can be fixed by wrapping into `expand-file-name', but that might or
might not be desirable (to expand from relative path).

If it is a "feature" to get the native namestring, at least perhaps mention it?