Subject: bug#60929: 30.0.50; [FR] `file-name-extension' and backup suffixes

From: Ihor Radchenko <[email-masked]>
Date: Mon, 23 Jan 2023 10:05:18 +0000

Eli Zaretskii <[email-masked]> writes:

>> > file-name-sans-extension isn't supposed to remove backup suffixes,
>> > it's supposed to remove file _versions_.
>> 
>> Then, its docstring is totally misleading:
>
> Please read the just-updated one.  I did say that the doc string was
> misleading, so we are in violent agreement here.
>
>> (file-name-sans-extension "asd.org.~12~") ; => "asd" <-- surprising
>> (file-name-sans-extension "asd.org~") ; => "asd"
>> (file-name-sans-extension "asd.org.bak") ; => "asd.org"
>> (file-name-sans-extension "asd.org") ; => "asd"
>
> Does the new doc string explain the above well enough?

Yes. It is completely accurate now, AFAIU.

>> >> auto-mode-alist recognizes
>> >> 
>> >>  ("\\.~?[0-9]+\\.[0-9][-.0-9]*~?\\'" nil t)
>> >>  ("\\.\\(?:orig\\|in\\|[bB][aA][kK]\\)\\'" nil t)
>> >> 
>> >> as backup extension and thus opens files like foo.org.bak with Org mode.
>> >
>> > And this is wrong because...?
>> 
>> Nothing wrong. Just inconsistent.
>> The first regexp is covered by `file-name-extension'
>> But not the second.
>
> I don't see how the mode in which we visit the file can or should be
> "consistent" with what file-name-extension does.  These are two
> different (although somewhat related) operations, and for two
> different purposes.  You seem to explain that the fact we visit
> foo.org.bak in Org mode by what file-name-sans-extension does, but
> that's not what actually happens, and you know it.

Sure. I did not imply the `file-name-extension' must follow selection of
major-mode. What I mean is that Emacs has an additional regexp about
what files can be considered "backup". This regexp is not reachable if
other places in code happen to need it.

>> The issue is how Org calculates export file name.
>> As another part of the linked message points, foo.org.bak is transformed
>> to foo.org.html, when exporting to HTML. This is because Org uses
>> `file-name-sans-extension' to find "base" file name, which is not giving
>> the expected results for backup files like foo.org.bak (note that
>>  (file-name-base "foo.org.bak") ; => "foo.org" and cannot be used either)
>
> It sounds like your code assumes that any file visited in Org mode has
> only one extension?  Is that assumption justified?

It is not, indeed. Just some reasonable default. Users can always
override the file name Org uses when exporting. However, stripping known
double extension in .org.bak files would make the Org's default even
more intuitive (Org already strips Emacs' default backup suffix anyway).

>> So, I'd need to have a separate code branch to fix the original issue
>> with export file name from backup files. It will need to match against
>> some regexp for backup files. Rather than trying to re-invent the regexp
>> of copy-paste from auto-mode-alist, I was hoping that some API exists in
>> Emacs to work with backup files. Thus, this FR.
>
> AFAIU, you want an API that would recursively remove extensions until
> some criteria (perhaps the same ones we use when processing
> auto-mode-alist?) are satisfied.  We don't have such an API, AFAIK.
> And I think your request as written makes the problem sound less
> general than it actually is: your problem is not just with backup
> files and their various extensions in auto-mode-alist, the problem
> will also happen in other cases, like foo.org.gpg, or with any
> customizations of auto-mode-alist that add extensions which are
> processed like backup files are processed now.  So I think your
> feature request should be redefined in more general terms.

You are right. In fact, Org mode does strip .gpg as well---another
special case. Some third-party extensions go further and similarly strip
.age suffix (https://github.com/FiloSottile/age).

So, let me formulate the FR more generally:

1. Emacs is currently able to work with double-extension files
   transparently.

   - For example, opening encrypted foo.ext.gpg files looks as if the
      file foo.ext were opened - no special action is required on the user
      side.
   - Similarly, backup foo.ext.bak/foo.ext.~12~ file versions are opened
     using the same rules (in auto-mode-alist) as foo.ext. Again, users
     mostly get the same experience as if they simply opened foo.ext.

2. These double-extension functionality is, however, implemented on
   ad-hoc basis with no clear common Elisp API provided. Elisp libraries
   may need to re-implement handling of files foo.ext.extra specially,
   even though, otherwise, the files are seen to the libraries as
   foo.ext

3. It would be nice to have Elisp API to determine (1) "effective" file
   name as seen to the user wrt editing functionality (foo.ext); (2) a
   list of transformations Emacs applied to the file contents when
   opening the file (decrypt, strip backup/version, tramp connection,
   etc)

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>