summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/lisp-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/lisp-mode.el')
-rw-r--r--lisp/emacs-lisp/lisp-mode.el219
1 files changed, 120 insertions, 99 deletions
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 0b1e5abd1ad..9bed4374dff 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -94,68 +94,68 @@
(defvar lisp-imenu-generic-expression
(list
(list nil
- (purecopy (concat "^\\s-*("
- (regexp-opt
- '("defun" "defmacro"
- ;; Elisp.
- "defun*" "defsubst" "define-inline"
- "define-advice" "defadvice" "define-skeleton"
- "define-compilation-mode" "define-minor-mode"
- "define-global-minor-mode"
- "define-globalized-minor-mode"
- "define-derived-mode" "define-generic-mode"
- "ert-deftest"
- "cl-defun" "cl-defsubst" "cl-defmacro"
- "cl-define-compiler-macro" "cl-defgeneric"
- "cl-defmethod"
- ;; CL.
- "define-compiler-macro" "define-modify-macro"
- "defsetf" "define-setf-expander"
- "define-method-combination"
- ;; CLOS and EIEIO
- "defgeneric" "defmethod")
- t)
- "\\s-+\\(" (rx lisp-mode-symbol) "\\)"))
+ (concat "^\\s-*("
+ (regexp-opt
+ '("defun" "defmacro"
+ ;; Elisp.
+ "defun*" "defsubst" "define-inline"
+ "define-advice" "defadvice" "define-skeleton"
+ "define-compilation-mode" "define-minor-mode"
+ "define-global-minor-mode"
+ "define-globalized-minor-mode"
+ "define-derived-mode" "define-generic-mode"
+ "ert-deftest"
+ "cl-defun" "cl-defsubst" "cl-defmacro"
+ "cl-define-compiler-macro" "cl-defgeneric"
+ "cl-defmethod"
+ ;; CL.
+ "define-compiler-macro" "define-modify-macro"
+ "defsetf" "define-setf-expander"
+ "define-method-combination"
+ ;; CLOS and EIEIO
+ "defgeneric" "defmethod")
+ t)
+ "\\s-+\\(" (rx lisp-mode-symbol) "\\)")
2)
;; Like the previous, but uses a quoted symbol as the name.
(list nil
- (purecopy (concat "^\\s-*("
- (regexp-opt
- '("defalias" "define-obsolete-function-alias")
- t)
- "\\s-+'\\(" (rx lisp-mode-symbol) "\\)"))
+ (concat "^\\s-*("
+ (regexp-opt
+ '("defalias" "define-obsolete-function-alias")
+ t)
+ "\\s-+'\\(" (rx lisp-mode-symbol) "\\)")
2)
- (list (purecopy "Variables")
- (purecopy (concat "^\\s-*("
- (regexp-opt
- '(;; Elisp
- "defconst" "defcustom" "defvar-keymap"
- ;; CL
- "defconstant"
- "defparameter" "define-symbol-macro")
- t)
- "\\s-+\\(" (rx lisp-mode-symbol) "\\)"))
+ (list "Variables"
+ (concat "^\\s-*("
+ (regexp-opt
+ '(;; Elisp
+ "defconst" "defcustom" "defvar-keymap"
+ ;; CL
+ "defconstant"
+ "defparameter" "define-symbol-macro")
+ t)
+ "\\s-+\\(" (rx lisp-mode-symbol) "\\)")
2)
;; For `defvar'/`defvar-local', we ignore (defvar FOO) constructs.
- (list (purecopy "Variables")
- (purecopy (concat "^\\s-*(defvar\\(?:-local\\)?\\s-+\\("
- (rx lisp-mode-symbol) "\\)"
- "[[:space:]\n]+[^)]"))
+ (list "Variables"
+ (concat "^\\s-*(defvar\\(?:-local\\)?\\s-+\\("
+ (rx lisp-mode-symbol) "\\)"
+ "[[:space:]\n]+[^)]")
1)
- (list (purecopy "Types")
- (purecopy (concat "^\\s-*("
- (regexp-opt
- '(;; Elisp
- "defgroup" "deftheme"
- "define-widget" "define-error"
- "defface" "cl-deftype" "cl-defstruct"
- ;; CL
- "deftype" "defstruct"
- "define-condition" "defpackage"
- ;; CLOS and EIEIO
- "defclass")
- t)
- "\\s-+'?\\(" (rx lisp-mode-symbol) "\\)"))
+ (list "Types"
+ (concat "^\\s-*("
+ (regexp-opt
+ '(;; Elisp
+ "defgroup" "deftheme"
+ "define-widget" "define-error"
+ "defface" "cl-deftype" "cl-defstruct"
+ ;; CL
+ "deftype" "defstruct"
+ "define-condition" "defpackage"
+ ;; CLOS and EIEIO
+ "defclass")
+ t)
+ "\\s-+'?\\(" (rx lisp-mode-symbol) "\\)")
2))
"Imenu generic expression for Lisp mode. See `imenu-generic-expression'.")
@@ -308,7 +308,7 @@ This will generate compile-time constants from BINDINGS."
(buffer-substring-no-properties
beg0 end0)))))
(buffer-substring-no-properties (1+ beg0) end0))
- `(face ,font-lock-warning-face
+ '(face font-lock-warning-face
help-echo "This \\ has no effect"))))
(defun lisp--match-confusable-symbol-character (limit)
@@ -490,14 +490,17 @@ This will generate compile-time constants from BINDINGS."
(2 font-lock-constant-face nil t))
;; Words inside \\[], \\<>, \\{} or \\`' tend to be for
;; `substitute-command-keys'.
- (,(rx "\\\\" (or (seq "[" (group-n 1 lisp-mode-symbol) "]")
+ (,(rx "\\\\" (or (seq "["
+ (group-n 1 (seq lisp-mode-symbol (not "\\"))) "]")
(seq "`" (group-n 1
;; allow multiple words, e.g. "C-x a"
lisp-mode-symbol (* " " lisp-mode-symbol))
"'")))
(1 font-lock-constant-face prepend))
- (,(rx "\\\\" (or (seq "<" (group-n 1 lisp-mode-symbol) ">")
- (seq "{" (group-n 1 lisp-mode-symbol) "}")))
+ (,(rx "\\\\" (or (seq "<"
+ (group-n 1 (seq lisp-mode-symbol (not "\\"))) ">")
+ (seq "{"
+ (group-n 1 (seq lisp-mode-symbol (not "\\"))) "}")))
(1 font-lock-variable-name-face prepend))
;; Ineffective backslashes (typically in need of doubling).
("\\(\\\\\\)\\([^\"\\]\\)"
@@ -556,7 +559,9 @@ This will generate compile-time constants from BINDINGS."
(,(concat "(" cl-errs-re "\\_>")
(1 font-lock-warning-face))
;; Words inside ‘’ and `' tend to be symbol names.
- (,(concat "[`‘]\\(" (rx lisp-mode-symbol) "\\)['’]")
+ (,(concat "[`‘]\\("
+ (rx (* lisp-mode-symbol (+ space)) lisp-mode-symbol)
+ "\\)['’]")
(1 font-lock-constant-face prepend))
;; Uninterned symbols, e.g., (defpackage #:my-package ...)
;; must come before keywords below to have effect
@@ -657,9 +662,9 @@ Lisp font lock syntactic face function."
(let ((listbeg (nth 1 state)))
(if (or (lisp-string-in-doc-position-p listbeg startpos)
(lisp-string-after-doc-keyword-p listbeg startpos))
- font-lock-doc-face
- font-lock-string-face))))
- font-lock-comment-face))
+ 'font-lock-doc-face
+ 'font-lock-string-face))))
+ 'font-lock-comment-face))
(defun lisp-adaptive-fill ()
"Return fill prefix found at point.
@@ -1153,7 +1158,7 @@ is the buffer position of the start of the containing expression."
(defun lisp--local-defform-body-p (state)
"Return non-nil when at local definition body according to STATE.
STATE is the `parse-partial-sexp' state for current position."
- (when-let ((start-of-innermost-containing-list (nth 1 state)))
+ (when-let* ((start-of-innermost-containing-list (nth 1 state)))
(let* ((parents (nth 9 state))
(first-cons-after (cdr parents))
(second-cons-after (cdr first-cons-after))
@@ -1171,11 +1176,11 @@ STATE is the `parse-partial-sexp' state for current position."
(let (local-definitions-starting-point)
(and (save-excursion
(goto-char (1+ second-order-parent))
- (when-let ((head (ignore-errors
- ;; FIXME: This does not distinguish
- ;; between reading nil and a read error.
- ;; We don't care but still, better fix this.
- (read (current-buffer)))))
+ (when-let* ((head (ignore-errors
+ ;; FIXME: This does not distinguish
+ ;; between reading nil and a read error.
+ ;; We don't care but still, better fix this.
+ (read (current-buffer)))))
(when (memq head '( cl-flet cl-labels cl-macrolet cl-flet*
cl-symbol-macrolet))
;; In what follows, we rely on (point) returning non-nil.
@@ -1428,6 +1433,20 @@ Any non-integer value means do not use a different value of
:group 'lisp
:version "30.1")
+(defvar lisp-fill-paragraphs-as-doc-string t
+ "Whether `lisp-fill-paragraph' should fill strings as ELisp doc strings.
+The default behavior of `lisp-fill-paragraph' is tuned for filling Emacs
+Lisp doc strings, with their special treatment for the first line.
+Specifically, strings are filled in a narrowed context to avoid filling
+surrounding code, which means any leading indent is disregarded, which
+can cause the filled string to extend passed the configured
+`fill-column' variable value. If you would rather fill the string in
+its original context, disregarding the special conventions of ELisp doc
+strings, and want to ensure the `fill-column' value is more strictly
+respected, set this variable to nil. Doing so makes
+`lisp-fill-paragraph' behave as it used to in Emacs 27 and prior
+versions.")
+
(defun lisp-fill-paragraph (&optional justify)
"Like \\[fill-paragraph], but handle Emacs Lisp comments and docstrings.
If any of the current line is a comment, fill the comment or the
@@ -1477,42 +1496,44 @@ and initial semicolons."
(derived-mode-p 'emacs-lisp-mode))
emacs-lisp-docstring-fill-column
fill-column)))
- (let ((ppss (syntax-ppss))
- (start (point))
- ;; Avoid recursion if we're being called directly with
- ;; `M-x lisp-fill-paragraph' in an `emacs-lisp-mode' buffer.
- (fill-paragraph-function t))
+ (let* ((ppss (syntax-ppss))
+ (start (point))
+ ;; Avoid recursion if we're being called directly with
+ ;; `M-x lisp-fill-paragraph' in an `emacs-lisp-mode' buffer.
+ (fill-paragraph-function t)
+ (string-start (ppss-comment-or-string-start ppss)))
(save-excursion
(save-restriction
;; If we're not inside a string, then do very basic
;; filling. This avoids corrupting embedded strings in
;; code.
- (if (not (ppss-comment-or-string-start ppss))
+ (if (not string-start)
(lisp--fill-line-simple)
- ;; If we're in a string, then narrow (roughly) to that
- ;; string before filling. This avoids filling Lisp
- ;; statements that follow the string.
- (when (ppss-string-terminator ppss)
- (goto-char (ppss-comment-or-string-start ppss))
- ;; The string may be unterminated -- in that case, don't
- ;; narrow.
- (when (ignore-errors
- (progn
- (forward-sexp 1)
- t))
- (narrow-to-region (1+ (ppss-comment-or-string-start ppss))
- (1- (point)))))
- ;; Move back to where we were.
- (goto-char start)
- ;; We should fill the first line of a string
- ;; separately (since it's usually a doc string).
- (if (= (line-number-at-pos) 1)
- (narrow-to-region (line-beginning-position)
- (line-beginning-position 2))
- (save-excursion
- (goto-char (point-min))
- (forward-line 1)
- (narrow-to-region (point) (point-max))))
+ (when lisp-fill-paragraphs-as-doc-string
+ ;; If we're in a string, then narrow (roughly) to that
+ ;; string before filling. This avoids filling Lisp
+ ;; statements that follow the string.
+ (when (ppss-string-terminator ppss)
+ (goto-char string-start)
+ ;; The string may be unterminated -- in that case, don't
+ ;; narrow.
+ (when (ignore-errors
+ (progn
+ (forward-sexp 1)
+ t))
+ (narrow-to-region (1+ string-start)
+ (1- (point)))))
+ ;; Move back to where we were.
+ (goto-char start)
+ ;; We should fill the first line of a string
+ ;; separately (since it's usually a doc string).
+ (if (= (line-number-at-pos) 1)
+ (narrow-to-region (line-beginning-position)
+ (line-beginning-position 2))
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (narrow-to-region (point) (point-max)))))
(fill-paragraph justify)))))))
;; Never return nil.
t)