pkg update and first config fix
org-brain not working, add org-roam
This commit is contained in:
@@ -94,10 +94,26 @@
|
||||
:group 'org)
|
||||
|
||||
|
||||
(defcustom org-ref-activate-glossary-links t
|
||||
"If non-nil activate acronym and glossary links.
|
||||
Checks in `org-ref-glossary-face-fn' and `org-ref-acronym-face-fn'.
|
||||
This is not always fast, so we provide a way to disable it."
|
||||
:type 'boolean
|
||||
:group 'org-ref-glossary)
|
||||
|
||||
|
||||
(defvar org-ref-glsentries '()
|
||||
"Variable to hold locations of glsentries load files.")
|
||||
|
||||
|
||||
(defvar-local org-ref-glossary-cache nil
|
||||
"Buffer-local variable for glossary entry cache.")
|
||||
|
||||
|
||||
(defvar-local org-ref-acronym-cache nil
|
||||
"Buffer-local variable for acronym entry cache.")
|
||||
|
||||
|
||||
(defun or-find-closing-curly-bracket (&optional limit)
|
||||
"Find closing bracket for the bracket at point and move point to it.
|
||||
Go up to LIMIT or `point-max'. This is a parsing function. I
|
||||
@@ -122,107 +138,127 @@ there is an escaped \" for example. This seems pretty robust."
|
||||
;;* Glossary
|
||||
(defun or-parse-glossary-entry (entry)
|
||||
"Parse a LaTeX glossary ENTRY definition to a p-list of key=value.
|
||||
Typically:
|
||||
(:name name :description description)
|
||||
but there could be other :key value pairs."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let* (end-of-entry
|
||||
data
|
||||
(external (when (re-search-forward "\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t)
|
||||
(match-string 1)))
|
||||
(glsentries (and external
|
||||
(or (cdr (assoc external org-ref-glsentries))
|
||||
(progn
|
||||
(cl-pushnew (cons external (s-trim (shell-command-to-string
|
||||
(format "kpsewhich tex %s" external))))
|
||||
org-ref-glsentries)
|
||||
(cdr (assoc external org-ref-glsentries))))))
|
||||
key value p1 p2)
|
||||
(catch 'data
|
||||
;; look inside first for latex-headers
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward
|
||||
(format "\\newglossaryentry{%s}" entry) nil t)
|
||||
(re-search-forward "{")
|
||||
(save-excursion
|
||||
(backward-char)
|
||||
(or-find-closing-curly-bracket)
|
||||
(setq end-of-entry (point)))
|
||||
ENTRY is the label we are looking for.
|
||||
Typically returns (:name name :description description)
|
||||
but there could be other :key value pairs.
|
||||
|
||||
(while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
|
||||
(setq key (match-string 1))
|
||||
;; get value
|
||||
(goto-char (+ 1 (match-end 1)))
|
||||
(setq p1 (point))
|
||||
(if (looking-at "{")
|
||||
;; value is wrapped in {}
|
||||
(progn
|
||||
(or-find-closing-curly-bracket)
|
||||
(setq p2 (point)
|
||||
value (buffer-substring (+ 1 p1) p2)))
|
||||
;; value is up to the next comma
|
||||
(re-search-forward "," end-of-entry 'mv)
|
||||
(setq value (buffer-substring p1 (- (point) 1))))
|
||||
;; remove #+latex_header_extra:
|
||||
(setq value (replace-regexp-in-string
|
||||
"#\\+latex_header_extra: " "" value))
|
||||
(setq value (replace-regexp-in-string
|
||||
"\n +" " " value))
|
||||
(setq data (append data
|
||||
(list :label entry)
|
||||
(list (intern (format ":%s" key)))
|
||||
(list value))))
|
||||
(throw 'data data))
|
||||
This is a source of performance loss, because this is search
|
||||
based and it is done on each fontification. It is easy to cache
|
||||
the results, but not easy to invalidate them, e.g. to reflect
|
||||
changes."
|
||||
(if (and org-ref-glossary-cache (gethash entry org-ref-glossary-cache))
|
||||
;; We have the cache, and an entry and use it
|
||||
(gethash entry org-ref-glossary-cache)
|
||||
;; We don't have a cache, or an entry in it, so we find it.
|
||||
;; No cache? we make one
|
||||
(unless org-ref-glossary-cache
|
||||
(setq-local org-ref-glossary-cache (make-hash-table)))
|
||||
|
||||
;; check for a glossary table
|
||||
(let* ((entries (save-excursion
|
||||
(catch 'found
|
||||
(org-element-map
|
||||
(org-element-parse-buffer)
|
||||
'table
|
||||
(lambda (el)
|
||||
(when (string= "glossary" (org-element-property :name el))
|
||||
(goto-char (org-element-property :contents-begin el))
|
||||
(throw 'found
|
||||
(nthcdr 2 (org-babel-read-table)))))))))
|
||||
(result (assoc entry entries)))
|
||||
(when result
|
||||
(throw 'data (list :label entry :name (cl-second result) :description (cl-third result)))))
|
||||
;; Now we search to get the data
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let* (end-of-entry
|
||||
data
|
||||
(external (when (re-search-forward
|
||||
"\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t)
|
||||
(match-string 1)))
|
||||
(glsentries (and external
|
||||
(or (cdr (assoc external org-ref-glsentries))
|
||||
(progn
|
||||
(cl-pushnew (cons external (s-trim
|
||||
(shell-command-to-string
|
||||
(format "kpsewhich tex %s"
|
||||
external))))
|
||||
org-ref-glsentries)
|
||||
(cdr (assoc external org-ref-glsentries))))))
|
||||
key value p1 p2)
|
||||
(setq data
|
||||
(catch 'data
|
||||
;; look inside first for latex-headers
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward
|
||||
(format "\\newglossaryentry{%s}" entry) nil t)
|
||||
(re-search-forward "{")
|
||||
(save-excursion
|
||||
(backward-char)
|
||||
(or-find-closing-curly-bracket)
|
||||
(setq end-of-entry (point)))
|
||||
|
||||
;; then external
|
||||
(when (and glsentries
|
||||
(file-exists-p glsentries))
|
||||
(while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
|
||||
(setq key (match-string 1))
|
||||
;; get value
|
||||
(goto-char (+ 1 (match-end 1)))
|
||||
(setq p1 (point))
|
||||
(if (looking-at "{")
|
||||
;; value is wrapped in {}
|
||||
(progn
|
||||
(or-find-closing-curly-bracket)
|
||||
(setq p2 (point)
|
||||
value (buffer-substring (+ 1 p1) p2)))
|
||||
;; value is up to the next comma
|
||||
(re-search-forward "," end-of-entry 'mv)
|
||||
(setq value (buffer-substring p1 (- (point) 1))))
|
||||
;; remove #+latex_header_extra:
|
||||
(setq value (replace-regexp-in-string
|
||||
"#\\+latex_header_extra: " "" value))
|
||||
(setq value (replace-regexp-in-string
|
||||
"\n +" " " value))
|
||||
(setq data (append data
|
||||
(list :label entry)
|
||||
(list (intern (format ":%s" key)))
|
||||
(list value))))
|
||||
(throw 'data data))
|
||||
|
||||
(with-current-buffer (find-file-noselect glsentries)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward
|
||||
(format "\\newglossaryentry{%s}" entry) nil t)
|
||||
(re-search-forward "{")
|
||||
(save-excursion
|
||||
(backward-char)
|
||||
(or-find-closing-curly-bracket)
|
||||
(setq end-of-entry (point)))
|
||||
;; check for a glossary table
|
||||
(let* ((entries (save-excursion
|
||||
(catch 'found
|
||||
(org-element-map
|
||||
(org-element-parse-buffer)
|
||||
'table
|
||||
(lambda (el)
|
||||
(when (string= "glossary" (org-element-property :name el))
|
||||
(goto-char (org-element-property :contents-begin el))
|
||||
(throw 'found
|
||||
(nthcdr 2 (org-babel-read-table)))))))))
|
||||
(result (assoc entry entries)))
|
||||
(when result
|
||||
(throw 'data (list :label entry :name (cl-second result) :description (cl-third result)))))
|
||||
|
||||
(while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
|
||||
(setq key (match-string 1))
|
||||
;; get value
|
||||
(goto-char (+ 1 (match-end 1)))
|
||||
(setq p1 (point))
|
||||
(if (looking-at "{")
|
||||
;; value is wrapped in {}
|
||||
(progn
|
||||
(or-find-closing-curly-bracket)
|
||||
(setq p2 (point)
|
||||
value (buffer-substring (+ 1 p1) p2)))
|
||||
;; value is up to the next comma
|
||||
(re-search-forward "," end-of-entry 'mv)
|
||||
(setq value (buffer-substring p1 (- (point) 1))))
|
||||
(setq data (append data
|
||||
(list :label entry)
|
||||
(list (intern (format ":%s" key)))
|
||||
(list value))))
|
||||
(throw 'data data))))))))
|
||||
;; then external
|
||||
(when (and glsentries
|
||||
(file-exists-p glsentries))
|
||||
|
||||
(with-current-buffer (find-file-noselect glsentries)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward
|
||||
(format "\\newglossaryentry{%s}" entry) nil t)
|
||||
(re-search-forward "{")
|
||||
(save-excursion
|
||||
(backward-char)
|
||||
(or-find-closing-curly-bracket)
|
||||
(setq end-of-entry (point)))
|
||||
|
||||
(while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
|
||||
(setq key (match-string 1))
|
||||
;; get value
|
||||
(goto-char (+ 1 (match-end 1)))
|
||||
(setq p1 (point))
|
||||
(if (looking-at "{")
|
||||
;; value is wrapped in {}
|
||||
(progn
|
||||
(or-find-closing-curly-bracket)
|
||||
(setq p2 (point)
|
||||
value (buffer-substring (+ 1 p1) p2)))
|
||||
;; value is up to the next comma
|
||||
(re-search-forward "," end-of-entry 'mv)
|
||||
(setq value (buffer-substring p1 (- (point) 1))))
|
||||
(setq data (append data
|
||||
(list :label entry)
|
||||
(list (intern (format ":%s" key)))
|
||||
(list value))))
|
||||
(throw 'data data))))))
|
||||
(puthash entry data org-ref-glossary-cache)
|
||||
data))))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
@@ -251,12 +287,14 @@ manually add them to the glossary table."
|
||||
|
||||
(defun org-ref-glossary-face-fn (label)
|
||||
"Return a face for a glossary link."
|
||||
(save-match-data
|
||||
(cond
|
||||
((or-parse-glossary-entry label)
|
||||
'org-ref-glossary-face)
|
||||
(t
|
||||
'font-lock-warning-face))))
|
||||
(if org-ref-activate-glossary-links
|
||||
(save-match-data
|
||||
(cond
|
||||
((or-parse-glossary-entry label)
|
||||
'org-ref-glossary-face)
|
||||
(t
|
||||
'font-lock-warning-face)))
|
||||
'org-ref-glossary-face))
|
||||
|
||||
|
||||
;;** Glossary links
|
||||
@@ -371,31 +409,33 @@ names are arbitrary, but three columns are expected, and the
|
||||
hline is expected.
|
||||
|
||||
This is intended to be run in `org-export-before-parsing-hook'."
|
||||
(let* (begin
|
||||
end
|
||||
(entries (save-excursion
|
||||
(catch 'found
|
||||
(org-element-map
|
||||
(org-element-parse-buffer)
|
||||
'table
|
||||
(lambda (el)
|
||||
(when (and (org-element-property :name el)
|
||||
(stringp (org-element-property :name el))
|
||||
(string= "glossary" (org-element-property :name el)))
|
||||
(setq begin (org-element-property :begin el)
|
||||
end (org-element-property :end el))
|
||||
(goto-char (org-element-property :contents-begin el))
|
||||
(throw 'found
|
||||
(nthcdr 2 (org-babel-read-table))))))))))
|
||||
;; Delete the table
|
||||
(when entries
|
||||
(setf (buffer-substring begin end) "")
|
||||
(save-restriction
|
||||
(widen)
|
||||
(let* (begin
|
||||
end
|
||||
(entries (save-excursion
|
||||
(catch 'found
|
||||
(org-element-map
|
||||
(org-element-parse-buffer)
|
||||
'table
|
||||
(lambda (el)
|
||||
(when (and (org-element-property :name el)
|
||||
(stringp (org-element-property :name el))
|
||||
(string= "glossary" (org-element-property :name el)))
|
||||
(setq begin (org-element-property :begin el)
|
||||
end (org-element-property :end el))
|
||||
(goto-char (org-element-property :contents-begin el))
|
||||
(throw 'found
|
||||
(nthcdr 2 (org-babel-read-table))))))))))
|
||||
;; Delete the table
|
||||
(when entries
|
||||
(setf (buffer-substring begin end) "")
|
||||
|
||||
(goto-char (point-min))
|
||||
(cl-loop for (label name description) in entries
|
||||
do
|
||||
(insert (format "#+latex_header_extra: \\newglossaryentry{%s}{name=%s,description={{%s}}}\n"
|
||||
label name description))))))
|
||||
(goto-char (point-min))
|
||||
(cl-loop for (label name description) in entries
|
||||
do
|
||||
(insert (format "#+latex_header_extra: \\newglossaryentry{%s}{name=%s,description={{%s}}}\n"
|
||||
label name description)))))))
|
||||
|
||||
|
||||
;;* Acronyms
|
||||
@@ -422,65 +462,85 @@ them manually to the acroynms table."
|
||||
|
||||
(defun or-parse-acronym-entry (label)
|
||||
"Parse an acronym entry LABEL to a plist.
|
||||
(:abbrv abbrv :full full :label label)
|
||||
Returns (:abbrv abbrv :full full :label label)
|
||||
The plist maps to \newacronym{<label>}{<abbrv>}{<full>}"
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let* (abbrv
|
||||
full p1
|
||||
(external (when (re-search-forward "\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t)
|
||||
(match-string 1)))
|
||||
(glsentries (and external
|
||||
(or (cdr (assoc external org-ref-glsentries))
|
||||
(progn
|
||||
(cl-pushnew (cons external
|
||||
(s-trim (shell-command-to-string
|
||||
(format "kpsewhich tex %s" external))))
|
||||
org-ref-glsentries)
|
||||
(cdr (assoc external org-ref-glsentries)))))))
|
||||
(catch 'data
|
||||
(goto-char (point-min))
|
||||
;; check in the definitions of newacronym
|
||||
(when (re-search-forward (format "\\newacronym{%s}" label) nil t)
|
||||
(setq p1 (+ 1 (point)))
|
||||
(forward-list)
|
||||
(setq abbrv (buffer-substring p1 (- (point) 1)))
|
||||
(setq p1 (+ 1 (point)))
|
||||
(forward-list)
|
||||
(setq full (buffer-substring p1 (- (point) 1)))
|
||||
(throw 'data
|
||||
(list :label label :abbrv abbrv :full full)))
|
||||
(if (and org-ref-acronym-cache (gethash label org-ref-acronym-cache))
|
||||
;; We have the cache, and an entry and use it
|
||||
(gethash label org-ref-acronym-cache)
|
||||
;; We don't have a cache, or an label in it, so we find it.
|
||||
;; No cache? we make one
|
||||
(unless org-ref-acronym-cache
|
||||
(setq-local org-ref-acronym-cache (make-hash-table)))
|
||||
|
||||
;; look for acronyms table
|
||||
(let* ((entries (save-excursion
|
||||
(catch 'found
|
||||
(org-element-map
|
||||
(org-element-parse-buffer)
|
||||
'table
|
||||
(lambda (el)
|
||||
(when (string= "acronyms" (org-element-property :name el))
|
||||
(goto-char (org-element-property :contents-begin el))
|
||||
(throw 'found
|
||||
(nthcdr 2 (org-babel-read-table)))))))))
|
||||
(result (assoc label entries)))
|
||||
(when result
|
||||
(throw 'data (list :label label
|
||||
:abbrv (cl-second result) :full (cl-third result)))))
|
||||
;; Now search for the data
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let* (abbrv
|
||||
full p1
|
||||
(external (when (re-search-forward "\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t)
|
||||
(match-string 1)))
|
||||
(glsentries (and external
|
||||
(or (cdr (assoc external org-ref-glsentries))
|
||||
(progn
|
||||
(cl-pushnew (cons external
|
||||
(s-trim (shell-command-to-string
|
||||
(format "kpsewhich tex %s" external))))
|
||||
org-ref-glsentries)
|
||||
(cdr (assoc external org-ref-glsentries))))))
|
||||
data)
|
||||
(setq data
|
||||
(catch 'data
|
||||
(goto-char (point-min))
|
||||
;; check in the definitions of newacronym
|
||||
(when (re-search-forward (format "\\newacronym{%s}" label) nil t)
|
||||
(setq p1 (+ 1 (point)))
|
||||
(forward-list)
|
||||
(setq abbrv (buffer-substring p1 (- (point) 1)))
|
||||
(setq p1 (+ 1 (point)))
|
||||
(forward-list)
|
||||
(setq full (buffer-substring p1 (- (point) 1)))
|
||||
(throw 'data
|
||||
(list :label label :abbrv abbrv :full full)))
|
||||
|
||||
;; look external
|
||||
(when (and glsentries
|
||||
(file-exists-p glsentries))
|
||||
(with-current-buffer (find-file-noselect glsentries)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward (format "\\newacronym{%s}" label) nil t)
|
||||
(setq p1 (+ 1 (point)))
|
||||
(forward-list)
|
||||
(setq abbrv (buffer-substring p1 (- (point) 1)))
|
||||
(setq p1 (+ 1 (point)))
|
||||
(forward-list)
|
||||
(setq full (buffer-substring p1 (- (point) 1)))
|
||||
(throw 'data
|
||||
(list :label label :abbrv abbrv :full full )))))))))
|
||||
;; look for acronyms table
|
||||
(let* ((entries (save-excursion
|
||||
(catch 'found
|
||||
(org-element-map
|
||||
(org-element-parse-buffer)
|
||||
'table
|
||||
(lambda (el)
|
||||
(when (string= "acronyms" (org-element-property :name el))
|
||||
(goto-char (org-element-property :contents-begin el))
|
||||
(throw 'found
|
||||
(nthcdr 2 (org-babel-read-table)))))))))
|
||||
(result (assoc label entries)))
|
||||
(when result
|
||||
(throw 'data (list :label label
|
||||
:abbrv (cl-second result) :full (cl-third result)))))
|
||||
|
||||
;; look external
|
||||
(when (and glsentries
|
||||
(file-exists-p glsentries))
|
||||
(with-current-buffer (find-file-noselect glsentries)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward (format "\\newacronym{%s}" label) nil t)
|
||||
(setq p1 (+ 1 (point)))
|
||||
(forward-list)
|
||||
(setq abbrv (buffer-substring p1 (- (point) 1)))
|
||||
(setq p1 (+ 1 (point)))
|
||||
(forward-list)
|
||||
(setq full (buffer-substring p1 (- (point) 1)))
|
||||
(throw 'data
|
||||
(list :label label :abbrv abbrv :full full )))))))
|
||||
(puthash label data org-ref-acronym-cache)
|
||||
data))))
|
||||
|
||||
|
||||
(defun org-ref-glossary-invalidate-caches ()
|
||||
"Function to invalidate the caches."
|
||||
(interactive)
|
||||
(setq-local org-ref-acronym-cache (make-hash-table))
|
||||
(setq-local org-ref-glossary-cache (make-hash-table)))
|
||||
|
||||
;;** Acronym links
|
||||
(defun or-follow-acronym (label)
|
||||
@@ -520,7 +580,7 @@ The plist maps to \newacronym{<label>}{<abbrv>}{<full>}"
|
||||
("Acrfull" "Capitalized both the acronym and its definition")
|
||||
("Acrfullpl" "Capitalized both the acronym and its definition in plural")
|
||||
("ACRfull" "Both the acronym and its definition in ALL-CAPS")
|
||||
("ACRfullpl" "Both the acronym and its definition in plurall ALL-CAPS"))
|
||||
("ACRfullpl" "Both the acronym and its definition in plural ALL-CAPS"))
|
||||
"list of acronym types (type description)")
|
||||
|
||||
|
||||
@@ -545,12 +605,14 @@ The plist maps to \newacronym{<label>}{<abbrv>}{<full>}"
|
||||
|
||||
(defun org-ref-acronym-face-fn (label)
|
||||
"Return a face for an acronym link."
|
||||
(save-match-data
|
||||
(cond
|
||||
((or-parse-acronym-entry label)
|
||||
'org-ref-acronym-face)
|
||||
(t
|
||||
'font-lock-warning-face))))
|
||||
(if org-ref-activate-glossary-links
|
||||
(save-match-data
|
||||
(cond
|
||||
((or-parse-acronym-entry label)
|
||||
'org-ref-acronym-face)
|
||||
(t
|
||||
'font-lock-warning-face)))
|
||||
'org-ref-acronym-face))
|
||||
|
||||
|
||||
(defun or-acronym-tooltip (_window _object position)
|
||||
@@ -586,31 +648,33 @@ This assumes a table like
|
||||
is in the org-buffer, and will add the relevant latex_header items if there is. The table is deleted in a copy of the buffer before the export.
|
||||
|
||||
This will run in `org-export-before-parsing-hook'."
|
||||
(let* (begin
|
||||
end
|
||||
(entries (save-excursion
|
||||
(catch 'found
|
||||
(org-element-map
|
||||
(org-element-parse-buffer)
|
||||
'table
|
||||
(lambda (el)
|
||||
(when (and (org-element-property :name el)
|
||||
(stringp (org-element-property :name el))
|
||||
(string= "acronyms" (org-element-property :name el)))
|
||||
(setq begin (org-element-property :begin el)
|
||||
end (org-element-property :end el))
|
||||
(goto-char (org-element-property :contents-begin el))
|
||||
(throw 'found
|
||||
(nthcdr 2 (org-babel-read-table))))))))))
|
||||
(when entries
|
||||
;; Delete the table
|
||||
(setf (buffer-substring begin end) "")
|
||||
(save-restriction
|
||||
(widen)
|
||||
(let* (begin
|
||||
end
|
||||
(entries (save-excursion
|
||||
(catch 'found
|
||||
(org-element-map
|
||||
(org-element-parse-buffer)
|
||||
'table
|
||||
(lambda (el)
|
||||
(when (and (org-element-property :name el)
|
||||
(stringp (org-element-property :name el))
|
||||
(string= "acronyms" (org-element-property :name el)))
|
||||
(setq begin (org-element-property :begin el)
|
||||
end (org-element-property :end el))
|
||||
(goto-char (org-element-property :contents-begin el))
|
||||
(throw 'found
|
||||
(nthcdr 2 (org-babel-read-table))))))))))
|
||||
(when entries
|
||||
;; Delete the table
|
||||
(setf (buffer-substring begin end) "")
|
||||
|
||||
(goto-char (point-min))
|
||||
(cl-loop for (label name description) in entries
|
||||
do
|
||||
(insert (format "#+latex_header_extra: \\newacronym{%s}{%s}{%s}\n"
|
||||
label name description))))))
|
||||
(goto-char (point-min))
|
||||
(cl-loop for (label name description) in entries
|
||||
do
|
||||
(insert (format "#+latex_header_extra: \\newacronym{%s}{%s}{%s}\n"
|
||||
label name description)))))))
|
||||
|
||||
|
||||
;; * Interactive command to insert acroynm/glossary links
|
||||
@@ -794,7 +858,7 @@ This will run in `org-export-before-parsing-hook'."
|
||||
("acrfull" (format "%s (%s)"
|
||||
(plist-get entry :full)
|
||||
(plist-get entry :abbrv)))
|
||||
("acrfullpl" (format "%s (%s)s"
|
||||
("acrfullpl" (format "%ss (%ss)"
|
||||
(plist-get entry :full)
|
||||
(plist-get entry :abbrv)))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user