summaryrefslogtreecommitdiff
path: root/lisp/textmodes
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/textmodes')
-rw-r--r--lisp/textmodes/artist.el144
-rw-r--r--lisp/textmodes/bibtex.el91
-rw-r--r--lisp/textmodes/css-mode.el109
-rw-r--r--lisp/textmodes/dns-mode.el6
-rw-r--r--lisp/textmodes/emacs-news-mode.el269
-rw-r--r--lisp/textmodes/enriched.el24
-rw-r--r--lisp/textmodes/etc-authors-mode.el10
-rw-r--r--lisp/textmodes/fill.el150
-rw-r--r--lisp/textmodes/flyspell.el17
-rw-r--r--lisp/textmodes/glyphless-mode.el68
-rw-r--r--lisp/textmodes/ispell.el149
-rw-r--r--lisp/textmodes/page-ext.el15
-rw-r--r--lisp/textmodes/page.el17
-rw-r--r--lisp/textmodes/paragraphs.el90
-rw-r--r--lisp/textmodes/pixel-fill.el240
-rw-r--r--lisp/textmodes/reftex-cite.el6
-rw-r--r--lisp/textmodes/reftex-global.el10
-rw-r--r--lisp/textmodes/reftex-index.el15
-rw-r--r--lisp/textmodes/reftex-parse.el29
-rw-r--r--lisp/textmodes/reftex-sel.el4
-rw-r--r--lisp/textmodes/reftex-toc.el43
-rw-r--r--lisp/textmodes/reftex-vars.el39
-rw-r--r--lisp/textmodes/reftex.el3
-rw-r--r--lisp/textmodes/remember.el5
-rw-r--r--lisp/textmodes/rst.el151
-rw-r--r--lisp/textmodes/sgml-mode.el98
-rw-r--r--lisp/textmodes/string-edit.el136
-rw-r--r--lisp/textmodes/table.el119
-rw-r--r--lisp/textmodes/tex-mode.el189
-rw-r--r--lisp/textmodes/texinfo.el139
-rw-r--r--lisp/textmodes/texnfo-upd.el2
-rw-r--r--lisp/textmodes/tildify.el5
-rw-r--r--lisp/textmodes/word-wrap-mode.el80
33 files changed, 1813 insertions, 659 deletions
diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el
index e6fddd216d7..2cf9ded04bf 100644
--- a/lisp/textmodes/artist.el
+++ b/lisp/textmodes/artist.el
@@ -184,7 +184,6 @@
;; Variables
-(defconst artist-version "1.2.6")
(defconst artist-maintainer-address "tab@lysator.liu.se, bug-gnu-emacs@gnu.org")
(defvar x-pointer-crosshair)
@@ -338,7 +337,8 @@ Example:
(defvar artist-pointer-shape (if (eq window-system 'x) x-pointer-crosshair nil)
"If in X Windows, use this pointer shape while drawing with the mouse.")
-(defvaralias 'artist-text-renderer 'artist-text-renderer-function)
+(define-obsolete-variable-alias 'artist-text-renderer
+ 'artist-text-renderer-function "29.1")
(defcustom artist-text-renderer-function 'artist-figlet
"Function for doing text rendering."
@@ -474,60 +474,57 @@ This variable is initialized by the `artist-make-prev-next-op-alist' function.")
(defvar artist-arrow-point-1 nil)
(defvar artist-arrow-point-2 nil)
-(defvar artist-mode-map
- (let ((map (make-sparse-keymap)))
- (setq artist-mode-map (make-sparse-keymap))
- (define-key map [down-mouse-1] 'artist-down-mouse-1)
- (define-key map [S-down-mouse-1] 'artist-down-mouse-1)
- (define-key map [down-mouse-2] 'artist-mouse-choose-operation)
- (define-key map [S-down-mouse-2] 'artist-mouse-choose-operation)
- (define-key map [down-mouse-3] 'artist-down-mouse-3)
- (define-key map [S-down-mouse-3] 'artist-down-mouse-3)
- (define-key map [C-mouse-4] 'artist-select-prev-op-in-list)
- (define-key map [C-mouse-5] 'artist-select-next-op-in-list)
- (define-key map "\r" 'artist-key-set-point) ; return
- (define-key map [up] 'artist-previous-line)
- (define-key map "\C-p" 'artist-previous-line)
- (define-key map [down] 'artist-next-line)
- (define-key map "\C-n" 'artist-next-line)
- (define-key map [left] 'artist-backward-char)
- (define-key map "\C-b" 'artist-backward-char)
- (define-key map [right] 'artist-forward-char)
- (define-key map "\C-f" 'artist-forward-char)
- (define-key map "<" 'artist-toggle-first-arrow)
- (define-key map ">" 'artist-toggle-second-arrow)
- (define-key map "\C-c\C-a\C-e" 'artist-select-erase-char)
- (define-key map "\C-c\C-a\C-f" 'artist-select-fill-char)
- (define-key map "\C-c\C-a\C-l" 'artist-select-line-char)
- (define-key map "\C-c\C-a\C-o" 'artist-select-operation)
- (define-key map "\C-c\C-a\C-r" 'artist-toggle-rubber-banding)
- (define-key map "\C-c\C-a\C-t" 'artist-toggle-trim-line-endings)
- (define-key map "\C-c\C-a\C-s" 'artist-toggle-borderless-shapes)
- (define-key map "\C-c\C-c" 'artist-mode-off)
- (define-key map "\C-c\C-al" 'artist-select-op-line)
- (define-key map "\C-c\C-aL" 'artist-select-op-straight-line)
- (define-key map "\C-c\C-ar" 'artist-select-op-rectangle)
- (define-key map "\C-c\C-aR" 'artist-select-op-square)
- (define-key map "\C-c\C-as" 'artist-select-op-square)
- (define-key map "\C-c\C-ap" 'artist-select-op-poly-line)
- (define-key map "\C-c\C-aP" 'artist-select-op-straight-poly-line)
- (define-key map "\C-c\C-ae" 'artist-select-op-ellipse)
- (define-key map "\C-c\C-ac" 'artist-select-op-circle)
- (define-key map "\C-c\C-at" 'artist-select-op-text-see-thru)
- (define-key map "\C-c\C-aT" 'artist-select-op-text-overwrite)
- (define-key map "\C-c\C-aS" 'artist-select-op-spray-can)
- (define-key map "\C-c\C-az" 'artist-select-op-spray-set-size)
- (define-key map "\C-c\C-a\C-d" 'artist-select-op-erase-char)
- (define-key map "\C-c\C-aE" 'artist-select-op-erase-rectangle)
- (define-key map "\C-c\C-av" 'artist-select-op-vaporize-line)
- (define-key map "\C-c\C-aV" 'artist-select-op-vaporize-lines)
- (define-key map "\C-c\C-a\C-k" 'artist-select-op-cut-rectangle)
- (define-key map "\C-c\C-a\M-w" 'artist-select-op-copy-rectangle)
- (define-key map "\C-c\C-a\C-y" 'artist-select-op-paste)
- (define-key map "\C-c\C-af" 'artist-select-op-flood-fill)
- (define-key map "\C-c\C-a\C-b" 'artist-submit-bug-report)
- map)
- "Keymap for `artist-mode'.")
+(defvar-keymap artist-mode-map
+ :doc "Keymap for `artist-mode'."
+ "<down-mouse-1>" #'artist-down-mouse-1
+ "S-<down-mouse-1>" #'artist-down-mouse-1
+ "<down-mouse-2>" #'artist-mouse-choose-operation
+ "S-<down-mouse-2>" #'artist-mouse-choose-operation
+ "<down-mouse-3>" #'artist-down-mouse-3
+ "S-<down-mouse-3>" #'artist-down-mouse-3
+ "C-<mouse-4>" #'artist-select-prev-op-in-list
+ "C-<mouse-5>" #'artist-select-next-op-in-list
+ "RET" #'artist-key-set-point ; return
+ "<up>" #'artist-previous-line
+ "C-p" #'artist-previous-line
+ "<down>" #'artist-next-line
+ "C-n" #'artist-next-line
+ "<left>" #'artist-backward-char
+ "C-b" #'artist-backward-char
+ "<right>" #'artist-forward-char
+ "C-f" #'artist-forward-char
+ "<" #'artist-toggle-first-arrow
+ ">" #'artist-toggle-second-arrow
+ "C-c C-a C-e" #'artist-select-erase-char
+ "C-c C-a C-f" #'artist-select-fill-char
+ "C-c C-a C-l" #'artist-select-line-char
+ "C-c C-a C-o" #'artist-select-operation
+ "C-c C-a C-r" #'artist-toggle-rubber-banding
+ "C-c C-a C-t" #'artist-toggle-trim-line-endings
+ "C-c C-a C-s" #'artist-toggle-borderless-shapes
+ "C-c C-c" #'artist-mode-off
+ "C-c C-a l" #'artist-select-op-line
+ "C-c C-a L" #'artist-select-op-straight-line
+ "C-c C-a r" #'artist-select-op-rectangle
+ "C-c C-a R" #'artist-select-op-square
+ "C-c C-a s" #'artist-select-op-square
+ "C-c C-a p" #'artist-select-op-poly-line
+ "C-c C-a P" #'artist-select-op-straight-poly-line
+ "C-c C-a e" #'artist-select-op-ellipse
+ "C-c C-a c" #'artist-select-op-circle
+ "C-c C-a t" #'artist-select-op-text-see-thru
+ "C-c C-a T" #'artist-select-op-text-overwrite
+ "C-c C-a S" #'artist-select-op-spray-can
+ "C-c C-a z" #'artist-select-op-spray-set-size
+ "C-c C-a C-d" #'artist-select-op-erase-char
+ "C-c C-a E" #'artist-select-op-erase-rectangle
+ "C-c C-a v" #'artist-select-op-vaporize-line
+ "C-c C-a V" #'artist-select-op-vaporize-lines
+ "C-c C-a C-k" #'artist-select-op-cut-rectangle
+ "C-c C-a M-w" #'artist-select-op-copy-rectangle
+ "C-c C-a C-y" #'artist-select-op-paste
+ "C-c C-a f" #'artist-select-op-flood-fill
+ "C-c C-a C-b" #'artist-submit-bug-report)
(easy-menu-define artist-menu-map artist-mode-map
"Menu for `artist-mode'."
@@ -1370,8 +1367,11 @@ Keymap summary
(t
;; Turn mode on
(artist-mode-init)
- (let ((font (face-attribute 'default :font)))
- (when (and (fontp font) (not (font-get font :spacing)))
+ (let* ((font (face-attribute 'default :font))
+ (spacing-prop (if (fontp font)
+ (font-get font :spacing)
+ t)))
+ (when (or (null spacing-prop) (eq spacing-prop 0))
(message "The default font isn't monospaced, so the drawings in this buffer may look odd"))))))
;; Init and exit
@@ -2840,9 +2840,8 @@ Returns a list of strings."
(if (memq system-type '(windows-nt ms-dos))
(artist-figlet-get-font-list-windows)
(artist-figlet-get-font-list)))
- (font (completing-read (concat "Select font (default "
- artist-figlet-default-font
- "): ")
+ (font (completing-read (format-prompt "Select font"
+ artist-figlet-default-font)
(mapcar
(lambda (font) (cons font font))
avail-fonts))))
@@ -4916,7 +4915,7 @@ The event, EV, is the mouse event."
(arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op))
(ev-start (event-start ev))
(initial-win (posn-window ev-start))
- (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start)))
+ (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start t)))
(x1 (artist--adjust-x (car ev-start-pos)))
(y1 (cdr ev-start-pos))
(timer nil))
@@ -4932,7 +4931,7 @@ The event, EV, is the mouse event."
(while (or (mouse-movement-p ev)
(member 'down (event-modifiers ev)))
(setq ev-start-pos (artist-coord-win-to-buf
- (posn-col-row (event-start ev))))
+ (posn-col-row (event-start ev) t)))
(setq x1 (artist--adjust-x (car ev-start-pos)))
(setq y1 (cdr ev-start-pos))
@@ -5012,7 +5011,7 @@ The event, EV, is the mouse event."
(arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op))
(ev-start (event-start ev))
(initial-win (posn-window ev-start))
- (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start)))
+ (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start t)))
(x1-last (artist--adjust-x (car ev-start-pos)))
(y1-last (cdr ev-start-pos))
(x2 x1-last)
@@ -5104,7 +5103,7 @@ The event, EV, is the mouse event."
;; set x2 and y2
;;
(setq ev-start-pos (artist-coord-win-to-buf
- (posn-col-row (event-start ev))))
+ (posn-col-row (event-start ev) t)))
(setq x2 (artist--adjust-x (car ev-start-pos)))
(setq y2 (cdr ev-start-pos))
@@ -5131,7 +5130,7 @@ The event, EV, is the mouse event."
;;
;; set x2 and y2
(setq ev-start-pos (artist-coord-win-to-buf
- (posn-col-row (event-start ev))))
+ (posn-col-row (event-start ev) t)))
(setq x2 (artist--adjust-x (car ev-start-pos)))
(setq y2 (cdr ev-start-pos))
@@ -5215,7 +5214,8 @@ Operation is done once. The event, EV, is the mouse event."
(arrow-pred (artist-go-get-arrow-pred-from-symbol op))
(arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op))
(ev-start (event-start ev))
- (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start)))
+ (ev-start-pos (artist-coord-win-to-buf
+ (posn-col-row ev-start t)))
(x1 (artist--adjust-x (car ev-start-pos)))
(y1 (cdr ev-start-pos)))
(select-window (posn-window ev-start))
@@ -5249,7 +5249,8 @@ The event, EV, is the mouse event."
(arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op))
(ev-start (event-start ev))
(initial-win (posn-window ev-start))
- (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start)))
+ (ev-start-pos (artist-coord-win-to-buf
+ (posn-col-row ev-start t)))
(x1 (artist--adjust-x (car ev-start-pos)))
(y1 (cdr ev-start-pos))
(x2)
@@ -5263,7 +5264,7 @@ The event, EV, is the mouse event."
(while (or (mouse-movement-p ev)
(member 'down (event-modifiers ev)))
(setq ev-start-pos (artist-coord-win-to-buf
- (posn-col-row (event-start ev))))
+ (posn-col-row (event-start ev) t)))
(setq x2 (artist--adjust-x (car ev-start-pos)))
(setq y2 (cdr ev-start-pos))
@@ -5359,7 +5360,7 @@ The event, EV, is the mouse event."
(setq vars (delq x vars)))) vars)
(reporter-submit-bug-report
artist-maintainer-address
- (concat "artist.el " artist-version)
+ (concat "artist.el in Emacs " emacs-version)
vars
nil nil
(concat "Hello Tomas,\n\n"
@@ -5367,6 +5368,9 @@ The event, EV, is the mouse event."
(define-obsolete-function-alias 'artist-uniq #'seq-uniq "28.1")
+(defconst artist-version "1.2.6")
+(make-obsolete-variable 'artist-version 'emacs-version "29.1")
+
(provide 'artist)
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
index e4df28d03de..6763da046ff 100644
--- a/lisp/textmodes/bibtex.el
+++ b/lisp/textmodes/bibtex.el
@@ -316,8 +316,6 @@ If parsing fails, try to set this variable to nil."
(option (choice :tag "Alternative" :value nil
(const nil) integer)))))))
-(define-obsolete-variable-alias 'bibtex-entry-field-alist
- 'bibtex-BibTeX-entry-alist "24.1")
(defcustom bibtex-BibTeX-entry-alist
'(("Article" "Article in Journal"
(("author")
@@ -764,6 +762,20 @@ for a new entry."
("eprint") ("eprintclass" nil nil 4) ("primaryclass" nil nil -4)
("eprinttype" nil nil 5) ("archiveprefix" nil nil -5)
("url") ("urldate")))
+ ("Conference" "Article in Conference Proceedings" ; same as InProceedings
+ (("author")
+ ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)"))
+ (("booktitle" "Name of the conference proceedings")
+ ("year"))
+ (("editor")
+ ("volume" "Volume of the conference proceedings in the series")
+ ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
+ ("series" "Series in which the conference proceedings appeared")
+ ("pages" "Pages in the conference proceedings")
+ ("month") ("address")
+ ("organization" "Sponsoring organization of the conference")
+ ("publisher" "Publishing company, its location")
+ ("note")))
("Reference" "Single-Volume Work of Reference" ; same as @collection
(("editor") ("title") ("date" nil nil 1) ("year" nil nil -1))
nil
@@ -839,6 +851,33 @@ for a new entry."
("eprint") ("eprintclass" nil nil 4) ("primaryclass" nil nil -4)
("eprinttype" nil nil 5) ("archiveprefix" nil nil -5)
("url") ("urldate")))
+ ("PhdThesis" "PhD Thesis"
+ (("author")
+ ("title" "Title of the PhD thesis")
+ ("school" "School where the PhD thesis was written")
+ ("year"))
+ nil
+ (("type" "Type of the PhD thesis")
+ ("address" "Address of the school (if not part of field \"school\") or country")
+ ("month") ("note")))
+ ("MastersThesis" "Master's Thesis"
+ (("author")
+ ("title" "Title of the master's thesis (BibTeX converts it to lowercase)")
+ ("school" "School where the master's thesis was written")
+ ("year"))
+ nil
+ (("type" "Type of the master's thesis (if other than \"Master's thesis\")")
+ ("address" "Address of the school (if not part of field \"school\") or country")
+ ("month") ("note")))
+ ("TechReport" "Technical Report"
+ (("author")
+ ("title" "Title of the technical report (BibTeX converts it to lowercase)")
+ ("institution" "Sponsoring institution of the report")
+ ("year"))
+ nil
+ (("type" "Type of the report (if other than \"technical report\")")
+ ("number" "Number of the technical report")
+ ("address") ("month") ("note")))
("Unpublished" "Unpublished"
(("author") ("title") ("date" nil nil 1) ("year" nil nil -1))
nil
@@ -1193,8 +1232,8 @@ See `bibtex-generate-autokey' for details."
:type '(repeat (cons (regexp :tag "Old")
(string :tag "New"))))
-(defvaralias 'bibtex-autokey-name-case-convert
- 'bibtex-autokey-name-case-convert-function)
+(define-obsolete-variable-alias 'bibtex-autokey-name-case-convert
+ 'bibtex-autokey-name-case-convert-function "29.1")
(defcustom bibtex-autokey-name-case-convert-function #'downcase
"Function called for each name to perform case conversion.
@@ -1268,8 +1307,8 @@ Case is significant. See `bibtex-generate-autokey' for details."
:group 'bibtex-autokey
:type '(repeat regexp))
-(defvaralias 'bibtex-autokey-titleword-case-convert
- 'bibtex-autokey-titleword-case-convert-function)
+(define-obsolete-variable-alias 'bibtex-autokey-titleword-case-convert
+ 'bibtex-autokey-titleword-case-convert-function "29.1")
(defcustom bibtex-autokey-titleword-case-convert-function #'downcase
"Function called for each titleword to perform case conversion.
@@ -2257,11 +2296,17 @@ is non-nil, FUN is not called for @String entries."
(set-marker-insertion-type end-marker t)
(save-excursion
(goto-char (point-min))
- (while (setq found (bibtex-skip-to-valid-entry))
- (set-marker end-marker (cdr found))
- (looking-at bibtex-any-entry-maybe-empty-head)
- (funcall fun (bibtex-key-in-head "") (car found) end-marker)
- (goto-char end-marker)))))
+ (let ((prev nil))
+ (while (setq found (bibtex-skip-to-valid-entry))
+ ;; If we have invalid entries, ensure that we have forward
+ ;; progress so that we don't infloop.
+ (if (equal (point) prev)
+ (forward-line 1)
+ (setq prev (point))
+ (set-marker end-marker (cdr found))
+ (looking-at bibtex-any-entry-maybe-empty-head)
+ (funcall fun (bibtex-key-in-head "") (car found) end-marker)
+ (goto-char end-marker)))))))
(defun bibtex-progress-message (&optional flag interval)
"Echo a message about progress of current buffer.
@@ -3626,14 +3671,6 @@ if that value is non-nil.
(if (not (consp (nth 1 (car entry-alist))))
;; new format
entry-alist
- ;; Convert old format of `bibtex-entry-field-alist'
- (unless (get var 'entry-list-format)
- (put var 'entry-list-format "pre-24")
- (message "Old format of `%s' (pre GNU Emacs 24).
-Please convert to the new format."
- (if (eq (indirect-variable 'bibtex-entry-field-alist) var)
- 'bibtex-entry-field-alist var))
- (sit-for 3))
(let (lst)
(dolist (entry entry-alist)
(let ((fl (nth 1 entry)) req xref opt)
@@ -4101,11 +4138,11 @@ Optional arg POS is the position of the BibTeX entry to use."
(goto-char pnt)))))
(defun bibtex-mark-entry ()
- "Put mark at beginning, point at end of current BibTeX entry.
+ "Put mark at end, point at beginning of current BibTeX entry.
Activate mark in Transient Mark mode."
(interactive)
- (push-mark (bibtex-beginning-of-entry) t t)
- (bibtex-end-of-entry))
+ (push-mark (bibtex-end-of-entry) t t)
+ (bibtex-beginning-of-entry))
(defun bibtex-count-entries (&optional count-string-entries)
"Count number of entries in current buffer or region.
@@ -4317,8 +4354,6 @@ for a crossref key, t otherwise."
(eqb (goto-char pos))
(t (set-buffer buffer) (goto-char pos)))
pos))
-;; backward compatibility
-(defalias 'bibtex-find-crossref 'bibtex-search-crossref)
(defun bibtex-dist (pos beg end)
"Return distance between POS and region delimited by BEG and END."
@@ -4381,8 +4416,6 @@ A prefix arg negates the value of `bibtex-search-entry-globally'."
(if display (bibtex-reposition-window)))
(display (message "Key `%s' not found" key)))
pnt)))
-;; backward compatibility
-(defalias 'bibtex-find-entry 'bibtex-search-entry)
(defun bibtex-prepare-new-entry (index)
"Prepare a new BibTeX entry with index INDEX.
@@ -4996,7 +5029,7 @@ on the value of `bibtex-entry-format'.
If the reference key of the entry is empty or a prefix argument is given,
calculate a new reference key. (Note: this works only if fields in entry
begin on separate lines prior to calling `bibtex-clean-entry' or if
-'realign is contained in `bibtex-entry-format'.)
+`realign' is contained in `bibtex-entry-format'.)
Don't call `bibtex-clean-entry' on @Preamble entries.
At end of the cleaning process, the functions in
`bibtex-clean-entry-hook' are called with region narrowed to entry."
@@ -5275,7 +5308,6 @@ entries from minibuffer."
(goto-char (point-max))
(message "Buffer is now parsable. Please save it.")))
-(define-obsolete-function-alias 'bibtex-complete #'completion-at-point "24.1")
(defun bibtex-completion-at-point-function ()
(let ((pnt (point))
(case-fold-search t)
@@ -5608,5 +5640,8 @@ If APPEND is non-nil, append ENTRIES to those already displayed."
(setq buffer-read-only t)
(goto-char (point-min)))
+(define-obsolete-function-alias 'bibtex-find-crossref #'bibtex-search-crossref "29.1")
+(define-obsolete-function-alias 'bibtex-find-entry #'bibtex-search-entry "29.1")
+
(provide 'bibtex)
;;; bibtex.el ends here
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 1139fd1976e..a2a7774aba7 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -269,6 +269,10 @@
("resize" "none" "both" "horizontal" "vertical")
("text-overflow" "clip" "ellipsis" string)
+ ;; CSS Cascading and Inheritance Level 3
+ ;; (https://www.w3.org/TR/css-cascade-3/#property-index)
+ ("all")
+
;; CSS Color Module Level 3
;; (https://www.w3.org/TR/css3-color/#property)
("color" color)
@@ -304,27 +308,27 @@
;; CSS Box Alignment Module Level 3
;; (https://www.w3.org/TR/css-align-3/#property-index)
- ("align-content"
- baseline-position content-distribution overflow-position content-position)
- ("align-items"
- "normal" "stretch" baseline-position overflow-position self-position)
- ("align-self"
- "auto" "normal" "stretch"
- baseline-position overflow-position self-position)
- ("justify-content" "normal"
- content-distribution overflow-position content-position "left" "right")
- ("justify-items"
- "normal" "stretch" baseline-position overflow-position self-position
- "left" "right" "legacy")
- ("justify-self"
- "auto" "normal" "stretch" baseline-position overflow-position self-position
- "left" "right")
+ ("align-content" baseline-position content-distribution
+ overflow-position content-position)
+ ("align-items" "normal" "stretch" baseline-position
+ overflow-position self-position)
+ ("align-self" "auto" "normal" "stretch" baseline-position
+ overflow-position self-position)
+ ("column-gap" "normal" length-percentage)
+ ("gap" row-gap column-gap)
+ ("justify-content" "normal" content-distribution overflow-position
+ content-position "left" "right")
+ ("justify-items" "normal" "stretch" baseline-position
+ overflow-position self-position "left" "right" "legacy" "center")
+ ("justify-self" "auto" "normal" "stretch" baseline-position
+ overflow-position self-position "left" "right")
("place-content" align-content justify-content)
("place-items" align-items justify-items)
("place-self" justify-self align-self)
+ ("row-gap" "normal" length-percentage)
- ;; CSS Flexible Box Layout Module Level 2
- ;; (https://www.w3.org/TR/css-flexbox-2/#property-index)
+ ;; CSS Flexible Box Layout Module Level 1
+ ;; (https://www.w3.org/TR/css-flexbox-1/#property-index)
("flex" "none" flex-grow flex-shrink flex-basis)
("flex-basis" "auto" "content" width)
("flex-direction" "row" "row-reverse" "column" "column-reverse")
@@ -413,21 +417,20 @@
("mask-type" "luminance" "alpha")
("clip" "rect()" "auto")
- ;; CSS Multi-column Layout Module
+ ;; CSS Multi-column Layout Module Level 1
;; (https://www.w3.org/TR/css3-multicol/#property-index)
;; "break-after", "break-before", and "break-inside" are left out
;; below, because they're already included in CSS Fragmentation
;; Module Level 3.
- ("column-count" integer "auto")
- ("column-fill" "auto" "balance")
- ("column-gap" length "normal")
+ ("column-count" "auto" integer)
+ ("column-fill" "auto" "balance" "balance-all")
("column-rule" column-rule-width column-rule-style
- column-rule-color "transparent")
+ column-rule-color)
("column-rule-color" color)
- ("column-rule-style" border-style)
- ("column-rule-width" border-width)
+ ("column-rule-style" line-style)
+ ("column-rule-width" line-width)
("column-span" "none" "all")
- ("column-width" length "auto")
+ ("column-width" "auto" length)
("columns" column-width column-count)
;; CSS Overflow Module Level 3
@@ -925,6 +928,32 @@ cannot be completed sensibly: `custom-ident',
(defface css-proprietary-property '((t :inherit (css-property italic)))
"Face to use for vendor-specific properties.")
+(defun css--selector-regexp (sassy)
+ (concat
+ "\\(?:"
+ (if (not sassy)
+ "[-_%*#.>[:alnum:]]+"
+ ;; Same as for non-sassy except we do want to allow { and }
+ ;; chars in selectors in the case of #{$foo}
+ ;; variable interpolation!
+ (concat "\\(?:[-_%*#.>&+~[:alnum:]]*" scss--hash-re
+ "\\|[-_%*#.>&+~[:alnum:]]+\\)"))
+ ;; Even though pseudo-elements should be prefixed by ::, a
+ ;; single colon is accepted for backward compatibility.
+ "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids
+ css-pseudo-element-ids)
+ t)
+ "\\|::" (regexp-opt css-pseudo-element-ids t) "\\)\\)?"
+ ;; Braces after selectors.
+ "\\(?:\\[[^]\n]+\\]\\)?"
+ ;; Parentheses after selectors.
+ "\\(?:([^)]+)\\)?"
+ ;; Main bit over. But perhaps just [target]?
+ "\\|\\[[^]\n]+\\]"
+ ;; :root, ::marker and the like.
+ "\\|::?[[:alnum:]]+\\(?:([^)]+)\\)?"
+ "\\)"))
+
(defun css--font-lock-keywords (&optional sassy)
`((,(concat "!\\s-*" (regexp-opt css--bang-ids))
(0 font-lock-builtin-face))
@@ -945,28 +974,16 @@ cannot be completed sensibly: `custom-ident',
;; selector between [...] should simply not be highlighted.
(,(concat
"^[ \t]*\\("
- (if (not sassy)
- ;; We don't allow / as first char, so as not to
- ;; take a comment as the beginning of a selector.
- "[^@/:{}() \t\n][^:{}()]*"
- ;; Same as for non-sassy except we do want to allow { and }
- ;; chars in selectors in the case of #{$foo}
- ;; variable interpolation!
- (concat "\\(?:" scss--hash-re
- "\\|[^@/:{}() \t\n#]\\)"
- "[^:{}()#]*\\(?:" scss--hash-re "[^:{}()#]*\\)*"))
- ;; Even though pseudo-elements should be prefixed by ::, a
- ;; single colon is accepted for backward compatibility.
- "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids
- css-pseudo-element-ids)
- t)
- "\\|::" (regexp-opt css-pseudo-element-ids t) "\\)"
- "\\(?:([^)]+)\\)?"
- (if (not sassy)
- "[^:{}()\n]*"
- (concat "[^:{}()\n#]*\\(?:" scss--hash-re "[^:{}()\n#]*\\)*"))
+ ;; We have at least one selector.
+ (css--selector-regexp sassy)
+ ;; And then possibly more.
+ "\\(?:"
+ ;; Separators between selectors.
+ "[ \n\t,+~>]+"
+ (css--selector-regexp sassy)
"\\)*"
- "\\)\\(?:\n[ \t]*\\)*{")
+ ;; And then a brace.
+ "\\)[ \n\t]*{")
(1 'css-selector keep))
;; In the above rule, we allow the open-brace to be on some subsequent
;; line. This will only work if we properly mark the intervening text
diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el
index d4acbe24ebb..42d547504c1 100644
--- a/lisp/textmodes/dns-mode.el
+++ b/lisp/textmodes/dns-mode.el
@@ -110,11 +110,11 @@
"26.1" 'set)
(defcustom dns-mode-font-lock-keywords
- `((,(concat "^\\$" (regexp-opt dns-mode-control-entities))
+ `((,(concat "^\\$" (regexp-opt dns-mode-control-entities) "\\>")
0 ,dns-mode-control-entity-face)
("^\\$[a-z0-9A-Z]+" 0 ,dns-mode-bad-control-entity-face)
- (,(regexp-opt dns-mode-classes) 0 ,dns-mode-class-face)
- (,(regexp-opt dns-mode-types) 0 ,dns-mode-type-face))
+ (,(regexp-opt dns-mode-classes 'words) 0 ,dns-mode-class-face)
+ (,(regexp-opt dns-mode-types 'words) 0 ,dns-mode-type-face))
"Font lock keywords used to highlight text in DNS master file mode."
:version "26.1"
:type 'sexp)
diff --git a/lisp/textmodes/emacs-news-mode.el b/lisp/textmodes/emacs-news-mode.el
new file mode 100644
index 00000000000..af0aa2ddeab
--- /dev/null
+++ b/lisp/textmodes/emacs-news-mode.el
@@ -0,0 +1,269 @@
+;;; emacs-news-mode.el --- major mode to edit and view the NEWS file -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Keywords: tools
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+(require 'outline)
+
+(defgroup emacs-news-mode nil
+ "Major mode for editing and viewing the Emacs NEWS file."
+ :group 'lisp)
+
+(defface emacs-news-is-documented
+ '((t :inherit font-lock-type-face))
+ "Face used for displaying the \"is documented\" tag."
+ :version "29.1")
+
+(defface emacs-news-does-not-need-documentation
+ '((t :inherit font-lock-preprocessor-face))
+ "Face used for displaying the \"does not need documentation\" tag."
+ :version "29.1")
+
+(defvar-keymap emacs-news-common-map
+ ;; Navigation like `org-mode'/`outline-minor-mode'.
+ "C-c C-f" #'outline-forward-same-level
+ "C-c C-b" #'outline-backward-same-level
+ "C-c C-n" #'outline-next-visible-heading
+ "C-c C-p" #'outline-previous-visible-heading
+ "C-c C-u" #'outline-up-heading)
+
+(defvar-keymap emacs-news-mode-map
+ :parent emacs-news-common-map
+ "C-c C-s" #'emacs-news-next-untagged-entry
+ "C-c C-r" #'emacs-news-previous-untagged-entry
+ "C-c C-t" #'emacs-news-toggle-tag
+ "C-c C-g" #'emacs-news-goto-section
+ "C-c C-j" #'emacs-news-find-heading
+ "C-c C-e" #'emacs-news-count-untagged-entries
+ "<remap> <open-line>" #'emacs-news-open-line)
+
+(defvar-keymap emacs-news-view-mode-map
+ :parent emacs-news-common-map)
+
+(defvar emacs-news-mode-font-lock-keywords
+ `(("^---$" 0 'emacs-news-does-not-need-documentation)
+ ("^\\+\\+\\+$" 0 'emacs-news-is-documented)))
+
+(defun emacs-news--mode-common ()
+ (setq-local font-lock-defaults '(emacs-news-mode-font-lock-keywords t))
+ (setq-local outline-regexp "\\*+ "
+ outline-minor-mode-cycle t
+ ;; We subtract one from the level, because we have a
+ ;; space after the asterisks.
+ outline-level (lambda () (1- (length (match-string 0))))
+ outline-minor-mode-highlight 'append)
+ (outline-minor-mode))
+
+;;;###autoload
+(define-derived-mode emacs-news-mode text-mode "NEWS"
+ "Major mode for editing the Emacs NEWS file."
+ (setq-local fill-paragraph-function #'emacs-news--fill-paragraph)
+ (emacs-news--mode-common))
+
+;;;###autoload
+(define-derived-mode emacs-news-view-mode special-mode "NEWS"
+ "Major mode for viewing the Emacs NEWS file."
+ (setq buffer-read-only t)
+ (emacs-news--buttonize)
+ (button-mode)
+ (emacs-news--mode-common))
+
+(defun emacs-news--fill-paragraph (&optional justify)
+ (cond
+ ;; We're in a heading -- do nothing.
+ ((save-excursion
+ (beginning-of-line)
+ (looking-at "\\*+ "))
+ )
+ ;; We're in a news item -- exclude the heading before filling.
+ ((and (save-excursion
+ (re-search-backward (concat "^\\(?:" paragraph-start "\\|\\*+ \\)")
+ nil t))
+ (= (char-after (match-beginning 0)) ?*))
+ (save-restriction
+ (narrow-to-region (save-excursion
+ (goto-char (match-beginning 0))
+ (forward-line 1)
+ (point))
+ (point-max))
+ (fill-paragraph justify)))
+ ;; Fill normally.
+ (t
+ (fill-paragraph justify))))
+
+(defun emacs-news-next-untagged-entry (&optional reverse)
+ "Go to the next untagged NEWS entry.
+If REVERSE (interactively, the prefix), go to the previous
+untagged NEWS entry."
+ (interactive "P" emacs-news-mode)
+ (let ((start (point))
+ (found nil))
+ ;; Don't consider the current line, because that would stop
+ ;; progress if calling this command repeatedly.
+ (unless reverse
+ (forward-line 1))
+ (while (and (not found)
+ (funcall (if reverse #'re-search-backward
+ #'re-search-forward)
+ "^\\(\\*+\\) " nil t))
+ (when (and (not (save-excursion
+ (forward-line -1)
+ (looking-at "---$\\|\\+\\+\\+$")))
+ ;; We have an entry without a tag before it, but
+ ;; check whether it's a heading (which we can
+ ;; determine if the next entry has more asterisks).
+ (not (emacs-news--heading-p)))
+ ;; It wasn't a sub-heading, so we've found one.
+ (setq found t)))
+ (if found
+ (progn
+ (push-mark start)
+ (message "Untagged entry")
+ (beginning-of-line)
+ t)
+ (message "No further untagged entries")
+ (goto-char start)
+ nil)))
+
+(defun emacs-news--heading-p ()
+ (save-excursion
+ (beginning-of-line)
+ ;; A heading starts with * characters, and then a blank line, and
+ ;; then paragraphs with more * characters than in the heading.
+ (and (looking-at "\\(\\*+\\) ")
+ (let ((level (length (match-string 1))))
+ (forward-line 1)
+ (and (looking-at "$")
+ (re-search-forward "^\\(\\*+\\) " nil t)
+ (> (length (match-string 1)) level))))))
+
+(defun emacs-news-previous-untagged-entry ()
+ "Go to the previous untagged NEWS entry."
+ (interactive nil emacs-news-mode)
+ (emacs-news-next-untagged-entry t))
+
+(defun emacs-news-toggle-tag ()
+ "Toggle documentation tag of current headline in the Emacs NEWS file."
+ (interactive nil emacs-news-mode)
+ (save-excursion
+ (goto-char (line-beginning-position))
+ (cond ((or (looking-at (rx bol (or "---" "+++") eol)))
+ (forward-line 2))
+ ((or (looking-at (rx bol "*** ")))
+ (forward-line 1)))
+ (outline-previous-visible-heading 1)
+ (forward-line -1)
+ (cond ((not (looking-at (rx bol (or "---" "+++") eol)))
+ (insert "\n---"))
+ ((looking-at (rx bol "---" eol))
+ (delete-char 3)
+ (insert "+++"))
+ ((looking-at (rx bol "+++" eol))
+ (delete-char 4))
+ (t (user-error "Invalid headline tag; can't toggle")))))
+
+(defun emacs-news-count-untagged-entries ()
+ "Say how many untagged entries there are in the current NEWS buffer."
+ (interactive nil emacs-news-mode)
+ (save-excursion
+ (goto-char (point-min))
+ (let ((i 0))
+ (while (emacs-news-next-untagged-entry)
+ (setq i (1+ i)))
+ (message (if (= i 1)
+ "There's 1 untagged entry"
+ (format "There are %s untagged entries" i))))))
+
+(defun emacs-news--buttonize ()
+ "Make manual and symbol references into buttons."
+ (save-excursion
+ (with-silent-modifications
+ (let ((inhibit-read-only t))
+ ;; Do functions and variables.
+ (goto-char (point-min))
+ (search-forward "\f" nil t)
+ (while (re-search-forward "'\\([^-][^ \t\n]+\\)'" nil t)
+ ;; Filter out references to key sequences.
+ (let ((string (match-string 1)))
+ (when-let ((symbol (intern-soft string)))
+ (when (or (boundp symbol)
+ (fboundp symbol))
+ (buttonize-region (match-beginning 1) (match-end 1)
+ (lambda (symbol)
+ (describe-symbol symbol))
+ symbol)))))
+ ;; Do manual references.
+ (goto-char (point-min))
+ (search-forward "\f" nil t)
+ (while (re-search-forward "\"\\(([a-z0-9]+)[ \n][^\"]\\{1,80\\}\\)\""
+ nil t)
+ (buttonize-region (match-beginning 1) (match-end 1)
+ (lambda (node) (info node))
+ (match-string 1)))))))
+
+(defun emacs-news--sections (regexp)
+ (let ((sections nil))
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward (concat "^" regexp "\\(.*\\)") nil t)
+ (when (save-match-data (emacs-news--heading-p))
+ (push (buffer-substring-no-properties
+ (match-beginning 1) (match-end 1))
+ sections))))
+ (nreverse sections)))
+
+(defun emacs-news-goto-section (section)
+ "Go to SECTION in the Emacs NEWS file."
+ (interactive (list
+ (completing-read "Goto section: " (emacs-news--sections "\\* ")
+ nil t))
+ emacs-news-mode)
+ (goto-char (point-min))
+ (when (search-forward (concat "\n* " section) nil t)
+ (beginning-of-line)))
+
+(defun emacs-news-find-heading (heading)
+ "Go to HEADING in the Emacs NEWS file."
+ (interactive (list
+ (completing-read "Goto heading: "
+ (emacs-news--sections "\\*\\*\\*? ")
+ nil t))
+ emacs-news-mode)
+ (goto-char (point-min))
+ (when (re-search-forward (concat "^*+ " (regexp-quote heading)) nil t)
+ (beginning-of-line)))
+
+(defun emacs-news-open-line (n)
+ "Open a new line in a NEWS file.
+This is like `open-line', but skips any temporary NEWS-style
+documentation marks on the previous line."
+ (interactive "*p" emacs-news-mode)
+ (when (save-excursion (forward-line -1)
+ (looking-at (rx bol (or "---" "+++") eol)))
+ (forward-line -1))
+ (open-line n))
+
+(provide 'emacs-news-mode)
+
+;;; emacs-news-mode.el ends here
diff --git a/lisp/textmodes/enriched.el b/lisp/textmodes/enriched.el
index 50ff668a9ff..935be06812f 100644
--- a/lisp/textmodes/enriched.el
+++ b/lisp/textmodes/enriched.el
@@ -539,6 +539,30 @@ the range of text to assign text property SYMBOL with value VALUE."
(list start end 'display prop)
(list start end 'display (list 'disable-eval prop)))))
+(defvar enriched--markup-shown)
+(defun enriched-toggle-markup ()
+ "Toggle whether to see markup in the current buffer."
+ (interactive)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (with-silent-modifications
+ (if (bound-and-true-p enriched--markup-shown)
+ (progn
+ (setq-local enriched--markup-shown nil)
+ ;; Remove any faces, because they will be decoded, too.
+ (goto-char (point-min))
+ (let (match)
+ (while (setq match (text-property-search-forward 'face))
+ (put-text-property (prop-match-beginning match)
+ (prop-match-end match)
+ 'face nil)))
+ (enriched-decode (point-min) (point-max))
+ (enriched-mode 1))
+ (setq-local enriched--markup-shown t)
+ (enriched-encode (point-min) (point-max) (current-buffer))
+ (enriched-mode -1))))))
+
(provide 'enriched)
;;; enriched.el ends here
diff --git a/lisp/textmodes/etc-authors-mode.el b/lisp/textmodes/etc-authors-mode.el
index 3912b829d20..7eabdd4c2b8 100644
--- a/lisp/textmodes/etc-authors-mode.el
+++ b/lisp/textmodes/etc-authors-mode.el
@@ -115,12 +115,10 @@ With a prefix arg ARG, move point that many authors backward."
(interactive "p" etc-authors-mode)
(etc-authors-next-author (- arg)))
-(defvar etc-authors-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "n" #'etc-authors-next-author)
- (define-key map "p" #'etc-authors-prev-author)
- map)
- "Keymap for `etc-authors-mode'.")
+(defvar-keymap etc-authors-mode-map
+ :doc "Keymap for `etc-authors-mode'."
+ "n" #'etc-authors-next-author
+ "p" #'etc-authors-prev-author)
;;;###autoload
(define-derived-mode etc-authors-mode special-mode "Authors View"
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
index ff84c353aa8..23ba1a24f1f 100644
--- a/lisp/textmodes/fill.el
+++ b/lisp/textmodes/fill.el
@@ -29,6 +29,8 @@
;;; Code:
+(eval-when-compile (require 'subr-x))
+
(defgroup fill nil
"Indenting and filling text."
:link '(custom-manual "(emacs)Filling")
@@ -44,8 +46,8 @@ A value of nil means that any change in indentation starts a new paragraph."
(defcustom colon-double-space nil
"Non-nil means put two spaces after a colon when filling."
- :type 'boolean)
-(put 'colon-double-space 'safe-local-variable #'booleanp)
+ :type 'boolean
+ :safe #'booleanp)
(defcustom fill-separate-heterogeneous-words-with-space nil
"Non-nil means to use a space to separate words of a different kind.
@@ -396,12 +398,8 @@ and `fill-nobreak-invisible'."
(save-excursion
(skip-chars-backward " ")
(and (eq (preceding-char) ?.)
- (looking-at " \\([^ ]\\|$\\)"))))
- ;; Another approach to the same problem.
- (save-excursion
- (skip-chars-backward " ")
- (and (eq (preceding-char) ?.)
- (not (progn (forward-char -1) (looking-at (sentence-end))))))
+ ;; There's something more after the space.
+ (looking-at " [^ \n]"))))
;; Don't split a line if the rest would look like a new paragraph.
(unless use-hard-newlines
(save-excursion
@@ -716,7 +714,10 @@ space does not end a sentence, so don't break a line there."
(goto-char from-plus-indent))
(if (not (> to (point)))
- nil ;; There is no paragraph, only whitespace: exit now.
+ ;; There is no paragraph, only whitespace: exit now.
+ (progn
+ (set-marker to nil)
+ nil)
(or justify (setq justify (current-justification)))
@@ -792,6 +793,7 @@ space does not end a sentence, so don't break a line there."
;; Leave point after final newline.
(goto-char to)
(unless (eobp) (forward-char 1))
+ (set-marker to nil)
;; Return the fill-prefix we used
fill-prefix)))
@@ -839,75 +841,67 @@ region, instead of just filling the current paragraph."
(interactive (progn
(barf-if-buffer-read-only)
(list (if current-prefix-arg 'full) t)))
- (let ((hash (and (not (buffer-modified-p))
- (buffer-hash))))
- (prog1
- (or
- ;; 1. Fill the region if it is active when called interactively.
- (and region transient-mark-mode mark-active
- (not (eq (region-beginning) (region-end)))
- (or (fill-region (region-beginning) (region-end) justify) t))
- ;; 2. Try fill-paragraph-function.
- (and (not (eq fill-paragraph-function t))
- (or fill-paragraph-function
- (and (minibufferp (current-buffer))
- (= 1 (point-min))))
- (let ((function (or fill-paragraph-function
- ;; In the minibuffer, don't count
- ;; the width of the prompt.
- 'fill-minibuffer-function))
- ;; If fill-paragraph-function is set, it probably
- ;; takes care of comments and stuff. If not, it
- ;; will have to set fill-paragraph-handle-comment
- ;; back to t explicitly or return nil.
- (fill-paragraph-handle-comment nil)
- (fill-paragraph-function t))
- (funcall function justify)))
- ;; 3. Try our syntax-aware filling code.
- (and fill-paragraph-handle-comment
- ;; Our code only handles \n-terminated comments right now.
- comment-start (equal comment-end "")
- (let ((fill-paragraph-handle-comment nil))
- (fill-comment-paragraph justify)))
- ;; 4. If it all fails, default to the good ol' text paragraph filling.
- (let ((before (point))
- (paragraph-start paragraph-start)
- ;; Fill prefix used for filling the paragraph.
- fill-pfx)
- ;; Try to prevent code sections and comment sections from being
- ;; filled together.
- (when (and fill-paragraph-handle-comment comment-start-skip)
- (setq paragraph-start
- (concat paragraph-start "\\|[ \t]*\\(?:"
- comment-start-skip "\\)")))
- (save-excursion
- ;; To make sure the return value of forward-paragraph is
- ;; meaningful, we have to start from the beginning of
- ;; line, otherwise skipping past the last few chars of a
- ;; paragraph-separator would count as a paragraph (and
- ;; not skipping any chars at EOB would not count as a
- ;; paragraph even if it is).
- (move-to-left-margin)
- (if (not (zerop (fill-forward-paragraph 1)))
- ;; There's no paragraph at or after point: give up.
- (setq fill-pfx "")
- (let ((end (point))
- (beg (progn (fill-forward-paragraph -1) (point))))
- (goto-char before)
- (setq fill-pfx
- (if use-hard-newlines
- ;; Can't use fill-region-as-paragraph, since this
- ;; paragraph may still contain hard newlines. See
- ;; fill-region.
- (fill-region beg end justify)
- (fill-region-as-paragraph beg end justify))))))
- fill-pfx))
- ;; If we didn't change anything in the buffer (and the buffer
- ;; was previously unmodified), then flip the modification status
- ;; back to "unchanged".
- (when (and hash
- (equal hash (buffer-hash)))
- (set-buffer-modified-p nil)))))
+ (with-buffer-unmodified-if-unchanged
+ (or
+ ;; 1. Fill the region if it is active when called interactively.
+ (and region transient-mark-mode mark-active
+ (not (eq (region-beginning) (region-end)))
+ (or (fill-region (region-beginning) (region-end) justify) t))
+ ;; 2. Try fill-paragraph-function.
+ (and (not (eq fill-paragraph-function t))
+ (or fill-paragraph-function
+ (and (minibufferp (current-buffer))
+ (= 1 (point-min))))
+ (let ((function (or fill-paragraph-function
+ ;; In the minibuffer, don't count
+ ;; the width of the prompt.
+ 'fill-minibuffer-function))
+ ;; If fill-paragraph-function is set, it probably
+ ;; takes care of comments and stuff. If not, it
+ ;; will have to set fill-paragraph-handle-comment
+ ;; back to t explicitly or return nil.
+ (fill-paragraph-handle-comment nil)
+ (fill-paragraph-function t))
+ (funcall function justify)))
+ ;; 3. Try our syntax-aware filling code.
+ (and fill-paragraph-handle-comment
+ ;; Our code only handles \n-terminated comments right now.
+ comment-start (equal comment-end "")
+ (let ((fill-paragraph-handle-comment nil))
+ (fill-comment-paragraph justify)))
+ ;; 4. If it all fails, default to the good ol' text paragraph filling.
+ (let ((before (point))
+ (paragraph-start paragraph-start)
+ ;; Fill prefix used for filling the paragraph.
+ fill-pfx)
+ ;; Try to prevent code sections and comment sections from being
+ ;; filled together.
+ (when (and fill-paragraph-handle-comment comment-start-skip)
+ (setq paragraph-start
+ (concat paragraph-start "\\|[ \t]*\\(?:"
+ comment-start-skip "\\)")))
+ (save-excursion
+ ;; To make sure the return value of forward-paragraph is
+ ;; meaningful, we have to start from the beginning of
+ ;; line, otherwise skipping past the last few chars of a
+ ;; paragraph-separator would count as a paragraph (and
+ ;; not skipping any chars at EOB would not count as a
+ ;; paragraph even if it is).
+ (move-to-left-margin)
+ (if (not (zerop (fill-forward-paragraph 1)))
+ ;; There's no paragraph at or after point: give up.
+ (setq fill-pfx "")
+ (let ((end (point))
+ (beg (progn (fill-forward-paragraph -1) (point))))
+ (goto-char before)
+ (setq fill-pfx
+ (if use-hard-newlines
+ ;; Can't use fill-region-as-paragraph, since this
+ ;; paragraph may still contain hard newlines. See
+ ;; fill-region.
+ (fill-region beg end justify)
+ (fill-region-as-paragraph beg end justify))))))
+ fill-pfx))))
(declare-function comment-search-forward "newcomment" (limit &optional noerror))
(declare-function comment-string-strip "newcomment" (str beforep afterp))
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 21612cd5e38..2c5e30fecd8 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -1942,9 +1942,7 @@ before point that's highlighted as misspelled."
'face 'flyspell-incorrect
string))
(setq pos (cdr pos)))
- (if (fboundp 'display-message)
- (display-message 'no-log string)
- (message "%s" string))))
+ (message "%s" string)))
;;*---------------------------------------------------------------------*/
;;* flyspell-abbrev-table ... */
@@ -2273,17 +2271,8 @@ If OPOINT is non-nil, restore point there after adjusting it for replacement."
;;*---------------------------------------------------------------------*/
(defun flyspell-emacs-popup (event poss word)
"The Emacs popup menu."
- (if (and (not event)
- (display-mouse-p))
- (let* ((mouse-pos (mouse-position))
- (mouse-pos (if (nth 1 mouse-pos)
- mouse-pos
- (set-mouse-position (car mouse-pos)
- (/ (frame-width) 2) 2)
- (mouse-position))))
- (setq event (list (list (car (cdr mouse-pos))
- (1+ (cdr (cdr mouse-pos))))
- (car mouse-pos)))))
+ (unless event
+ (setq event (popup-menu-normalize-position (point))))
(let* ((corrects (flyspell-sort (car (cdr (cdr poss))) word))
(cor-menu (if (consp corrects)
(mapcar (lambda (correct)
diff --git a/lisp/textmodes/glyphless-mode.el b/lisp/textmodes/glyphless-mode.el
new file mode 100644
index 00000000000..4d48d90b562
--- /dev/null
+++ b/lisp/textmodes/glyphless-mode.el
@@ -0,0 +1,68 @@
+;;; glyphless-mode.el --- minor mode for displaying glyphless characters -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(defcustom glyphless-mode-types '(all)
+ "Which glyphless characters to display.
+The value can be any of the groups supported by
+`glyphless-char-display-control' (which see), and in addition
+`all', for all glyphless characters."
+ :version "29.1"
+ :type '(repeat (choice (const :tag "All" all)
+ (const :tag "No font" no-font)
+ (const :tag "C0 Control" c0-control)
+ (const :tag "C1 Control" c1-control)
+ (const :tag "Format Control" format-control)
+ (const :tag "Bidirectional Control" bidi-control)
+ (const :tag "Variation Selectors" variation-selectors)
+ (const :tag "No Font" no-font)))
+ :group 'display)
+
+;;;###autoload
+(define-minor-mode glyphless-display-mode
+ "Minor mode for displaying glyphless characters in the current buffer.
+If enabled, all glyphless characters will be displayed as boxes
+that display their acronyms."
+ :lighter " Glyphless"
+ (if glyphless-display-mode
+ (progn
+ (setq-local glyphless-char-display
+ (let ((table (make-display-table)))
+ (set-char-table-parent table glyphless-char-display)
+ table))
+ (glyphless-mode--setup))
+ (kill-local-variable 'glyphless-char-display)))
+
+(defun glyphless-mode--setup ()
+ (let ((types (if (memq 'all glyphless-mode-types)
+ '(c0-control c1-control format-control
+ variation-selectors no-font)
+ glyphless-mode-types)))
+ (when types
+ (update-glyphless-char-display
+ nil (mapcar (lambda (e) (cons e 'acronym)) types)))))
+
+(provide 'glyphless-mode)
+
+;;; glyphless-mode.el ends here
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index a4bf454fdcb..8c8522a6e5e 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -296,7 +296,8 @@ The following values are supported:
"Non-nil means suppress messages in `ispell-word'."
:type 'boolean)
-(defvaralias 'ispell-format-word 'ispell-format-word-function)
+(define-obsolete-variable-alias 'ispell-format-word
+ 'ispell-format-word-function "29.1")
(defcustom ispell-format-word-function (function upcase)
"Formatting function for displaying word being spell checked.
@@ -796,6 +797,9 @@ See `ispell-buffer-with-debug' for an example of use."
"An alist of parsed Aspell dicts and associated parameters.
Internal use.")
+(defvar ispell--aspell-found-dictionaries nil
+ "An alist of identified aspell dictionaries.")
+
(defun ispell-find-aspell-dictionaries ()
"Find Aspell's dictionaries, and record in `ispell-aspell-dictionary-alist'."
(let* ((dictionaries
@@ -809,7 +813,8 @@ Internal use.")
(mapcar #'ispell-aspell-find-dictionary dictionaries))))
;; Ensure aspell's alias dictionary will override standard
;; definitions.
- (setq found (ispell-aspell-add-aliases found))
+ (setq found (ispell-aspell-add-aliases found)
+ ispell--aspell-found-dictionaries (copy-sequence found))
;; Merge into FOUND any elements from the standard ispell-dictionary-base-alist
;; which have no element in FOUND at all.
(dolist (dict ispell-dictionary-base-alist)
@@ -1377,9 +1382,11 @@ The variable `ispell-library-directory' defines their location."
(if (and name
(or
;; Include all for Aspell (we already know existing dicts)
- ispell-really-aspell
+ (and ispell-really-aspell
+ (assoc name ispell--aspell-found-dictionaries))
;; Include all if `ispell-library-directory' is nil (Hunspell)
- (not ispell-library-directory)
+ (and (not ispell-really-aspell)
+ (not ispell-library-directory))
;; If explicit (-d with an absolute path) and existing dict.
(and dict-explt
(file-name-absolute-p dict-explt)
@@ -1672,14 +1679,13 @@ Valid forms include:
("\\\\bibliographystyle" ispell-tex-arg-end)
("\\\\makebox" ispell-tex-arg-end 0)
("\\\\e?psfig" ispell-tex-arg-end)
- ("\\\\document\\(class\\|style\\)" .
- "\\\\begin[ \t\n]*{[ \t\n]*document[ \t\n]*}"))
+ ("\\\\document\\(class\\|style\\)" . "\\\\begin[ \t\n]*{document}"))
(;; delimited with \begin. In ispell: displaymath, eqnarray, eqnarray*,
;; equation, minipage, picture, tabular, tabular* (ispell)
("\\(figure\\|table\\)\\*?" ispell-tex-arg-end 0)
("list" ispell-tex-arg-end 2)
- ("program" . "\\\\end[ \t\n]*{[ \t\n]*program[ \t\n]*}")
- ("verbatim\\*?" . "\\\\end[ \t\n]*{[ \t\n]*verbatim\\*?[ \t\n]*}"))))
+ ("program" . "\\\\end[ \t]*{program}")
+ ("verbatim\\*?" . "\\\\end[ \t]*{verbatim\\*?}"))))
"Lists of regions to be skipped in TeX mode.
First list is used raw.
Second list has key placed inside \\begin{}.
@@ -2398,24 +2404,24 @@ Global `ispell-quit' set to start location to continue spell session."
Selections are:
-DIGIT: Replace the word with a digit offered in the *Choices* buffer.
-SPC: Accept word this time.
-`i': Accept word and insert into private dictionary.
-`a': Accept word for this session.
-`A': Accept word and place in `buffer-local dictionary'.
-`r': Replace word with typed-in value. Rechecked.
-`R': Replace word with typed-in value. Query-replaced in buffer. Rechecked.
-`?': Show these commands.
-`x': Exit spelling buffer. Move cursor to original point.
-`X': Exit spelling buffer. Leaves cursor at the current point, and permits
+\\`0'..\\`9' Replace the word with a digit offered in the *Choices* buffer.
+\\`SPC' Accept word this time.
+\\`i' Accept word and insert into private dictionary.
+\\`a' Accept word for this session.
+\\`A' Accept word and place in `buffer-local dictionary'.
+\\`r' Replace word with typed-in value. Rechecked.
+\\`R' Replace word with typed-in value. Query-replaced in buffer. Rechecked.
+\\`?' Show these commands.
+\\`x' Exit spelling buffer. Move cursor to original point.
+\\`X' Exit spelling buffer. Leaves cursor at the current point, and permits
the aborted check to be completed later.
-`q': Quit spelling session (Kills ispell process).
-`l': Look up typed-in replacement in alternate dictionary. Wildcards okay.
-`u': Like `i', but the word is lower-cased first.
-`m': Place typed-in value in personal dictionary, then recheck current word.
-`C-l': Redraw screen.
-`C-r': Recursive edit.
-`C-z': Suspend Emacs or iconify frame."
+\\`q' Quit spelling session (Kills ispell process).
+\\`l' Look up typed-in replacement in alternate dictionary. Wildcards okay.
+\\`u' Like \\`i', but the word is lower-cased first.
+\\`m' Place typed-in value in personal dictionary, then recheck current word.
+\\`C-l' Redraw screen.
+\\`C-r' Recursive edit.
+\\`C-z' Suspend Emacs or iconify frame."
(if (equal ispell-help-in-bufferp 'electric)
(progn
@@ -2428,26 +2434,28 @@ SPC: Accept word this time.
;;(if (< (window-height) 15)
;; (enlarge-window
;; (- 15 (ispell-adjusted-window-height))))
- (princ "Selections are:
-
-DIGIT: Replace the word with a digit offered in the *Choices* buffer.
-SPC: Accept word this time.
-`i': Accept word and insert into private dictionary.
-`a': Accept word for this session.
-`A': Accept word and place in `buffer-local dictionary'.
-`r': Replace word with typed-in value. Rechecked.
-`R': Replace word with typed-in value. Query-replaced in buffer. Rechecked.
-`?': Show these commands.
-`x': Exit spelling buffer. Move cursor to original point.
-`X': Exit spelling buffer. Leaves cursor at the current point, and permits
- the aborted check to be completed later.
-`q': Quit spelling session (Kills ispell process).
-`l': Look up typed-in replacement in alternate dictionary. Wildcards okay.
-`u': Like `i', but the word is lower-cased first.
-`m': Place typed-in value in personal dictionary, then recheck current word.
-`C-l': Redraw screen.
-`C-r': Recursive edit.
-`C-z': Suspend Emacs or iconify frame.")
+ (princ
+ (substitute-command-keys
+ "Selections are:
+
+\\`0'..\\`9' Replace the word with a digit offered in the *Choices* buffer.
+\\`SPC' Accept word this time.
+\\`i' Accept word and insert into private dictionary.
+\\`a' Accept word for this session.
+\\`A' Accept word and place in `buffer-local dictionary'.
+\\`r' Replace word with typed-in value. Rechecked.
+\\`R' Replace word with typed-in value. Query-replaced in buffer. Rechecked.
+\\`?' Show these commands.
+\\`x' Exit spelling buffer. Move cursor to original point.
+\\`X' Exit spelling buffer. Leaves cursor at the current point, and permits
+ the aborted check to be completed later.
+\\`q' Quit spelling session (Kills ispell process).
+\\`l' Look up typed-in replacement in alternate dictionary. Wildcards okay.
+\\`u' Like \\`i', but the word is lower-cased first.
+\\`m' Place typed-in value in personal dictionary, then recheck current word.
+\\`C-l' Redraw screen.
+\\`C-r' Recursive edit.
+\\`C-z' Suspend Emacs or iconify frame."))
nil)))
@@ -2607,15 +2615,18 @@ Optional REFRESH will unhighlighted then highlight, using block cursor
(text (buffer-substring-no-properties start end))
; Save highlight region.
(inhibit-quit t) ; inhibit interrupt processing here.
- (buffer-undo-list t)) ; don't clutter the undo list.
+ (buffer-undo-list t) ; don't clutter the undo list.
+ (end1 (if (markerp end) (marker-position end) end)))
(goto-char end)
(delete-region start end)
- (insert-char ? (- end start)) ; minimize amount of redisplay
+ (insert-char ? (- end1 start)) ; minimize amount of redisplay
(sit-for 0) ; update display
(if highlight (setq inverse-video (not inverse-video))) ; toggle video
- (delete-region start end) ; delete whitespace
+ (delete-region start end1) ; delete whitespace
(insert text) ; insert text in inverse video.
(sit-for 0) ; update display showing inverse video.
+ (if (markerp end)
+ (set-marker end end1)) ; restore marker position
(if (not highlight)
(goto-char end)
(setq inverse-video (not inverse-video)) ; toggle video
@@ -2984,8 +2995,7 @@ By just answering RET you can find out what the current dictionary is."
(interactive
(list (completing-read
"Use new dictionary (RET for current, SPC to complete): "
- (and (fboundp 'ispell-valid-dictionary-list)
- (mapcar #'list (ispell-valid-dictionary-list)))
+ (mapcar #'list (ispell-valid-dictionary-list))
nil t)
current-prefix-arg))
(ispell-set-spellchecker-params) ; Initialize variables and dicts alists
@@ -3045,6 +3055,8 @@ when needed."
;;;###autoload
(defun ispell-region (reg-start reg-end &optional recheckp shift)
"Interactively check a region for spelling errors.
+Leave the mark at the last misspelled word that the user was queried about.
+
Return nil if spell session was terminated, otherwise returns shift offset
amount for last line processed."
(interactive "r") ; Don't flag errors on read-only bufs.
@@ -3056,7 +3068,8 @@ amount for last line processed."
(region-type (if (and (= reg-start (point-min)) (= reg-end (point-max)))
(buffer-name) "region"))
(program-basename (file-name-nondirectory ispell-program-name))
- (dictionary (or ispell-current-dictionary "default")))
+ (dictionary (or ispell-current-dictionary "default"))
+ max-word)
(unwind-protect
(save-excursion
(message "Spell-checking %s using %s with %s dictionary..."
@@ -3152,10 +3165,14 @@ ispell-region: Search for first region to skip after (ispell-begin-skip-region-r
;; Reset `in-comment' (and indirectly `add-comment') for new line
in-comment nil))
(setq ispell-end (point)) ; "end" tracks region retrieved.
- (if string ; there is something to spell check!
- ;; (special start end)
- (setq shift (ispell-process-line string
- (and recheckp shift))))
+ ;; There is something to spell check!
+ (when string
+ ;; (special start end)
+ (let ((res (ispell-process-line string
+ (and recheckp shift))))
+ (setq shift (car res))
+ (when (cdr res)
+ (setq max-word (cdr res)))))
(goto-char ispell-end)))))
(if ispell-quit
nil
@@ -3166,6 +3183,9 @@ ispell-region: Search for first region to skip after (ispell-begin-skip-region-r
(kill-buffer ispell-choices-buffer))
(set-marker skip-region-start nil)
(set-marker rstart nil)
+ ;; Allow the user to pop back to the last position.
+ (when max-word
+ (push-mark max-word t))
(if ispell-quit
(progn
;; preserve or clear the region for ispell-continue.
@@ -3400,9 +3420,12 @@ Returns a string with the line data."
This will modify the buffer for spelling errors.
Requires variables ISPELL-START and ISPELL-END to be defined in its
dynamic scope.
-Returns the sum SHIFT due to changes in word replacements."
+
+Returns a cons cell where the `car' is sum SHIFT due to changes
+in word replacements, and the `cdr' is the location of the final
+word that was queried about."
;;(declare special ispell-start ispell-end)
- (let (poss accept-list)
+ (let (poss accept-list max-word)
(if (not (numberp shift))
(setq shift 0))
;; send string to spell process and get input.
@@ -3456,6 +3479,7 @@ Returns the sum SHIFT due to changes in word replacements."
(error (concat "Ispell misalignment: word "
"`%s' point %d; probably incompatible versions")
ispell-pipe-word actual-point)))
+ (setq max-word (marker-position word-start))
;; ispell-cmd-loop can go recursive & change buffer
(if ispell-keep-choices-win
(setq replace (ispell-command-loop
@@ -3552,7 +3576,7 @@ Returns the sum SHIFT due to changes in word replacements."
(set-marker line-end nil)))
;; Finished with misspelling!
(setq ispell-filter (cdr ispell-filter)))
- shift))
+ (cons shift max-word)))
;;;###autoload
@@ -3593,7 +3617,8 @@ to limit the check."
;;;###autoload
(defun ispell-buffer ()
- "Check the current buffer for spelling errors interactively."
+ "Check the current buffer for spelling errors interactively.
+Leave the mark at the last misspelled word that the user was queried about."
(interactive)
(ispell-region (point-min) (point-max)))
@@ -3883,8 +3908,8 @@ Don't check spelling of message headers except the Subject field.
Don't check included messages.
To abort spell checking of a message region and send the message anyway,
-use the `x' command. (Any subsequent regions will be checked.)
-The `X' command aborts sending the message so that you can edit the buffer.
+use the \\`x' command. (Any subsequent regions will be checked.)
+The \\`X' command aborts sending the message so that you can edit the buffer.
To spell-check whenever a message is sent, include the appropriate lines
in your init file:
@@ -3975,7 +4000,7 @@ You can bind this to the key C-c i in GNUS or mail by adding to
(if (re-search-forward "^Subject: *" end-of-headers t)
(progn
(goto-char (match-end 0))
- (if (and (not (looking-at ".*Re\\>"))
+ (if (and (not (looking-at ".*\\<Re\\>"))
(not (looking-at "\\[")))
(progn
(setq case-fold-search old-case-fold-search)
diff --git a/lisp/textmodes/page-ext.el b/lisp/textmodes/page-ext.el
index 24149f9afb8..6b71f26e4f2 100644
--- a/lisp/textmodes/page-ext.el
+++ b/lisp/textmodes/page-ext.el
@@ -515,13 +515,12 @@ resets the page-delimiter to the original value."
(defvar pages-buffer-original-position)
(defvar pages-buffer-original-page)
-(defun pages-directory
- (pages-list-all-headers-p count-lines-p &optional regexp)
+(defun pages-directory (pages-list-all-headers-p count-lines-p &optional regexp)
"Display a directory of the page headers in a temporary buffer.
A header is the first non-blank line after the `page-delimiter'.
-\\[pages-directory-mode]
+\\<pages-directory-mode-map>
You may move point to one of the lines in the temporary buffer,
-then use \\<pages-directory-goto> to go to the same line in the pages buffer.
+then use \\[pages-directory-goto] to go to the same line in the pages buffer.
In interactive use:
@@ -587,7 +586,9 @@ directory for only the accessible portion of the buffer."
(pages-directory-mode)
(setq buffer-read-only nil)
(insert
- "==== Pages Directory: use `C-c C-c' to go to page under cursor. ====" ?\n)
+ (substitute-command-keys
+ "==== Pages Directory: use \\<pages-directory-mode-map>\
+\\[pages-directory-goto] to go to page under cursor. ====") "\n")
(setq pages-buffer pages-target-buffer)
(setq pages-pos-list nil))
@@ -772,7 +773,9 @@ directory."
(goto-char (point-min))
(delete-region (point) (line-end-position))
(insert
- "=== Address List Directory: use `C-c C-c' to go to page under cursor. ===")
+ (substitute-command-keys
+ "=== Address List Directory: use \\<pages-directory-mode-map>\
+\\[pages-directory-goto] to go to page under cursor. ==="))
(set-buffer-modified-p nil)
))
(error "No addresses file found!")))
diff --git a/lisp/textmodes/page.el b/lisp/textmodes/page.el
index 3fc18323349..5d6f017eb99 100644
--- a/lisp/textmodes/page.el
+++ b/lisp/textmodes/page.el
@@ -35,11 +35,18 @@ A page boundary is any line whose beginning matches the regexp
(interactive "p")
(or count (setq count 1))
(while (and (> count 0) (not (eobp)))
- ;; In case the page-delimiter matches the null string,
- ;; don't find a match without moving.
- (if (bolp) (forward-char 1))
- (unless (re-search-forward page-delimiter nil t)
- (goto-char (point-max)))
+ (if (and (looking-at page-delimiter)
+ (> (match-end 0) (point)))
+ ;; If we're standing at the page delimiter, then just skip to
+ ;; the end of it. (But only if it's not a zero-length
+ ;; delimiter, because then we wouldn't have forward progress.)
+ (goto-char (match-end 0))
+ ;; In case the page-delimiter matches the null string,
+ ;; don't find a match without moving.
+ (when (bolp)
+ (forward-char 1))
+ (unless (re-search-forward page-delimiter nil t)
+ (goto-char (point-max))))
(setq count (1- count)))
(while (and (< count 0) (not (bobp)))
;; In case the page-delimiter matches the null string,
diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el
index 29804c3bfd2..cd726ad4776 100644
--- a/lisp/textmodes/paragraphs.el
+++ b/lisp/textmodes/paragraphs.el
@@ -96,8 +96,8 @@ lines that start paragraphs from lines that separate them.
If the variable `use-hard-newlines' is non-nil, then only lines following a
hard newline are considered to match."
- :type 'regexp)
-(put 'paragraph-start 'safe-local-variable #'stringp)
+ :type 'regexp
+ :safe #'stringp)
;; paragraph-start requires a hard newline, but paragraph-separate does not:
;; It is assumed that paragraph-separate is distinctive enough to be believed
@@ -113,8 +113,8 @@ This is matched against the text at the left margin, which is not necessarily
the beginning of the line, so it should not use \"^\" as an anchor. This
ensures that the paragraph functions will work equally within a region of
text indented by a margin setting."
- :type 'regexp)
-(put 'paragraph-separate 'safe-local-variable #'stringp)
+ :type 'regexp
+ :safe #'stringp)
(defcustom sentence-end-double-space t
"Non-nil means a single space does not end a sentence.
@@ -125,8 +125,8 @@ This value is used by the function `sentence-end' to construct the
regexp describing the end of a sentence, when the value of the variable
`sentence-end' is nil. See Info node `(elisp)Standard Regexps'."
:type 'boolean
+ :safe #'booleanp
:group 'fill)
-(put 'sentence-end-double-space 'safe-local-variable #'booleanp)
(defcustom sentence-end-without-period nil
"Non-nil means a sentence will end without a period.
@@ -137,8 +137,8 @@ This value is used by the function `sentence-end' to construct the
regexp describing the end of a sentence, when the value of the variable
`sentence-end' is nil. See Info node `(elisp)Standard Regexps'."
:type 'boolean
+ :safe #'booleanp
:group 'fill)
-(put 'sentence-end-without-period 'safe-local-variable #'booleanp)
(defcustom sentence-end-without-space
"。.?!"
@@ -147,8 +147,8 @@ regexp describing the end of a sentence, when the value of the variable
This value is used by the function `sentence-end' to construct the
regexp describing the end of a sentence, when the value of the variable
`sentence-end' is nil. See Info node `(elisp)Standard Regexps'."
- :type 'string)
-(put 'sentence-end-without-space 'safe-local-variable #'stringp)
+ :type 'string
+ :safe #'stringp)
(defcustom sentence-end nil
"Regexp describing the end of a sentence.
@@ -158,14 +158,14 @@ All paragraph boundaries also end sentences, regardless.
The value nil means to use the default value defined by the
function `sentence-end'. You should always use this function
to obtain the value of this variable."
- :type '(choice regexp (const :tag "Use default value" nil)))
-(put 'sentence-end 'safe-local-variable #'string-or-null-p)
+ :type '(choice regexp (const :tag "Use default value" nil))
+ :safe #'string-or-null-p)
(defcustom sentence-end-base "[.?!…‽][]\"'”’)}»›]*"
"Regexp matching the basic end of a sentence, not including following space."
:type 'regexp
+ :safe #'stringp
:version "25.1")
-(put 'sentence-end-base 'safe-local-variable #'stringp)
(defun sentence-end ()
"Return the regexp describing the end of a sentence.
@@ -192,14 +192,14 @@ in between. See Info node `(elisp)Standard Regexps'."
(defcustom page-delimiter "^\014"
"Regexp describing line-beginnings that separate pages."
- :type 'regexp)
-(put 'page-delimiter 'safe-local-variable #'stringp)
+ :type 'regexp
+ :safe #'stringp)
(defcustom paragraph-ignore-fill-prefix nil
"Non-nil means the paragraph commands are not affected by `fill-prefix'.
This is desirable in modes where blank lines are the paragraph delimiters."
- :type 'boolean)
-(put 'paragraph-ignore-fill-prefix 'safe-local-variable #'booleanp)
+ :type 'boolean
+ :safe #'booleanp)
;; Silence the compiler.
(defun forward-paragraph (&optional arg)
@@ -477,20 +477,60 @@ sentences. Also, every paragraph boundary terminates sentences as well."
(skip-chars-backward " \t\n")
(goto-char par-end)))
(setq arg (1- arg)))
- (constrain-to-field nil opoint t)))
-
-(defun repunctuate-sentences (&optional no-query)
+ (let ((npoint (constrain-to-field nil opoint t)))
+ (not (= npoint opoint)))))
+
+(defun count-sentences (start end)
+ "Count sentences in current buffer from START to END."
+ (let ((sentences 0)
+ (inhibit-field-text-motion t))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (while (ignore-errors (forward-sentence))
+ (setq sentences (1+ sentences)))
+ ;; Remove last possibly empty sentence
+ (when (/= (skip-chars-backward " \t\n") 0)
+ (setq sentences (1- sentences)))
+ sentences))))
+
+(defun repunctuate-sentences-filter (_start _end)
+ "Search filter used by `repunctuate-sentences' to skip unneeded spaces.
+By default, it skips occurrences that already have two spaces."
+ (/= 2 (- (point) (save-excursion (skip-chars-backward " ") (point)))))
+
+(defvar repunctuate-sentences-filter #'repunctuate-sentences-filter
+ "The default filter used by `repunctuate-sentences'.
+It is advised to use `add-function' on this to add more filters,
+for example, `(looking-back (rx (or \"e.g.\" \"i.e.\") \" \") 5)'
+with a set of predefined abbreviations to skip from adding two spaces.")
+
+(defun repunctuate-sentences (&optional no-query start end)
"Put two spaces at the end of sentences from point to the end of buffer.
-It works using `query-replace-regexp'.
-If optional argument NO-QUERY is non-nil, make changes without
-asking for confirmation."
- (interactive)
+It works using `query-replace-regexp'. In Transient Mark mode,
+if the mark is active, operate on the contents of the region.
+Second and third arg START and END specify the region to operate on.
+If optional argument NO-QUERY is non-nil, make changes without asking
+for confirmation. You can use `repunctuate-sentences-filter' to add
+filters to skip occurrences of spaces that don't need to be replaced."
+ (interactive (list nil
+ (if (use-region-p) (region-beginning))
+ (if (use-region-p) (region-end))))
(let ((regexp "\\([]\"')]?\\)\\([.?!]\\)\\([]\"')]?\\) +")
(to-string "\\1\\2\\3 "))
(if no-query
- (while (re-search-forward regexp nil t)
- (replace-match to-string))
- (query-replace-regexp regexp to-string))))
+ (progn
+ (when start (goto-char start))
+ (while (re-search-forward regexp end t)
+ (replace-match to-string)))
+ (unwind-protect
+ (progn
+ (add-function :after-while isearch-filter-predicate
+ repunctuate-sentences-filter)
+ (query-replace-regexp regexp to-string nil start end))
+ (remove-function isearch-filter-predicate
+ repunctuate-sentences-filter)))))
(defun backward-sentence (&optional arg)
diff --git a/lisp/textmodes/pixel-fill.el b/lisp/textmodes/pixel-fill.el
new file mode 100644
index 00000000000..e47653e734a
--- /dev/null
+++ b/lisp/textmodes/pixel-fill.el
@@ -0,0 +1,240 @@
+;;; pixel-fill.el --- variable pitch filling functions -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+;; Keywords: filling
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The main entry point is `pixel-fill-region', but
+;; `pixel-fill-find-fill-point' can also be useful by itself.
+
+;;; Code:
+
+(require 'kinsoku)
+
+(defgroup pixel-fill nil
+ "Filling based on pixel widths."
+ :group 'fill
+ :version "29.1")
+
+(defcustom pixel-fill-respect-kinsoku t
+ "If nil, fill even if we can't find a good kinsoku point.
+Kinsoku is a Japanese word meaning a rule that should not be violated.
+In Emacs, it is a term used for characters, e.g. punctuation marks,
+parentheses, and so on, that should not be placed in the beginning
+of a line or the end of a line."
+ :type 'boolean
+ :version "29.1")
+
+(defun pixel-fill-width (&optional columns window)
+ "Return the pixel width corresponding to COLUMNS in WINDOW.
+If COLUMNS is nil or omitted, use the entire window width.
+
+If WINDOW is nil or omitted, this defaults to the selected window."
+ (unless window
+ (setq window (selected-window)))
+ (let ((frame (window-frame window)))
+ (if columns
+ (* (frame-char-width frame) columns)
+ (- (window-body-width nil t)
+ (* 2 (frame-char-width frame))
+ ;; We need to adjust the available width for when the user
+ ;; disables the fringes, which will cause the display
+ ;; engine usurp one column for the continuation glyph.
+ (if (and (fboundp 'fringe-columns)
+ (or (not (zerop (fringe-columns 'right)))
+ (not (zerop (fringe-columns 'left)))))
+ 0
+ (* (frame-char-width frame) 2))
+ 1))))
+
+(defun pixel-fill-region (start end pixel-width)
+ "Fill the region between START and END.
+This will attempt to reformat the text in the region to have no
+lines that are visually wider than PIXEL-WIDTH.
+
+If START isn't at the start of a line, the horizontal position of
+START, converted to pixel units, will be used as the indentation
+prefix on subsequent lines."
+ (save-excursion
+ (goto-char start)
+ (let ((indentation
+ (car (window-text-pixel-size nil (line-beginning-position)
+ (point))))
+ (newline-end nil))
+ (when (> indentation pixel-width)
+ (error "The indentation (%s) is wider than the fill width (%s)"
+ indentation pixel-width))
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-max))
+ (when (looking-back "\n[ \t]*" (point-min))
+ (setq newline-end t))
+ (goto-char (point-min))
+ ;; First replace all whitespace with space.
+ (while (re-search-forward "[ \t\n]+" nil t)
+ (cond
+ ((or (= (match-beginning 0) start)
+ (= (match-end 0) end))
+ (delete-region (match-beginning 0) (match-end 0)))
+ ;; If there's just a single space here, don't replace.
+ ((not (and (= (- (match-end 0) (match-beginning 0)) 1)
+ (= (char-after (match-beginning 0)) ?\s)))
+ (replace-match
+ ;; We need to use a space that has an appropriate width.
+ (propertize " " 'face
+ (get-text-property (match-beginning 0) 'face))))))
+ (goto-char start)
+ (pixel-fill--fill-line pixel-width indentation)
+ (goto-char (point-max))
+ (when newline-end
+ (insert "\n"))))))
+
+(defun pixel-fill--goto-pixel (width)
+ (vertical-motion (cons (/ width (frame-char-width)) 0)))
+
+(defun pixel-fill--fill-line (width &optional indentation)
+ (let ((start (point)))
+ (pixel-fill--goto-pixel width)
+ (while (not (eolp))
+ ;; We have to do some folding. First find the first previous
+ ;; point suitable for folding.
+ (when (or (not (pixel-fill-find-fill-point (line-beginning-position)))
+ (= (point) start))
+ ;; We had unbreakable text (for this width), so just go to
+ ;; the first space and carry on.
+ (beginning-of-line)
+ (skip-chars-forward " ")
+ (search-forward " " (line-end-position) 'move))
+ (when (= (preceding-char) ?\s)
+ (delete-char -1))
+ (unless (eobp)
+ (insert ?\n)
+ (when (> indentation 0)
+ (insert (propertize " " 'display
+ (list 'space :align-to (list indentation))))))
+ (setq start (point))
+ (unless (eobp)
+ (pixel-fill--goto-pixel width)))))
+
+(define-inline pixel-fill--char-breakable-p (char)
+ "Return non-nil if a line can be broken before and after CHAR."
+ (inline-quote (aref fill-find-break-point-function-table ,char)))
+
+(define-inline pixel-fill--char-nospace-p (char)
+ "Return non-nil if no space is required before and after CHAR."
+ (inline-quote (aref fill-nospace-between-words-table ,char)))
+
+(define-inline pixel-fill--char-kinsoku-bol-p (char)
+ "Return non-nil if a line ought not to begin with CHAR."
+ (inline-letevals (char)
+ (inline-quote (and (not (eq ,char ?'))
+ (aref (char-category-set ,char) ?>)))))
+
+(define-inline pixel-fill--char-kinsoku-eol-p (char)
+ "Return non-nil if a line ought not to end with CHAR."
+ (inline-quote (aref (char-category-set ,char) ?<)))
+
+(defun pixel-fill-find-fill-point (start)
+ "Find a place suitable for breaking the current line.
+START should be the earliest buffer position that should be considered
+(typically the start of the line), and this function will search
+backward in the current buffer from the current position."
+ (let ((bp (point))
+ (end (point))
+ failed)
+ (while (not
+ (or (setq failed (<= (point) start))
+ (eq (preceding-char) ?\s)
+ (eq (following-char) ?\s)
+ (pixel-fill--char-breakable-p (preceding-char))
+ (pixel-fill--char-breakable-p (following-char))
+ (and (pixel-fill--char-kinsoku-bol-p (preceding-char))
+ (pixel-fill--char-breakable-p (following-char))
+ (not (pixel-fill--char-kinsoku-bol-p (following-char))))
+ (pixel-fill--char-kinsoku-eol-p (following-char))
+ (bolp)))
+ (backward-char 1))
+ (if failed
+ ;; There's no breakable point, so we give it up.
+ (let (found)
+ (goto-char bp)
+ ;; Don't overflow the window edge, even if
+ ;; `pixel-fill-respect-kinsoku' is t.
+ (when pixel-fill-respect-kinsoku
+ (while (setq found (re-search-forward
+ "\\(\\c>\\)\\| \\|\\c<\\|\\c|"
+ (line-end-position) 'move)))
+ (if (and found
+ (not (match-beginning 1)))
+ (goto-char (match-beginning 0)))))
+ (or
+ (eolp)
+ ;; Don't put kinsoku-bol characters at the beginning of a line,
+ ;; or kinsoku-eol characters at the end of a line.
+ (cond
+ ;; Don't overflow the window edge, even if `pixel-fill-respect-kinsoku'
+ ;; is t.
+ ((not pixel-fill-respect-kinsoku)
+ (while (and (not (eq (preceding-char) ?\s))
+ (or (pixel-fill--char-kinsoku-eol-p (preceding-char))
+ (pixel-fill--char-kinsoku-bol-p (following-char))))
+ (backward-char 1))
+ (when (setq failed (<= (point) start))
+ ;; There's no breakable point that doesn't violate kinsoku,
+ ;; so we look for the second best position.
+ (while (and (progn
+ (forward-char 1)
+ (<= (point) end))
+ (progn
+ (setq bp (point))
+ (pixel-fill--char-kinsoku-eol-p (following-char)))))
+ (goto-char bp)))
+ ((pixel-fill--char-kinsoku-eol-p (preceding-char))
+ ;; Find backward the point where kinsoku-eol characters begin.
+ (let ((count 4))
+ (while
+ (progn
+ (backward-char 1)
+ (and (> (setq count (1- count)) 0)
+ (not (eq (preceding-char) ?\s))
+ (or (pixel-fill--char-kinsoku-eol-p (preceding-char))
+ (pixel-fill--char-kinsoku-bol-p (following-char)))))))
+ (when (setq failed (<= (point) start))
+ ;; There's no breakable point that doesn't violate kinsoku,
+ ;; so we go to the second best position.
+ (if (looking-at "\\(\\c<+\\)\\c<")
+ (goto-char (match-end 1))
+ (forward-char 1))))
+ ((pixel-fill--char-kinsoku-bol-p (following-char))
+ ;; Find forward the point where kinsoku-bol characters end.
+ (let ((count 4))
+ (while (progn
+ (forward-char 1)
+ (and (>= (setq count (1- count)) 0)
+ (pixel-fill--char-kinsoku-bol-p (following-char))
+ (pixel-fill--char-breakable-p (following-char))))))))
+ (when (eq (following-char) ?\s)
+ (forward-char 1))))
+ (not failed)))
+
+(provide 'pixel-fill)
+
+;;; pixel-fill.el ends here
diff --git a/lisp/textmodes/reftex-cite.el b/lisp/textmodes/reftex-cite.el
index 4e487d745c2..26b14ebc79e 100644
--- a/lisp/textmodes/reftex-cite.el
+++ b/lisp/textmodes/reftex-cite.el
@@ -360,7 +360,7 @@ The name of the first different author/editor is used."
;; Parse the bibliography environment
(defun reftex-extract-bib-entries-from-thebibliography (files)
- "Extract bib-entries from the \begin{thebibliography} environment.
+ "Extract bib-entries from the \\begin{thebibliography} environment.
Parsing is not as good as for the BibTeX database stuff.
The environment should be located in FILES."
(let* (start end buf entries re re-list file default)
@@ -580,7 +580,7 @@ If FORMAT is non-nil `format' entry accordingly."
(concat key "\n " authors " " year " " extra "\n " title "\n\n")))
(defun reftex-parse-bibitem (item)
- "Parse a \bibitem entry in ITEM."
+ "Parse a \\bibitem entry in ITEM."
(let ((key "") (text ""))
(when (string-match "\\`{\\([^}]+\\)}\\([^\000]*\\)" item)
(setq key (match-string 1 item)
@@ -596,7 +596,7 @@ If FORMAT is non-nil `format' entry accordingly."
(cons "&entry" (concat key " " text)))))
(defun reftex-format-bibitem (item)
- "Format a \bibitem entry in ITEM so that it is (relatively) nice to look at."
+ "Format a \\bibitem entry in ITEM so that it is (relatively) nice to look at."
(let ((text (reftex-get-bib-field "&text" item))
(key (reftex-get-bib-field "&key" item))
(lines nil))
diff --git a/lisp/textmodes/reftex-global.el b/lisp/textmodes/reftex-global.el
index c7e34b4b90a..062cea9c505 100644
--- a/lisp/textmodes/reftex-global.el
+++ b/lisp/textmodes/reftex-global.el
@@ -154,8 +154,10 @@ No active TAGS table is required."
(erase-buffer)
(insert " MULTIPLE LABELS IN CURRENT DOCUMENT:\n")
(insert
- " Move point to label and type `r' to run a query-replace on the label\n"
- " and its references. Type `q' to exit this buffer.\n\n")
+ (substitute-command-keys
+ " Move point to label and type \\`r' to run a query-replace on the label\n")
+ (substitute-command-keys
+ " and its references. Type \\`q' to exit this buffer.\n\n"))
(insert " LABEL FILE\n")
(insert " -------------------------------------------------------------\n")
(use-local-map (make-sparse-keymap))
@@ -188,8 +190,8 @@ No active TAGS table is required."
default))))
(if (string= from "") (setq from default))
(unless to
- (setq to (read-string (format "Replace label %s with: "
- from))))
+ (setq to (read-string (format "Replace label %s with: " from)
+ nil nil from)))
(reftex-query-replace-document
(concat "{" (regexp-quote from) "}")
(format "{%s}" to))))
diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el
index c28f31d5647..b517cc16634 100644
--- a/lisp/textmodes/reftex-index.el
+++ b/lisp/textmodes/reftex-index.el
@@ -29,9 +29,7 @@
(require 'reftex)
-;; START remove for XEmacs release
(defvar TeX-master)
-;; END remove for XEmacs release
;;;###autoload
(defun reftex-index-selection-or-word (&optional arg phrase)
@@ -271,8 +269,6 @@ will prompt for other arguments."
(and newtag (cdr cell) (not (member newtag (cdr cell)))
(push newtag (cdr cell)))))
-(define-obsolete-variable-alias
- 'reftex-index-map 'reftex-index-mode-map "24.1")
(defvar reftex-index-mode-map
(let ((map (make-sparse-keymap)))
;; Index map
@@ -1200,8 +1196,6 @@ This gets refreshed in every phrases command.")
'((reftex-index-phrases-font-lock-keywords)
nil t nil beginning-of-line)
"Font lock defaults for `reftex-index-phrases-mode'.")
-(define-obsolete-variable-alias
- 'reftex-index-phrases-map 'reftex-index-phrases-mode-map "24.1")
(defvar reftex-index-phrases-mode-map
(let ((map (make-sparse-keymap)))
;; Keybindings and Menu for phrases buffer
@@ -1274,10 +1268,11 @@ This gets refreshed in every phrases command.")
;;;###autoload
(defun reftex-index-phrase-selection-or-word (arg)
"Add current selection or word at point to the phrases buffer.
+\\<reftex-index-phrases-mode-map>
When you are in transient-mark-mode and the region is active, the
selection will be used - otherwise the word at point.
You get a chance to edit the entry in the phrases buffer - finish with
-`C-c C-c'."
+\\[reftex-index-phrases-save-and-return]."
(interactive "P")
(set-marker reftex-index-return-marker (point))
(reftex-index-selection-or-word arg 'phrase)
@@ -1375,7 +1370,7 @@ If the buffer is non-empty, delete the old header first."
;;;###autoload
(define-derived-mode reftex-index-phrases-mode fundamental-mode "Phrases"
"Major mode for managing the Index phrases of a LaTeX document.
-This buffer was created with RefTeX.
+This buffer was created with RefTeX. \\<reftex-index-phrases-mode-map>
To insert new phrases, use
- `C-c \\' in the LaTeX document to copy selection or word
@@ -1686,8 +1681,8 @@ this function repeatedly."
(defun reftex-index-phrases-set-macro-key ()
"Change the macro key for the current line.
Prompts for a macro key and insert is at the beginning of the line.
-If you reply with SPACE, the macro keyn will be removed, so that the
-default macro will be used. If you reply with `RET', just prints
+If you reply with \\`SPC', the macro key will be removed, so that the
+default macro will be used. If you reply with \\`RET', just prints
information about the currently selected macro."
(interactive)
(reftex-index-phrases-parse-header)
diff --git a/lisp/textmodes/reftex-parse.el b/lisp/textmodes/reftex-parse.el
index e34c45178b4..49cef297882 100644
--- a/lisp/textmodes/reftex-parse.el
+++ b/lisp/textmodes/reftex-parse.el
@@ -345,7 +345,17 @@ of master file."
;; Find external document specifications
(goto-char 1)
- (while (re-search-forward "[\n\r][ \t]*\\\\externaldocument\\(\\[\\([^]]*\\)\\]\\)?{\\([^}]+\\)}" nil t)
+ (while (re-search-forward
+ (concat "[\n\r][ \t]*"
+ ;; Support \externalcitedocument macro
+ "\\\\external\\(?:cite\\)?document"
+ ;; The optional prefix
+ "\\(\\[\\([^]]*\\)\\]\\)?"
+ ;; The 2nd opt. arg can only be nocite
+ "\\(?:\\[nocite\\]\\)?"
+ ;; Mandatory file argument
+ "{\\([^}]+\\)}")
+ nil t)
(push (list 'xr-doc (reftex-match-string 2)
(reftex-match-string 3))
docstruct))
@@ -360,13 +370,18 @@ of master file."
docstruct))
(defun reftex-using-biblatex-p ()
- "Return non-nil if we are using biblatex rather than bibtex."
+ "Return non-nil if we are using biblatex or other specific cite package.
+biblatex and other similar packages like multibib allow multiple macro
+calls to load a bibliography file. This function should be able to
+detect those packages."
(if (boundp 'TeX-active-styles)
;; the sophisticated AUCTeX way
- (member "biblatex" TeX-active-styles)
+ (or (member "biblatex" TeX-active-styles)
+ (member "multibib" TeX-active-styles))
;; poor-man's check...
(save-excursion
- (re-search-forward "^[^%\n]*?\\\\usepackage.*{biblatex}" nil t))))
+ (re-search-forward
+ "^[^%\n]*?\\\\usepackage\\(\\[[^]]*\\]\\)?{biblatex\\|multibib}" nil t))))
;;;###autoload
(defun reftex-locate-bibliography-files (master-dir &optional files)
@@ -374,7 +389,7 @@ of master file."
(unless files
(save-excursion
(goto-char (point-min))
- ;; when biblatex is used, multiple \bibliography or
+ ;; when biblatex or multibib are used, multiple \bibliography or
;; \addbibresource macros are allowed. With plain bibtex, only
;; the first is used.
(let ((using-biblatex (reftex-using-biblatex-p))
@@ -382,7 +397,7 @@ of master file."
(while (and again
(re-search-forward
(concat
- ;; "\\(\\`\\|[\n\r]\\)[^%]*\\\\\\("
+ ;; "\\(\\`\\|[\n\r]\\)[^%]*\\\\\\("
"\\(^\\)[^%\n\r]*\\\\\\("
(mapconcat #'identity reftex-bibliography-commands "\\|")
"\\)\\(\\[.+?\\]\\)?{[ \t]*\\([^}]+\\)")
@@ -405,7 +420,7 @@ of master file."
;; find the file
(reftex-locate-file x "bib" master-dir)))
files))
- (delq nil files)))
+ (delq nil (delete-dups files))))
(defun reftex-replace-label-list-segment (old insert &optional entirely)
"Replace the segment in OLD which corresponds to INSERT.
diff --git a/lisp/textmodes/reftex-sel.el b/lisp/textmodes/reftex-sel.el
index d77411483f7..5942801a8a9 100644
--- a/lisp/textmodes/reftex-sel.el
+++ b/lisp/textmodes/reftex-sel.el
@@ -59,8 +59,6 @@
(define-key map [follow-link] 'mouse-face)
map))
-(define-obsolete-variable-alias
- 'reftex-select-label-map 'reftex-select-label-mode-map "24.1")
(defvar reftex-select-label-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map reftex-select-shared-map)
@@ -109,8 +107,6 @@ During a selection process, these are the local bindings.
;; We do not set a local map - reftex-select-item does this.
)
-(define-obsolete-variable-alias
- 'reftex-select-bib-map 'reftex-select-bib-mode-map "24.1")
(defvar reftex-select-bib-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map reftex-select-shared-map)
diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el
index 4ba3c2193ee..5599eaee024 100644
--- a/lisp/textmodes/reftex-toc.el
+++ b/lisp/textmodes/reftex-toc.el
@@ -28,7 +28,6 @@
(require 'reftex)
;;;
-(define-obsolete-variable-alias 'reftex-toc-map 'reftex-toc-mode-map "24.1")
(defvar reftex-toc-mode-map
(let ((map (make-sparse-keymap)))
@@ -157,22 +156,22 @@ Here are all local bindings.
(defconst reftex-toc-help
" AVAILABLE KEYS IN TOC BUFFER
============================
-n / p next-line / previous-line
-SPC Show the corresponding location of the LaTeX document.
-TAB Goto the location and keep the TOC window.
-RET Goto the location and hide the TOC window (also on mouse-2).
-< / > Promote / Demote section, or all sections in region.
-C-c > Display Index. With prefix arg, restrict index to current section.
-q / k Hide/Kill *toc* buffer, return to position of reftex-toc command.
-l i c F Toggle display of [l]abels, [i]ndex, [c]ontext, [F]ile borders.
-t Change maximum toc depth (e.g. `3 t' hides levels greater than 3).
-f / g Toggle follow mode / Refresh *toc* buffer.
-a / d Toggle auto recenter / Toggle dedicated frame
-r / C-u r Reparse the LaTeX document / Reparse entire LaTeX document.
-. In other window, show position from where `reftex-toc' was called.
-M-% Global search and replace to rename label at point.
-x Switch to TOC of external document (with LaTeX package `xr').
-z Jump to a specific section (e.g. '3 z' goes to section 3).")
+\\`n' / \\`p' `next-line' / `previous-line'
+\\`SPC' Show the corresponding location of the LaTeX document.
+\\`TAB' Goto the location and keep the TOC window.
+\\`RET' Goto the location and hide the TOC window (also on `mouse-2').
+\\`<' / \\`>' Promote / Demote section, or all sections in region.
+\\`C-c >' Display Index. With prefix arg, restrict index to current section.
+\\`q' / \\`k' Hide/Kill *toc* buffer, return to position of reftex-toc command.
+\\`l' \\`i' \\`c' \\`F' Toggle display of [l]abels, [i]ndex, [c]ontext, [F]ile borders.
+\\`t' Change maximum toc depth (e.g. `3 t' hides levels greater than 3).
+\\`f' / \\`g' Toggle follow mode / Refresh *toc* buffer.
+\\`a' / \\`d' Toggle auto recenter / Toggle dedicated frame
+\\`r' / \\`C-u r' Reparse the LaTeX document / Reparse entire LaTeX document.
+\\`.' In other window, show position from where `reftex-toc' was called.
+\\`M-%' Global search and replace to rename label at point.
+\\`x' Switch to TOC of external document (with LaTeX package `xr').
+\\`z' Jump to a specific section (e.g. \\`3 z' goes to section 3).")
(defvar reftex--rebuilding-toc nil)
@@ -381,7 +380,7 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help
(- (or reftex-last-window-height (window-height))
(window-height)))))
(when (> count 0)
- (with-demoted-errors ;E.g. the window might be the root window!
+ (with-demoted-errors "Enlarge window error: %S"
(enlarge-window count reftex-toc-split-windows-horizontally)))))
(defun reftex-toc-dframe-p (&optional frame error)
@@ -394,7 +393,9 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help
(frame-parameter frame 'name))
"RefTeX TOC Frame")))
(if (and res error)
- (error "This frame is view-only. Use `C-c =' to create TOC window for commands"))
+ (error (substitute-command-keys
+ "This frame is view-only. Use \\[reftex-toc] \
+to create TOC window for commands")))
res))
(defun reftex-toc-show-help ()
@@ -402,7 +403,9 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help
(interactive)
(reftex-toc-dframe-p nil 'error)
(with-output-to-temp-buffer "*RefTeX Help*"
- (princ reftex-toc-help))
+ (let ((help (substitute-command-keys reftex-toc-help)))
+ (with-current-buffer standard-output
+ (insert help))))
(reftex-enlarge-to-fit "*RefTeX Help*" t)
;; If follow mode is active, arrange to delay it one command
(if reftex-toc-follow-mode
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index 36dd36c95ea..f9f09825fa0 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -70,12 +70,16 @@
("tabwindow" ?f nil nil 1)))
(rotating "Sidewaysfigure and table"
- (("sidewaysfigure" ?f nil nil caption)
- ("sidewaystable" ?t nil nil caption)))
+ (("sidewaysfigure" ?f nil nil caption)
+ ("sidewaysfigure*" ?f nil nil caption)
+ ("sidewaystable" ?t nil nil caption)
+ ("sidewaystable*" ?t nil nil caption)))
- (sidecap "CSfigure and SCtable"
- (("SCfigure" ?f nil nil caption)
- ("SCtable" ?t nil nil caption)))
+ (sidecap "SCfigure and SCtable"
+ (("SCfigure" ?f nil nil caption)
+ ("SCfigure*" ?f nil nil caption)
+ ("SCtable" ?t nil nil caption)
+ ("SCtable*" ?t nil nil caption)))
(subfigure "Subfigure environments/macro"
(("subfigure" ?f nil nil caption)
@@ -392,19 +396,19 @@ that the *toc* window fills half the frame."
(defcustom reftex-toc-include-file-boundaries nil
"Non-nil means, include file boundaries in *toc* buffer.
-This flag can be toggled from within the *toc* buffer with the `F' key."
+This flag can be toggled from within the *toc* buffer with the \\`F' key."
:group 'reftex-table-of-contents-browser
:type 'boolean)
(defcustom reftex-toc-include-labels nil
"Non-nil means, include labels in *toc* buffer.
-This flag can be toggled from within the *toc* buffer with the `l' key."
+This flag can be toggled from within the *toc* buffer with the \\`l' key."
:group 'reftex-table-of-contents-browser
:type 'boolean)
(defcustom reftex-toc-include-index-entries nil
"Non-nil means, include index entries in *toc* buffer.
-This flag can be toggled from within the *toc* buffer with the `i' key."
+This flag can be toggled from within the *toc* buffer with the \\`i' key."
:group 'reftex-table-of-contents-browser
:type 'boolean)
@@ -422,14 +426,14 @@ changed."
(defcustom reftex-toc-include-context nil
"Non-nil means, include context with labels in the *toc* buffer.
Context will only be shown when labels are visible as well.
-This flag can be toggled from within the *toc* buffer with the `c' key."
+This flag can be toggled from within the *toc* buffer with the \\`c' key."
:group 'reftex-table-of-contents-browser
:type 'boolean)
(defcustom reftex-toc-follow-mode nil
"Non-nil means, point in *toc* buffer will cause other window to follow.
The other window will show the corresponding part of the document.
-This flag can be toggled from within the *toc* buffer with the `f' key."
+This flag can be toggled from within the *toc* buffer with the \\`f' key."
:group 'reftex-table-of-contents-browser
:type 'boolean)
@@ -1314,7 +1318,7 @@ macro before insertion. For example, it will change
\\cite[][]{Jones} -> \\cite{Jones}
\\cite[][Chapter 1]{Jones} -> \\cite[Chapter 1]{Jones}
\\cite[see][]{Jones} -> \\cite[see][]{Jones}
- \\cite[see][Chapter 1]{Jones} -> \\cite{Jones}
+ \\cite[see][Chapter 1]{Jones} -> \\cite[see][Chapter 1]{Jones}
It is possible that other packages have other conventions about which
optional argument is interpreted how - that is why this cleaning up
can be turned off."
@@ -1627,14 +1631,14 @@ to that section."
(defcustom reftex-index-include-context nil
"Non-nil means, display the index definition context in the index buffer.
-This flag may also be toggled from the index buffer with the `c' key."
+This flag may also be toggled from the index buffer with the \\`c' key."
:group 'reftex-index-support
:type 'boolean)
(defcustom reftex-index-follow-mode nil
"Non-nil means, point in *Index* buffer will cause other window to follow.
The other window will show the corresponding part of the document.
-This flag can be toggled from within the *Index* buffer with the `f' key."
+This flag can be toggled from within the *Index* buffer with the \\`f' key."
:group 'reftex-table-of-contents-browser
:type 'boolean)
@@ -1863,10 +1867,11 @@ of the regular expressions in this list, that file is not parsed by RefTeX."
(defcustom reftex-enable-partial-scans nil
"Non-nil means, re-parse only 1 file when asked to re-parse.
Re-parsing is normally requested with a \\[universal-argument] prefix to many RefTeX commands,
-or with the `r' key in menus. When this option is t in a multifile document,
+or with the \\`r' key in menus. When this option is t in a multifile document,
we will only parse the current buffer, or the file associated with the label
or section heading near point in a menu. Requesting re-parsing of an entire
-multifile document then requires a \\[universal-argument] \\[universal-argument] prefix or the capital `R' key
+multifile document then requires a \\[universal-argument] \
+\\[universal-argument] prefix or the capital \\`R' key
in menus."
:group 'reftex-optimizations-for-large-documents
:type 'boolean)
@@ -1912,7 +1917,7 @@ when new labels in its category are added. See the variable
When a new label is defined with `reftex-label', all selection buffers
associated with that label category are emptied, in order to force an
update upon next use. When nil, the buffers are left alone and have to be
-updated by hand, with the `g' key from the label selection process.
+updated by hand, with the \\`g' key from the label selection process.
The value of this variable will only have any effect when
`reftex-use-multiple-selection-buffers' is non-nil."
:group 'reftex-optimizations-for-large-documents
@@ -1964,7 +1969,7 @@ instead or as well. The variable may have one of these values:
both Both cursor and mouse trigger highlighting.
Changing this variable requires rebuilding the selection and *toc* buffers
-to become effective (keys `g' or `r')."
+to become effective (keys \\`g' or \\`r')."
:group 'reftex-fontification-configurations
:type '(choice
(const :tag "Never" nil)
diff --git a/lisp/textmodes/reftex.el b/lisp/textmodes/reftex.el
index 907d50889a1..e72576cdc74 100644
--- a/lisp/textmodes/reftex.el
+++ b/lisp/textmodes/reftex.el
@@ -2257,8 +2257,7 @@ IGNORE-WORDS List of words which should be removed from the string."
("Customize"
["Browse RefTeX Group" reftex-customize t]
"--"
- ["Build Full Customize Menu" reftex-create-customize-menu
- (fboundp 'customize-menu-create)])
+ ["Build Full Customize Menu" reftex-create-customize-menu])
("Documentation"
["Info" reftex-info t]
["Commentary" reftex-show-commentary t])))
diff --git a/lisp/textmodes/remember.el b/lisp/textmodes/remember.el
index d65aea62862..f7ebe04bcf5 100644
--- a/lisp/textmodes/remember.el
+++ b/lisp/textmodes/remember.el
@@ -296,7 +296,8 @@ With a prefix or a visible region, use the region as INITIAL."
(insert "\n\n" annotation))
(setq remember-initial-contents nil)
(goto-char (point-min)))
- (message "Use C-c C-c to remember the data.")))
+ (message (substitute-command-keys
+ "Use \\[remember-finalize] to remember the data"))))
;;;###autoload
(defun remember-other-frame (&optional initial)
@@ -653,7 +654,7 @@ to turn the *scratch* buffer into your notes buffer."
(remember-notes-mode 1)
(current-buffer)))))
(when switch-to
- (switch-to-buffer buf))
+ (pop-to-buffer-same-window buf))
buf))
(defun remember-notes--kill-buffer-query ()
diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el
index 104812f43cd..10313e99393 100644
--- a/lisp/textmodes/rst.el
+++ b/lisp/textmodes/rst.el
@@ -522,7 +522,7 @@ argument list for `rst-re'.")
(defvar rst-re-alist) ; Forward declare to use it in `rst-re'.
-;; FIXME: Use `sregex' or `rx' instead of re-inventing the wheel.
+;; FIXME: Use `rx' instead of re-inventing the wheel.
(rst-testcover-add-compose 'rst-re)
(defun rst-re (&rest args)
;; testcover: ok.
@@ -2351,7 +2351,7 @@ If user selects bullets or #, it's just added with position arranged by
`rst-insert-list-new-tag'.
If user selects enumerations, a further prompt is given. User need to
-input a starting item, for example 'e' for 'A)' style. The position is
+input a starting item, for example `e' for `A)' style. The position is
also arranged by `rst-insert-list-new-tag'."
(let* ((itemstyle (completing-read
(format-prompt "Select preferred item style" "#.")
@@ -3569,8 +3569,6 @@ Region is from BEG to END. With WITH-EMPTY prefix empty lines too."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Font lock
-;; FIXME: The obsolete variables need to disappear.
-
;; The following versions have been done inside Emacs and should not be
;; replaced by `:package-version' attributes until a change.
@@ -3584,125 +3582,46 @@ Region is from BEG to END. With WITH-EMPTY prefix empty lines too."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-block-face 'rst-block
- "All syntax marking up a special block."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-block-face
- "customize the face `rst-block' instead."
- "24.1")
-
(defface rst-external '((t :inherit font-lock-type-face))
"Face used for field names and interpreted text."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-external-face 'rst-external
- "Field names and interpreted text."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-external-face
- "customize the face `rst-external' instead."
- "24.1")
-
(defface rst-definition '((t :inherit font-lock-function-name-face))
"Face used for all other defining constructs."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-definition-face 'rst-definition
- "All other defining constructs."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-definition-face
- "customize the face `rst-definition' instead."
- "24.1")
-
(defface rst-directive '((t :inherit font-lock-builtin-face))
"Face used for directives and roles."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-directive-face 'rst-directive
- "Directives and roles."
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-directive-face
- "customize the face `rst-directive' instead."
- "24.1")
-
(defface rst-comment '((t :inherit font-lock-comment-face))
"Face used for comments."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-comment-face 'rst-comment
- "Comments."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-comment-face
- "customize the face `rst-comment' instead."
- "24.1")
-
(defface rst-emphasis1 '((t :inherit italic))
"Face used for simple emphasis."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-emphasis1-face 'rst-emphasis1
- "Simple emphasis."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-emphasis1-face
- "customize the face `rst-emphasis1' instead."
- "24.1")
-
(defface rst-emphasis2 '((t :inherit bold))
"Face used for double emphasis."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-emphasis2-face 'rst-emphasis2
- "Double emphasis."
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-emphasis2-face
- "customize the face `rst-emphasis2' instead."
- "24.1")
-
(defface rst-literal '((t :inherit font-lock-string-face))
"Face used for literal text."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-literal-face 'rst-literal
- "Literal text."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-literal-face
- "customize the face `rst-literal' instead."
- "24.1")
-
(defface rst-reference '((t :inherit font-lock-variable-name-face))
"Face used for references to a definition."
:version "24.1"
:group 'rst-faces)
-(defcustom rst-reference-face 'rst-reference
- "References to a definition."
- :version "24.1"
- :group 'rst-faces
- :type '(face))
-(make-obsolete-variable 'rst-reference-face
- "customize the face `rst-reference' instead."
- "24.1")
-
(defface rst-transition '((t :inherit font-lock-keyword-face))
"Face used for a transition."
:package-version '(rst . "1.3.0")
@@ -3794,23 +3713,23 @@ of your own."
;; `Bullet Lists`_
;; FIXME: A bullet directly after a field name is not recognized.
(,(rst-re 'lin-beg '(:grp bul-sta))
- 1 rst-block-face)
+ 1 'rst-block)
;; `Enumerated Lists`_
(,(rst-re 'lin-beg '(:grp enmany-sta))
- 1 rst-block-face)
+ 1 'rst-block)
;; `Definition Lists`_
;; FIXME: missing.
;; `Field Lists`_
(,(rst-re 'lin-beg '(:grp fld-tag) 'bli-sfx)
- 1 rst-external-face)
+ 1 'rst-external)
;; `Option Lists`_
(,(rst-re 'lin-beg '(:grp opt-tag (:shy optsep-tag opt-tag) "*")
'(:alt "$" (:seq hws-prt "\\{2\\}")))
- 1 rst-block-face)
+ 1 'rst-block)
;; `Line Blocks`_
;; Only for lines containing no more bar - to distinguish from tables.
(,(rst-re 'lin-beg '(:grp "|" bli-sfx) "[^|\n]*$")
- 1 rst-block-face)
+ 1 'rst-block)
;; `Tables`_
;; FIXME: missing
@@ -3818,22 +3737,22 @@ of your own."
;; All the `Explicit Markup Blocks`_
;; `Footnotes`_ / `Citations`_
(,(rst-re 'lin-beg 'fnc-sta-2)
- (1 rst-definition-face)
- (2 rst-definition-face))
+ (1 'rst-definition)
+ (2 'rst-definition))
;; `Directives`_ / `Substitution Definitions`_
(,(rst-re 'lin-beg 'dir-sta-3)
- (1 rst-directive-face)
- (2 rst-definition-face)
- (3 rst-directive-face))
+ (1 'rst-directive)
+ (2 'rst-definition)
+ (3 'rst-directive))
;; `Hyperlink Targets`_
(,(rst-re 'lin-beg
'(:grp exm-sta "_" (:alt
(:seq "`" ilcbkqdef-tag "`")
(:seq (:alt "[^:\\\n]" "\\\\.") "+")) ":")
'bli-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
(,(rst-re 'lin-beg '(:grp "__") 'bli-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
;; All `Inline Markup`_
;; Most of them may be multiline though this is uninteresting.
@@ -3841,16 +3760,16 @@ of your own."
;; FIXME: Condition 5 preventing fontification of e.g. "*" not implemented
;; `Strong Emphasis`_.
(,(rst-re 'ilm-pfx '(:grp "\\*\\*" ilcast-tag "\\*\\*") 'ilm-sfx)
- 1 rst-emphasis2-face)
+ 1 'rst-emphasis2)
;; `Emphasis`_
(,(rst-re 'ilm-pfx '(:grp "\\*" ilcast-tag "\\*") 'ilm-sfx)
- 1 rst-emphasis1-face)
+ 1 'rst-emphasis1)
;; `Inline Literals`_
(,(rst-re 'ilm-pfx '(:grp "``" ilcbkq-tag "``") 'ilm-sfx)
- 1 rst-literal-face)
+ 1 'rst-literal)
;; `Inline Internal Targets`_
(,(rst-re 'ilm-pfx '(:grp "_`" ilcbkq-tag "`") 'ilm-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
;; `Hyperlink References`_
;; FIXME: `Embedded URIs and Aliases`_ not considered.
;; FIXME: Directly adjacent marked up words are not fontified correctly
@@ -3858,28 +3777,28 @@ of your own."
(,(rst-re 'ilm-pfx '(:grp (:alt (:seq "`" ilcbkq-tag "`")
(:seq "\\sw" (:alt "\\sw" "-") "+\\sw"))
"__?") 'ilm-sfx)
- 1 rst-reference-face)
+ 1 'rst-reference)
;; `Interpreted Text`_
(,(rst-re 'ilm-pfx '(:grp (:shy ":" sym-tag ":") "?")
'(:grp "`" ilcbkq-tag "`")
'(:grp (:shy ":" sym-tag ":") "?") 'ilm-sfx)
- (1 rst-directive-face)
- (2 rst-external-face)
- (3 rst-directive-face))
+ (1 'rst-directive)
+ (2 'rst-external)
+ (3 'rst-directive))
;; `Footnote References`_ / `Citation References`_
(,(rst-re 'ilm-pfx '(:grp fnc-tag "_") 'ilm-sfx)
- 1 rst-reference-face)
+ 1 'rst-reference)
;; `Substitution References`_
;; FIXME: References substitutions like |this|_ or |this|__ are not
;; fontified correctly.
(,(rst-re 'ilm-pfx '(:grp sub-tag) 'ilm-sfx)
- 1 rst-reference-face)
+ 1 'rst-reference)
;; `Standalone Hyperlinks`_
;; FIXME: This takes it easy by using a whitespace as delimiter.
(,(rst-re 'ilm-pfx '(:grp uri-tag ":\\S +") 'ilm-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
(,(rst-re 'ilm-pfx '(:grp sym-tag "@" sym-tag ) 'ilm-sfx)
- 1 rst-definition-face)
+ 1 'rst-definition)
;; Do all block fontification as late as possible so 'append works.
@@ -3906,18 +3825,18 @@ of your own."
;; `Comments`_
;; This is multiline.
(,(rst-re 'lin-beg 'cmt-sta-1)
- (1 rst-comment-face)
+ (1 'rst-comment)
(rst-font-lock-find-unindented-line-match
(rst-font-lock-find-unindented-line-limit (match-end 1))
nil
- (0 rst-comment-face append)))
+ (0 'rst-comment append)))
(,(rst-re 'lin-beg '(:grp exm-tag) '(:grp hws-tag) "$")
- (1 rst-comment-face)
- (2 rst-comment-face)
+ (1'rst-comment)
+ (2'rst-comment)
(rst-font-lock-find-unindented-line-match
(rst-font-lock-find-unindented-line-limit 'next)
nil
- (0 rst-comment-face append)))
+ (0 'rst-comment append)))
;; FIXME: This is not rendered as comment::
;; .. .. list-table::
@@ -3941,11 +3860,11 @@ of your own."
;; `Indented Literal Blocks`_
;; This is multiline.
(,(rst-re 'lin-beg 'lit-sta-2)
- (2 rst-block-face)
+ (2 'rst-block)
(rst-font-lock-find-unindented-line-match
(rst-font-lock-find-unindented-line-limit t)
nil
- (0 rst-literal-face append)))
+ (0 'rst-literal append)))
;; FIXME: `Quoted Literal Blocks`_ missing.
;; This is multiline.
@@ -3972,8 +3891,8 @@ of your own."
;;
;; Indentation is not required for doctest blocks.
(,(rst-re 'lin-beg '(:grp (:alt ">>>" ell-tag)) '(:grp ".+"))
- (1 rst-block-face)
- (2 rst-literal-face)))
+ (1 'rst-block)
+ (2 'rst-literal)))
"Keywords to highlight in rst mode.")
(defvar font-lock-beg)
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
index efebee0521b..8f9b603ef5f 100644
--- a/lisp/textmodes/sgml-mode.el
+++ b/lisp/textmodes/sgml-mode.el
@@ -75,7 +75,8 @@ a DOCTYPE or an XML declaration."
:type 'boolean
:version "22.1")
-(defvaralias 'sgml-transformation 'sgml-transformation-function)
+(define-obsolete-variable-alias 'sgml-transformation
+ 'sgml-transformation-function "29.1")
(defcustom sgml-transformation-function 'identity
"Default value for `skeleton-transformation-function' in SGML mode."
@@ -418,11 +419,11 @@ These have to be run via `sgml-syntax-propertize'"))
(defun sgml-syntax-propertize (start end &optional rules-function)
"Syntactic keywords for `sgml-mode'."
(setq sgml--syntax-propertize-ppss (cons start (syntax-ppss start)))
- (cl-assert (>= (cadr sgml--syntax-propertize-ppss) 0))
- (sgml-syntax-propertize-inside end)
- (funcall (or rules-function sgml--syntax-propertize) (point) end)
- ;; Catch any '>' after the last quote.
- (sgml--syntax-propertize-ppss end))
+ (when (>= (cadr sgml--syntax-propertize-ppss) 0)
+ (sgml-syntax-propertize-inside end)
+ (funcall (or rules-function sgml--syntax-propertize) (point) end)
+ ;; Catch any '>' after the last quote.
+ (sgml--syntax-propertize-ppss end)))
(defun sgml-syntax-propertize-inside (end)
(let ((ppss (syntax-ppss)))
@@ -440,7 +441,8 @@ These have to be run via `sgml-syntax-propertize'"))
;; internal
(defvar sgml-face-tag-alist ()
- "Alist of face and tag name for facemenu.")
+ "Alist of face and tag name for facemenu.
+The tag name can be a string or a list of strings.")
(defvar sgml-tag-face-alist ()
"Tag names and face or list of faces to fontify with when invisible.
@@ -478,8 +480,8 @@ The attribute alist is made up as
ATTRIBUTERULE is a list of optionally t (no value when no input) followed by
an optional alist of possible values."
:type '(repeat (cons (string :tag "Tag Name")
- (repeat :tag "Tag Rule" sexp))))
-(put 'sgml-tag-alist 'risky-local-variable t)
+ (repeat :tag "Tag Rule" sexp)))
+ :risky t)
(defcustom sgml-tag-help
'(("!" . "Empty declaration for comment")
@@ -528,11 +530,13 @@ an optional alist of possible values."
(comment-indent-new-line soft)))
(defun sgml-mode-facemenu-add-face-function (face _end)
- (let ((tag-face (cdr (assq face sgml-face-tag-alist))))
+ "Add \"face\" tags with `facemenu-keymap' commands."
+ (let ((tag-face (ensure-list (cdr (assq face sgml-face-tag-alist)))))
(cond (tag-face
(setq tag-face (funcall skeleton-transformation-function tag-face))
- (setq facemenu-end-add-face (concat "</" tag-face ">"))
- (concat "<" tag-face ">"))
+ (setq facemenu-end-add-face
+ (mapconcat (lambda (f) (concat "</" f ">")) (reverse tag-face) ""))
+ (mapconcat (lambda (f) (concat "<" f ">")) tag-face ""))
((and (consp face)
(consp (car face))
(null (cdr face))
@@ -596,12 +600,11 @@ Do \\[describe-key] on the following bindings to discover what they do.
(setq-local tildify-foreach-region-function
(apply-partially
'tildify-foreach-ignore-environments
- `((,(eval-when-compile
- (concat
- "<\\("
- (regexp-opt '("pre" "dfn" "code" "samp" "kbd" "var"
- "PRE" "DFN" "CODE" "SAMP" "KBD" "VAR"))
- "\\)\\>[^>]*>"))
+ `((,(concat
+ "<\\("
+ (regexp-opt '("pre" "dfn" "code" "samp" "kbd" "var"
+ "PRE" "DFN" "CODE" "SAMP" "KBD" "VAR"))
+ "\\)\\>[^>]*>")
. ("</" 1 ">"))
("<! *--" . "-- *>")
("<" . ">"))))
@@ -620,6 +623,7 @@ Do \\[describe-key] on the following bindings to discover what they do.
(setq-local comment-indent-function 'sgml-comment-indent)
(setq-local comment-line-break-function 'sgml-comment-indent-new-line)
(setq-local skeleton-further-elements '((completion-ignore-case t)))
+ (setq-local skeleton-end-newline nil)
(setq-local skeleton-end-hook
(lambda ()
(or (eolp)
@@ -1868,6 +1872,7 @@ This takes effect when first loading the library.")
(defvar html-face-tag-alist
'((bold . "strong")
(italic . "em")
+ (bold-italic . ("strong" "em"))
(underline . "u")
(mode-line . "rev"))
"Value of `sgml-face-tag-alist' for HTML mode.")
@@ -2403,6 +2408,7 @@ To work around that, do:
(lambda () (char-before (match-end 0))))
(setq-local add-log-current-defun-function #'html-current-defun-name)
(setq-local sentence-end-base "[.?!][]\"'”)}]*\\(<[^>]*>\\)*")
+ (add-hook 'completion-at-point-functions 'html-mode--complete-at-point nil t)
(when (fboundp 'libxml-parse-html-region)
(defvar css-class-list-function)
@@ -2411,6 +2417,8 @@ To work around that, do:
(setq-local css-id-list-function #'html-current-buffer-ids))
(setq imenu-create-index-function 'html-imenu-index)
+ (yank-media-handler 'text/html #'html-mode--html-yank-handler)
+ (yank-media-handler "image/.*" #'html-mode--image-yank-handler)
(setq-local sgml-empty-tags
;; From HTML-4.01's loose.dtd, parsed with
@@ -2426,6 +2434,60 @@ To work around that, do:
;; (setq imenu-sort-function nil) ; sorting the menu defeats the purpose
)
+(defun html-mode--complete-at-point ()
+ ;; Complete a tag like <colg etc.
+ (or
+ (when-let ((tag (save-excursion
+ (and (looking-back "<\\([^ \t\n]*\\)"
+ (line-beginning-position))
+ (match-string 1)))))
+ (list (match-beginning 1) (point)
+ (mapcar #'car html-tag-alist)))
+ ;; Complete params like <colgroup ali etc.
+ (when-let ((tag (save-excursion (sgml-beginning-of-tag)))
+ (params (seq-filter #'consp (cdr (assoc tag html-tag-alist))))
+ (param (save-excursion
+ (and (looking-back "[ \t\n]\\([^= \t\n]*\\)"
+ (line-beginning-position))
+ (match-string 1)))))
+ (list (match-beginning 1) (point)
+ (mapcar #'car params)))
+ ;; Complete param values like <colgroup align=mi etc.
+ (when-let ((tag (save-excursion (sgml-beginning-of-tag)))
+ (params (seq-filter #'consp (cdr (assoc tag html-tag-alist))))
+ (param (save-excursion
+ (and (looking-back
+ "[ \t\n]\\([^= \t\n]+\\)=\\([^= \t\n]*\\)"
+ (line-beginning-position))
+ (match-string 1))))
+ (values (cdr (assoc param params))))
+ (list (match-beginning 2) (point)
+ (mapcar #'car values)))))
+
+(defun html-mode--html-yank-handler (_type html)
+ (save-restriction
+ (insert html)
+ (ignore-errors
+ (sgml-pretty-print (point-min) (point-max)))))
+
+(defun html-mode--image-yank-handler (type image)
+ (let ((file (read-file-name (format "Save %s image to: " type))))
+ (when (file-directory-p file)
+ (user-error "%s is a directory"))
+ (when (and (file-exists-p file)
+ (not (yes-or-no-p (format "%s exists; overwrite?" file))))
+ (user-error "%s exists"))
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert image)
+ (write-region (point-min) (point-max) file))
+ (insert (format "<img src=%S>\n" (file-relative-name file)))
+ (insert-image
+ (create-image file (mailcap-mime-type-to-extension type) nil
+ :max-width 200
+ :max-height 200)
+ " ")))
+
(defvar html-imenu-regexp
"\\s-*<h\\([1-9]\\)[^\n<>]*>\\(<[^\n<>]*>\\)*\\s-*\\([^\n<>]*\\)"
"A regular expression matching a head line to be added to the menu.
diff --git a/lisp/textmodes/string-edit.el b/lisp/textmodes/string-edit.el
new file mode 100644
index 00000000000..53850674ac0
--- /dev/null
+++ b/lisp/textmodes/string-edit.el
@@ -0,0 +1,136 @@
+;;; string-edit.el --- editing long strings -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defface string-edit-prompt
+ '((t (:inherit font-lock-comment-face)))
+ "Face used on `string-edit' help text."
+ :group 'text
+ :version "29.1")
+
+(defvar string-edit--success-callback)
+(defvar string-edit--abort-callback)
+
+;;;###autoload
+(cl-defun string-edit (prompt string success-callback
+ &key abort-callback)
+ "Switch to a new buffer to edit STRING.
+When the user finishes editing (with \\<string-edit-mode-map>\\[string-edit-done]), SUCCESS-CALLBACK
+is called with the resulting string.
+
+If the user aborts (with \\<string-edit-mode-map>\\[string-edit-abort]), ABORT-CALLBACK (if any) is
+called with no parameters.
+
+PROMPT will be inserted at the start of the buffer, but won't be
+included in the resulting string. If PROMPT is nil, no help text
+will be inserted."
+ (with-current-buffer (generate-new-buffer "*edit string*")
+ (when prompt
+ (let ((inhibit-read-only t))
+ (insert prompt)
+ (ensure-empty-lines 0)
+ (add-text-properties (point-min) (point)
+ (list 'intangible t
+ 'face 'string-edit-prompt
+ 'read-only t))
+ (insert (propertize (make-separator-line) 'rear-nonsticky t))
+ (add-text-properties (point-min) (point)
+ (list 'string-edit--prompt t))))
+ (let ((start (point)))
+ (insert string)
+ (goto-char start))
+
+ ;; Use `fit-window-to-buffer' after the buffer is filled with text.
+ (pop-to-buffer (current-buffer)
+ '(display-buffer-below-selected
+ (window-height . (lambda (window)
+ (fit-window-to-buffer window nil 10)))))
+
+ (set-buffer-modified-p nil)
+ (setq buffer-undo-list nil)
+ (string-edit-mode)
+ (setq-local string-edit--success-callback success-callback)
+ (when abort-callback
+ (setq-local string-edit--abort-callback abort-callback))
+ (setq-local header-line-format
+ (substitute-command-keys
+ "Type \\<string-edit-mode-map>\\[string-edit-done] when you've finished editing or \\[string-edit-abort] to abort"))
+ (message "%s" (substitute-command-keys
+ "Type \\<string-edit-mode-map>\\[string-edit-done] when you've finished editing"))))
+
+;;;###autoload
+(defun read-string-from-buffer (prompt string)
+ "Switch to a new buffer to edit STRING in a recursive edit.
+The user finishes editing with \\<string-edit-mode-map>\\[string-edit-done], or aborts with \\<string-edit-mode-map>\\[string-edit-abort]).
+
+PROMPT will be inserted at the start of the buffer, but won't be
+included in the resulting string. If nil, no prompt will be
+inserted in the buffer."
+ (string-edit
+ prompt
+ string
+ (lambda (edited)
+ (setq string edited)
+ (exit-recursive-edit))
+ :abort-callback (lambda ()
+ (exit-recursive-edit)
+ (error "Aborted edit")))
+ (recursive-edit)
+ string)
+
+(defvar-keymap string-edit-mode-map
+ "C-c C-c" #'string-edit-done
+ "C-c C-k" #'string-edit-abort)
+
+(define-derived-mode string-edit-mode text-mode "String"
+ "Mode for editing strings."
+ :interactive nil)
+
+(defun string-edit-done ()
+ "Finish editing the string and call the callback function.
+This will kill the current buffer."
+ (interactive)
+ (goto-char (point-min))
+ ;; Skip past the help text.
+ (when-let ((match (text-property-search-forward
+ 'string-edit--prompt nil t)))
+ (goto-char (prop-match-beginning match)))
+ (let ((string (buffer-substring (point) (point-max)))
+ (callback string-edit--success-callback))
+ (quit-window 'kill)
+ (funcall callback string)))
+
+(defun string-edit-abort ()
+ "Abort editing the current string."
+ (interactive)
+ (let ((callback string-edit--abort-callback))
+ (quit-window 'kill)
+ (when callback
+ (funcall callback))))
+
+(provide 'string-edit)
+
+;;; string-edit.el ends here
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index 30a07cbefea..fc06c4c0da1 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -753,6 +753,18 @@ the cell contents dynamically."
:type 'string
:group 'table)
+(defcustom table-latex-environment "tabular"
+ "Tabular-compatible environment to use when generating latex.
+The value should be a string suitable for use as a LaTeX environment
+that's compatible with the \"tabular\" protocol, such as \"tabular\"
+and \"longtable\"."
+ :tag "Latex environment used to export tables"
+ :type '(choice
+ (const :tag "tabular" "tabular")
+ (const :tag "longtable" "longtable")
+ string)
+ :version "29.1")
+
(defcustom table-cals-thead-rows 1
"Number of top rows to become header rows in CALS table."
:tag "CALS Header Rows"
@@ -1195,6 +1207,21 @@ executing body forms.")
(easy-menu-add-item (current-global-map)
'("menu-bar" "tools") table-global-menu-map)
+;;;###autoload
+(define-minor-mode table-fixed-width-mode
+ "Cell width is fixed when this is non-nil.
+Normally it should be nil for allowing automatic cell width expansion
+that widens a cell when it is necessary. When non-nil, typing in a
+cell does not automatically expand the cell width. A word that is too
+long to fit in a cell is chopped into multiple lines. The chopped
+location is indicated by `table-word-continuation-char'. This
+variable's value can be toggled by \\[table-fixed-width-mode] at
+run-time."
+ :tag "Fix Cell Width"
+ :group 'table
+ (table--finish-delayed-tasks)
+ (table--update-cell-face))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Macros
@@ -1219,43 +1246,49 @@ original buffer's point is moved to the location that corresponds to
the last cache point coordinate."
(declare (debug (body)) (indent 0))
(let ((height-expansion (make-symbol "height-expansion-var-symbol"))
- (width-expansion (make-symbol "width-expansion-var-symbol")))
- `(let (,height-expansion ,width-expansion)
+ (width-expansion (make-symbol "width-expansion-var-symbol"))
+ (fixed-width (make-symbol "fixed-width")))
+ `(let ((,fixed-width table-fixed-width-mode)
+ ,height-expansion ,width-expansion)
;; make sure cache has valid data unless it is explicitly inhibited.
(unless table-inhibit-update
(table-recognize-cell))
(with-current-buffer (get-buffer-create table-cache-buffer-name)
- ;; goto the cell coordinate based on `table-cell-cache-point-coordinate'.
- (set-mark (table--goto-coordinate table-cell-cache-mark-coordinate))
- (table--goto-coordinate table-cell-cache-point-coordinate)
- (table--untabify-line)
- ;; always reset before executing body forms because auto-fill behavior is the default.
- (setq table-inhibit-auto-fill-paragraph nil)
- ;; do the body
- ,@body
- ;; fill paragraph unless the body does not want to by setting `table-inhibit-auto-fill-paragraph'.
- (unless table-inhibit-auto-fill-paragraph
- (if (and table-cell-info-justify
- (not (eq table-cell-info-justify 'left)))
- (table--fill-region (point-min) (point-max))
- (table--fill-region
- (save-excursion (forward-paragraph -1) (point))
- (save-excursion (forward-paragraph 1) (point)))))
- ;; keep the updated cell coordinate.
- (setq table-cell-cache-point-coordinate (table--get-coordinate))
- ;; determine the cell width expansion.
- (setq ,width-expansion (table--measure-max-width))
- (if (<= ,width-expansion table-cell-info-width) nil
- (table--fill-region (point-min) (point-max) ,width-expansion)
- ;; keep the updated cell coordinate.
- (setq table-cell-cache-point-coordinate (table--get-coordinate)))
- (setq ,width-expansion (- ,width-expansion table-cell-info-width))
- ;; determine the cell height expansion.
- (if (looking-at "\\s *\\'") nil
- (goto-char (point-min))
- (if (re-search-forward "\\(\\s *\\)\\'" nil t)
- (goto-char (match-beginning 1))))
- (setq ,height-expansion (- (cdr (table--get-coordinate)) (1- table-cell-info-height))))
+ (let ((table-fixed-width-mode ,fixed-width))
+ ;; Go to the cell coordinate based on
+ ;; `table-cell-cache-point-coordinate'.
+ (set-mark (table--goto-coordinate table-cell-cache-mark-coordinate))
+ (table--goto-coordinate table-cell-cache-point-coordinate)
+ (table--untabify-line)
+ ;; Always reset before executing body forms because
+ ;; auto-fill behavior is the default.
+ (setq table-inhibit-auto-fill-paragraph nil)
+ ;; Do the body
+ ,@body
+ ;; Fill paragraph unless the body does not want to by
+ ;; setting `table-inhibit-auto-fill-paragraph'.
+ (unless table-inhibit-auto-fill-paragraph
+ (if (and table-cell-info-justify
+ (not (eq table-cell-info-justify 'left)))
+ (table--fill-region (point-min) (point-max))
+ (table--fill-region
+ (save-excursion (forward-paragraph -1) (point))
+ (save-excursion (forward-paragraph 1) (point)))))
+ ;; Keep the updated cell coordinate.
+ (setq table-cell-cache-point-coordinate (table--get-coordinate))
+ ;; Determine the cell width expansion.
+ (setq ,width-expansion (table--measure-max-width))
+ (if (<= ,width-expansion table-cell-info-width) nil
+ (table--fill-region (point-min) (point-max) ,width-expansion)
+ ;; Keep the updated cell coordinate.
+ (setq table-cell-cache-point-coordinate (table--get-coordinate)))
+ (setq ,width-expansion (- ,width-expansion table-cell-info-width))
+ ;; Determine the cell height expansion.
+ (if (looking-at "\\s *\\'") nil
+ (goto-char (point-min))
+ (if (re-search-forward "\\(\\s *\\)\\'" nil t)
+ (goto-char (match-beginning 1))))
+ (setq ,height-expansion (- (cdr (table--get-coordinate)) (1- table-cell-info-height)))))
;; now back to the table buffer.
;; expand the cell width in the table buffer if necessary.
(if (> ,width-expansion 0)
@@ -2823,21 +2856,6 @@ or `top', `middle', `bottom' or `none' for vertical."
(table--justify-cell-contents justify))))))
;;;###autoload
-(define-minor-mode table-fixed-width-mode
- "Cell width is fixed when this is non-nil.
-Normally it should be nil for allowing automatic cell width expansion
-that widens a cell when it is necessary. When non-nil, typing in a
-cell does not automatically expand the cell width. A word that is too
-long to fit in a cell is chopped into multiple lines. The chopped
-location is indicated by `table-word-continuation-char'. This
-variable's value can be toggled by \\[table-fixed-width-mode] at
-run-time."
- :tag "Fix Cell Width"
- :group 'table
- (table--finish-delayed-tasks)
- (table--update-cell-face))
-
-;;;###autoload
(defun table-query-dimension (&optional where)
"Return the dimension of the current cell and the current table.
The result is a list (cw ch tw th c r cells) where cw is the cell
@@ -3019,7 +3037,8 @@ CALS (DocBook DTD):
"")))
((eq language 'latex)
(insert (format "%% This LaTeX table template is generated by emacs %s\n" emacs-version)
- "\\begin{tabular}{|" (apply #'concat (make-list (length col-list) "l|")) "}\n"
+ "\\begin{" table-latex-environment "}{|"
+ (apply #'concat (make-list (length col-list) "l|")) "}\n"
"\\hline\n"))
((eq language 'cals)
(insert (format "<!-- This CALS table template is generated by emacs %s -->\n" emacs-version)
@@ -3045,7 +3064,7 @@ CALS (DocBook DTD):
((eq language 'html)
(insert "</table>\n"))
((eq language 'latex)
- (insert "\\end{tabular}\n"))
+ (insert "\\end{" table-latex-environment "}\n"))
((eq language 'cals)
(set-marker-insertion-type (table-get-source-info 'colspec-marker) t) ;; insert before
(save-excursion
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index 64e38ad6973..d34133f8564 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -248,9 +248,9 @@ Normally set to either `plain-tex-mode' or `latex-mode'."
(defcustom tex-fontify-script t
"If non-nil, fontify subscript and superscript strings."
:type 'boolean
+ :safe #'booleanp
:group 'tex
:version "23.1")
-(put 'tex-fontify-script 'safe-local-variable #'booleanp)
(defcustom tex-font-script-display '(-0.2 0.2)
"How much to lower and raise subscript and superscript content.
@@ -505,7 +505,9 @@ An alternative value is \" . \", if you use a font with a narrow period."
"documentstyle" "documentclass" "verbatiminput"
"includegraphics" "includegraphics*")
t))
- (verbish (regexp-opt '("url" "nolinkurl" "path") t))
+ (verbish (regexp-opt '("url" "nolinkurl" "path"
+ "href" "ProvidesFile")
+ t))
;; Miscellany.
(slash "\\\\")
(opt " *\\(\\[[^]]*\\] *\\)*")
@@ -981,14 +983,13 @@ Inherits `shell-mode-map' with a few additions.")
(when (and slash (not comment))
(setq mode
(if (looking-at
- (eval-when-compile
- (concat
- (regexp-opt '("documentstyle" "documentclass"
- "begin" "subsection" "section"
- "part" "chapter" "newcommand"
- "renewcommand" "RequirePackage")
- 'words)
- "\\|NeedsTeXFormat{LaTeX")))
+ (concat
+ (regexp-opt '("documentstyle" "documentclass"
+ "begin" "subsection" "section"
+ "part" "chapter" "newcommand"
+ "renewcommand" "RequirePackage")
+ 'words)
+ "\\|NeedsTeXFormat{LaTeX"))
(if (and (looking-at
"document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
;; SliTeX is almost never used any more nowadays.
@@ -1176,12 +1177,7 @@ subshell is initiated, `tex-shell-hook' is run."
(setq-local outline-regexp latex-outline-regexp)
(setq-local outline-level #'latex-outline-level)
(setq-local forward-sexp-function #'latex-forward-sexp)
- (setq-local skeleton-end-hook nil)
- (setq-local comment-region-function #'latex--comment-region)
- (setq-local comment-style 'plain))
-
-(defun latex--comment-region (beg end &optional arg)
- (comment-region-default-1 beg end arg t))
+ (setq-local skeleton-end-hook nil))
;;;###autoload
(define-derived-mode slitex-mode latex-mode "SliTeX"
@@ -1245,11 +1241,10 @@ Entering SliTeX mode runs the hook `text-mode-hook', then the hook
(apply-partially
#'tildify-foreach-ignore-environments
`(("\\\\\\\\" . "") ; do not remove this
- (,(eval-when-compile
- (concat "\\\\begin{\\("
- (regexp-opt '("verbatim" "math" "displaymath"
- "equation" "eqnarray" "eqnarray*"))
- "\\)}"))
+ (,(concat "\\\\begin{\\("
+ (regexp-opt '("verbatim" "math" "displaymath"
+ "equation" "eqnarray" "eqnarray*"))
+ "\\)}")
. ("\\\\end{" 1 "}"))
("\\\\verb\\*?\\(.\\)" . (1))
("\\$\\$?" . (0))
@@ -2037,7 +2032,7 @@ In the tex shell buffer this command behaves like `comint-send-input'."
(defun tex-display-shell ()
"Make the TeX shell buffer visible in a window."
- (display-buffer (tex-shell-buf))
+ (display-buffer (tex-shell-buf) display-comint-buffer-action)
(tex-recenter-output-buffer nil))
(defun tex-shell-sentinel (proc _msg)
@@ -2129,11 +2124,10 @@ If NOT-ALL is non-nil, save the `.dvi' file."
(defvar tex-compile-history nil)
(defvar tex-input-files-re
- (eval-when-compile
- (concat "\\." (regexp-opt '("tex" "texi" "texinfo"
- "bbl" "ind" "sty" "cls") t)
- ;; Include files with no dots (for directories).
- "\\'\\|\\`[^.]+\\'")))
+ (concat "\\." (regexp-opt '("tex" "texi" "texinfo"
+ "bbl" "ind" "sty" "cls") t)
+ ;; Include files with no dots (for directories).
+ "\\'\\|\\`[^.]+\\'"))
(defcustom tex-use-reftex t
"If non-nil, use RefTeX's list of files to determine what command to use."
@@ -2441,7 +2435,7 @@ Only applies the FSPEC to the args part of FORMAT."
(if cmds (tex-format-cmd (caar cmds) fspec))))))
(defun tex-cmd-doc-view (file)
- (pop-to-buffer (find-file-noselect file)))
+ (pop-to-buffer (find-file-noselect file) display-comint-buffer-action))
(defun tex-compile (dir cmd)
"Run a command CMD on current TeX buffer's file in DIR."
@@ -2457,7 +2451,7 @@ Only applies the FSPEC to the args part of FORMAT."
(default (tex-compile-default fspec)))
(list default-directory
(completing-read
- (format "Command [%s]: " (tex-summarize-command default))
+ (format-prompt "Command" (tex-summarize-command default))
(mapcar (lambda (x)
(list (tex-format-cmd (eval (car x) t) fspec)))
tex-compile-commands)
@@ -2698,7 +2692,7 @@ line LINE of the window, or centered if LINE is nil."
(window))
(if (null tex-shell)
(message "No TeX output buffer")
- (setq window (display-buffer tex-shell))
+ (setq window (display-buffer tex-shell display-comint-buffer-action))
(with-selected-window window
(bury-buffer tex-shell)
(goto-char (point-max))
@@ -2987,13 +2981,7 @@ There might be text before point."
(put-text-property
(1- (match-beginning 1)) (match-beginning 1)
'syntax-table
- (if (= (1+ (line-beginning-position)) (match-beginning 1))
- ;; The `%' is a single-char comment, which Emacs
- ;; syntax-table can't deal with. We could turn it
- ;; into a non-comment, or use `\n%' or `%^' as the comment.
- ;; Instead, we include it in the ^^A comment.
- (string-to-syntax "< b")
- (string-to-syntax ">")))
+ (string-to-syntax ">"))
(let ((end (line-end-position)))
(if (< end (point-max))
(put-text-property
@@ -3016,8 +3004,9 @@ There might be text before point."
(defconst doctex-syntax-propertize-rules
(syntax-propertize-precompile-rules
latex-syntax-propertize-rules
- ;; For DocTeX comment-in-doc.
- ("\\(\\^\\)\\^A" (1 (doctex-font-lock-^^A))))))
+ ;; For DocTeX comment-in-doc (DocTeX ≥3 also allows ^^X).
+ ;; We make the comment start on the second char because of bug#35140.
+ ("\\^\\(\\^\\)[AX]" (1 (doctex-font-lock-^^A))))))
(defvar doctex-font-lock-keywords
(append tex-font-lock-keywords
@@ -3566,28 +3555,122 @@ There might be text before point."
("\\ordmasculine" . ?º)
("\\lambdabar" . ?ƛ)
("\\celsius" . ?℃)
+ ;; Text symbols formerly part of textcomp package:
+ ("\\textdollar" . ?$)
+ ("\\textborn" . ?*)
+ ("\\textless" . ?<)
+ ("\\textgreater" . ?>)
+ ("\\textbackslash" . ?\\)
+ ("\\textasciicircum" . ?^)
+ ("\\textunderscore" . ?_)
+ ("\\textbraceleft" . ?\{)
+ ("\\textbar" . ?|)
+ ("\\textbraceright" . ?\})
+ ("\\textasciitilde" . ?~)
+ ("\\textexclamdown" . ?¡)
+ ("\\textcent" . ?¢)
+ ("\\textsterling" . ?£)
+ ("\\textcurrency" . ?¤)
+ ("\\textyen" . ?¥)
+ ("\\textbrokenbar" . ?¦)
+ ("\\textsection" . ?§)
+ ("\\textasciidieresis" . ?¨)
+ ("\\textcopyright" . ?©)
+ ("\\textordfeminine" . ?ª)
+ ("\\guillemetleft" . ?«)
+ ("\\guillemotleft" . ?«)
+ ("\\textlnot" . ?¬)
+ ("\\textregistered" . ?®)
+ ("\\textasciimacron" . ?¯)
+ ("\\textdegree" . ?°)
+ ("\\textpm" . ?±)
+ ("\\texttwosuperior" . ?²)
+ ("\\textthreesuperior" . ?³)
+ ("\\textasciiacute" . ?´)
("\\textmu" . ?µ)
+ ("\\textparagraph" . ?¶)
+ ("\\textpilcrow" . ?¶)
+ ("\\textperiodcentered" . ?·)
+ ("\\textonesuperior" . ?¹)
+ ("\\textordmasculine" . ?º)
+ ("\\guillemetright" . ?»)
+ ("\\guillemotright" . ?»)
+ ("\\textonequarter" . ?¼)
+ ("\\textonehalf" . ?½)
+ ("\\textthreequarters" . ?¾)
+ ("\\textquestiondown" . ?¿)
+ ("\\texttimes" . ?×)
+ ("\\textdiv" . ?÷)
+ ("\\textflorin" . ?ƒ)
+ ("\\textasciicaron" . ?ˇ)
+ ("\\textasciibreve" . ?˘)
+ ("\\textacutedbl" . ?˝)
+ ("\\textgravedbl" . 757)
+ ("\\texttildelow" . 759)
+ ("\\textbaht" . ?฿)
+ ("\\textendash" . ?–)
+ ("\\textemdash" . ?—)
+ ("\\textbardbl" . ?‖)
+ ("\\textquoteleft" . 8216)
+ ("\\textquoteright" . 8217)
+ ("\\quotesinglbase" . 8218)
+ ("\\textquotedblleft" . 8220)
+ ("\\textquotedblright" . 8221)
+ ("\\quotedblbase" . 8222)
+ ;; \textdagger and \textdied are replaced with DAGGER (#x2020) and
+ ;; not with LATIN CROSS (#x271d)
+ ("\\textdagger" . ?†)
+ ("\\textdied" . ?†)
+ ("\\textdaggerdbl" . ?‡)
+ ("\\textbullet" . ?•)
+ ("\\textellipsis" . ?…)
+ ("\\textperthousand" . ?‰)
+ ("\\textpertenthousand" . ?‱)
+ ("\\guilsinglleft" . ?‹)
+ ("\\guilsinglright" . ?›)
+ ("\\textreferencemark" . ?※)
+ ("\\textinterrobang" . ?‽)
("\\textfractionsolidus" . ?⁄)
- ("\\textbigcircle" . ?⃝)
- ("\\textmusicalnote" . ?♪)
- ("\\textdied" . ?✝)
+ ("\\textlquill" . 8261) ; Literal ?⁅ breaks indentation
+ ("\\textrquill" . 8262) ; Literal ?⁆ breaks indentation
+ ("\\textdiscount" . ?⁒)
("\\textcolonmonetary" . ?₡)
- ("\\textwon" . ?₩)
+ ("\\textlira" . ?₤)
("\\textnaira" . ?₦)
+ ("\\textwon" . ?₩)
+ ("\\textdong" . ?₫)
+ ("\\texteuro" . ?€)
("\\textpeso" . ?₱)
- ("\\textlira" . ?₤)
- ("\\textrecipe" . ?℞)
- ("\\textinterrobang" . ?‽)
- ("\\textpertenthousand" . ?‱)
- ("\\textbaht" . ?฿)
+ ("\\textguarani" . ?₲)
+ ("\\textcelsius" . ?℃)
("\\textnumero" . ?№)
- ("\\textdiscount" . ?⁒)
+ ("\\textcircledP" . ?℗)
+ ("\\textrecipe" . ?℞)
+ ("\\textservicemark" . ?℠)
+ ("\\texttrademark" . ?™)
+ ("\\textohm" . ?Ω)
+ ("\\textmho" . ?℧)
("\\textestimated" . ?℮)
+ ("\\textleftarrow" . ?←)
+ ("\\textuparrow" . ?↑)
+ ("\\textrightarrow" . ?→)
+ ("\\textdownarrow" . ?↓)
+ ("\\textminus" . ?−)
+ ("\\textsurd" . ?√)
+ ("\\textlangle" . 9001) ; Literal ?〈 breaks indentation
+ ("\\textrangle" . 9002) ; Literal ?〉 breaks indentation
+ ("\\textblank" . ?␢)
+ ("\\textvisiblespace" . ?␣)
("\\textopenbullet" . ?◦)
- ("\\textlquill" . 8261) ; Literal ?⁅ breaks indentation.
- ("\\textrquill" . 8262) ; Literal ?⁆ breaks indentation.
- ("\\textcircledP" . ?℗)
- ("\\textreferencemark" . ?※))
+ ;; \textbigcircle is replaced with LARGE CIRCLE (#x25ef) and not
+ ;; with COMBINING ENCLOSING CIRCLE (#x20dd)
+ ("\\textbigcircle" . ?◯)
+ ("\\textmusicalnote" . ?♪)
+ ("\\textmarried" . ?⚭)
+ ("\\textdivorced" . ?⚮)
+ ("\\textlbrackdbl" . 10214) ; Literal ?⟦ breaks indentation
+ ("\\textrbrackdbl" . 10215) ; Literal ?⟧ breaks indentation
+ ("\\textinterrobangdown" . ?⸘))
"A `prettify-symbols-alist' usable for (La)TeX modes.")
(defun tex--prettify-symbols-compose-p (_start end _match)
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
index 81ac45eb6c4..5d6f5deae1b 100644
--- a/lisp/textmodes/texinfo.el
+++ b/lisp/textmodes/texinfo.el
@@ -4,7 +4,6 @@
;; Foundation, Inc.
;; Author: Robert J. Chassell
-;; Date: [See date below for texinfo-version]
;; Maintainer: emacs-devel@gnu.org
;; Keywords: maint, tex, docs
@@ -32,6 +31,16 @@
;;; Code:
+(eval-when-compile (require 'cl-lib)
+ (require 'flymake)
+ (require 'rx))
+(declare-function flymake-diag-region "flymake"
+ (buffer line &optional col))
+(declare-function flymake-make-diagnostic "flymake"
+ ( locus beg end type text
+ &optional data overlay-properties))
+(declare-function flymake--log-1 "flymake" (level sublog msg &rest args))
+
(eval-when-compile (require 'tex-mode))
(declare-function tex-buffer "tex-mode" ())
(declare-function tex-region "tex-mode" (beg end))
@@ -336,6 +345,69 @@ Subexpression 1 is what goes into the corresponding `@end' statement.")
(if (re-search-backward "^@node[ \t]+\\([^,\n]+\\)" nil t)
(match-string-no-properties 1))))
+;;; Flymake support
+(defvar-local texinfo--flymake-proc nil)
+(defun texinfo-flymake (report-fn &rest _)
+ "Texinfo checking for Flymake.
+
+REPORT-FN is the callback function."
+ (let ((executable (or (executable-find "makeinfo")
+ (executable-find "texi2any")))
+ (source (current-buffer)))
+
+ (unless executable
+ (error "Flymake for Texinfo requires `makeinfo' or `texi2any'"))
+
+ (when (process-live-p texinfo--flymake-proc)
+ (kill-process texinfo--flymake-proc))
+
+ (save-restriction
+ (widen)
+ (setq texinfo--flymake-proc
+ (make-process
+ :name "texinfo-flymake"
+ :noquery t
+ :connection-type 'pipe
+ :buffer (generate-new-buffer " *texinfo-flymake*")
+ :command `(,executable "-o" ,null-device "-")
+ :sentinel
+ (lambda (proc _event)
+ (when (memq (process-status proc) '(exit signal))
+ (unwind-protect
+ (if (eq (buffer-local-value 'texinfo--flymake-proc
+ source)
+ proc)
+ (with-current-buffer (process-buffer proc)
+ (goto-char (point-min))
+ (cl-loop
+ while (search-forward-regexp
+ (rx line-start
+ "-:"
+ (group-n 1 (0+ digit)) ; Line
+ (optional ":" (group-n 2 (0+ digit))) ; col
+ ": "
+ (optional (group-n 3 "warning: ")) ; warn
+ (group-n 4 (0+ nonl)) ; Message
+ line-end)
+ nil t)
+ for msg = (match-string 4)
+ for (beg . end) = (flymake-diag-region
+ source
+ (string-to-number (match-string 1)))
+ for type = (if (match-string 3)
+ :warning
+ :error)
+ collect (flymake-make-diagnostic
+ source beg end type msg)
+ into diags
+ finally (funcall report-fn diags)))
+ (flymake-log :warning "Cancelling obsolete check %s"
+ proc))
+ (kill-buffer (process-buffer proc)))))))
+ (process-send-region texinfo--flymake-proc (point-min) (point-max))
+ (process-send-eof texinfo--flymake-proc))))
+
+
;;; Texinfo mode
;;;###autoload
@@ -411,13 +483,13 @@ value of `texinfo-mode-hook'."
"\\)\\>"))
(setq-local require-final-newline mode-require-final-newline)
(setq-local indent-tabs-mode nil)
- (setq-local paragraph-separate
- (concat "@[a-zA-Z]*[ \n]\\|"
- paragraph-separate))
(setq-local paragraph-start (concat "@[a-zA-Z]*[ \n]\\|"
paragraph-start))
+ (setq-local fill-paragraph-function 'texinfo--fill-paragraph)
(setq-local sentence-end-base "\\(@\\(end\\)?dots{}\\|[.?!]\\)[]\"'”)}]*")
(setq-local fill-column 70)
+ (setq-local beginning-of-defun-function #'texinfo--beginning-of-defun)
+ (setq-local end-of-defun-function #'texinfo--end-of-defun)
(setq-local comment-start "@c ")
(setq-local comment-start-skip "@c +\\|@comment +")
(setq-local words-include-escapes t)
@@ -455,8 +527,63 @@ value of `texinfo-mode-hook'."
(let ((prevent-filling "^@\\(def\\|multitable\\)"))
(if (null auto-fill-inhibit-regexp)
prevent-filling
- (concat auto-fill-inhibit-regexp "\\|" prevent-filling)))))
-
+ (concat auto-fill-inhibit-regexp "\\|" prevent-filling))))
+
+ ;; Set up Flymake support.
+ (add-hook 'flymake-diagnostic-functions #'texinfo-flymake nil t))
+
+(defvar texinfo-fillable-commands '("@noindent")
+ "A list of commands that can be filled.")
+
+(defun texinfo--fill-paragraph (justify)
+ "Function to fill a paragraph in `texinfo-mode'."
+ (let ((command-re "\\(@[a-zA-Z]+\\)[ \t\n]"))
+ (catch 'no-fill
+ (save-restriction
+ ;; First check whether we're on a command line that can be
+ ;; filled by itself.
+ (or
+ (save-excursion
+ (beginning-of-line)
+ (when (looking-at command-re)
+ (let ((command (match-string 1)))
+ (if (member command texinfo-fillable-commands)
+ (progn
+ (narrow-to-region (point) (progn (forward-line 1) (point)))
+ t)
+ (throw 'no-fill nil)))))
+ ;; We're not on such a line, so fill the region.
+ (save-excursion
+ (let ((regexp (concat command-re "\\|^[ \t]*$\\|\f")))
+ (narrow-to-region
+ (if (re-search-backward regexp nil t)
+ (progn
+ (forward-line 1)
+ (point))
+ (point-min))
+ (if (re-search-forward regexp nil t)
+ (match-beginning 0)
+ (point-max)))
+ (goto-char (point-min)))))
+ ;; We've now narrowed to the region we want to fill.
+ (let ((fill-paragraph-function nil)
+ (adaptive-fill-mode nil))
+ (fill-paragraph justify))))
+ t))
+
+(defun texinfo--beginning-of-defun (&optional arg)
+ "Go to the previous @node line."
+ (while (and (> arg 0)
+ (re-search-backward "^@node " nil t))
+ (setq arg (1- arg))))
+
+(defun texinfo--end-of-defun ()
+ "Go to the start of the next @node line."
+ (when (looking-at-p "@node")
+ (forward-line))
+ (if (re-search-forward "^@node " nil t)
+ (goto-char (match-beginning 0))
+ (goto-char (point-max))))
;;; Insert string commands
diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el
index 5b468dc808b..e44aa06e3dd 100644
--- a/lisp/textmodes/texnfo-upd.el
+++ b/lisp/textmodes/texnfo-upd.el
@@ -1367,7 +1367,7 @@ left at the end of the node line."
;; There may be an @chapter or other such command between
;; the top node line and the next node line, as a title
;; for an `ifinfo' section. This @chapter command must
- ;; must be skipped. So the procedure is to search for
+ ;; be skipped. So the procedure is to search for
;; the next `@node' line, and then copy its name.
(if (re-search-forward "^@node" nil t)
(progn
diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el
index 9dcfb10d6df..2a7ad295ab7 100644
--- a/lisp/textmodes/tildify.el
+++ b/lisp/textmodes/tildify.el
@@ -494,9 +494,8 @@ variable will be set to the representation."
(if (not (string-equal " " (or space tildify-space-string)))
(when space
(setq tildify-space-string space))
- (message (eval-when-compile
- (concat "Hard space is a single space character, tildify-"
- "mode won't have any effect, disabling.")))
+ (message (concat "Hard space is a single space character, tildify-"
+ "mode won't have any effect, disabling."))
(setq tildify-mode nil))))
(if tildify-mode
(add-hook 'post-self-insert-hook #'tildify-space nil t)
diff --git a/lisp/textmodes/word-wrap-mode.el b/lisp/textmodes/word-wrap-mode.el
new file mode 100644
index 00000000000..c354fc773a7
--- /dev/null
+++ b/lisp/textmodes/word-wrap-mode.el
@@ -0,0 +1,80 @@
+;;; word-wrap-mode.el --- minor mode for `word-wrap' tweaks -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+;; The list below lists all characters that have a general-category of
+;; Zs, but with the ones we don't want to add here commented out.
+(defcustom word-wrap-whitespace-characters
+ '(;;?\N{SPACE}
+ ;;?\N{NO-BREAK SPACE}
+ ?\N{OGHAM SPACE MARK}
+ ?\N{EN QUAD}
+ ?\N{EM QUAD}
+ ?\N{EN SPACE}
+ ?\N{EM SPACE}
+ ?\N{THREE-PER-EM SPACE}
+ ?\N{FOUR-PER-EM SPACE}
+ ?\N{SIX-PER-EM SPACE}
+ ?\N{FIGURE SPACE}
+ ?\N{PUNCTUATION SPACE}
+ ?\N{THIN SPACE}
+ ?\N{HAIR SPACE}
+ ;;?\N{NARROW NO-BREAK SPACE}
+ ?\N{MEDIUM MATHEMATICAL SPACE}
+ ?\N{IDEOGRAPHIC SPACE}
+ ;; Not in the Zs category:
+ ?\N{ZERO WIDTH SPACE})
+ "Characters that `word-wrap-whitespace-mode' should add to `word-wrap'."
+ :version "29.1"
+ :type '(repeat character)
+ :group 'display)
+
+(defvar word-wrap-mode--previous-state)
+
+;;;###autoload
+(define-minor-mode word-wrap-whitespace-mode
+ "Allow `word-wrap' to fold on all breaking whitespace characters.
+The characters to break on are defined by `word-wrap-whitespace-characters'."
+ :group 'display
+ (if word-wrap-whitespace-mode
+ (progn
+ (setq-local word-wrap-mode--previous-state
+ (cons (category-table)
+ (buffer-local-set-state
+ word-wrap-by-category t
+ word-wrap t)))
+ (set-category-table (copy-category-table))
+ (dolist (char word-wrap-whitespace-characters)
+ (modify-category-entry char ?|)))
+ (set-category-table (car word-wrap-mode--previous-state))
+ (buffer-local-restore-state (cdr word-wrap-mode--previous-state))))
+
+;;;###autoload
+(define-globalized-minor-mode global-word-wrap-whitespace-mode
+ word-wrap-whitespace-mode word-wrap-whitespace-mode
+ :group 'display)
+
+(provide 'word-wrap-mode)
+
+;;; word-wrap-mode.el ends here