branch: elpa/annotate commit fdf41ed93a31386a8b4fddaf01f15ee256e2f91f Merge: 7b1c5aa531 65338aff67 Author: cage2 <1257703+ca...@users.noreply.github.com> Commit: GitHub <nore...@github.com>
Merge pull request #169 from cage2/master Added annotation's text expansion feature --- Changelog | 9 +++++++++ NEWS.org | 8 ++++++++ README.org | 13 +++++++++++++ annotate.el | 41 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/Changelog b/Changelog index d7f4f7d05e..a471f96bcf 100644 --- a/Changelog +++ b/Changelog @@ -1,10 +1,19 @@ +2025-03-20 cage + + Merge pull request #168 from cage2/optimize-searching-for-annotations + 2025-03-19 cage + * Changelog, + * NEWS.org, * annotate.el: - optimized 'annotate-annotations-overlay-in-range' by jumping from an annotation to another, instead of scanning every single character of the buffer. + - increased version number; + - updated NEWS file and changelog; + - fixed docstring. 2025-03-06 cage diff --git a/NEWS.org b/NEWS.org index 95ea04b051..daa4ad8b37 100644 --- a/NEWS.org +++ b/NEWS.org @@ -1,3 +1,11 @@ +- 2025-04-23 v2.4.0 cage :: + + This version adds annotation's text expansion feature: + + #+BEGIN_SRC text + "%d foo" → "2025-04-23 foo" + #+END_SRC + - 2025-03-05 v2.3.1 cage :: This version optimizes a function that searches for annotations in a buffer; this changes should speed up commands like ~annotate-toggle-all-annotations-text~. diff --git a/README.org b/README.org index 5a36f2574f..036c875cbd 100644 --- a/README.org +++ b/README.org @@ -221,6 +221,19 @@ Shows or hides the annotation's text in the whole buffer. ** annotate-autosave Whether annotations should be saved after each user action, e.g. new annotation created, existing one amended or deleted. Boolean value, default is ~nil~ i.e. do not perform autosave and update the annotations in a buffer, just after killing buffer or quitting Emacs. +** annotate-annotation-expansion-map + +The expansion map for the annotation text. If a substring in the annotation text matches the string in the first item of each element of this list, it will be expanded with the results of passing the second item — as a command — to a system shell, if the third item is not null, the output string of the command's results will be trimmed (spaces or some others non printable characters will be removed from both ends, see: `string-trim'). Example below. + +The expression: + +#+BEGIN_SRC lisp + (setf annotate-annotation-expansion-map + '((\"%d\" \"date +%Y-%m-%d\" t))) +#+END_SRC + +Will expand any occurrence of \"%d\" in the annotation's text with the current date (format: \"YYYY-MM-DD\"), moreover the results will be trimmed. + * More documentation Please check ~M-x customize-group RET annotate~ as there is extensive documentation for each customizable variable. diff --git a/annotate.el b/annotate.el index b666ae1533..fbaa32b382 100644 --- a/annotate.el +++ b/annotate.el @@ -7,7 +7,7 @@ ;; Maintainer: Bastian Bechtold <bastibe....@mailbox.org>, cage <cage-...@twistfold.it> ;; URL: https://github.com/bastibe/annotate.el ;; Created: 2015-06-10 -;; Version: 2.3.1 +;; Version: 2.4.0 ;; This file is NOT part of GNU Emacs. @@ -58,7 +58,7 @@ ;;;###autoload (defgroup annotate nil "Annotate files without changing them." - :version "2.3.1" + :version "2.4.0" :group 'text) (defvar annotate-mode-map @@ -251,11 +251,22 @@ of lines. The center of the region is the position of the annotation as defined in the database." :type 'number) -(defcustom annotate-autosave nil +(defcustom annotate-autosave t "Whether annotations should be saved after each user action, e.g. new annotation created, existing one amended or deleted." :type 'boolean) +(defcustom annotate-annotation-expansion-map '() + "The expansion map for the annotation text. If a substring in the annotation text matches the string in the first item of each element of this list, it is expanded with the results of passing the second item — as a command — to a system shell, if the third item is not null, the output string of the command's results are trimmed (spaces or some others non printable characters are removed from both ends, see: `string-trim'). Example below. + +The expression: + +(setf annotate-annotation-expansion-map + '((\"%d\" \"date +%Y-%m-%d\" t))) + +Will expand any occurrence of \"%d\" in the annotation's text with the current date (format: \"YYYY-MM-DD\"), moreover the results will be trimmed" + :type '(repeat (list string string boolean))) + (defconst annotate-prop-chain-position 'position) @@ -727,6 +738,27 @@ specified by `FROM' and `TO'." (cl-count-if (lambda (a) (char-equal a ?\n)) (buffer-substring-no-properties from to))) +(defun annotate--expand-annotation-text (annotation-text) + (cl-flet ((regex (expansion-item) + (cl-first expansion-item)) + (trimp (expansion-item) + (cl-third expansion-item)) + (command (expansion-item) + (cl-second expansion-item))) + (cl-loop with results = annotation-text + for expansion in annotate-annotation-expansion-map + when (string-match-p (regex expansion) results) + do (let ((expansion-results (shell-command-to-string (command expansion)))) + (when (trimp expansion) + (setf expansion-results (string-trim expansion-results))) + (setf results + (replace-regexp-in-string (regex expansion) + expansion-results + results + t + t))) + finally (return results)))) + (defun annotate-annotate (&optional color-index) "Create, modify, or delete annotation. if `COLOR-INDEX' is not null must be an index that adresses an element both in @@ -741,7 +773,8 @@ and ;; create a new annotation in the region returned by `annotate-bound' (cl-destructuring-bind (start end) (annotate-bounds) - (let ((annotation-text (read-from-minibuffer annotate-annotation-prompt))) + (let* ((raw-text (read-from-minibuffer annotate-annotation-prompt)) + (annotation-text (annotate--expand-annotation-text raw-text))) (condition-case nil (annotate-create-annotation start end annotation-text nil color-index) (annotate-no-new-line-at-end-file-error