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

From: Ihor Radchenko <[email-masked]>
Date: Wed, 18 Jan 2023 13:01:51 +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:

    Return FILENAME sans final "extension".
    
    The extension, in a file name, is the part that begins with the last .,
    except that a leading . of the file name, if there is one, doesn't count.

Nothing is said about versions. Yet,

(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"

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

>> But it only works for the native Emacs "~" style of backups (on Linux,
>> at least). If one tries (file-name-extension "foo.org.bak") ; => "bak",
>> we do not see backup extension stripped, which is correct wrt the
>> docstring, but problematic when we need to handle backup files on
>> Windows.
>> 
>> If one needs to strip backup extension/suffix for .bak and similar
>> files, there is a need to re-use
>> "\\.\\(?:orig\\|in\\|[bB][aA][kK]\\)\\'" regexp, which is not ideal
>> because auto-mode-alist may include other backup suffixes in future.
>> 
>> It would be useful if functions like `file-name-extension',
>> `file-name-sans-extension', and similar could optionally strip backup
>> suffixes that contain ".".
>
> Can't you do this by binding file-name-version-regexp to something
> that gets the job done.

Sure, but I wanted to keep things between what Emacs considers a backup
file and my code in sync.

Also, `file-name-version-regexp' is not the most obvious variable name
when I think about backups. I thought that version and backup are
totally unrelated.

>> Context: https://orgmode.org/list/[email-masked]
>
> FWIW, I don't understand this context: is it wrong for some reason
> that foo.org.bak is visited in Org mode?  If it's wrong, then why?

It is not wrong.

> And what does that have to do with the main issue you are raising
> here?  I feel there's some logical gap here.

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)

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.

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