Add denote-slug-remove-accents function

This is based on the code originally written by Jean-Philippe Gagné
Guay in issue 603: <https://github.com/protesilaos/denote/issues/603#issuecomment-2869702877>.
I made stylistic changes to it to make it fit with the rest of denote.el.

I am adding this in response to issue 603 and 718:

- <https://github.com/protesilaos/denote/issues/603> with
  participation from Davi Ramos and Jean-Philippe Gagné Guay;
- <https://github.com/protesilaos/denote/issues/718> with
  participation from o-rxw and Alan Schmitt.

In implementing this, I am changing my mind that this is purely a
documentation issue. I realised it is better for us to have the main
function in denote.el, so that we can test it better.
This commit is contained in:
Protesilaos 2026-07-27 19:51:51 +03:00
parent 1004f735b7
commit c8aa01c56a
No known key found for this signature in database
GPG key ID: 99BD6459CD5CA3EA
3 changed files with 89 additions and 7 deletions

View file

@ -2450,6 +2450,8 @@ You have been warned.
:CUSTOM_ID: h:d1e4eb5b-e7f2-4a3b-9243-e1c653817a4a :CUSTOM_ID: h:d1e4eb5b-e7f2-4a3b-9243-e1c653817a4a
:END: :END:
[ Also see: [[#h:65a6a2ec-02b9-4c9e-995f-19dfe0611e20][Custom sluggification to remove diacterics or accented characters]]. ]
A common use-case for Denote is to rename files such as videos A common use-case for Denote is to rename files such as videos
downloaded from the Internet. Sometimes, those files have Unicode downloaded from the Internet. Sometimes, those files have Unicode
characters that (i) not all fonts support and (ii) create all sorts of characters that (i) not all fonts support and (ii) create all sorts of
@ -2482,7 +2484,52 @@ use the following in their Emacs configuration ([[#h:d375c6d2-92c7-425f-9d9d-219
(denote-slug-keep-only-ascii str)))) (denote-slug-keep-only-ascii str))))
(defcustom denote-file-name-slug-functions (defcustom denote-file-name-slug-functions
'((title . my-denote-sluggify-title) '((identifier . identity) ; keep the original
(title . my-denote-sluggify-title)
(signature . my-denote-sluggify-signature)
(keyword . my-denote-sluggify-keyword)))
#+end_src
*** Custom sluggification to remove diacterics or accented characters
:PROPERTIES:
:CUSTOM_ID: h:65a6a2ec-02b9-4c9e-995f-19dfe0611e20
:END:
[ Also see: [[#h:d1e4eb5b-e7f2-4a3b-9243-e1c653817a4a][Custom sluggification to remove non-ASCII characters]]. ]
For languages with diacretics, like =ê= and =ñ=, users may want to
instruct Denote to remove the diacretical marks from the underlying
characters. This way, the file names will be uniform and easier to
search through, instead of checking if, say, =être= is written thus or
as =etre=.
This is only for the sluggification of file name components ([[#h:d375c6d2-92c7-425f-9d9d-219ff47ed2a3][User-defined sluggification of file name components]]).
Any front matter will retain the diacretics.
#+begin_src emacs-lisp
;; These are the same as the default Denote sluggification functions,
;; except they remove all diacretics from the underlying characters
;; (e.g. ê becomes e while ñ becomes n).
(defun my-denote-sluggify-title (str)
(downcase
(denote-slug-hyphenate
(replace-regexp-in-string "[][{}!@#$%^&*()+'\"?,.\|;:~`‘’“”/=]*" ""
(denote-slug-remove-accents str)))))
(defun my-denote-sluggify-signature (str)
(downcase
(denote-slug-put-equals
(replace-regexp-in-string "[][{}!@#$%^&*()+'\"?,.\|;:~`‘’“”/-]*" ""
(denote-slug-remove-accents str)))))
(defun my-denote-sluggify-keyword (str)
(downcase
(replace-regexp-in-string "[][{}!@#$%^&*()+'\"?,.\|;:~`‘’“”/_ =-]*" ""
(denote-slug-remove-accents str))))
(defcustom denote-file-name-slug-functions
'((identifier . identity) ; keep the original
(title . my-denote-sluggify-title)
(signature . my-denote-sluggify-signature) (signature . my-denote-sluggify-signature)
(keyword . my-denote-sluggify-keyword))) (keyword . my-denote-sluggify-keyword)))
#+end_src #+end_src
@ -7165,8 +7212,8 @@ Denote is meant to be a collective effort. Every bit of help matters.
Purslane, Alfredo Borrás, Alp Eren Kose, André Bering, Ashton Purslane, Alfredo Borrás, Alp Eren Kose, André Bering, Ashton
Wiersdorf, Bhargav Kulkarni, Benjamin Kästner, Claudio Migliorelli, Wiersdorf, Bhargav Kulkarni, Benjamin Kästner, Claudio Migliorelli,
Claudiu Tănăselia, Colin McLear, Cosmin-Octavian C, Damien Cassou, Claudiu Tănăselia, Colin McLear, Cosmin-Octavian C, Damien Cassou,
Elias Storms, Federico Stilman, Florian, Frédéric Willem Frank Davi Ramos, Elias Storms, Federico Stilman, Florian, Frédéric Willem
Ehmsen, Glenna D., Guo Yong, Hanspeter Gisler Harold Ollivier, Frank Ehmsen, Glenna D., Guo Yong, Hanspeter Gisler Harold Ollivier,
IceAsteroid, Jack Baty, Jay Rajput, Jean-Charles Bagneris, Jeff IceAsteroid, Jack Baty, Jay Rajput, Jean-Charles Bagneris, Jeff
Valk, Jens Östlund, Jeremy Friesen, Jonathan Sahar, Johan Bolmsjö, Valk, Jens Östlund, Jeremy Friesen, Jonathan Sahar, Johan Bolmsjö,
Jonas Großekathöfer, Jousimies, Juanjo Presa, Julian Hoch, Kai von Jonas Großekathöfer, Jousimies, Juanjo Presa, Julian Hoch, Kai von
@ -7180,10 +7227,10 @@ Denote is meant to be a collective effort. Every bit of help matters.
Mealing, Wilf, Yi Liu, Ypot, 82Kang, atanasj, azegas, babusri, Mealing, Wilf, Yi Liu, Ypot, 82Kang, atanasj, azegas, babusri,
bdillahu, coherentstate, doolio, duli, drcxd, elge70, elliottw, bdillahu, coherentstate, doolio, duli, drcxd, elge70, elliottw,
fingerknight, GuutBoy, hpgisler, hyperfocus1337,johkneisl, fingerknight, GuutBoy, hpgisler, hyperfocus1337,johkneisl,
jtpavlock, juh, leafarbelm, mentalisttraceur, mjkalyan, oatmealm, jtpavlock, juh, leafarbelm, mentalisttraceur, mjkalyan, o-rxw,
potchie-maker, Pratik-Mishra-4979, pRot0ta1p, rbenit68, relict007, oatmealm, potchie-maker, Pratik-Mishra-4979, pRot0ta1p, rbenit68,
sarcom-sar, sienic, skissue, sundar bp, wuzhihao, yetanotherfossman, relict007, sarcom-sar, sienic, skissue, sundar bp, wuzhihao,
zadca123 yetanotherfossman, zadca123
Special thanks to Peter Povinec who helped refine the file-naming Special thanks to Peter Povinec who helped refine the file-naming
scheme, which is the cornerstone of this project. scheme, which is the cornerstone of this project.

View file

@ -1059,6 +1059,36 @@ This is useful as a helper function to construct
(characters (seq-filter #'characterp ascii-range))) (characters (seq-filter #'characterp ascii-range)))
(mapconcat #'string characters))) (mapconcat #'string characters)))
(defun denote-slug-remove-accents (str)
"Remove diacterics or accents from STR.
This means that something like ê becomes e while ñ becomes n."
;; Combining Diacritical Marks https://www.unicode.org/charts/PDF/U0300.pdf
(let* ((slug-trim-chars '(768 ; U+0300 COMBINING GRAVE ACCENT
769 ; U+0301 COMBINING ACUTE ACCENT
770 ; U+0302 COMBINING CIRCUMFLEX ACCENT
771 ; U+0303 COMBINING TILDE
772 ; U+0304 COMBINING MACRON
774 ; U+0306 COMBINING BREVE
775 ; U+0307 COMBINING DOT ABOVE
776 ; U+0308 COMBINING DIAERESIS
777 ; U+0309 COMBINING HOOK ABOVE
778 ; U+030A COMBINING RING ABOVE
779 ; U+030B COMBINING DOUBLE ACUTE ACCENT
780 ; U+030C COMBINING CARON
795 ; U+031B COMBINING HORN
803 ; U+0323 COMBINING DOT BELOW
804 ; U+0324 COMBINING DIAERESIS BELOW
805 ; U+0325 COMBINING RING BELOW
807 ; U+0327 COMBINING CEDILLA
813 ; U+032D COMBINING CIRCUMFLEX ACCENT BELOW
814 ; U+032E COMBINING BREVE BELOW
816 ; U+0330 COMBINING TILDE BELOW
817)) ; U+0331 COMBINING MACRON BELOW
(fn (lambda (char) (memq char slug-trim-chars)))
(chars (seq-remove fn (string-glyph-decompose str)))
(string (apply #'string chars)))
(string-glyph-compose string)))
(define-obsolete-function-alias (define-obsolete-function-alias
'denote--slug-hyphenate 'denote--slug-hyphenate
'denote-slug-hyphenate 'denote-slug-hyphenate

View file

@ -146,6 +146,11 @@ The function also account for the value of the user option
`denote-allow-multi-word-keywords'." `denote-allow-multi-word-keywords'."
(should (equal (denote-sluggify-keywords '("one !@# --- one" " two" "__ three __")) '("oneone" "two" "three")))) (should (equal (denote-sluggify-keywords '("one !@# --- one" " two" "__ three __")) '("oneone" "two" "three"))))
(ert-deftest dt-denote-slug-remove-accents ()
"Test that `denote-slug-remove-accents' removed diacretics."
(should (string= (denote-slug-remove-accents "ê") "e"))
(should (string= (denote-slug-remove-accents "ñ") "n")))
(ert-deftest dt-denote--file-empty-p () (ert-deftest dt-denote--file-empty-p ()
"Test that `denote--file-empty-p' returns non-nil on empty file." "Test that `denote--file-empty-p' returns non-nil on empty file."
(let ((file (make-temp-file "denote-test"))) (let ((file (make-temp-file "denote-test")))