dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

denote-rename-buffer.el (6889B)


      1 ;;; denote-rename-buffer.el --- Rename Denote buffers to be shorter and easier to read -*- lexical-binding: t -*-
      2 
      3 ;; Copyright (C) 2023-2024  Free Software Foundation, Inc.
      4 
      5 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
      6 ;; Maintainer: Protesilaos Stavrou <info@protesilaos.com>
      7 ;; URL: https://github.com/protesilaos/denote
      8 
      9 ;; This file is NOT part of GNU Emacs.
     10 
     11 ;; This program is free software; you can redistribute it and/or modify
     12 ;; it under the terms of the GNU General Public License as published by
     13 ;; the Free Software Foundation, either version 3 of the License, or
     14 ;; (at your option) any later version.
     15 ;;
     16 ;; This program is distributed in the hope that it will be useful,
     17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19 ;; GNU General Public License for more details.
     20 ;;
     21 ;; You should have received a copy of the GNU General Public License
     22 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
     23 
     24 ;;; Commentary:
     25 ;;
     26 ;; Rename Denote buffers to be shorter and easier to read.  Enable
     27 ;; `denote-rename-buffer-mode' to automatically rename the buffer of a
     28 ;; Denote file.  The renaming function is specified in the user option
     29 ;; `denote-rename-buffer-function'.
     30 
     31 ;;; Code:
     32 
     33 (require 'denote)
     34 
     35 (defgroup denote-rename-buffer nil
     36   "Rename Denote buffers to be shorter and easier to read."
     37   :group 'denote
     38   :link '(info-link "(denote) Top")
     39   :link '(url-link :tag "Homepage" "https://protesilaos.com/emacs/denote"))
     40 
     41 (defcustom denote-rename-buffer-format "%t"
     42   "The format of the buffer name `denote-rename-buffer' should use.
     43 Thie value is a string that treats specially the following
     44 specifiers:
     45 
     46 - The %t is the Denote TITLE of the file.
     47 - The %i is the Denote IDENTIFIER of the file.
     48 - The %d is the same as %i (DATE mnemonic).
     49 - The %s is the Denote SIGNATURE of the file.
     50 - The %k is the Denote KEYWORDS of the file.
     51 - The %% is a literal percent sign.
     52 
     53 In addition, the following flags are available for each of the specifiers:
     54 
     55 - 0 :: Pad to the width, if given, with zeros instead of spaces.
     56 - - :: Pad to the width, if given, on the right instead of the left.
     57 - < :: Truncate to the width and precision, if given, on the left.
     58 - > :: Truncate to the width and precision, if given, on the right.
     59 - ^ :: Convert to upper case.
     60 - _ :: Convert to lower case.
     61 
     62 When combined all together, the above are written thus:
     63 
     64     %<flags><width><precision>SPECIFIER-CHARACTER
     65 
     66 Any other string it taken as-is.  Users may want, for example, to
     67 include some text that makes Denote buffers stand out, such as
     68 a [D] prefix."
     69   :type 'string
     70   :package-version '(denote . "2.1.0")
     71   :group 'denote-rename-buffer)
     72 
     73 (defcustom denote-rename-buffer-function #'denote-rename-buffer
     74   "Symbol of function that is called to rename the Denote file buffer.
     75 The default `denote-rename-buffer' function uses the pattern
     76 described in `denote-rename-buffer-format'.
     77 
     78 Users can set this variable to an arbitrary function that does
     79 something else.  The function is called without arguments from
     80 the `find-file-hook' and `denote-after-new-note-hook'.
     81 
     82 A nil value for this variable means that the title of the Denote
     83 buffer will be used, if available."
     84   :type '(choice
     85           (const :tag "Rename using the `denote-rename-buffer-format'" denote-rename-buffer)
     86           (function :tag "Use a custom renaming function"))
     87   :package-version '(denote . "2.1.0")
     88   :group 'denote-rename-buffer)
     89 
     90 (defun denote-rename-buffer--format (buffer)
     91   "Parse the BUFFER through the `denote-rename-buffer-format'."
     92   (when-let ((file (buffer-file-name buffer))
     93              (type (denote-filetype-heuristics file)))
     94     (string-trim
     95      (format-spec denote-rename-buffer-format
     96                   (list (cons ?t (cond
     97                                   ((denote-retrieve-front-matter-title-value file type))
     98                                   ((denote-retrieve-filename-title file))
     99                                   (t  "")))
    100                         (cons ?i (or (denote-retrieve-filename-identifier file) ""))
    101                         (cons ?d (or (denote-retrieve-filename-identifier file) ""))
    102                         (cons ?s (or (denote-retrieve-filename-signature file) ""))
    103                         (cons ?k (if-let ((kws (denote-retrieve-front-matter-keywords-value file type)))
    104                                      (denote-keywords-combine kws)
    105                                    (or (denote-retrieve-filename-keywords file) "")))
    106                         (cons ?% "%"))
    107                   'delete))))
    108 
    109 (defun denote-rename-buffer (&optional buffer)
    110   "Rename current buffer or optional BUFFER with `denote-rename-buffer-format'.
    111 The symbol of this function is the default value of the user
    112 option `denote-rename-buffer-function' and is thus used by the
    113 `denote-rename-buffer-mode'."
    114   (when-let ((file (buffer-file-name buffer))
    115              ((denote-file-has-identifier-p file))
    116              (new-name (denote-rename-buffer--format (or buffer (current-buffer))))
    117              ((not (string-blank-p new-name))))
    118     (rename-buffer new-name :unique)))
    119 
    120 (make-obsolete
    121  'denote-rename-buffer-with-title
    122  'denote-rename-buffer
    123  "2.1.0")
    124 
    125 (make-obsolete
    126  'denote-rename-buffer-with-identifier
    127  'denote-rename-buffer
    128  "2.1.0")
    129 
    130 (defun denote-rename-buffer--fallback (&optional buffer)
    131   "Fallback to rename BUFFER or `current-buffer'.
    132 This is called if `denote-rename-buffer-rename-function' is nil."
    133   (let ((denote-rename-buffer-format "%t"))
    134     (denote-rename-buffer buffer)))
    135 
    136 (defun denote-rename-buffer-rename-function-or-fallback ()
    137   "Call `denote-rename-buffer-function' or its fallback to rename with title.
    138 Add this to `find-file-hook' and `denote-after-new-note-hook'."
    139   (funcall (or denote-rename-buffer-function #'denote-rename-buffer--fallback)))
    140 
    141 ;;;###autoload
    142 (define-minor-mode denote-rename-buffer-mode
    143   "Automatically rename Denote buffers to be easier to read.
    144 A buffer is renamed upon visiting the underlying file.  This
    145 means that existing buffers are not renamed until they are
    146 visited again in a new buffer (files are visited with the command
    147 `find-file' or related)."
    148   :global t
    149   (if denote-rename-buffer-mode
    150       (progn
    151         (add-hook 'denote-after-new-note-hook #'denote-rename-buffer-rename-function-or-fallback)
    152         (add-hook 'denote-after-rename-file-hook #'denote-rename-buffer-rename-function-or-fallback)
    153         (add-hook 'find-file-hook #'denote-rename-buffer-rename-function-or-fallback))
    154     (remove-hook 'denote-after-new-note-hook #'denote-rename-buffer-rename-function-or-fallback)
    155     (remove-hook 'denote-after-rename-file-hook #'denote-rename-buffer-rename-function-or-fallback)
    156     (remove-hook 'find-file-hook #'denote-rename-buffer-rename-function-or-fallback)))
    157 
    158 (provide 'denote-rename-buffer)
    159 ;;; denote-rename-buffer.el ends here