summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2018-08-09 17:56:53 -0600
committerTom Tromey <tom@tromey.com>2018-08-09 17:56:53 -0600
commitaccb7b7ecc19f85c2750ded1046a464bc73c6a52 (patch)
tree1aa94af022d6700a93a8ff2b73f5b210046ac010 /lisp
parentf822a2516d88eeb2118fbbc8554f155e86dfd74e (diff)
parent53483df0de0085dbc9ef0b15a0f629ab808b0147 (diff)
downloademacs-accb7b7ecc19f85c2750ded1046a464bc73c6a52.tar.gz
Merge remote-tracking branch 'origin/master' into feature/bignum
Diffstat (limited to 'lisp')
-rw-r--r--lisp/auth-source.el2
-rw-r--r--lisp/bookmark.el7
-rw-r--r--lisp/calendar/todo-mode.el202
-rw-r--r--lisp/char-fold.el2
-rw-r--r--lisp/comint.el19
-rw-r--r--lisp/cus-theme.el63
-rw-r--r--lisp/custom.el257
-rw-r--r--lisp/dired-aux.el37
-rw-r--r--lisp/dired.el3
-rw-r--r--lisp/emacs-lisp/backtrace.el916
-rw-r--r--lisp/emacs-lisp/cl-macs.el5
-rw-r--r--lisp/emacs-lisp/cl-print.el301
-rw-r--r--lisp/emacs-lisp/debug.el463
-rw-r--r--lisp/emacs-lisp/easy-mmode.el28
-rw-r--r--lisp/emacs-lisp/edebug.el276
-rw-r--r--lisp/emacs-lisp/ert.el41
-rw-r--r--lisp/emacs-lisp/lisp-mode.el26
-rw-r--r--lisp/emacs-lisp/map-ynp.el18
-rw-r--r--lisp/emacs-lisp/rx.el32
-rw-r--r--lisp/emacs-lisp/subr-x.el12
-rw-r--r--lisp/env.el6
-rw-r--r--lisp/epg-config.el27
-rw-r--r--lisp/eshell/em-dirs.el3
-rw-r--r--lisp/eshell/em-ls.el1
-rw-r--r--lisp/eshell/em-unix.el10
-rw-r--r--lisp/eshell/esh-cmd.el51
-rw-r--r--lisp/eshell/esh-ext.el1
-rw-r--r--lisp/files.el22
-rw-r--r--lisp/format.el2
-rw-r--r--lisp/gnus/gnus-art.el6
-rw-r--r--lisp/gnus/gnus-sum.el8
-rw-r--r--lisp/ielm.el14
-rw-r--r--lisp/imenu.el13
-rw-r--r--lisp/indent.el9
-rw-r--r--lisp/international/fontset.el9
-rw-r--r--lisp/international/mule-cmds.el9
-rw-r--r--lisp/international/mule-conf.el9
-rw-r--r--lisp/international/mule-diag.el3
-rw-r--r--lisp/international/quail.el20
-rw-r--r--lisp/jsonrpc.el88
-rw-r--r--lisp/language/thai.el4
-rw-r--r--lisp/ldefs-boot.el874
-rw-r--r--lisp/mh-e/mh-comp.el100
-rw-r--r--lisp/mh-e/mh-funcs.el2
-rw-r--r--lisp/mh-e/mh-identity.el27
-rw-r--r--lisp/net/rcirc.el2
-rw-r--r--lisp/net/rlogin.el8
-rw-r--r--lisp/net/soap-client.el21
-rw-r--r--lisp/net/tramp-gvfs.el37
-rw-r--r--lisp/net/tramp-sh.el6
-rw-r--r--lisp/net/tramp.el12
-rw-r--r--lisp/net/trampver.el2
-rw-r--r--lisp/profiler.el6
-rw-r--r--lisp/progmodes/cc-engine.el12
-rw-r--r--lisp/progmodes/elisp-mode.el2
-rw-r--r--lisp/progmodes/grep.el4
-rw-r--r--lisp/progmodes/hideif.el2
-rw-r--r--lisp/progmodes/python.el95
-rw-r--r--lisp/progmodes/subword.el4
-rw-r--r--lisp/register.el16
-rw-r--r--lisp/scroll-bar.el24
-rw-r--r--lisp/shadowfile.el478
-rw-r--r--lisp/shell.el4
-rw-r--r--lisp/simple.el12
-rw-r--r--lisp/subr.el31
-rw-r--r--lisp/term.el20
-rw-r--r--lisp/term/tty-colors.el14
-rw-r--r--lisp/textmodes/flyspell.el19
-rw-r--r--lisp/textmodes/ispell.el5
-rw-r--r--lisp/textmodes/reftex-vars.el6
-rw-r--r--lisp/thingatpt.el2
-rw-r--r--lisp/vc/add-log.el77
-rw-r--r--lisp/vc/diff-mode.el35
-rw-r--r--lisp/vc/diff.el5
-rw-r--r--lisp/vc/log-edit.el6
-rw-r--r--lisp/w32-fns.el2
-rw-r--r--lisp/wdired.el51
77 files changed, 3513 insertions, 1535 deletions
diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index abff0def95f..261e9726131 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -779,7 +779,7 @@ Calls `auth-source-search' with the :delete property in SPEC set to t.
The backend may not actually delete the entries.
Returns the deleted entries."
- (auth-source-search (plist-put spec :delete t)))
+ (apply #'auth-source-search (plist-put spec :delete t)))
(defun auth-source-search-collection (collection value)
"Returns t is VALUE is t or COLLECTION is t or COLLECTION contains VALUE."
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index 78f3e324034..58a279473d0 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -1102,7 +1102,7 @@ BOOKMARK is usually a bookmark name (a string). It can also be a
bookmark record, but this is usually only done by programmatic callers.
If DISPLAY-FUNC is non-nil, it is a function to invoke to display the
-bookmark. It defaults to `switch-to-buffer'. A typical value for
+bookmark. It defaults to `pop-to-buffer-same-window'. A typical value for
DISPLAY-FUNC would be `switch-to-buffer-other-window'."
(interactive
(list (bookmark-completing-read "Jump to bookmark"
@@ -1110,7 +1110,10 @@ DISPLAY-FUNC would be `switch-to-buffer-other-window'."
(unless bookmark
(error "No bookmark specified"))
(bookmark-maybe-historicize-string bookmark)
- (bookmark--jump-via bookmark (or display-func 'switch-to-buffer)))
+ ;; Don't use `switch-to-buffer' because it would let the
+ ;; window-point override the bookmark's point when
+ ;; `switch-to-buffer-preserve-window-point' is non-nil.
+ (bookmark--jump-via bookmark (or display-func 'pop-to-buffer-same-window)))
;;;###autoload
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index 5161ae8d668..c1c292129e2 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -853,17 +853,18 @@ category. With non-nil argument BACK, visit the numerically
previous category (the highest numbered one, if the current
category is the first)."
(interactive)
- (setq todo-category-number
- (1+ (mod (- todo-category-number (if back 2 0))
- (length todo-categories))))
- (when todo-skip-archived-categories
- (while (and (zerop (todo-get-count 'todo))
- (zerop (todo-get-count 'done))
- (not (zerop (todo-get-count 'archived))))
- (setq todo-category-number
- (funcall (if back #'1- #'1+) todo-category-number))))
- (todo-category-select)
- (goto-char (point-min)))
+ (let ((setcatnum (lambda () (1+ (mod (- todo-category-number
+ (if back 2 0))
+ (length todo-categories))))))
+ (setq todo-category-number (funcall setcatnum))
+ (when todo-skip-archived-categories
+ (while (and (zerop (todo-get-count 'todo))
+ (zerop (todo-get-count 'done))
+ (not (zerop (todo-get-count 'archived))))
+ (setq todo-category-number (funcall setcatnum))))
+ (todo-category-select)
+ (if transient-mark-mode (deactivate-mark))
+ (goto-char (point-min))))
(defun todo-backward-category ()
"Visit the numerically previous category in this todo file.
@@ -928,11 +929,13 @@ Categories mode."
(when goto-archive (todo-archive-mode))
(set-window-buffer (selected-window)
(set-buffer (find-buffer-visiting file0)))
+ (if transient-mark-mode (deactivate-mark))
(unless todo-global-current-todo-file
(setq todo-global-current-todo-file todo-current-todo-file))
(todo-category-number category)
(todo-category-select)
(goto-char (point-min))
+ (if (bound-and-true-p hl-line-mode) (hl-line-highlight))
(when add-item (todo-insert-item--basic))))))
(defun todo-next-item (&optional count)
@@ -1018,15 +1021,17 @@ empty line above the done items separator."
(setq shown (progn
(goto-char (point-min))
(re-search-forward todo-done-string-start nil t)))
- (if (not (pos-visible-in-window-p shown))
- (recenter)
- (goto-char opoint)))))))
+ (if (pos-visible-in-window-p shown)
+ (goto-char opoint)
+ (recenter)
+ (if transient-mark-mode (deactivate-mark))))))))
(defun todo-toggle-view-done-only ()
"Switch between displaying only done or only todo items."
(interactive)
(setq todo-show-done-only (not todo-show-done-only))
- (todo-category-select))
+ (todo-category-select)
+ (if transient-mark-mode (deactivate-mark)))
(defun todo-toggle-item-highlighting ()
"Highlight or unhighlight the todo item the cursor is on."
@@ -1860,15 +1865,18 @@ their associated keys and their effects."
(region (eq where 'region))
(here (eq where 'here))
diary-item)
- (when copy
- (cond
- ((not (eq major-mode 'todo-mode))
- (user-error "You must be in Todo mode to copy a todo item"))
- ((todo-done-item-p)
- (user-error "You cannot copy a done item as a new todo item"))
- ((looking-at "^$")
- (user-error "Point must be on a todo item to copy it")))
- (setq diary-item (todo-diary-item-p)))
+ (when (and arg here)
+ (user-error "Here insertion only valid in current category"))
+ (when (and (or copy here)
+ (or (not (eq major-mode 'todo-mode)) (todo-done-item-p)
+ (when copy (looking-at "^$"))
+ (save-excursion
+ (beginning-of-line)
+ ;; Point is on done items separator.
+ (looking-at todo-category-done))))
+ (user-error (concat "Item " (if copy "copying" "insertion")
+ " is not valid here")))
+ (when copy (setq diary-item (todo-diary-item-p)))
(when region
(let (use-empty-active-region)
(unless (and todo-use-only-highlighted-region (use-region-p))
@@ -1876,7 +1884,6 @@ their associated keys and their effects."
(let* ((obuf (current-buffer))
(ocat (todo-current-category))
(opoint (point))
- (todo-mm (eq major-mode 'todo-mode))
(cat+file (cond ((equal arg '(4))
(todo-read-category "Insert in category: "))
((equal arg '(16))
@@ -1894,7 +1901,10 @@ their associated keys and their effects."
(new-item (cond (copy (todo-item-string))
(region (buffer-substring-no-properties
(region-beginning) (region-end)))
- (t (read-from-minibuffer "Todo item: "))))
+ (t (if (eq major-mode 'todo-archive-mode)
+ (user-error (concat "Cannot insert a new Todo"
+ " item in an archive"))
+ (read-from-minibuffer "Todo item: ")))))
(date-string (cond
((eq date-type 'date)
(todo-read-date))
@@ -1931,7 +1941,6 @@ their associated keys and their effects."
(unless todo-global-current-todo-file
(setq todo-global-current-todo-file todo-current-todo-file))
(let ((buffer-read-only nil)
- (called-from-outside (not (and todo-mm (equal cat ocat))))
done-only item-added)
(unless copy
(setq new-item
@@ -1955,14 +1964,8 @@ their associated keys and their effects."
"\n\t" new-item nil nil 1)))
(unwind-protect
(progn
- ;; Make sure the correct category is selected. There
- ;; are two cases: (i) we just visited the file, so no
- ;; category is selected yet, or (ii) we invoked
- ;; insertion "here" from outside the category we want
- ;; to insert in (with priority insertion, category
- ;; selection is done by todo-set-item-priority).
- (when (or (= (- (point-max) (point-min)) (buffer-size))
- (and here called-from-outside))
+ ;; If we just visited the file, no category is selected yet.
+ (when (= (- (point-max) (point-min)) (buffer-size))
(todo-category-number cat)
(todo-category-select))
;; If only done items are displayed in category,
@@ -1973,16 +1976,7 @@ their associated keys and their effects."
(setq done-only t)
(todo-toggle-view-done-only))
(if here
- (progn
- ;; If command was invoked with point in done
- ;; items section or outside of the current
- ;; category, can't insert "here", so to be
- ;; useful give new item top priority.
- (when (or (todo-done-item-section-p)
- called-from-outside
- done-only)
- (goto-char (point-min)))
- (todo-insert-with-overlays new-item))
+ (todo-insert-with-overlays new-item)
(todo-set-item-priority new-item cat t))
(setq item-added t))
;; If user cancels before setting priority, restore
@@ -2097,7 +2091,14 @@ the item at point."
(setq todo-categories-with-marks
(assq-delete-all cat todo-categories-with-marks)))
(todo-update-categories-sexp)
- (todo-prefix-overlays)))
+ (todo-prefix-overlays)
+ (when (and (zerop (todo-get-count 'diary))
+ (save-excursion
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^" (regexp-quote todo-category-done))
+ nil t)))
+ (let (todo-show-with-done) (todo-category-select)))))
(if ov (delete-overlay ov)))))
(defvar todo-edit-item--param-key-alist)
@@ -2233,7 +2234,8 @@ made in the number or names of categories."
(insert item))
(kill-buffer)
(unless (eq (current-buffer) buf)
- (set-window-buffer (selected-window) (set-buffer buf))))
+ (set-window-buffer (selected-window) (set-buffer buf)))
+ (if transient-mark-mode (deactivate-mark)))
;; We got here via `F e'.
(when (todo-check-format)
;; FIXME: separate out sexp check?
@@ -2340,7 +2342,7 @@ made in the number or names of categories."
((or (string= omonth "*") (= mm 13))
(user-error "Cannot increment *"))
(t
- (let ((mminc (+ mm inc)))
+ (let ((mminc (+ mm inc (if (< inc 0) 12 0))))
;; Increment or decrement month by INC
;; modulo 12.
(setq mm (% mminc 12))
@@ -2549,7 +2551,11 @@ whose value can be either of the symbols `raise' or `lower',
meaning to raise or lower the item's priority by one."
(interactive)
(unless (and (or (called-interactively-p 'any) (memq arg '(raise lower)))
- (or (todo-done-item-p) (looking-at "^$")))
+ ;; Noop if point is not on a todo (i.e. not done) item.
+ (or (todo-done-item-p) (looking-at "^$")
+ ;; On done items separator.
+ (save-excursion (beginning-of-line)
+ (looking-at todo-category-done))))
(let* ((item (or item (todo-item-string)))
(marked (todo-marked-item-p))
(cat (or cat (cond ((eq major-mode 'todo-mode)
@@ -2697,9 +2703,13 @@ section in the category moved to."
(interactive "P")
(let* ((cat1 (todo-current-category))
(marked (assoc cat1 todo-categories-with-marks)))
- ;; Noop if point is not on an item and there are no marked items.
- (unless (and (looking-at "^$")
- (not marked))
+ (unless
+ ;; Noop if point is not on an item and there are no marked items.
+ (and (or (looking-at "^$")
+ ;; On done items separator.
+ (save-excursion (beginning-of-line)
+ (looking-at todo-category-done)))
+ (not marked))
(let* ((buffer-read-only)
(file1 todo-current-todo-file)
(item (todo-item-string))
@@ -2856,10 +2866,14 @@ visible."
(let* ((cat (todo-current-category))
(marked (assoc cat todo-categories-with-marks)))
(when marked (todo--user-error-if-marked-done-item))
- (unless (and (not marked)
- (or (todo-done-item-p)
- ;; Point is between todo and done items.
- (looking-at "^$")))
+ (unless
+ ;; Noop if point is not on a todo (i.e. not done) item and
+ ;; there are no marked items.
+ (and (or (todo-done-item-p) (looking-at "^$")
+ ;; On done items separator.
+ (save-excursion (beginning-of-line)
+ (looking-at todo-category-done)))
+ (not marked))
(let* ((date-string (calendar-date-string (calendar-current-date) t t))
(time-string (if todo-always-add-time-string
(concat " " (substring (current-time-string)
@@ -3830,6 +3844,7 @@ face."
(goto-char (point-min))
(while (not (eobp))
(setq match (re-search-forward regex nil t))
+ (if (and match transient-mark-mode) (deactivate-mark))
(goto-char (line-beginning-position))
(unless (or (equal (point) 1)
(looking-at (concat "^" (regexp-quote todo-category-beg))))
@@ -4028,19 +4043,22 @@ regexp items."
(interactive "P")
(todo-filter-items 'regexp arg t))
+(defvar todo--fifiles-history nil
+ "List of short file names used by todo-find-filtered-items-file.")
+
(defun todo-find-filtered-items-file ()
"Choose a filtered items file and visit it."
(interactive)
(let ((files (directory-files todo-directory t "\\.tod[rty]$" t))
falist file)
(dolist (f files)
- (let ((type (cond ((equal (file-name-extension f) "todr") "regexp")
+ (let ((sf-name (todo-short-file-name f))
+ (type (cond ((equal (file-name-extension f) "todr") "regexp")
((equal (file-name-extension f) "todt") "top")
((equal (file-name-extension f) "tody") "diary"))))
- (push (cons (concat (todo-short-file-name f) " (" type ")") f)
- falist)))
- (setq file (completing-read "Choose a filtered items file: "
- falist nil t nil nil (car falist)))
+ (push (cons (concat sf-name " (" type ")") f) falist)))
+ (setq file (completing-read "Choose a filtered items file: " falist nil t nil
+ 'todo--fifiles-history (caar falist)))
(setq file (cdr (assoc-string file falist)))
(find-file file)
(unless (derived-mode-p 'todo-filtered-items-mode)
@@ -4050,25 +4068,27 @@ regexp items."
(defun todo-go-to-source-item ()
"Display the file and category of the filtered item at point."
(interactive)
- (let* ((str (todo-item-string))
- (buf (current-buffer))
- (res (todo-find-item str))
- (found (nth 0 res))
- (file (nth 1 res))
- (cat (nth 2 res)))
- (if (not found)
- (message "Category %s does not contain this item." cat)
- (kill-buffer buf)
- (set-window-buffer (selected-window)
- (set-buffer (find-buffer-visiting file)))
- (setq todo-current-todo-file file)
- (setq todo-category-number (todo-category-number cat))
- (let ((todo-show-with-done (if (or todo-filter-done-items
- (eq (cdr found) 'done))
- t
- todo-show-with-done)))
- (todo-category-select))
- (goto-char (car found)))))
+ (unless (looking-at "^$") ; Empty line at EOB.
+ (let* ((str (todo-item-string))
+ (buf (current-buffer))
+ (res (todo-find-item str))
+ (found (nth 0 res))
+ (file (nth 1 res))
+ (cat (nth 2 res)))
+ (if (not found)
+ (message "Category %s does not contain this item." cat)
+ (kill-buffer buf)
+ (set-window-buffer (selected-window)
+ (set-buffer (find-buffer-visiting file)))
+ (setq todo-current-todo-file file)
+ (setq todo-category-number (todo-category-number cat))
+ (let ((todo-show-with-done (if (or todo-filter-done-items
+ (eq (cdr found) 'done))
+ t
+ todo-show-with-done)))
+ (todo-category-select))
+ (if transient-mark-mode (deactivate-mark))
+ (goto-char (car found))))))
(defvar todo-multiple-filter-files nil
"List of files selected from `todo-multiple-filter-files' widget.")
@@ -4520,8 +4540,11 @@ its priority has changed, and `same' otherwise."
(defun todo-save-filtered-items-buffer ()
"Save current Filtered Items buffer to a file.
If the file already exists, overwrite it only on confirmation."
- (let ((filename (or (buffer-file-name) (todo-filter-items-filename))))
- (write-file filename t)))
+ (let ((filename (or (buffer-file-name) (todo-filter-items-filename)))
+ (bufname (buffer-name)))
+ (write-file filename t)
+ (setq buffer-read-only t)
+ (rename-buffer bufname)))
;; -----------------------------------------------------------------------------
;;; Printing Todo mode buffers
@@ -5132,6 +5155,8 @@ but the categories sexp differs from the current value of
(forward-line)
(looking-at (concat "^"
(regexp-quote todo-category-done))))))
+ ;; Point is on done items separator.
+ (save-excursion (beginning-of-line) (looking-at todo-category-done))
;; Buffer is widened.
(looking-at (regexp-quote todo-category-beg)))
(goto-char (line-beginning-position))
@@ -5141,8 +5166,11 @@ but the categories sexp differs from the current value of
(defun todo-item-end ()
"Move to end of current todo item and return its position."
- ;; Items cannot end with a blank line.
- (unless (looking-at "^$")
+ (unless (or
+ ;; Items cannot end with a blank line.
+ (looking-at "^$")
+ ;; Point is on done items separator.
+ (save-excursion (beginning-of-line) (looking-at todo-category-done)))
(let* ((done (todo-done-item-p))
(to-lim nil)
;; For todo items, end is before the done items section, for done
@@ -5293,6 +5321,7 @@ Overrides `diary-goto-entry'."
nil t)
(todo-category-number (match-string 1))
(todo-category-select)
+ (if transient-mark-mode (deactivate-mark))
(goto-char opoint))))))
(add-function :override diary-goto-entry-function #'todo-diary-goto-entry)
@@ -6419,9 +6448,6 @@ Filtered Items mode following todo (not done) items."
("N" todo-toggle-prefix-numbers)
("PB" todo-print-buffer)
("PF" todo-print-buffer-to-file)
- ("b" todo-backward-category)
- ("d" todo-item-done)
- ("f" todo-forward-category)
("j" todo-jump-to-category)
("n" todo-next-item)
("p" todo-previous-item)
@@ -6436,6 +6462,8 @@ Filtered Items mode following todo (not done) items."
("Fc" todo-show-categories-table)
("S" todo-search)
("X" todo-clear-matches)
+ ("b" todo-backward-category)
+ ("f" todo-forward-category)
("*" todo-toggle-mark-item)
)
"List of key bindings for Todo and Todo Archive modes.")
diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index 9c05e364dfd..86bd6038e36 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -214,7 +214,7 @@ from which to start."
(when (> spaces 0)
(push (char-fold--make-space-string spaces) out))
(let ((regexp (apply #'concat (nreverse out))))
- ;; Limited by `MAX_BUF_SIZE' in `regex.c'.
+ ;; Limited by `MAX_BUF_SIZE' in `regex-emacs.c'.
(if (> (length regexp) 5000)
(regexp-quote string)
regexp))))
diff --git a/lisp/comint.el b/lisp/comint.el
index 71a2b5eca55..a9c3e47f88e 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -78,7 +78,7 @@
;;
;; Not bound by default in comint-mode (some are in shell mode)
;; comint-run Run a program under comint-mode
-;; send-invisible Read a line w/o echo, and send to proc
+;; comint-send-invisible Read a line w/o echo, and send to proc
;; comint-dynamic-complete-filename Complete filename at point.
;; comint-dynamic-list-filename-completions List completions in help buffer.
;; comint-replace-by-expanded-filename Expand and complete filename at point;
@@ -632,7 +632,7 @@ Input ring history expansion can be achieved with the commands
Input ring expansion is controlled by the variable `comint-input-autoexpand',
and addition is controlled by the variable `comint-input-ignoredups'.
-Commands with no default key bindings include `send-invisible',
+Commands with no default key bindings include `comint-send-invisible',
`completion-at-point', `comint-dynamic-list-filename-completions', and
`comint-magic-space'.
@@ -2247,7 +2247,7 @@ This function could be on `comint-output-filter-functions' or bound to a key."
(error nil))
(while (re-search-forward "\r+$" pmark t)
(replace-match "" t t)))))
-(defalias 'shell-strip-ctrl-m 'comint-strip-ctrl-m)
+(define-obsolete-function-alias 'shell-strip-ctrl-m #'comint-strip-ctrl-m "27.1")
(defun comint-show-maximum-output ()
"Put the end of the buffer at the bottom of the window."
@@ -2357,9 +2357,9 @@ a buffer local variable."
;; These three functions are for entering text you don't want echoed or
;; saved -- typically passwords to ftp, telnet, or somesuch.
-;; Just enter m-x send-invisible and type in your line.
+;; Just enter m-x comint-send-invisible and type in your line.
-(defun send-invisible (&optional prompt)
+(defun comint-send-invisible (&optional prompt)
"Read a string without echoing.
Then send it to the process running in the current buffer.
The string is sent using `comint-input-sender'.
@@ -2382,18 +2382,19 @@ Security bug: your string can still be temporarily recovered with
(message "Warning: text will be echoed")))
(error "Buffer %s has no process" (current-buffer)))))
+(define-obsolete-function-alias 'send-invisible #'comint-send-invisible "27.1")
+
(defun comint-watch-for-password-prompt (string)
"Prompt in the minibuffer for password and send without echoing.
-This function uses `send-invisible' to read and send a password to the buffer's
-process if STRING contains a password prompt defined by
-`comint-password-prompt-regexp'.
+Looks for a match to `comint-password-prompt-regexp' in order
+to detect the need to (prompt and) send a password.
This function could be in the list `comint-output-filter-functions'."
(when (let ((case-fold-search t))
(string-match comint-password-prompt-regexp string))
(when (string-match "^[ \n\r\t\v\f\b\a]+" string)
(setq string (replace-match "" t t string)))
- (send-invisible string)))
+ (comint-send-invisible string)))
;; Low-level process communication
diff --git a/lisp/cus-theme.el b/lisp/cus-theme.el
index e5e787771b9..995c55b2b20 100644
--- a/lisp/cus-theme.el
+++ b/lisp/cus-theme.el
@@ -1,4 +1,4 @@
-;;; cus-theme.el -- custom theme creation user interface
+;;; cus-theme.el -- custom theme creation user interface -*- lexical-binding: t -*-
;;
;; Copyright (C) 2001-2018 Free Software Foundation, Inc.
;;
@@ -47,7 +47,7 @@
Do not call this mode function yourself. It is meant for internal use."
(use-local-map custom-new-theme-mode-map)
(custom--initialize-widget-variables)
- (set (make-local-variable 'revert-buffer-function) 'custom-theme-revert))
+ (setq-local revert-buffer-function #'custom-theme-revert))
(put 'custom-new-theme-mode 'mode-class 'special)
(defvar custom-theme-name nil)
@@ -93,15 +93,14 @@ named *Custom Theme*."
(switch-to-buffer (get-buffer-create (or buffer "*Custom Theme*")))
(let ((inhibit-read-only t))
(erase-buffer)
- (dolist (ov (overlays-in (point-min) (point-max)))
- (delete-overlay ov)))
+ (delete-all-overlays))
(custom-new-theme-mode)
(make-local-variable 'custom-theme-name)
- (set (make-local-variable 'custom-theme--save-name) theme)
- (set (make-local-variable 'custom-theme-faces) nil)
- (set (make-local-variable 'custom-theme-variables) nil)
- (set (make-local-variable 'custom-theme-description) "")
- (set (make-local-variable 'custom-theme--migrate-settings) nil)
+ (setq-local custom-theme--save-name theme)
+ (setq-local custom-theme-faces nil)
+ (setq-local custom-theme-variables nil)
+ (setq-local custom-theme-description "")
+ (setq-local custom-theme--migrate-settings nil)
(make-local-variable 'custom-theme-insert-face-marker)
(make-local-variable 'custom-theme-insert-variable-marker)
(make-local-variable 'custom-theme--listed-faces)
@@ -118,13 +117,13 @@ remove them from your saved Custom file.\n\n"))
:tag " Visit Theme "
:help-echo "Insert the settings of a pre-defined theme."
:action (lambda (_widget &optional _event)
- (call-interactively 'custom-theme-visit-theme)))
+ (call-interactively #'custom-theme-visit-theme)))
(widget-insert " ")
(widget-create 'push-button
:tag " Merge Theme "
:help-echo "Merge in the settings of a pre-defined theme."
:action (lambda (_widget &optional _event)
- (call-interactively 'custom-theme-merge-theme)))
+ (call-interactively #'custom-theme-merge-theme)))
(widget-insert " ")
(widget-create 'push-button
:tag " Revert "
@@ -142,7 +141,7 @@ remove them from your saved Custom file.\n\n"))
(widget-create 'text
:value (format-time-string "Created %Y-%m-%d.")))
(widget-create 'push-button
- :notify (function custom-theme-write)
+ :notify #'custom-theme-write
" Save Theme ")
(when (eq theme 'user)
(setq custom-theme--migrate-settings t)
@@ -188,7 +187,7 @@ remove them from your saved Custom file.\n\n"))
:mouse-face 'highlight
:pressed-face 'highlight
:action (lambda (_widget &optional _event)
- (call-interactively 'custom-theme-add-face)))
+ (call-interactively #'custom-theme-add-face)))
;; If THEME is non-nil, insert all of that theme's variables.
(widget-insert "\n\n Theme variables:\n ")
@@ -207,7 +206,7 @@ remove them from your saved Custom file.\n\n"))
:mouse-face 'highlight
:pressed-face 'highlight
:action (lambda (_widget &optional _event)
- (call-interactively 'custom-theme-add-variable)))
+ (call-interactively #'custom-theme-add-variable)))
(widget-insert ?\n)
(widget-setup)
(goto-char (point-min))
@@ -254,7 +253,7 @@ interactively, this defaults to the current value of VAR."
:tag (custom-unlispify-tag-name symbol)
:value symbol
:shown-value (list val)
- :notify 'ignore
+ :notify #'ignore
:custom-level 0
:custom-state 'hidden
:custom-style 'simple))
@@ -313,7 +312,7 @@ SPEC, if non-nil, should be a face spec to which to set the widget."
(interactive
(list
(intern (completing-read "Find custom theme: "
- (mapcar 'symbol-name
+ (mapcar #'symbol-name
(custom-available-themes))))))
(unless (custom-theme-name-valid-p theme)
(error "No valid theme named `%s'" theme))
@@ -328,7 +327,7 @@ SPEC, if non-nil, should be a face spec to which to set the widget."
(interactive
(list
(intern (completing-read "Merge custom theme: "
- (mapcar 'symbol-name
+ (mapcar #'symbol-name
(custom-available-themes))))))
(unless (eq theme 'user)
(unless (custom-theme-name-valid-p theme)
@@ -343,8 +342,8 @@ SPEC, if non-nil, should be a face spec to which to set the widget."
(memq name '(custom-enabled-themes
custom-safe-themes)))
(funcall (if option
- 'custom-theme-add-variable
- 'custom-theme-add-face)
+ #'custom-theme-add-variable
+ #'custom-theme-add-face)
name value)))))
theme)
@@ -475,7 +474,7 @@ It includes all faces in list FACES."
(interactive
(list
(intern (completing-read "Describe custom theme: "
- (mapcar 'symbol-name
+ (mapcar #'symbol-name
(custom-available-themes))))))
(unless (custom-theme-name-valid-p theme)
(error "Invalid theme name `%s'" theme))
@@ -513,8 +512,7 @@ It includes all faces in list FACES."
(condition-case nil
(read (current-buffer))
(end-of-file nil)))))
- (and sexp (listp sexp)
- (eq (car sexp) 'deftheme)
+ (and (eq (car-safe sexp) 'deftheme)
(setq doc (nth 2 sexp)))))))
(princ "\n\nDocumentation:\n")
(princ (if (stringp doc)
@@ -552,10 +550,10 @@ It includes all faces in list FACES."
Do not call this mode function yourself. It is meant for internal use."
(use-local-map custom-theme-choose-mode-map)
(custom--initialize-widget-variables)
- (set (make-local-variable 'revert-buffer-function)
- (lambda (_ignore-auto noconfirm)
- (when (or noconfirm (y-or-n-p "Discard current choices? "))
- (customize-themes (current-buffer))))))
+ (setq-local revert-buffer-function
+ (lambda (_ignore-auto noconfirm)
+ (when (or noconfirm (y-or-n-p "Discard current choices? "))
+ (customize-themes (current-buffer))))))
(put 'custom-theme-choose-mode 'mode-class 'special)
;;;###autoload
@@ -568,7 +566,7 @@ omitted, a buffer named *Custom Themes* is used."
(let ((inhibit-read-only t))
(erase-buffer))
(custom-theme-choose-mode)
- (set (make-local-variable 'custom--listed-themes) nil)
+ (setq-local custom--listed-themes nil)
(make-local-variable 'custom-theme-allow-multiple-selections)
(and (null custom-theme-allow-multiple-selections)
(> (length custom-enabled-themes) 1)
@@ -616,11 +614,11 @@ Theme files are named *-theme.el in `"))
(widget-create 'push-button
:tag " Save Theme Settings "
:help-echo "Save the selected themes for future sessions."
- :action 'custom-theme-save)
+ :action #'custom-theme-save)
(widget-insert ?\n)
(widget-create 'checkbox
:value custom-theme-allow-multiple-selections
- :action 'custom-theme-selections-toggle)
+ :action #'custom-theme-selections-toggle)
(widget-insert (propertize " Select more than one theme at a time"
'face '(variable-pitch (:height 0.9))))
@@ -632,13 +630,13 @@ Theme files are named *-theme.el in `"))
:value (custom-theme-enabled-p theme)
:theme-name theme
:help-echo help-echo
- :action 'custom-theme-checkbox-toggle))
+ :action #'custom-theme-checkbox-toggle))
(push (cons theme widget) custom--listed-themes)
(widget-create-child-and-convert widget 'push-button
:button-face-get 'ignore
:mouse-face-get 'ignore
:value (format " %s" theme)
- :action 'widget-parent-action
+ :action #'widget-parent-action
:help-echo help-echo)
(widget-insert " -- "
(propertize (custom-theme-summary theme)
@@ -662,8 +660,7 @@ Theme files are named *-theme.el in `"))
(condition-case nil
(read (current-buffer))
(end-of-file nil)))))
- (and sexp (listp sexp)
- (eq (car sexp) 'deftheme)
+ (and (eq (car-safe sexp) 'deftheme)
(setq doc (nth 2 sexp))))))))
(cond ((null doc)
"(no documentation available)")
diff --git a/lisp/custom.el b/lisp/custom.el
index 4a778a0573e..a08f7fda705 100644
--- a/lisp/custom.el
+++ b/lisp/custom.el
@@ -1,4 +1,4 @@
-;;; custom.el --- tools for declaring and initializing options
+;;; custom.el --- tools for declaring and initializing options -*- lexical-binding: t -*-
;;
;; Copyright (C) 1996-1997, 1999, 2001-2018 Free Software Foundation,
;; Inc.
@@ -150,7 +150,7 @@ set to nil, as the value is no longer rogue."
(put symbol 'force-value nil))
(if (keywordp doc)
(error "Doc string is missing"))
- (let ((initialize 'custom-initialize-reset)
+ (let ((initialize #'custom-initialize-reset)
(requests nil))
(unless (memq :group args)
(custom-add-to-group (custom-current-group) symbol 'custom-variable))
@@ -426,7 +426,7 @@ information."
(defun custom-declare-group (symbol members doc &rest args)
"Like `defgroup', but SYMBOL is evaluated as a normal argument."
(while members
- (apply 'custom-add-to-group symbol (car members))
+ (apply #'custom-add-to-group symbol (car members))
(setq members (cdr members)))
(when doc
;; This text doesn't get into DOC.
@@ -618,11 +618,8 @@ VARIABLE is a symbol that names a user option.
The result is that the change is treated as having been made through Custom."
(put variable 'customized-value (list (custom-quote (eval variable)))))
-
-;;; Custom Themes
-
-;;; Loading files needed to customize a symbol.
-;;; This is in custom.el because menu-bar.el needs it for toggle cmds.
+;; Loading files needed to customize a symbol.
+;; This is in custom.el because menu-bar.el needs it for toggle cmds.
(defvar custom-load-recursion nil
"Hack to avoid recursive dependencies.")
@@ -633,14 +630,12 @@ The result is that the change is treated as having been made through Custom."
(let ((custom-load-recursion t))
;; Load these files if not already done,
;; to make sure we know all the dependencies of SYMBOL.
- (condition-case nil
- (require 'cus-load)
- (error nil))
- (condition-case nil
- (require 'cus-start)
- (error nil))
+ (ignore-errors
+ (require 'cus-load))
+ (ignore-errors
+ (require 'cus-start))
(dolist (load (get symbol 'custom-loads))
- (cond ((symbolp load) (condition-case nil (require load) (error nil)))
+ (cond ((symbolp load) (ignore-errors (require load)))
;; This is subsumed by the test below, but it's much faster.
((assoc load load-history))
;; This was just (assoc (locate-library load) load-history)
@@ -658,7 +653,7 @@ The result is that the change is treated as having been made through Custom."
;; We are still loading it when we call this,
;; and it is not in load-history yet.
((equal load "cus-edit"))
- (t (condition-case nil (load load) (error nil))))))))
+ (t (ignore-errors (load load))))))))
(defvar custom-local-buffer nil
"Non-nil, in a Customization buffer, means customize a specific buffer.
@@ -691,16 +686,12 @@ this sets the local binding in that buffer instead."
(defun custom-quote (sexp)
"Quote SEXP if it is not self quoting."
- (if (or (memq sexp '(t nil))
- (keywordp sexp)
- (and (listp sexp)
- (memq (car sexp) '(lambda)))
- (stringp sexp)
- (numberp sexp)
- (vectorp sexp)
-;;; (and (fboundp 'characterp)
-;;; (characterp sexp))
- )
+ ;; Can't use `macroexp-quote' because it is loaded after `custom.el'
+ ;; during bootstrap. See `loadup.el'.
+ (if (and (not (consp sexp))
+ (or (keywordp sexp)
+ (not (symbolp sexp))
+ (booleanp sexp)))
sexp
(list 'quote sexp)))
@@ -715,18 +706,16 @@ To actually save the value, call `custom-save-all'.
Return non-nil if the `saved-value' property actually changed."
(custom-load-symbol symbol)
- (let* ((get (or (get symbol 'custom-get) 'default-value))
+ (let* ((get (or (get symbol 'custom-get) #'default-value))
(value (funcall get symbol))
(saved (get symbol 'saved-value))
(standard (get symbol 'standard-value))
(comment (get symbol 'customized-variable-comment)))
;; Save default value if different from standard value.
- (if (or (null standard)
- (not (equal value (condition-case nil
- (eval (car standard))
- (error nil)))))
- (put symbol 'saved-value (list (custom-quote value)))
- (put symbol 'saved-value nil))
+ (put symbol 'saved-value
+ (unless (and standard
+ (equal value (ignore-errors (eval (car standard)))))
+ (list (custom-quote value))))
;; Clear customized information (set, but not saved).
(put symbol 'customized-value nil)
;; Save any comment that might have been set.
@@ -744,15 +733,14 @@ default value. Otherwise, set it to nil.
Return non-nil if the `customized-value' property actually changed."
(custom-load-symbol symbol)
- (let* ((get (or (get symbol 'custom-get) 'default-value))
+ (let* ((get (or (get symbol 'custom-get) #'default-value))
(value (funcall get symbol))
(customized (get symbol 'customized-value))
(old (or (get symbol 'saved-value) (get symbol 'standard-value))))
;; Mark default value as set if different from old value.
(if (not (and old
- (equal value (condition-case nil
- (eval (car old))
- (error nil)))))
+ (equal value (ignore-errors
+ (eval (car old))))))
(progn (put symbol 'customized-value (list (custom-quote value)))
(custom-push-theme 'theme-value symbol 'user 'set
(custom-quote value)))
@@ -776,7 +764,7 @@ E.g. dumped variables whose default depends on run-time information."
;; always do the funcall step, even if symbol was not bound before.
(or (default-boundp symbol)
(eval `(defvar ,symbol nil))) ; reset below, so any value is fine
- (funcall (or (get symbol 'custom-set) 'set-default)
+ (funcall (or (get symbol 'custom-set) #'set-default)
symbol
(eval (car (or (get symbol 'saved-value) (get symbol 'standard-value))))))
@@ -946,7 +934,7 @@ the default value for the SYMBOL to the value of EXP.
REQUEST is a list of features we must require in order to
handle SYMBOL properly.
COMMENT is a comment string about SYMBOL."
- (apply 'custom-theme-set-variables 'user args))
+ (apply #'custom-theme-set-variables 'user args))
(defun custom-theme-set-variables (theme &rest args)
"Initialize variables for theme THEME according to settings in ARGS.
@@ -994,8 +982,8 @@ COMMENT is a comment string about SYMBOL."
set)
(when requests
(put symbol 'custom-requests requests)
- (mapc 'require requests))
- (setq set (or (get symbol 'custom-set) 'custom-set-default))
+ (mapc #'require requests))
+ (setq set (or (get symbol 'custom-set) #'custom-set-default))
(put symbol 'saved-value (list value))
(put symbol 'saved-variable-comment comment)
;; Allow for errors in the case where the setter has
@@ -1091,26 +1079,29 @@ list, in which A occurs before B if B was defined with a
;; they were used to supply keyword-value pairs like `:immediate',
;; `:variable-reset-string', etc. We don't use any of these, so ignore them.
-(defmacro deftheme (theme &optional doc &rest ignored)
+(defmacro deftheme (theme &optional doc &rest _ignored)
"Declare THEME to be a Custom theme.
The optional argument DOC is a doc string describing the theme.
Any theme `foo' should be defined in a file called `foo-theme.el';
see `custom-make-theme-feature' for more information."
- (declare (doc-string 2))
+ (declare (doc-string 2)
+ (advertised-calling-convention (theme &optional doc) "22.1"))
(let ((feature (custom-make-theme-feature theme)))
;; It is better not to use backquote in this file,
;; because that makes a bootstrapping problem
;; if you need to recompile all the Lisp files using interpreted code.
(list 'custom-declare-theme (list 'quote theme) (list 'quote feature) doc)))
-(defun custom-declare-theme (theme feature &optional doc &rest ignored)
+(defun custom-declare-theme (theme feature &optional doc &rest _ignored)
"Like `deftheme', but THEME is evaluated as a normal argument.
FEATURE is the feature this theme provides. Normally, this is a symbol
created from THEME by `custom-make-theme-feature'."
+ (declare (advertised-calling-convention (theme feature &optional doc) "22.1"))
(unless (custom-theme-name-valid-p theme)
(error "Custom theme cannot be named %S" theme))
- (add-to-list 'custom-known-themes theme)
+ (unless (memq theme custom-known-themes)
+ (push theme custom-known-themes))
(put theme 'theme-feature feature)
(when doc (put theme 'theme-documentation doc)))
@@ -1218,7 +1209,7 @@ Return t if THEME was successfully loaded, nil otherwise."
(interactive
(list
(intern (completing-read "Load custom theme: "
- (mapcar 'symbol-name
+ (mapcar #'symbol-name
(custom-available-themes))))
nil nil))
(unless (custom-theme-name-valid-p theme)
@@ -1233,43 +1224,47 @@ Return t if THEME was successfully loaded, nil otherwise."
(put theme 'theme-settings nil)
(put theme 'theme-feature nil)
(put theme 'theme-documentation nil))
- (let ((fn (locate-file (concat (symbol-name theme) "-theme.el")
- (custom-theme--load-path)
- '("" "c"))))
- (unless fn
- (error "Unable to find theme file for `%s'" theme))
- (with-temp-buffer
- (insert-file-contents fn)
- ;; Check file safety with `custom-safe-themes', prompting the
- ;; user if necessary.
- (when (or no-confirm
- (eq custom-safe-themes t)
- (and (memq 'default custom-safe-themes)
- (equal (file-name-directory fn)
- (expand-file-name "themes/" data-directory)))
- (let ((hash (secure-hash 'sha256 (current-buffer))))
- (or (member hash custom-safe-themes)
- (custom-theme-load-confirm hash))))
- (let ((custom--inhibit-theme-enable t)
- (buffer-file-name fn)) ;For load-history.
- (eval-buffer))
- ;; Optimization: if the theme changes the `default' face, put that
- ;; entry first. This avoids some `frame-set-background-mode' rigmarole
- ;; by assigning the new background immediately.
- (let* ((settings (get theme 'theme-settings))
- (tail settings)
- found)
- (while (and tail (not found))
- (and (eq (nth 0 (car tail)) 'theme-face)
- (eq (nth 1 (car tail)) 'default)
- (setq found (car tail)))
- (setq tail (cdr tail)))
- (if found
- (put theme 'theme-settings (cons found (delq found settings)))))
- ;; Finally, enable the theme.
- (unless no-enable
- (enable-theme theme))
- t))))
+ (let ((file (locate-file (concat (symbol-name theme) "-theme.el")
+ (custom-theme--load-path)
+ '("" "c")))
+ (custom--inhibit-theme-enable t))
+ ;; Check file safety with `custom-safe-themes', prompting the
+ ;; user if necessary.
+ (cond ((not file)
+ (error "Unable to find theme file for `%s'" theme))
+ ((or no-confirm
+ (eq custom-safe-themes t)
+ (and (memq 'default custom-safe-themes)
+ (equal (file-name-directory file)
+ (expand-file-name "themes/" data-directory))))
+ ;; Theme is safe; load byte-compiled version if available.
+ (load (file-name-sans-extension file) nil t nil t))
+ ((with-temp-buffer
+ (insert-file-contents file)
+ (let ((hash (secure-hash 'sha256 (current-buffer))))
+ (when (or (member hash custom-safe-themes)
+ (custom-theme-load-confirm hash))
+ (eval-buffer nil nil file)
+ t))))
+ (t
+ (error "Unable to load theme `%s'" theme))))
+ ;; Optimization: if the theme changes the `default' face, put that
+ ;; entry first. This avoids some `frame-set-background-mode' rigmarole
+ ;; by assigning the new background immediately.
+ (let* ((settings (get theme 'theme-settings))
+ (tail settings)
+ found)
+ (while (and tail (not found))
+ (and (eq (nth 0 (car tail)) 'theme-face)
+ (eq (nth 1 (car tail)) 'default)
+ (setq found (car tail)))
+ (setq tail (cdr tail)))
+ (when found
+ (put theme 'theme-settings (cons found (delq found settings)))))
+ ;; Finally, enable the theme.
+ (unless no-enable
+ (enable-theme theme))
+ t)
(defun custom-theme-load-confirm (hash)
"Query the user about loading a Custom theme that may not be safe.
@@ -1292,11 +1287,9 @@ query also about adding HASH to `custom-safe-themes'."
(defun custom-theme-name-valid-p (name)
"Return t if NAME is a valid name for a Custom theme, nil otherwise.
NAME should be a symbol."
- (and (symbolp name)
- name
- (not (or (zerop (length (symbol-name name)))
- (eq name 'user)
- (eq name 'changed)))))
+ (and (not (memq name '(nil user changed)))
+ (symbolp name)
+ (not (string= "" (symbol-name name)))))
(defun custom-available-themes ()
"Return a list of Custom themes available for loading.
@@ -1307,19 +1300,25 @@ The returned symbols may not correspond to themes that have been
loaded, and no effort is made to check that the files contain
valid Custom themes. For a list of loaded themes, check the
variable `custom-known-themes'."
- (let (sym themes)
+ (let ((suffix "-theme\\.el\\'")
+ themes)
(dolist (dir (custom-theme--load-path))
- (when (file-directory-p dir)
- (dolist (file (file-expand-wildcards
- (expand-file-name "*-theme.el" dir) t))
- (setq file (file-name-nondirectory file))
- (and (string-match "\\`\\(.+\\)-theme.el\\'" file)
- (setq sym (intern (match-string 1 file)))
- (custom-theme-name-valid-p sym)
- (push sym themes)))))
- (nreverse (delete-dups themes))))
+ ;; `custom-theme--load-path' promises DIR exists and is a
+ ;; directory, but `custom.el' is loaded too early during
+ ;; bootstrap to use `cl-lib' macros, so guard with
+ ;; `file-directory-p' instead of calling `cl-assert'.
+ (dolist (file (and (file-directory-p dir)
+ (directory-files dir nil suffix)))
+ (let ((theme (intern (substring file 0 (string-match-p suffix file)))))
+ (and (custom-theme-name-valid-p theme)
+ (not (memq theme themes))
+ (push theme themes)))))
+ (nreverse themes)))
(defun custom-theme--load-path ()
+ "Expand `custom-theme-load-path' into a list of directories.
+Members of `custom-theme-load-path' that either don't exist or
+are not directories are omitted from the expansion."
(let (lpath)
(dolist (f custom-theme-load-path)
(cond ((eq f 'custom-theme-directory)
@@ -1346,8 +1345,8 @@ function runs. To disable other themes, use `disable-theme'."
(completing-read
"Enable custom theme: "
obarray (lambda (sym) (get sym 'theme-settings)) t))))
- (if (not (custom-theme-p theme))
- (error "Undefined Custom theme %s" theme))
+ (unless (custom-theme-p theme)
+ (error "Undefined Custom theme %s" theme))
(let ((settings (get theme 'theme-settings)))
;; Loop through theme settings, recalculating vars/faces.
(dolist (s settings)
@@ -1387,23 +1386,23 @@ Setting this variable through Customize calls `enable-theme' or
(let (failures)
(setq themes (delq 'user (delete-dups themes)))
;; Disable all themes not in THEMES.
- (if (boundp symbol)
- (dolist (theme (symbol-value symbol))
- (if (not (memq theme themes))
- (disable-theme theme))))
+ (dolist (theme (and (boundp symbol)
+ (symbol-value symbol)))
+ (unless (memq theme themes)
+ (disable-theme theme)))
;; Call `enable-theme' or `load-theme' on each of THEMES.
(dolist (theme (reverse themes))
(condition-case nil
(if (custom-theme-p theme)
(enable-theme theme)
(load-theme theme))
- (error (setq failures (cons theme failures)
- themes (delq theme themes)))))
+ (error (push theme failures)
+ (setq themes (delq theme themes)))))
(enable-theme 'user)
(custom-set-default symbol themes)
- (if failures
- (message "Failed to enable theme: %s"
- (mapconcat 'symbol-name failures ", "))))))
+ (when failures
+ (message "Failed to enable theme(s): %s"
+ (mapconcat #'symbol-name failures ", "))))))
(defsubst custom-theme-enabled-p (theme)
"Return non-nil if THEME is enabled."
@@ -1415,7 +1414,7 @@ See `custom-enabled-themes' for a list of enabled themes."
(interactive (list (intern
(completing-read
"Disable custom theme: "
- (mapcar 'symbol-name custom-enabled-themes)
+ (mapcar #'symbol-name custom-enabled-themes)
nil t))))
(when (custom-theme-enabled-p theme)
(let ((settings (get theme 'theme-settings)))
@@ -1431,23 +1430,23 @@ See `custom-enabled-themes' for a list of enabled themes."
;; If the face spec specified by this theme is in the
;; saved-face property, reset that property.
(when (equal (nth 3 s) (get symbol 'saved-face))
- (put symbol 'saved-face (and val (cadr (car val)))))))))
- ;; Recompute faces on all frames.
- (dolist (frame (frame-list))
- ;; We must reset the fg and bg color frame parameters, or
- ;; `face-set-after-frame-default' will use the existing
- ;; parameters, which could be from the disabled theme.
- (set-frame-parameter frame 'background-color
- (custom--frame-color-default
- frame :background "background" "Background"
- "unspecified-bg" "white"))
- (set-frame-parameter frame 'foreground-color
- (custom--frame-color-default
- frame :foreground "foreground" "Foreground"
- "unspecified-fg" "black"))
- (face-set-after-frame-default frame))
- (setq custom-enabled-themes
- (delq theme custom-enabled-themes)))))
+ (put symbol 'saved-face (cadar val))))))))
+ ;; Recompute faces on all frames.
+ (dolist (frame (frame-list))
+ ;; We must reset the fg and bg color frame parameters, or
+ ;; `face-set-after-frame-default' will use the existing
+ ;; parameters, which could be from the disabled theme.
+ (set-frame-parameter frame 'background-color
+ (custom--frame-color-default
+ frame :background "background" "Background"
+ "unspecified-bg" "white"))
+ (set-frame-parameter frame 'foreground-color
+ (custom--frame-color-default
+ frame :foreground "foreground" "Foreground"
+ "unspecified-fg" "black"))
+ (face-set-after-frame-default frame))
+ (setq custom-enabled-themes
+ (delq theme custom-enabled-themes))))
;; Only used if window-system not null.
(declare-function x-get-resource "frame.c"
@@ -1481,7 +1480,7 @@ This function returns nil if no custom theme specifies a value for VARIABLE."
(if (and valspec
(or (get variable 'force-value)
(default-boundp variable)))
- (funcall (or (get variable 'custom-set) 'set-default) variable
+ (funcall (or (get variable 'custom-set) #'set-default) variable
(eval (car valspec))))))
(defun custom-theme-recalc-face (face)
@@ -1522,7 +1521,7 @@ Each of the arguments ARGS has this form:
(VARIABLE IGNORED)
This means reset VARIABLE. (The argument IGNORED is ignored)."
- (apply 'custom-theme-reset-variables 'user args))
+ (apply #'custom-theme-reset-variables 'user args))
;;; The End.
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 925a7d50d6f..21ee50ce5cd 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -1989,6 +1989,19 @@ Optional arg HOW-TO determines how to treat the target.
dired-dirs)))
+
+;; We use this function in `dired-create-directory' and
+;; `dired-create-empty-file'; the return value is the new entry
+;; in the updated Dired buffer.
+(defun dired--find-topmost-parent-dir (filename)
+ "Return the topmost nonexistent parent dir of FILENAME.
+FILENAME is a full file name."
+ (let ((try filename) new)
+ (while (and try (not (file-exists-p try)) (not (equal new try)))
+ (setq new try
+ try (directory-file-name (file-name-directory try))))
+ new))
+
;;;###autoload
(defun dired-create-directory (directory)
"Create a directory called DIRECTORY.
@@ -1997,18 +2010,32 @@ If DIRECTORY already exists, signal an error."
(interactive
(list (read-file-name "Create directory: " (dired-current-directory))))
(let* ((expanded (directory-file-name (expand-file-name directory)))
- (try expanded) new)
+ new)
(if (file-exists-p expanded)
(error "Cannot create directory %s: file exists" expanded))
- ;; Find the topmost nonexistent parent dir (variable `new')
- (while (and try (not (file-exists-p try)) (not (equal new try)))
- (setq new try
- try (directory-file-name (file-name-directory try))))
+ (setq new (dired--find-topmost-parent-dir expanded))
(make-directory expanded t)
(when new
(dired-add-file new)
(dired-move-to-filename))))
+;;;###autoload
+(defun dired-create-empty-file (file)
+ "Create an empty file called FILE.
+ Add a new entry for the new file in the Dired buffer.
+ Parent directories of FILE are created as needed.
+ If FILE already exists, signal an error."
+ (interactive (list (read-file-name "Create empty file: ")))
+ (let* ((expanded (expand-file-name file))
+ new)
+ (if (file-exists-p expanded)
+ (error "Cannot create file %s: file exists" expanded))
+ (setq new (dired--find-topmost-parent-dir expanded))
+ (make-empty-file file 'parents)
+ (when new
+ (dired-add-file new)
+ (dired-move-to-filename))))
+
(defun dired-into-dir-with-symlinks (target)
(and (file-directory-p target)
(not (file-symlink-p target))))
diff --git a/lisp/dired.el b/lisp/dired.el
index 1348df6934b..26a7449e039 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1802,6 +1802,9 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
(define-key map [menu-bar immediate create-directory]
'(menu-item "Create Directory..." dired-create-directory
:help "Create a directory"))
+ (define-key map [menu-bar immediate create-empty-file]
+ '(menu-item "Create Empty file..." dired-create-empty-file
+ :help "Create an empty file"))
(define-key map [menu-bar immediate wdired-mode]
'(menu-item "Edit File Names" wdired-change-to-wdired-mode
:help "Put a Dired buffer in a mode in which filenames are editable"
diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el
new file mode 100644
index 00000000000..f13b43b465c
--- /dev/null
+++ b/lisp/emacs-lisp/backtrace.el
@@ -0,0 +1,916 @@
+;;; backtrace.el --- generic major mode for Elisp backtraces -*- lexical-binding: t -*-
+
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+
+;; Author: Gemini Lasswell
+;; Keywords: lisp, tools, maint
+;; Version: 1.0
+
+;; 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:
+
+;; This file defines Backtrace mode, a generic major mode for displaying
+;; Elisp stack backtraces, which can be used as is or inherited from
+;; by another mode.
+
+;; For usage information, see the documentation of `backtrace-mode'.
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'pcase))
+(eval-when-compile (require 'subr-x)) ; if-let
+(require 'help-mode) ; Define `help-function-def' button type.
+(require 'lisp-mode)
+
+;;; Options
+
+(defgroup backtrace nil
+ "Viewing of Elisp backtraces."
+ :group 'lisp)
+
+(defcustom backtrace-fontify t
+ "If non-nil, fontify Backtrace buffers.
+Set to nil to disable fontification, which may be necessary in
+order to debug the code that does fontification."
+ :type 'boolean
+ :group 'backtrace
+ :version "27.1")
+
+(defcustom backtrace-line-length 5000
+ "Target length for lines in Backtrace buffers.
+Backtrace mode will attempt to abbreviate printing of backtrace
+frames to make them shorter than this, but success is not
+guaranteed. If set to nil or zero, Backtrace mode will not
+abbreviate the forms it prints."
+ :type 'integer
+ :group 'backtrace
+ :version "27.1")
+
+;;; Backtrace frame data structure
+
+(cl-defstruct
+ (backtrace-frame
+ (:constructor backtrace-make-frame))
+ evald ; Non-nil if argument evaluation is complete.
+ fun ; The function called/to call in this frame.
+ args ; Either evaluated or unevaluated arguments to the function.
+ flags ; A plist, possible properties are :debug-on-exit and :source-available.
+ locals ; An alist containing variable names and values.
+ buffer ; If non-nil, the buffer in use by eval-buffer or eval-region.
+ pos ; The position in the buffer.
+ )
+
+(cl-defun backtrace-get-frames
+ (&optional base &key (constructor #'backtrace-make-frame))
+ "Collect all frames of current backtrace into a list.
+The list will contain objects made by CONSTRUCTOR, which
+defaults to `backtrace-make-frame' and which, if provided, should
+be the constructor of a structure which includes
+`backtrace-frame'. If non-nil, BASE should be a function, and
+frames before its nearest activation frame are discarded."
+ (let ((frames nil)
+ (eval-buffers eval-buffer-list))
+ (mapbacktrace (lambda (evald fun args flags)
+ (push (funcall constructor
+ :evald evald :fun fun
+ :args args :flags flags)
+ frames))
+ (or base 'backtrace-get-frames))
+ (setq frames (nreverse frames))
+ ;; Add local variables to each frame, and the buffer position
+ ;; to frames containing eval-buffer or eval-region.
+ (dotimes (idx (length frames))
+ (let ((frame (nth idx frames)))
+ ;; `backtrace--locals' gives an error when idx is 0. But the
+ ;; locals for frame 0 are not needed, because when we get here
+ ;; from debug-on-entry, the locals aren't bound yet, and when
+ ;; coming from Edebug or ERT there is an Edebug or ERT
+ ;; function at frame 0.
+ (when (> idx 0)
+ (setf (backtrace-frame-locals frame)
+ (backtrace--locals idx (or base 'backtrace-get-frames))))
+ (when (and eval-buffers (memq (backtrace-frame-fun frame)
+ '(eval-buffer eval-region)))
+ ;; This will get the wrong result if there are two nested
+ ;; eval-region calls for the same buffer. That's not a very
+ ;; useful case.
+ (with-current-buffer (pop eval-buffers)
+ (setf (backtrace-frame-buffer frame) (current-buffer))
+ (setf (backtrace-frame-pos frame) (point))))))
+ frames))
+
+;; Button definition for jumping to a buffer position.
+
+(define-button-type 'backtrace-buffer-pos
+ 'action #'backtrace--pop-to-buffer-pos
+ 'help-echo "mouse-2, RET: Show reading position")
+
+(defun backtrace--pop-to-buffer-pos (button)
+ "Pop to the buffer and position for the BUTTON at point."
+ (let* ((buffer (button-get button 'backtrace-buffer))
+ (pos (button-get button 'backtrace-pos)))
+ (if (buffer-live-p buffer)
+ (progn
+ (pop-to-buffer buffer)
+ (goto-char (max (point-min) (min (point-max) pos))))
+ (message "Buffer has been killed"))))
+
+;; Font Locking support
+
+(defconst backtrace--font-lock-keywords
+ '((backtrace--match-ellipsis-in-string
+ (1 'button prepend)))
+ "Expressions to fontify in Backtrace mode.
+Fontify these in addition to the expressions Emacs Lisp mode
+fontifies.")
+
+(defconst backtrace-font-lock-keywords
+ (append lisp-el-font-lock-keywords-for-backtraces
+ backtrace--font-lock-keywords)
+ "Default expressions to highlight in Backtrace mode.")
+(defconst backtrace-font-lock-keywords-1
+ (append lisp-el-font-lock-keywords-for-backtraces-1
+ backtrace--font-lock-keywords)
+ "Subdued level highlighting for Backtrace mode.")
+(defconst backtrace-font-lock-keywords-2
+ (append lisp-el-font-lock-keywords-for-backtraces-2
+ backtrace--font-lock-keywords)
+ "Gaudy level highlighting for Backtrace mode.")
+
+(defun backtrace--match-ellipsis-in-string (bound)
+ ;; Fontify ellipses within strings as buttons.
+ ;; This is necessary because ellipses are text property buttons
+ ;; instead of overlay buttons, which is done because there could
+ ;; be a large number of them.
+ (when (re-search-forward "\\(\\.\\.\\.\\)\"" bound t)
+ (and (get-text-property (- (point) 2) 'cl-print-ellipsis)
+ (get-text-property (- (point) 3) 'cl-print-ellipsis)
+ (get-text-property (- (point) 4) 'cl-print-ellipsis))))
+
+;;; Xref support
+
+(defun backtrace--xref-backend () 'elisp)
+
+;;; Backtrace mode variables
+
+(defvar-local backtrace-frames nil
+ "Stack frames displayed in the current Backtrace buffer.
+This should be a list of `backtrace-frame' objects.")
+
+(defvar-local backtrace-view nil
+ "A plist describing how to render backtrace frames.
+Possible entries are :show-flags, :show-locals and :print-circle.")
+
+(defvar-local backtrace-insert-header-function nil
+ "Function for inserting a header for the current Backtrace buffer.
+If nil, no header will be created. Note that Backtrace buffers
+are fontified as in Emacs Lisp Mode, the header text included.")
+
+(defvar backtrace-revert-hook nil
+ "Hook run before reverting a Backtrace buffer.
+This is commonly used to recompute `backtrace-frames'.")
+
+(defvar-local backtrace-print-function #'cl-prin1
+ "Function used to print values in the current Backtrace buffer.")
+
+(defvar-local backtrace-goto-source-functions nil
+ "Abnormal hook used to jump to the source code for the current frame.
+Each hook function is called with no argument, and should return
+non-nil if it is able to switch to the buffer containing the
+source code. Execution of the hook will stop if one of the
+functions returns non-nil. When adding a function to this hook,
+you should also set the :source-available flag for the backtrace
+frames where the source code location is known.")
+
+(defvar backtrace-mode-map
+ (let ((map (copy-keymap special-mode-map)))
+ (set-keymap-parent map button-buffer-map)
+ (define-key map "n" 'backtrace-forward-frame)
+ (define-key map "p" 'backtrace-backward-frame)
+ (define-key map "v" 'backtrace-toggle-locals)
+ (define-key map "#" 'backtrace-toggle-print-circle)
+ (define-key map "s" 'backtrace-goto-source)
+ (define-key map "\C-m" 'backtrace-help-follow-symbol)
+ (define-key map "+" 'backtrace-multi-line)
+ (define-key map "-" 'backtrace-single-line)
+ (define-key map "." 'backtrace-expand-ellipses)
+ (define-key map [follow-link] 'mouse-face)
+ (define-key map [mouse-2] 'mouse-select-window)
+ (easy-menu-define nil map ""
+ '("Backtrace"
+ ["Next Frame" backtrace-forward-frame
+ :help "Move cursor forwards to the start of a backtrace frame"]
+ ["Previous Frame" backtrace-backward-frame
+ :help "Move cursor backwards to the start of a backtrace frame"]
+ "--"
+ ["Show Variables" backtrace-toggle-locals
+ :style toggle
+ :active (backtrace-get-index)
+ :selected (plist-get (backtrace-get-view) :show-locals)
+ :help "Show or hide the local variables for the frame at point"]
+ ["Expand \"...\"s" backtrace-expand-ellipses
+ :help "Expand all the abbreviated forms in the current frame"]
+ ["Show on Multiple Lines" backtrace-multi-line
+ :help "Use line breaks and indentation to make a form more readable"]
+ ["Show on Single Line" backtrace-single-line]
+ "--"
+ ["Go to Source" backtrace-goto-source
+ :active (and (backtrace-get-index)
+ (plist-get (backtrace-frame-flags
+ (nth (backtrace-get-index) backtrace-frames))
+ :source-available))
+ :help "Show the source code for the current frame"]
+ ["Help for Symbol" backtrace-help-follow-symbol
+ :help "Show help for symbol at point"]
+ ["Describe Backtrace Mode" describe-mode
+ :help "Display documentation for backtrace-mode"]))
+ map)
+ "Local keymap for `backtrace-mode' buffers.")
+
+(defconst backtrace--flags-width 2
+ "Width in characters of the flags for a backtrace frame.")
+
+;;; Navigation and Text Properties
+
+;; This mode uses the following text properties:
+;; backtrace-index: The index into the buffer-local variable
+;; `backtrace-frames' for the frame at point, or nil if outside of a
+;; frame (in the buffer header).
+;; backtrace-view: A plist describing how the frame is printed. See
+;; the docstring for the buffer-local variable `backtrace-view.
+;; backtrace-section: The part of a frame which point is in. Either
+;; `func' or `locals'. At the moment just used to show and hide the
+;; local variables. Derived modes which do additional printing
+;; could define their own frame sections.
+;; backtrace-form: A value applied to each printed representation of a
+;; top-level s-expression, which needs to be different for sexps
+;; printed adjacent to each other, so the limits can be quickly
+;; found for pretty-printing.
+
+(defsubst backtrace-get-index (&optional pos)
+ "Return the index of the backtrace frame at POS.
+The value is an index into `backtrace-frames', or nil.
+POS, if omitted or nil, defaults to point."
+ (get-text-property (or pos (point)) 'backtrace-index))
+
+(defsubst backtrace-get-section (&optional pos)
+ "Return the section of a backtrace frame at POS.
+POS, if omitted or nil, defaults to point."
+ (get-text-property (or pos (point)) 'backtrace-section))
+
+(defsubst backtrace-get-view (&optional pos)
+ "Return the view plist of the backtrace frame at POS.
+POS, if omitted or nil, defaults to point."
+ (get-text-property (or pos (point)) 'backtrace-view))
+
+(defsubst backtrace-get-form (&optional pos)
+ "Return the backtrace form data for the form printed at POS.
+POS, if omitted or nil, defaults to point."
+ (get-text-property (or pos (point)) 'backtrace-form))
+
+(defun backtrace-get-frame-start (&optional pos)
+ "Return the beginning position of the frame at POS in the buffer.
+POS, if omitted or nil, defaults to point."
+ (let ((posn (or pos (point))))
+ (if (or (= (point-min) posn)
+ (not (eq (backtrace-get-index posn)
+ (backtrace-get-index (1- posn)))))
+ posn
+ (previous-single-property-change posn 'backtrace-index nil (point-min)))))
+
+(defun backtrace-get-frame-end (&optional pos)
+ "Return the position of the end of the frame at POS in the buffer.
+POS, if omitted or nil, defaults to point."
+ (next-single-property-change (or pos (point))
+ 'backtrace-index nil (point-max)))
+
+(defun backtrace-forward-frame ()
+ "Move forward to the beginning of the next frame."
+ (interactive)
+ (let ((max (backtrace-get-frame-end)))
+ (when (= max (point-max))
+ (user-error "No next stack frame"))
+ (goto-char max)))
+
+(defun backtrace-backward-frame ()
+ "Move backward to the start of a stack frame."
+ (interactive)
+ (let ((current-index (backtrace-get-index))
+ (min (backtrace-get-frame-start)))
+ (if (or (and (/= (point) (point-max)) (null current-index))
+ (= min (point-min))
+ (and (= min (point))
+ (null (backtrace-get-index (1- min)))))
+ (user-error "No previous stack frame"))
+ (if (= min (point))
+ (goto-char (backtrace-get-frame-start (1- min)))
+ (goto-char min))))
+
+;; Other Backtrace mode commands
+
+(defun backtrace-revert (&rest _ignored)
+ "The `revert-buffer-function' for `backtrace-mode'.
+It runs `backtrace-revert-hook', then calls `backtrace-print'."
+ (interactive)
+ (unless (derived-mode-p 'backtrace-mode)
+ (error "The current buffer is not in Backtrace mode"))
+ (run-hooks 'backtrace-revert-hook)
+ (backtrace-print t))
+
+(defmacro backtrace--with-output-variables (view &rest body)
+ "Bind output variables according to VIEW and execute BODY."
+ (declare (indent 1))
+ `(let ((print-escape-control-characters t)
+ (print-escape-newlines t)
+ (print-circle (plist-get ,view :print-circle))
+ (standard-output (current-buffer)))
+ ,@body))
+
+(defun backtrace-toggle-locals (&optional all)
+ "Toggle the display of local variables for the backtrace frame at point.
+With prefix argument ALL, toggle the value of :show-locals in
+`backtrace-view', which affects all of the backtrace frames in
+the buffer."
+ (interactive "P")
+ (if all
+ (let ((pos (make-marker))
+ (visible (not (plist-get backtrace-view :show-locals))))
+ (setq backtrace-view (plist-put backtrace-view :show-locals visible))
+ (set-marker-insertion-type pos t)
+ (set-marker pos (point))
+ (goto-char (point-min))
+ ;; Skip the header.
+ (unless (backtrace-get-index)
+ (goto-char (backtrace-get-frame-end)))
+ (while (< (point) (point-max))
+ (backtrace--set-frame-locals-visible visible)
+ (goto-char (backtrace-get-frame-end)))
+ (goto-char pos)
+ (when (invisible-p pos)
+ (goto-char (backtrace-get-frame-start))))
+ (let ((index (backtrace-get-index)))
+ (unless index
+ (user-error "Not in a stack frame"))
+ (backtrace--set-frame-locals-visible
+ (not (plist-get (backtrace-get-view) :show-locals))))))
+
+(defun backtrace--set-frame-locals-visible (visible)
+ "Set the visibility of the local vars for the frame at point to VISIBLE."
+ (let ((pos (point))
+ (index (backtrace-get-index))
+ (start (backtrace-get-frame-start))
+ (end (backtrace-get-frame-end))
+ (view (copy-sequence (backtrace-get-view)))
+ (inhibit-read-only t))
+ (setq view (plist-put view :show-locals visible))
+ (goto-char (backtrace-get-frame-start))
+ (while (not (or (= (point) end)
+ (eq (backtrace-get-section) 'locals)))
+ (goto-char (next-single-property-change (point)
+ 'backtrace-section nil end)))
+ (cond
+ ((and (= (point) end) visible)
+ ;; The locals section doesn't exist so create it.
+ (let ((standard-output (current-buffer)))
+ (backtrace--with-output-variables view
+ (backtrace--print-locals
+ (nth index backtrace-frames) view))
+ (add-text-properties end (point) `(backtrace-index ,index))
+ (goto-char pos)))
+ ((/= (point) end)
+ ;; The locals section does exist, so add or remove the overlay.
+ (backtrace--set-locals-visible-overlay (point) end visible)
+ (goto-char (if (invisible-p pos) start pos))))
+ (add-text-properties start (backtrace-get-frame-end)
+ `(backtrace-view ,view))))
+
+(defun backtrace--set-locals-visible-overlay (beg end visible)
+ (backtrace--change-button-skip beg end (not visible))
+ (if visible
+ (remove-overlays beg end 'invisible t)
+ (let ((o (make-overlay beg end)))
+ (overlay-put o 'invisible t)
+ (overlay-put o 'evaporate t))))
+
+(defun backtrace--change-button-skip (beg end value)
+ "Change the skip property on all buttons between BEG and END.
+Set it to VALUE unless the button is a `backtrace-ellipsis' button."
+ (let ((inhibit-read-only t))
+ (setq beg (next-button beg))
+ (while (and beg (< beg end))
+ (unless (eq (button-type beg) 'backtrace-ellipsis)
+ (button-put beg 'skip value))
+ (setq beg (next-button beg)))))
+
+(defun backtrace-toggle-print-circle (&optional all)
+ "Toggle `print-circle' for the backtrace frame at point.
+With prefix argument ALL, toggle the value of :print-circle in
+`backtrace-view', which affects all of the backtrace frames in
+the buffer."
+ (interactive "P")
+ (backtrace--toggle-feature :print-circle all))
+
+(defun backtrace--toggle-feature (feature all)
+ "Toggle FEATURE for the current backtrace frame or for the buffer.
+FEATURE should be one of the options in `backtrace-view'. If ALL
+is non-nil, toggle FEATURE for all frames in the buffer. After
+toggling the feature, reprint the affected frame(s). Afterwards
+position point at the start of the frame it was in before."
+ (if all
+ (let ((index (backtrace-get-index))
+ (pos (point))
+ (at-end (= (point) (point-max)))
+ (value (not (plist-get backtrace-view feature))))
+ (setq backtrace-view (plist-put backtrace-view feature value))
+ (goto-char (point-min))
+ ;; Skip the header.
+ (unless (backtrace-get-index)
+ (goto-char (backtrace-get-frame-end)))
+ (while (< (point) (point-max))
+ (backtrace--set-feature feature value)
+ (goto-char (backtrace-get-frame-end)))
+ (if (not index)
+ (goto-char (if at-end (point-max) pos))
+ (goto-char (point-min))
+ (while (and (not (eql index (backtrace-get-index)))
+ (< (point) (point-max)))
+ (goto-char (backtrace-get-frame-end)))))
+ (let ((index (backtrace-get-index)))
+ (unless index
+ (user-error "Not in a stack frame"))
+ (backtrace--set-feature feature
+ (not (plist-get (backtrace-get-view) feature))))))
+
+(defun backtrace--set-feature (feature value)
+ "Set FEATURE in the view plist of the frame at point to VALUE.
+Reprint the frame with the new view plist."
+ (let ((inhibit-read-only t)
+ (view (copy-sequence (backtrace-get-view)))
+ (index (backtrace-get-index))
+ (min (backtrace-get-frame-start))
+ (max (backtrace-get-frame-end)))
+ (setq view (plist-put view feature value))
+ (delete-region min max)
+ (goto-char min)
+ (backtrace-print-frame (nth index backtrace-frames) view)
+ (add-text-properties min (point)
+ `(backtrace-index ,index backtrace-view ,view))
+ (goto-char min)))
+
+(defun backtrace-expand-ellipsis (button)
+ "Expand display of the elided form at BUTTON."
+ (interactive)
+ (goto-char (button-start button))
+ (unless (get-text-property (point) 'cl-print-ellipsis)
+ (if (and (> (point) (point-min))
+ (get-text-property (1- (point)) 'cl-print-ellipsis))
+ (backward-char)
+ (user-error "No ellipsis to expand here")))
+ (let* ((end (next-single-property-change (point) 'cl-print-ellipsis))
+ (begin (previous-single-property-change end 'cl-print-ellipsis))
+ (value (get-text-property begin 'cl-print-ellipsis))
+ (props (backtrace-get-text-properties begin))
+ (inhibit-read-only t))
+ (backtrace--with-output-variables (backtrace-get-view)
+ (delete-region begin end)
+ (insert (cl-print-to-string-with-limit #'cl-print-expand-ellipsis value
+ backtrace-line-length))
+ (setq end (point))
+ (goto-char begin)
+ (while (< (point) end)
+ (let ((next (next-single-property-change (point) 'cl-print-ellipsis
+ nil end)))
+ (when (get-text-property (point) 'cl-print-ellipsis)
+ (make-text-button (point) next :type 'backtrace-ellipsis))
+ (goto-char next)))
+ (goto-char begin)
+ (add-text-properties begin end props))))
+
+(defun backtrace-expand-ellipses (&optional no-limit)
+ "Expand display of all \"...\"s in the backtrace frame at point.
+\\<backtrace-mode-map>
+Each ellipsis will be limited to `backtrace-line-length'
+characters in its expansion. With optional prefix argument
+NO-LIMIT, do not limit the number of characters. Note that with
+or without the argument, using this command can result in very
+long lines and very poor display performance. If this happens
+and is a problem, use `\\[revert-buffer]' to return to the
+initial state of the Backtrace buffer."
+ (interactive "P")
+ (save-excursion
+ (let ((start (backtrace-get-frame-start))
+ (end (backtrace-get-frame-end))
+ (backtrace-line-length (unless no-limit backtrace-line-length)))
+ (goto-char end)
+ (while (> (point) start)
+ (let ((next (previous-single-property-change (point) 'cl-print-ellipsis
+ nil start)))
+ (when (get-text-property (point) 'cl-print-ellipsis)
+ (push-button (point)))
+ (goto-char next))))))
+
+(defun backtrace-multi-line ()
+ "Show the top level s-expression at point on multiple lines with indentation."
+ (interactive)
+ (backtrace--reformat-sexp #'backtrace--multi-line))
+
+(defun backtrace--multi-line ()
+ "Pretty print the current buffer, then remove the trailing newline."
+ (set-syntax-table emacs-lisp-mode-syntax-table)
+ (pp-buffer)
+ (goto-char (1- (point-max)))
+ (delete-char 1))
+
+(defun backtrace-single-line ()
+ "Show the top level s-expression at point on one line."
+ (interactive)
+ (backtrace--reformat-sexp #'backtrace--single-line))
+
+(defun backtrace--single-line ()
+ "Replace line breaks and following indentation with spaces.
+Works on the current buffer."
+ (goto-char (point-min))
+ (while (re-search-forward "\n[[:blank:]]*" nil t)
+ (replace-match " ")))
+
+(defun backtrace--reformat-sexp (format-function)
+ "Reformat the top level sexp at point.
+Locate the top level sexp at or following point on the same line,
+and reformat it with FORMAT-FUNCTION, preserving the location of
+point within the sexp. If no sexp is found before the end of
+the line or buffer, signal an error.
+
+FORMAT-FUNCTION will be called without arguments, with the
+current buffer set to a temporary buffer containing only the
+content of the sexp."
+ (let* ((orig-pos (point))
+ (pos (point))
+ (tag (backtrace-get-form pos))
+ (end (next-single-property-change pos 'backtrace-form))
+ (begin (previous-single-property-change end 'backtrace-form
+ nil (point-min))))
+ (unless tag
+ (when (or (= end (point-max)) (> end (point-at-eol)))
+ (user-error "No form here to reformat"))
+ (goto-char end)
+ (setq pos end
+ end (next-single-property-change pos 'backtrace-form)
+ begin (previous-single-property-change end 'backtrace-form
+ nil (point-min))))
+ (let* ((offset (when (>= orig-pos begin) (- orig-pos begin)))
+ (offset-marker (when offset (make-marker)))
+ (content (buffer-substring begin end))
+ (props (backtrace-get-text-properties begin))
+ (inhibit-read-only t))
+ (delete-region begin end)
+ (insert (with-temp-buffer
+ (insert content)
+ (when offset
+ (set-marker-insertion-type offset-marker t)
+ (set-marker offset-marker (+ (point-min) offset)))
+ (funcall format-function)
+ (when offset
+ (setq offset (- (marker-position offset-marker) (point-min))))
+ (buffer-string)))
+ (when offset
+ (set-marker offset-marker (+ begin offset)))
+ (save-excursion
+ (goto-char begin)
+ (indent-sexp))
+ (add-text-properties begin (point) props)
+ (if offset
+ (goto-char (marker-position offset-marker))
+ (goto-char orig-pos)))))
+
+(defun backtrace-get-text-properties (pos)
+ "Return a plist of backtrace-mode's text properties at POS."
+ (apply #'append
+ (mapcar (lambda (prop)
+ (list prop (get-text-property pos prop)))
+ '(backtrace-section backtrace-index backtrace-view
+ backtrace-form))))
+
+(defun backtrace-goto-source ()
+ "If its location is known, jump to the source code for the frame at point."
+ (interactive)
+ (let* ((index (or (backtrace-get-index) (user-error "Not in a stack frame")))
+ (frame (nth index backtrace-frames))
+ (source-available (plist-get (backtrace-frame-flags frame)
+ :source-available)))
+ (unless (and source-available
+ (catch 'done
+ (dolist (func backtrace-goto-source-functions)
+ (when (funcall func)
+ (throw 'done t)))))
+ (user-error "Source code location not known"))))
+
+(defun backtrace-help-follow-symbol (&optional pos)
+ "Follow cross-reference at POS, defaulting to point.
+For the cross-reference format, see `help-make-xrefs'."
+ (interactive "d")
+ (unless pos
+ (setq pos (point)))
+ (unless (push-button pos)
+ ;; Check if the symbol under point is a function or variable.
+ (let ((sym
+ (intern
+ (save-excursion
+ (goto-char pos) (skip-syntax-backward "w_")
+ (buffer-substring (point)
+ (progn (skip-syntax-forward "w_")
+ (point)))))))
+ (when (or (boundp sym) (fboundp sym) (facep sym))
+ (describe-symbol sym)))))
+
+;; Print backtrace frames
+
+(defun backtrace-print (&optional remember-pos)
+ "Populate the current Backtrace mode buffer.
+This erases the buffer and inserts printed representations of the
+frames. Optional argument REMEMBER-POS, if non-nil, means to
+move point to the entry with the same ID element as the current
+line and recenter window line accordingly."
+ (let ((inhibit-read-only t)
+ entry-index saved-pt window-line)
+ (and remember-pos
+ (setq entry-index (backtrace-get-index))
+ (when (eq (window-buffer) (current-buffer))
+ (setq window-line
+ (count-screen-lines (window-start) (point)))))
+ (erase-buffer)
+ (when backtrace-insert-header-function
+ (funcall backtrace-insert-header-function))
+ (dotimes (idx (length backtrace-frames))
+ (let ((beg (point))
+ (elt (nth idx backtrace-frames)))
+ (and entry-index
+ (equal entry-index idx)
+ (setq entry-index nil
+ saved-pt (point)))
+ (backtrace-print-frame elt backtrace-view)
+ (add-text-properties
+ beg (point)
+ `(backtrace-index ,idx backtrace-view ,backtrace-view))))
+ (set-buffer-modified-p nil)
+ ;; If REMEMBER-POS was specified, move to the "old" location.
+ (if saved-pt
+ (progn (goto-char saved-pt)
+ (when window-line
+ (recenter window-line)))
+ (goto-char (point-min)))))
+
+;; Define button type used for ...'s.
+;; Set skip property so you don't have to TAB through 100 of them to
+;; get to the next function name.
+(define-button-type 'backtrace-ellipsis
+ 'skip t 'action #'backtrace-expand-ellipsis
+ 'help-echo "mouse-2, RET: expand this ellipsis")
+
+(defun backtrace-print-to-string (obj &optional limit)
+ "Return a printed representation of OBJ formatted for backtraces.
+Attempt to get the length of the returned string under LIMIT
+charcters with appropriate settings of `print-level' and
+`print-length.' LIMIT defaults to `backtrace-line-length'."
+ (backtrace--with-output-variables backtrace-view
+ (backtrace--print-to-string obj limit)))
+
+(defun backtrace--print-to-string (sexp &optional limit)
+ ;; This is for use by callers who wrap the call with
+ ;; backtrace--with-output-variables.
+ (setq limit (or limit backtrace-line-length))
+ (with-temp-buffer
+ (insert (cl-print-to-string-with-limit #'backtrace--print sexp limit))
+ ;; Add a unique backtrace-form property.
+ (put-text-property (point-min) (point) 'backtrace-form (gensym))
+ ;; Make buttons from all the "..."s. Since there might be many of
+ ;; them, use text property buttons.
+ (goto-char (point-min))
+ (while (< (point) (point-max))
+ (let ((end (next-single-property-change (point) 'cl-print-ellipsis
+ nil (point-max))))
+ (when (get-text-property (point) 'cl-print-ellipsis)
+ (make-text-button (point) end :type 'backtrace-ellipsis))
+ (goto-char end)))
+ (buffer-string)))
+
+(defun backtrace-print-frame (frame view)
+ "Insert a backtrace FRAME at point formatted according to VIEW.
+Tag the sections of the frame with the `backtrace-section' text
+property for use by navigation."
+ (backtrace--with-output-variables view
+ (backtrace--print-flags frame view)
+ (backtrace--print-func-and-args frame view)
+ (backtrace--print-locals frame view)))
+
+(defun backtrace--print-flags (frame view)
+ "Print the flags of a backtrace FRAME if enabled in VIEW."
+ (let ((beg (point))
+ (flag (plist-get (backtrace-frame-flags frame) :debug-on-exit))
+ (source (plist-get (backtrace-frame-flags frame) :source-available)))
+ (when (plist-get view :show-flags)
+ (when source (insert ">"))
+ (when flag (insert "*")))
+ (insert (make-string (- backtrace--flags-width (- (point) beg)) ?\s))
+ (put-text-property beg (point) 'backtrace-section 'func)))
+
+(defun backtrace--print-func-and-args (frame _view)
+ "Print the function, arguments and buffer position of a backtrace FRAME.
+Format it according to VIEW."
+ (let* ((beg (point))
+ (evald (backtrace-frame-evald frame))
+ (fun (backtrace-frame-fun frame))
+ (args (backtrace-frame-args frame))
+ (def (and (symbolp fun) (fboundp fun) (symbol-function fun)))
+ (fun-file (or (symbol-file fun 'defun)
+ (and (subrp def)
+ (not (eq 'unevalled (cdr (subr-arity def))))
+ (find-lisp-object-file-name fun def))))
+ (fun-pt (point)))
+ (cond
+ ((and evald (not debugger-stack-frame-as-list))
+ (if (atom fun)
+ (funcall backtrace-print-function fun)
+ (insert
+ (backtrace--print-to-string fun (when args (/ backtrace-line-length 2)))))
+ (if args
+ (insert (backtrace--print-to-string
+ args (max (truncate (/ backtrace-line-length 5))
+ (- backtrace-line-length (- (point) beg)))))
+ ;; The backtrace-form property is so that backtrace-multi-line
+ ;; will find it. backtrace-multi-line doesn't do anything
+ ;; useful with it, just being consistent.
+ (let ((start (point)))
+ (insert "()")
+ (put-text-property start (point) 'backtrace-form t))))
+ (t
+ (let ((fun-and-args (cons fun args)))
+ (insert (backtrace--print-to-string fun-and-args)))
+ (cl-incf fun-pt)))
+ (when fun-file
+ (make-text-button fun-pt (+ fun-pt (length (symbol-name fun)))
+ :type 'help-function-def
+ 'help-args (list fun fun-file)))
+ ;; After any frame that uses eval-buffer, insert a comment that
+ ;; states the buffer position it's reading at.
+ (when (backtrace-frame-pos frame)
+ (insert " ; Reading at ")
+ (let ((pos (point)))
+ (insert (format "buffer position %d" (backtrace-frame-pos frame)))
+ (make-button pos (point) :type 'backtrace-buffer-pos
+ 'backtrace-buffer (backtrace-frame-buffer frame)
+ 'backtrace-pos (backtrace-frame-pos frame))))
+ (insert "\n")
+ (put-text-property beg (point) 'backtrace-section 'func)))
+
+(defun backtrace--print-locals (frame view)
+ "Print a backtrace FRAME's local variables according to VIEW.
+Print them only if :show-locals is non-nil in the VIEW plist."
+ (when (plist-get view :show-locals)
+ (let* ((beg (point))
+ (locals (backtrace-frame-locals frame)))
+ (if (null locals)
+ (insert " [no locals]\n")
+ (pcase-dolist (`(,symbol . ,value) locals)
+ (insert " ")
+ (backtrace--print symbol)
+ (insert " = ")
+ (insert (backtrace--print-to-string value))
+ (insert "\n")))
+ (put-text-property beg (point) 'backtrace-section 'locals))))
+
+(defun backtrace--print (obj &optional stream)
+ "Attempt to print OBJ to STREAM using `backtrace-print-function'.
+Fall back to `prin1' if there is an error."
+ (condition-case err
+ (funcall backtrace-print-function obj stream)
+ (error
+ (message "Error in backtrace printer: %S" err)
+ (prin1 obj stream))))
+
+(defun backtrace-update-flags ()
+ "Update the display of the flags in the backtrace frame at point."
+ (let ((view (backtrace-get-view))
+ (begin (backtrace-get-frame-start)))
+ (when (plist-get view :show-flags)
+ (save-excursion
+ (goto-char begin)
+ (let ((props (backtrace-get-text-properties begin))
+ (inhibit-read-only t)
+ (standard-output (current-buffer)))
+ (delete-char backtrace--flags-width)
+ (backtrace--print-flags (nth (backtrace-get-index) backtrace-frames)
+ view)
+ (add-text-properties begin (point) props))))))
+
+(defun backtrace--filter-visible (beg end &optional _delete)
+ "Return the visible text between BEG and END."
+ (let ((result ""))
+ (while (< beg end)
+ (let ((next (next-single-char-property-change beg 'invisible)))
+ (unless (get-char-property beg 'invisible)
+ (setq result (concat result (buffer-substring beg (min end next)))))
+ (setq beg next)))
+ result))
+
+;;; The mode definition
+
+(define-derived-mode backtrace-mode special-mode "Backtrace"
+ "Generic major mode for examining an Elisp stack backtrace.
+This mode can be used directly, or other major modes can be
+derived from it, using `define-derived-mode'.
+
+In this major mode, the buffer contains some optional lines of
+header text followed by backtrace frames, each consisting of one
+or more whole lines.
+
+Letters in this mode do not insert themselves; instead they are
+commands.
+\\<backtrace-mode-map>
+\\{backtrace-mode-map}
+
+A mode which inherits from Backtrace mode, or a command which
+creates a backtrace-mode buffer, should usually do the following:
+
+ - Set `backtrace-revert-hook', if the buffer contents need
+ to be specially recomputed prior to `revert-buffer'.
+ - Maybe set `backtrace-insert-header-function' to a function to create
+ header text for the buffer.
+ - Set `backtrace-frames' (see below).
+ - Maybe modify `backtrace-view' (see below).
+ - Maybe set `backtrace-print-function'.
+
+A command which creates or switches to a Backtrace mode buffer,
+such as `ert-results-pop-to-backtrace-for-test-at-point', should
+initialize `backtrace-frames' to a list of `backtrace-frame'
+objects (`backtrace-get-frames' is provided for that purpose, if
+desired), and may optionally modify `backtrace-view', which is a
+plist describing the appearance of the backtrace. Finally, it
+should call `backtrace-print'.
+
+`backtrace-print' calls `backtrace-insert-header-function'
+followed by `backtrace-print-frame', once for each stack frame."
+ :syntax-table emacs-lisp-mode-syntax-table
+ (when backtrace-fontify
+ (setq font-lock-defaults
+ '((backtrace-font-lock-keywords
+ backtrace-font-lock-keywords-1
+ backtrace-font-lock-keywords-2)
+ nil nil nil nil
+ (font-lock-syntactic-face-function
+ . lisp-font-lock-syntactic-face-function))))
+ (setq truncate-lines t)
+ (buffer-disable-undo)
+ ;; In debug.el, from 1998 to 2009 this was set to nil, reason stated
+ ;; was because of bytecode. Since 2009 it's been set to t, but the
+ ;; default is t so I think this isn't necessary.
+ ;; (set-buffer-multibyte t)
+ (setq-local revert-buffer-function #'backtrace-revert)
+ (setq-local filter-buffer-substring-function #'backtrace--filter-visible)
+ (setq-local indent-line-function 'lisp-indent-line)
+ (setq-local indent-region-function 'lisp-indent-region)
+ (add-hook 'xref-backend-functions #'backtrace--xref-backend nil t))
+
+(put 'backtrace-mode 'mode-class 'special)
+
+;;; Backtrace printing
+
+;;;###autoload
+(defun backtrace ()
+ "Print a trace of Lisp function calls currently active.
+Output stream used is value of `standard-output'."
+ (princ (backtrace-to-string (backtrace-get-frames 'backtrace)))
+ nil)
+
+(defun backtrace-to-string(&optional frames)
+ "Format FRAMES, a list of `backtrace-frame' objects, for output.
+Return the result as a string. If FRAMES is nil, use all
+function calls currently active."
+ (unless frames (setq frames (backtrace-get-frames 'backtrace-to-string)))
+ (let ((backtrace-fontify nil))
+ (with-temp-buffer
+ (backtrace-mode)
+ (setq backtrace-view '(:show-flags t)
+ backtrace-frames frames
+ backtrace-print-function #'cl-prin1)
+ (backtrace-print)
+ (substring-no-properties (filter-buffer-substring (point-min)
+ (point-max))))))
+
+(provide 'backtrace)
+
+;;; backtrace.el ends here
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 011965acb54..d0d1c3b156a 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -2083,10 +2083,7 @@ This is like `cl-flet', but for macros instead of functions.
\(fn ((NAME ARGLIST BODY...) ...) FORM...)"
(declare (indent 1)
- (debug
- ((&rest (&define name (&rest arg) cl-declarations-or-string
- def-body))
- cl-declarations body)))
+ (debug (cl-macrolet-expr)))
(if (cdr bindings)
`(cl-macrolet (,(car bindings)) (cl-macrolet ,(cdr bindings) ,@body))
(if (null bindings) (macroexp-progn body)
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el
index 1eae8faf236..c63f5ac005c 100644
--- a/lisp/emacs-lisp/cl-print.el
+++ b/lisp/emacs-lisp/cl-print.el
@@ -55,10 +55,19 @@ call other entry points instead, such as `cl-prin1'."
;; we should only use it for objects which don't have nesting.
(prin1 object stream))
+(cl-defgeneric cl-print-object-contents (_object _start _stream)
+ "Dispatcher to print the contents of OBJECT on STREAM.
+Print the contents starting with the item at START, without
+delimiters."
+ ;; Every cl-print-object method which can print an ellipsis should
+ ;; have a matching cl-print-object-contents method to expand an
+ ;; ellipsis.
+ (error "Missing cl-print-object-contents method"))
+
(cl-defmethod cl-print-object ((object cons) stream)
(if (and cl-print--depth (natnump print-level)
(> cl-print--depth print-level))
- (princ "..." stream)
+ (cl-print-insert-ellipsis object 0 stream)
(let ((car (pop object))
(count 1))
(if (and print-quoted
@@ -84,23 +93,60 @@ call other entry points instead, such as `cl-prin1'."
(princ " " stream)
(if (or (not (natnump print-length)) (> print-length count))
(cl-print-object (pop object) stream)
- (princ "..." stream)
+ (cl-print-insert-ellipsis object print-length stream)
(setq object nil))
(cl-incf count))
(when object
(princ " . " stream) (cl-print-object object stream))
(princ ")" stream)))))
+(cl-defmethod cl-print-object-contents ((object cons) _start stream)
+ (let ((count 0))
+ (while (and (consp object)
+ (not (cond
+ (cl-print--number-table
+ (numberp (gethash object cl-print--number-table)))
+ ((memq object cl-print--currently-printing))
+ (t (push object cl-print--currently-printing)
+ nil))))
+ (unless (zerop count)
+ (princ " " stream))
+ (if (or (not (natnump print-length)) (> print-length count))
+ (cl-print-object (pop object) stream)
+ (cl-print-insert-ellipsis object print-length stream)
+ (setq object nil))
+ (cl-incf count))
+ (when object
+ (princ " . " stream) (cl-print-object object stream))))
+
(cl-defmethod cl-print-object ((object vector) stream)
- (princ "[" stream)
- (let ((count (length object)))
- (dotimes (i (if (natnump print-length)
- (min print-length count) count))
- (unless (zerop i) (princ " " stream))
- (cl-print-object (aref object i) stream))
- (when (and (natnump print-length) (< print-length count))
- (princ " ..." stream)))
- (princ "]" stream))
+ (if (and cl-print--depth (natnump print-level)
+ (> cl-print--depth print-level))
+ (cl-print-insert-ellipsis object 0 stream)
+ (princ "[" stream)
+ (let* ((len (length object))
+ (limit (if (natnump print-length)
+ (min print-length len) len)))
+ (dotimes (i limit)
+ (unless (zerop i) (princ " " stream))
+ (cl-print-object (aref object i) stream))
+ (when (< limit len)
+ (princ " " stream)
+ (cl-print-insert-ellipsis object limit stream)))
+ (princ "]" stream)))
+
+(cl-defmethod cl-print-object-contents ((object vector) start stream)
+ (let* ((len (length object))
+ (limit (if (natnump print-length)
+ (min (+ start print-length) len) len))
+ (i start))
+ (while (< i limit)
+ (unless (= i start) (princ " " stream))
+ (cl-print-object (aref object i) stream)
+ (cl-incf i))
+ (when (< limit len)
+ (princ " " stream)
+ (cl-print-insert-ellipsis object limit stream))))
(cl-defmethod cl-print-object ((object hash-table) stream)
(princ "#<hash-table " stream)
@@ -109,7 +155,7 @@ call other entry points instead, such as `cl-prin1'."
(princ (hash-table-count object) stream)
(princ "/" stream)
(princ (hash-table-size object) stream)
- (princ (format " 0x%x" (sxhash object)) stream)
+ (princ (format " %#x" (sxhash object)) stream)
(princ ">" stream))
(define-button-type 'help-byte-code
@@ -166,7 +212,7 @@ into a button whose action shows the function's disassembly.")
(let ((button-start (and cl-print-compiled-button
(bufferp stream)
(with-current-buffer stream (point)))))
- (princ (format "#<bytecode 0x%x>" (sxhash object)) stream)
+ (princ (format "#<bytecode %#x>" (sxhash object)) stream)
(when (eq cl-print-compiled 'static)
(princ " " stream)
(cl-print-object (aref object 2) stream))
@@ -199,21 +245,135 @@ into a button whose action shows the function's disassembly.")
(princ ")" stream)))
(cl-defmethod cl-print-object ((object cl-structure-object) stream)
- (princ "#s(" stream)
+ (if (and cl-print--depth (natnump print-level)
+ (> cl-print--depth print-level))
+ (cl-print-insert-ellipsis object 0 stream)
+ (princ "#s(" stream)
+ (let* ((class (cl-find-class (type-of object)))
+ (slots (cl--struct-class-slots class))
+ (len (length slots))
+ (limit (if (natnump print-length)
+ (min print-length len) len)))
+ (princ (cl--struct-class-name class) stream)
+ (dotimes (i limit)
+ (let ((slot (aref slots i)))
+ (princ " :" stream)
+ (princ (cl--slot-descriptor-name slot) stream)
+ (princ " " stream)
+ (cl-print-object (aref object (1+ i)) stream)))
+ (when (< limit len)
+ (princ " " stream)
+ (cl-print-insert-ellipsis object limit stream)))
+ (princ ")" stream)))
+
+(cl-defmethod cl-print-object-contents ((object cl-structure-object) start stream)
(let* ((class (cl-find-class (type-of object)))
(slots (cl--struct-class-slots class))
- (count (length slots)))
- (princ (cl--struct-class-name class) stream)
- (dotimes (i (if (natnump print-length)
- (min print-length count) count))
+ (len (length slots))
+ (limit (if (natnump print-length)
+ (min (+ start print-length) len) len))
+ (i start))
+ (while (< i limit)
(let ((slot (aref slots i)))
- (princ " :" stream)
+ (unless (= i start) (princ " " stream))
+ (princ ":" stream)
(princ (cl--slot-descriptor-name slot) stream)
(princ " " stream)
- (cl-print-object (aref object (1+ i)) stream)))
- (when (and (natnump print-length) (< print-length count))
- (princ " ..." stream)))
- (princ ")" stream))
+ (cl-print-object (aref object (1+ i)) stream))
+ (cl-incf i))
+ (when (< limit len)
+ (princ " " stream)
+ (cl-print-insert-ellipsis object limit stream))))
+
+(cl-defmethod cl-print-object ((object string) stream)
+ (unless stream (setq stream standard-output))
+ (let* ((has-properties (or (text-properties-at 0 object)
+ (next-property-change 0 object)))
+ (len (length object))
+ (limit (if (natnump print-length) (min print-length len) len)))
+ (if (and has-properties
+ cl-print--depth
+ (natnump print-level)
+ (> cl-print--depth print-level))
+ (cl-print-insert-ellipsis object 0 stream)
+ ;; Print all or part of the string
+ (when has-properties
+ (princ "#(" stream))
+ (if (= limit len)
+ (prin1 (if has-properties (substring-no-properties object) object)
+ stream)
+ (let ((part (concat (substring-no-properties object 0 limit) "...")))
+ (prin1 part stream)
+ (when (bufferp stream)
+ (with-current-buffer stream
+ (cl-print-propertize-ellipsis object limit
+ (- (point) 4)
+ (- (point) 1) stream)))))
+ ;; Print the property list.
+ (when has-properties
+ (let* ((interval-limit (and (natnump print-length)
+ (max 1 (/ print-length 3))))
+ (interval-count 0)
+ (start-pos (if (text-properties-at 0 object)
+ 0 (next-property-change 0 object)))
+ (end-pos (next-property-change start-pos object len)))
+ (while (and (or (null interval-limit)
+ (< interval-count interval-limit))
+ (< start-pos len))
+ (let ((props (text-properties-at start-pos object)))
+ (when props
+ (princ " " stream) (princ start-pos stream)
+ (princ " " stream) (princ end-pos stream)
+ (princ " " stream) (cl-print-object props stream)
+ (cl-incf interval-count))
+ (setq start-pos end-pos
+ end-pos (next-property-change start-pos object len))))
+ (when (< start-pos len)
+ (princ " " stream)
+ (cl-print-insert-ellipsis object (list start-pos) stream)))
+ (princ ")" stream)))))
+
+(cl-defmethod cl-print-object-contents ((object string) start stream)
+ ;; If START is an integer, it is an index into the string, and the
+ ;; ellipsis that needs to be expanded is part of the string. If
+ ;; START is a cons, its car is an index into the string, and the
+ ;; ellipsis that needs to be expanded is in the property list.
+ (let* ((len (length object)))
+ (if (atom start)
+ ;; Print part of the string.
+ (let* ((limit (if (natnump print-length)
+ (min (+ start print-length) len) len))
+ (substr (substring-no-properties object start limit))
+ (printed (prin1-to-string substr))
+ (trimmed (substring printed 1 (1- (length printed)))))
+ (princ trimmed)
+ (when (< limit len)
+ (cl-print-insert-ellipsis object limit stream)))
+
+ ;; Print part of the property list.
+ (let* ((first t)
+ (interval-limit (and (natnump print-length)
+ (max 1 (/ print-length 3))))
+ (interval-count 0)
+ (start-pos (car start))
+ (end-pos (next-property-change start-pos object len)))
+ (while (and (or (null interval-limit)
+ (< interval-count interval-limit))
+ (< start-pos len))
+ (let ((props (text-properties-at start-pos object)))
+ (when props
+ (if first
+ (setq first nil)
+ (princ " " stream))
+ (princ start-pos stream)
+ (princ " " stream) (princ end-pos stream)
+ (princ " " stream) (cl-print-object props stream)
+ (cl-incf interval-count))
+ (setq start-pos end-pos
+ end-pos (next-property-change start-pos object len))))
+ (when (< start-pos len)
+ (princ " " stream)
+ (cl-print-insert-ellipsis object (list start-pos) stream))))))
;;; Circularity and sharing.
@@ -275,8 +435,17 @@ into a button whose action shows the function's disassembly.")
(push cdr stack)
(push car stack))
((pred stringp)
- ;; We presumably won't print its text-properties.
- nil)
+ (let* ((len (length object))
+ (start (if (text-properties-at 0 object)
+ 0 (next-property-change 0 object)))
+ (end (and start
+ (next-property-change start object len))))
+ (while (and start (< start len))
+ (let ((props (text-properties-at start object)))
+ (when props
+ (push props stack))
+ (setq start end
+ end (next-property-change start object len))))))
((or (pred arrayp) (pred byte-code-function-p))
;; FIXME: Inefficient for char-tables!
(dotimes (i (length object))
@@ -291,6 +460,48 @@ into a button whose action shows the function's disassembly.")
(cl-print--find-sharing object print-number-table)))
print-number-table))
+(defun cl-print-insert-ellipsis (object start stream)
+ "Print \"...\" to STREAM with the `cl-print-ellipsis' text property.
+Save state in the text property in order to print the elided part
+of OBJECT later. START should be 0 if the whole OBJECT is being
+elided, otherwise it should be an index or other pointer into the
+internals of OBJECT which can be passed to
+`cl-print-object-contents' at a future time."
+ (unless stream (setq stream standard-output))
+ (let ((ellipsis-start (and (bufferp stream)
+ (with-current-buffer stream (point)))))
+ (princ "..." stream)
+ (when ellipsis-start
+ (with-current-buffer stream
+ (cl-print-propertize-ellipsis object start ellipsis-start (point)
+ stream)))))
+
+(defun cl-print-propertize-ellipsis (object start beg end stream)
+ "Add the `cl-print-ellipsis' property between BEG and END.
+STREAM should be a buffer. OBJECT and START are as described in
+`cl-print-insert-ellipsis'."
+ (let ((value (list object start cl-print--number-table
+ cl-print--currently-printing)))
+ (with-current-buffer stream
+ (put-text-property beg end 'cl-print-ellipsis value stream))))
+
+;;;###autoload
+(defun cl-print-expand-ellipsis (value stream)
+ "Print the expansion of an ellipsis to STREAM.
+VALUE should be the value of the `cl-print-ellipsis' text property
+which was attached to the ellipsis by `cl-prin1'."
+ (let ((cl-print--depth 1)
+ (object (nth 0 value))
+ (start (nth 1 value))
+ (cl-print--number-table (nth 2 value))
+ (print-number-table (nth 2 value))
+ (cl-print--currently-printing (nth 3 value)))
+ (when (eq object (car cl-print--currently-printing))
+ (pop cl-print--currently-printing))
+ (if (equal start 0)
+ (cl-print-object object stream)
+ (cl-print-object-contents object start stream))))
+
;;;###autoload
(defun cl-prin1 (object &optional stream)
"Print OBJECT on STREAM according to its type.
@@ -313,5 +524,45 @@ node `(elisp)Output Variables'."
(cl-prin1 object (current-buffer))
(buffer-string)))
+;;;###autoload
+(defun cl-print-to-string-with-limit (print-function value limit)
+ "Return a string containing a printed representation of VALUE.
+Attempt to get the length of the returned string under LIMIT
+characters with appropriate settings of `print-level' and
+`print-length.' Use PRINT-FUNCTION to print, which should take
+the arguments VALUE and STREAM and which should respect
+`print-length' and `print-level'. LIMIT may be nil or zero in
+which case PRINT-FUNCTION will be called with `print-level' and
+`print-length' bound to nil.
+
+Use this function with `cl-prin1' to print an object,
+abbreviating it with ellipses to fit within a size limit. Use
+this function with `cl-prin1-expand-ellipsis' to expand an
+ellipsis, abbreviating the expansion to stay within a size
+limit."
+ (setq limit (and (natnump limit)
+ (not (zerop limit))
+ limit))
+ ;; Since this is used by the debugger when stack space may be
+ ;; limited, if you increase print-level here, add more depth in
+ ;; call_debugger (bug#31919).
+ (let* ((print-length (when limit (min limit 50)))
+ (print-level (when limit (min 8 (truncate (log limit)))))
+ (delta (when limit
+ (max 1 (truncate (/ print-length print-level))))))
+ (with-temp-buffer
+ (catch 'done
+ (while t
+ (erase-buffer)
+ (funcall print-function value (current-buffer))
+ ;; Stop when either print-level is too low or the value is
+ ;; successfully printed in the space allowed.
+ (when (or (not limit)
+ (< (- (point-max) (point-min)) limit)
+ (= print-level 2))
+ (throw 'done (buffer-string)))
+ (cl-decf print-level)
+ (cl-decf print-length delta))))))
+
(provide 'cl-print)
;;; cl-print.el ends here
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index 0efaa637129..7fc2b41c70c 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -28,6 +28,7 @@
;;; Code:
(require 'cl-lib)
+(require 'backtrace)
(require 'button)
(defgroup debugger nil
@@ -133,6 +134,25 @@ where CAUSE can be:
- exit: called because of exit of a flagged function.
- error: called because of `debug-on-error'.")
+(cl-defstruct (debugger--buffer-state
+ (:constructor debugger--save-buffer-state
+ (&aux (mode major-mode)
+ (header backtrace-insert-header-function)
+ (frames backtrace-frames)
+ (content (buffer-string))
+ (pos (point)))))
+ mode header frames content pos)
+
+(defun debugger--restore-buffer-state (state)
+ (unless (derived-mode-p (debugger--buffer-state-mode state))
+ (funcall (debugger--buffer-state-mode state)))
+ (setq backtrace-insert-header-function (debugger--buffer-state-header state)
+ backtrace-frames (debugger--buffer-state-frames state))
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (insert (debugger--buffer-state-content state)))
+ (goto-char (debugger--buffer-state-pos state)))
+
;;;###autoload
(setq debugger 'debug)
;;;###autoload
@@ -174,7 +194,7 @@ first will be printed into the backtrace buffer."
(debugger-previous-state
(if (get-buffer "*Backtrace*")
(with-current-buffer (get-buffer "*Backtrace*")
- (list major-mode (buffer-string)))))
+ (debugger--save-buffer-state))))
(debugger-args args)
(debugger-buffer (get-buffer-create "*Backtrace*"))
(debugger-old-buffer (current-buffer))
@@ -236,7 +256,8 @@ first will be printed into the backtrace buffer."
(window-total-height debugger-window)))
(error nil)))
(setq debugger-previous-window debugger-window))
- (debugger-mode)
+ (unless (derived-mode-p 'debugger-mode)
+ (debugger-mode))
(debugger-setup-buffer debugger-args)
(when noninteractive
;; If the backtrace is long, save the beginning
@@ -280,15 +301,14 @@ first will be printed into the backtrace buffer."
(setq debugger-previous-window nil))
;; Restore previous state of debugger-buffer in case we were
;; in a recursive invocation of the debugger, otherwise just
- ;; erase the buffer and put it into fundamental mode.
+ ;; erase the buffer.
(when (buffer-live-p debugger-buffer)
(with-current-buffer debugger-buffer
- (let ((inhibit-read-only t))
- (erase-buffer)
- (if (null debugger-previous-state)
- (fundamental-mode)
- (insert (nth 1 debugger-previous-state))
- (funcall (nth 0 debugger-previous-state))))))
+ (if debugger-previous-state
+ (debugger--restore-buffer-state debugger-previous-state)
+ (setq backtrace-insert-header-function nil)
+ (setq backtrace-frames nil)
+ (backtrace-print))))
(with-timeout-unsuspend debugger-with-timeout-suspend)
(set-match-data debugger-outer-match-data)))
(setq debug-on-next-call debugger-step-after-exit)
@@ -301,112 +321,80 @@ first will be printed into the backtrace buffer."
(message "Error in debug printer: %S" err)
(prin1 obj stream))))
-(defun debugger-insert-backtrace (frames do-xrefs)
- "Format and insert the backtrace FRAMES at point.
-Make functions into cross-reference buttons if DO-XREFS is non-nil."
- (let ((standard-output (current-buffer))
- (eval-buffers eval-buffer-list))
- (require 'help-mode) ; Define `help-function-def' button type.
- (pcase-dolist (`(,evald ,fun ,args ,flags) frames)
- (insert (if (plist-get flags :debug-on-exit)
- "* " " "))
- (let ((fun-file (and do-xrefs (symbol-file fun 'defun)))
- (fun-pt (point)))
- (cond
- ((and evald (not debugger-stack-frame-as-list))
- (debugger--print fun)
- (if args (debugger--print args) (princ "()")))
- (t
- (debugger--print (cons fun args))
- (cl-incf fun-pt)))
- (when fun-file
- (make-text-button fun-pt (+ fun-pt (length (symbol-name fun)))
- :type 'help-function-def
- 'help-args (list fun fun-file))))
- ;; After any frame that uses eval-buffer, insert a line that
- ;; states the buffer position it's reading at.
- (when (and eval-buffers (memq fun '(eval-buffer eval-region)))
- (insert (format " ; Reading at buffer position %d"
- ;; This will get the wrong result if there are
- ;; two nested eval-region calls for the same
- ;; buffer. That's not a very useful case.
- (with-current-buffer (pop eval-buffers)
- (point)))))
- (insert "\n"))))
-
(defun debugger-setup-buffer (args)
"Initialize the `*Backtrace*' buffer for entry to the debugger.
-That buffer should be current already."
- (setq buffer-read-only nil)
- (erase-buffer)
- (set-buffer-multibyte t) ;Why was it nil ? -stef
- (setq buffer-undo-list t)
+That buffer should be current already and in debugger-mode."
+ (setq backtrace-frames (nthcdr
+ ;; Remove debug--implement-debug-on-entry and the
+ ;; advice's `apply' frame.
+ (if (eq (car args) 'debug) 3 1)
+ (backtrace-get-frames 'debug)))
+ (when (eq (car-safe args) 'exit)
+ (setq debugger-value (nth 1 args))
+ (setf (cl-getf (backtrace-frame-flags (car backtrace-frames))
+ :debug-on-exit)
+ nil))
+
+ (setq backtrace-view (plist-put backtrace-view :show-flags t)
+ backtrace-insert-header-function (lambda ()
+ (debugger--insert-header args))
+ backtrace-print-function debugger-print-function)
+ (backtrace-print)
+ ;; Place point on "stack frame 0" (bug#15101).
+ (goto-char (point-min))
+ (search-forward ":" (line-end-position) t)
+ (when (and (< (point) (line-end-position))
+ (= (char-after) ?\s))
+ (forward-char)))
+
+(defun debugger--insert-header (args)
+ "Insert the header for the debugger's Backtrace buffer.
+Include the reason for debugger entry from ARGS."
(insert "Debugger entered")
- (let ((frames (nthcdr
- ;; Remove debug--implement-debug-on-entry and the
- ;; advice's `apply' frame.
- (if (eq (car args) 'debug) 3 1)
- (backtrace-frames 'debug)))
- (print-escape-newlines t)
- (print-escape-control-characters t)
- ;; If you increase print-level, add more depth in call_debugger.
- (print-level 8)
- (print-length 50)
- (pos (point)))
- (pcase (car args)
- ;; lambda is for debug-on-call when a function call is next.
- ;; debug is for debug-on-entry function called.
- ((or `lambda `debug)
- (insert "--entering a function:\n")
- (setq pos (1- (point))))
- ;; Exiting a function.
- (`exit
- (insert "--returning value: ")
- (setq pos (point))
- (setq debugger-value (nth 1 args))
- (debugger--print debugger-value (current-buffer))
- (setf (cl-getf (nth 3 (car frames)) :debug-on-exit) nil)
- (insert ?\n))
- ;; Watchpoint triggered.
- ((and `watchpoint (let `(,symbol ,newval . ,details) (cdr args)))
- (insert
- "--"
- (pcase details
- (`(makunbound nil) (format "making %s void" symbol))
- (`(makunbound ,buffer) (format "killing local value of %s in buffer %s"
- symbol buffer))
- (`(defvaralias ,_) (format "aliasing %s to %s" symbol newval))
- (`(let ,_) (format "let-binding %s to %S" symbol newval))
- (`(unlet ,_) (format "ending let-binding of %s" symbol))
- (`(set nil) (format "setting %s to %S" symbol newval))
- (`(set ,buffer) (format "setting %s in buffer %s to %S"
- symbol buffer newval))
- (_ (error "unrecognized watchpoint triggered %S" (cdr args))))
- ": ")
- (setq pos (point))
- (insert ?\n))
- ;; Debugger entered for an error.
- (`error
- (insert "--Lisp error: ")
- (setq pos (point))
- (debugger--print (nth 1 args) (current-buffer))
- (insert ?\n))
- ;; debug-on-call, when the next thing is an eval.
- (`t
- (insert "--beginning evaluation of function call form:\n")
- (setq pos (1- (point))))
- ;; User calls debug directly.
- (_
- (insert ": ")
- (setq pos (point))
- (debugger--print
- (if (eq (car args) 'nil)
- (cdr args) args)
- (current-buffer))
- (insert ?\n)))
- (debugger-insert-backtrace frames t)
- ;; Place point on "stack frame 0" (bug#15101).
- (goto-char pos)))
+ (pcase (car args)
+ ;; lambda is for debug-on-call when a function call is next.
+ ;; debug is for debug-on-entry function called.
+ ((or `lambda `debug)
+ (insert "--entering a function:\n"))
+ ;; Exiting a function.
+ (`exit
+ (insert "--returning value: ")
+ (insert (backtrace-print-to-string debugger-value))
+ (insert ?\n))
+ ;; Watchpoint triggered.
+ ((and `watchpoint (let `(,symbol ,newval . ,details) (cdr args)))
+ (insert
+ "--"
+ (pcase details
+ (`(makunbound nil) (format "making %s void" symbol))
+ (`(makunbound ,buffer) (format "killing local value of %s in buffer %s"
+ symbol buffer))
+ (`(defvaralias ,_) (format "aliasing %s to %s" symbol newval))
+ (`(let ,_) (format "let-binding %s to %s" symbol
+ (backtrace-print-to-string newval)))
+ (`(unlet ,_) (format "ending let-binding of %s" symbol))
+ (`(set nil) (format "setting %s to %s" symbol
+ (backtrace-print-to-string newval)))
+ (`(set ,buffer) (format "setting %s in buffer %s to %s"
+ symbol buffer
+ (backtrace-print-to-string newval)))
+ (_ (error "unrecognized watchpoint triggered %S" (cdr args))))
+ ": ")
+ (insert ?\n))
+ ;; Debugger entered for an error.
+ (`error
+ (insert "--Lisp error: ")
+ (insert (backtrace-print-to-string (nth 1 args)))
+ (insert ?\n))
+ ;; debug-on-call, when the next thing is an eval.
+ (`t
+ (insert "--beginning evaluation of function call form:\n"))
+ ;; User calls debug directly.
+ (_
+ (insert ": ")
+ (insert (backtrace-print-to-string (if (eq (car args) 'nil)
+ (cdr args) args)))
+ (insert ?\n))))
(defun debugger-step-through ()
@@ -426,12 +414,12 @@ Enter another debugger on next entry to eval, apply or funcall."
(unless debugger-may-continue
(error "Cannot continue"))
(message "Continuing.")
- (save-excursion
- ;; Check to see if we've flagged some frame for debug-on-exit, in which
- ;; case we'll probably come back to the debugger soon.
- (goto-char (point-min))
- (if (re-search-forward "^\\* " nil t)
- (setq debugger-will-be-back t)))
+
+ ;; Check to see if we've flagged some frame for debug-on-exit, in which
+ ;; case we'll probably come back to the debugger soon.
+ (dolist (frame backtrace-frames)
+ (when (plist-get (backtrace-frame-flags frame) :debug-on-exit)
+ (setq debugger-will-be-back t)))
(exit-recursive-edit))
(defun debugger-return-value (val)
@@ -446,12 +434,11 @@ will be used, such as in a debug on exit from a frame."
(setq debugger-value val)
(princ "Returning " t)
(debugger--print debugger-value)
- (save-excursion
;; Check to see if we've flagged some frame for debug-on-exit, in which
;; case we'll probably come back to the debugger soon.
- (goto-char (point-min))
- (if (re-search-forward "^\\* " nil t)
- (setq debugger-will-be-back t)))
+ (dolist (frame backtrace-frames)
+ (when (plist-get (backtrace-frame-flags frame) :debug-on-exit)
+ (setq debugger-will-be-back t)))
(exit-recursive-edit))
(defun debugger-jump ()
@@ -473,63 +460,40 @@ removes itself from that hook."
(defun debugger-frame-number (&optional skip-base)
"Return number of frames in backtrace before the one point points at."
- (save-excursion
- (beginning-of-line)
- (if (looking-at " *;;;\\|[a-z]")
- (error "This line is not a function call"))
- (let ((opoint (point))
- (count 0))
- (unless skip-base
+ (let ((index (backtrace-get-index))
+ (count 0))
+ (unless index
+ (error "This line is not a function call"))
+ (unless skip-base
(while (not (eq (cadr (backtrace-frame count)) 'debug))
(setq count (1+ count)))
;; Skip debug--implement-debug-on-entry frame.
(when (eq 'debug--implement-debug-on-entry
(cadr (backtrace-frame (1+ count))))
(setq count (+ 2 count))))
- (goto-char (point-min))
- (when (looking-at "Debugger entered--\\(Lisp error\\|returning value\\):")
- (goto-char (match-end 0))
- (forward-sexp 1))
- (forward-line 1)
- (while (progn
- (forward-char 2)
- (cond ((debugger--locals-visible-p)
- (goto-char (next-single-char-property-change
- (point) 'locals-visible)))
- ((= (following-char) ?\()
- (forward-sexp 1))
- (t
- (forward-sexp 2)))
- (forward-line 1)
- (<= (point) opoint))
- (if (looking-at " *;;;")
- (forward-line 1))
- (setq count (1+ count)))
- count)))
+ (+ count index)))
(defun debugger-frame ()
"Request entry to debugger when this frame exits.
Applies to the frame whose line point is on in the backtrace."
(interactive)
(backtrace-debug (debugger-frame-number) t)
- (beginning-of-line)
- (if (= (following-char) ? )
- (let ((inhibit-read-only t))
- (delete-char 1)
- (insert ?*)))
- (beginning-of-line))
+ (setf
+ (cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
+ :debug-on-exit)
+ t)
+ (backtrace-update-flags))
(defun debugger-frame-clear ()
"Do not enter debugger when this frame exits.
Applies to the frame whose line point is on in the backtrace."
(interactive)
(backtrace-debug (debugger-frame-number) nil)
- (beginning-of-line)
- (if (= (following-char) ?*)
- (let ((inhibit-read-only t))
- (delete-char 1)
- (insert ? )))
- (beginning-of-line))
+ (setf
+ (cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
+ :debug-on-exit)
+ nil)
+ (backtrace-update-flags))
(defmacro debugger-env-macro (&rest body)
"Run BODY in original environment."
@@ -564,69 +528,10 @@ The environment used is the one when entering the activation frame at point."
(let ((str (eval-expression-print-format val)))
(if str (princ str t))))))))
-(defun debugger--locals-visible-p ()
- "Are the local variables of the current stack frame visible?"
- (save-excursion
- (move-to-column 2)
- (get-text-property (point) 'locals-visible)))
-
-(defun debugger--insert-locals (locals)
- "Insert the local variables LOCALS at point."
- (cond ((null locals)
- (insert "\n [no locals]"))
- (t
- (let ((print-escape-newlines t))
- (dolist (s+v locals)
- (let ((symbol (car s+v))
- (value (cdr s+v)))
- (insert "\n ")
- (prin1 symbol (current-buffer))
- (insert " = ")
- (debugger--print value (current-buffer))))))))
-
-(defun debugger--show-locals ()
- "For the frame at point, insert locals and add text properties."
- (let* ((nframe (1+ (debugger-frame-number 'skip-base)))
- (base (debugger--backtrace-base))
- (locals (backtrace--locals nframe base))
- (inhibit-read-only t))
- (save-excursion
- (let ((start (progn
- (move-to-column 2)
- (point))))
- (end-of-line)
- (debugger--insert-locals locals)
- (add-text-properties start (point) '(locals-visible t))))))
-
-(defun debugger--hide-locals ()
- "Delete local variables and remove the text property."
- (let* ((col (current-column))
- (end (progn
- (move-to-column 2)
- (next-single-char-property-change (point) 'locals-visible)))
- (start (previous-single-char-property-change end 'locals-visible))
- (inhibit-read-only t))
- (remove-text-properties start end '(locals-visible))
- (goto-char start)
- (end-of-line)
- (delete-region (point) end)
- (move-to-column col)))
-
-(defun debugger-toggle-locals ()
- "Show or hide local variables of the current stack frame."
- (interactive)
- (cond ((debugger--locals-visible-p)
- (debugger--hide-locals))
- (t
- (debugger--show-locals))))
-
(defvar debugger-mode-map
- (let ((map (make-keymap))
- (menu-map (make-sparse-keymap)))
- (set-keymap-parent map button-buffer-map)
- (suppress-keymap map)
- (define-key map "-" 'negative-argument)
+ (let ((map (make-keymap)))
+ (set-keymap-parent map backtrace-mode-map)
(define-key map "b" 'debugger-frame)
(define-key map "c" 'debugger-continue)
(define-key map "j" 'debugger-jump)
@@ -634,63 +539,47 @@ The environment used is the one when entering the activation frame at point."
(define-key map "u" 'debugger-frame-clear)
(define-key map "d" 'debugger-step-through)
(define-key map "l" 'debugger-list-functions)
- (define-key map "h" 'describe-mode)
- (define-key map "q" 'top-level)
+ (define-key map "q" 'debugger-quit)
(define-key map "e" 'debugger-eval-expression)
- (define-key map "v" 'debugger-toggle-locals) ; "v" is for "variables".
- (define-key map " " 'next-line)
(define-key map "R" 'debugger-record-expression)
- (define-key map "\C-m" 'debug-help-follow)
(define-key map [mouse-2] 'push-button)
- (define-key map [menu-bar debugger] (cons "Debugger" menu-map))
- (define-key menu-map [deb-top]
- '(menu-item "Quit" top-level
- :help "Quit debugging and return to top level"))
- (define-key menu-map [deb-s0] '("--"))
- (define-key menu-map [deb-descr]
- '(menu-item "Describe Debugger Mode" describe-mode
- :help "Display documentation for debugger-mode"))
- (define-key menu-map [deb-hfol]
- '(menu-item "Help Follow" debug-help-follow
- :help "Follow cross-reference"))
- (define-key menu-map [deb-nxt]
- '(menu-item "Next Line" next-line
- :help "Move cursor down"))
- (define-key menu-map [deb-s1] '("--"))
- (define-key menu-map [deb-lfunc]
- '(menu-item "List debug on entry functions" debugger-list-functions
- :help "Display a list of all the functions now set to debug on entry"))
- (define-key menu-map [deb-fclear]
- '(menu-item "Cancel debug frame" debugger-frame-clear
- :help "Do not enter debugger when this frame exits"))
- (define-key menu-map [deb-frame]
- '(menu-item "Debug frame" debugger-frame
- :help "Request entry to debugger when this frame exits"))
- (define-key menu-map [deb-s2] '("--"))
- (define-key menu-map [deb-ret]
- '(menu-item "Return value..." debugger-return-value
- :help "Continue, specifying value to return."))
- (define-key menu-map [deb-rec]
- '(menu-item "Display and Record Expression" debugger-record-expression
- :help "Display a variable's value and record it in `*Backtrace-record*' buffer"))
- (define-key menu-map [deb-eval]
- '(menu-item "Eval Expression..." debugger-eval-expression
- :help "Eval an expression, in an environment like that outside the debugger"))
- (define-key menu-map [deb-jump]
- '(menu-item "Jump" debugger-jump
- :help "Continue to exit from this frame, with all debug-on-entry suspended"))
- (define-key menu-map [deb-cont]
- '(menu-item "Continue" debugger-continue
- :help "Continue, evaluating this expression without stopping"))
- (define-key menu-map [deb-step]
- '(menu-item "Step through" debugger-step-through
- :help "Proceed, stepping through subexpressions of this expression"))
+ (easy-menu-define nil map ""
+ '("Debugger"
+ ["Step through" debugger-step-through
+ :help "Proceed, stepping through subexpressions of this expression"]
+ ["Continue" debugger-continue
+ :help "Continue, evaluating this expression without stopping"]
+ ["Jump" debugger-jump
+ :help "Continue to exit from this frame, with all debug-on-entry suspended"]
+ ["Eval Expression..." debugger-eval-expression
+ :help "Eval an expression, in an environment like that outside the debugger"]
+ ["Display and Record Expression" debugger-record-expression
+ :help "Display a variable's value and record it in `*Backtrace-record*' buffer"]
+ ["Return value..." debugger-return-value
+ :help "Continue, specifying value to return."]
+ "--"
+ ["Debug frame" debugger-frame
+ :help "Request entry to debugger when this frame exits"]
+ ["Cancel debug frame" debugger-frame-clear
+ :help "Do not enter debugger when this frame exits"]
+ ["List debug on entry functions" debugger-list-functions
+ :help "Display a list of all the functions now set to debug on entry"]
+ "--"
+ ["Next Line" next-line
+ :help "Move cursor down"]
+ ["Help for Symbol" backtrace-help-follow-symbol
+ :help "Show help for symbol at point"]
+ ["Describe Debugger Mode" describe-mode
+ :help "Display documentation for debugger-mode"]
+ "--"
+ ["Quit" debugger-quit
+ :help "Quit debugging and return to top level"]))
map))
(put 'debugger-mode 'mode-class 'special)
-(define-derived-mode debugger-mode fundamental-mode "Debugger"
- "Mode for backtrace buffers, selected in debugger.
+(define-derived-mode debugger-mode backtrace-mode "Debugger"
+ "Mode for debugging Emacs Lisp using a backtrace.
\\<debugger-mode-map>
A line starts with `*' if exiting that frame will call the debugger.
Type \\[debugger-frame] or \\[debugger-frame-clear] to set or remove the `*'.
@@ -704,8 +593,6 @@ which functions will enter the debugger when called.
Complete list of commands:
\\{debugger-mode-map}"
- (setq truncate-lines t)
- (set-syntax-table emacs-lisp-mode-syntax-table)
(add-hook 'kill-buffer-hook
(lambda () (if (> (recursion-depth) 0) (top-level)))
nil t)
@@ -732,27 +619,6 @@ Complete list of commands:
(buffer-substring (line-beginning-position 0)
(line-end-position 0)))))
-(defun debug-help-follow (&optional pos)
- "Follow cross-reference at POS, defaulting to point.
-
-For the cross-reference format, see `help-make-xrefs'."
- (interactive "d")
- ;; Ideally we'd just do (call-interactively 'help-follow) except that this
- ;; assumes we're already in a *Help* buffer and reuses it, so it ends up
- ;; incorrectly "reusing" the *Backtrace* buffer to show the help info.
- (unless pos
- (setq pos (point)))
- (unless (push-button pos)
- ;; check if the symbol under point is a function or variable
- (let ((sym
- (intern
- (save-excursion
- (goto-char pos) (skip-syntax-backward "w_")
- (buffer-substring (point)
- (progn (skip-syntax-forward "w_")
- (point)))))))
- (when (or (boundp sym) (fboundp sym) (facep sym))
- (describe-symbol sym)))))
;; When you change this, you may also need to change the number of
;; frames that the debugger skips.
@@ -853,6 +719,13 @@ To specify a nil argument interactively, exit with an empty minibuffer."
;;(princ "be set to debug on entry, even if it is in the list.")
)))))
+(defun debugger-quit ()
+ "Quit debugging and return to the top level."
+ (interactive)
+ (if (= (recursion-depth) 0)
+ (quit-window)
+ (top-level)))
+
(defun debug--implement-debug-watch (symbol newval op where)
"Conditionally call the debugger.
This function is called when SYMBOL's value is modified."
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index b83b53a8e52..4d8a5020267 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -474,22 +474,26 @@ See `%s' for more information on %s."
;; The function that calls TURN-ON in each buffer.
(defun ,MODE-enable-in-buffers ()
- (dolist (buf ,MODE-buffers)
- (when (buffer-live-p buf)
- (with-current-buffer buf
- (unless ,MODE-set-explicitly
- (unless (eq ,MODE-major-mode major-mode)
- (if ,mode
- (progn
- (,mode -1)
- (funcall #',turn-on))
- (funcall #',turn-on))))
- (setq ,MODE-major-mode major-mode)))))
+ (let ((buffers ,MODE-buffers))
+ ;; Clear MODE-buffers to avoid scanning the same list of
+ ;; buffers in recursive calls to MODE-enable-in-buffers.
+ ;; Otherwise it could lead to infinite recursion.
+ (setq ,MODE-buffers nil)
+ (dolist (buf buffers)
+ (when (buffer-live-p buf)
+ (with-current-buffer buf
+ (unless ,MODE-set-explicitly
+ (unless (eq ,MODE-major-mode major-mode)
+ (if ,mode
+ (progn
+ (,mode -1)
+ (funcall #',turn-on))
+ (funcall #',turn-on))))
+ (setq ,MODE-major-mode major-mode))))))
(put ',MODE-enable-in-buffers 'definition-name ',global-mode)
(defun ,MODE-check-buffers ()
(,MODE-enable-in-buffers)
- (setq ,MODE-buffers nil)
(remove-hook 'post-command-hook ',MODE-check-buffers))
(put ',MODE-check-buffers 'definition-name ',global-mode)
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index e759c5b5b24..fa418c68281 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -52,6 +52,7 @@
;;; Code:
+(require 'backtrace)
(require 'macroexp)
(require 'cl-lib)
(eval-when-compile (require 'pcase))
@@ -206,8 +207,7 @@ Use this with caution since it is not debugged."
"Non-nil if Edebug should unwrap results of expressions.
That is, Edebug will try to remove its own instrumentation from the result.
This is useful when debugging macros where the results of expressions
-are instrumented expressions. But don't do this when results might be
-circular or an infinite loop will result."
+are instrumented expressions."
:type 'boolean
:group 'edebug)
@@ -1198,6 +1198,8 @@ purpose by adding an entry to this alist, and setting
(defvar edebug-inside-func) ;; whether code is inside function context.
;; Currently def-form sets this to nil; def-body sets it to t.
+(defvar edebug--cl-macrolet-defs) ;; Fully defined below.
+
(defun edebug-interactive-p-name ()
;; Return a unique symbol for the variable used to store the
;; status of interactive-p for this function.
@@ -1263,25 +1265,59 @@ purpose by adding an entry to this alist, and setting
(defun edebug-unwrap (sexp)
"Return the unwrapped SEXP or return it as is if it is not wrapped.
The SEXP might be the result of wrapping a body, which is a list of
-expressions; a `progn' form will be returned enclosing these forms."
- (if (consp sexp)
- (cond
- ((eq 'edebug-after (car sexp))
- (nth 3 sexp))
- ((eq 'edebug-enter (car sexp))
- (macroexp-progn (nthcdr 2 (nth 1 (nth 3 sexp)))))
- (t sexp);; otherwise it is not wrapped, so just return it.
- )
- sexp))
+expressions; a `progn' form will be returned enclosing these forms.
+Does not unwrap inside vectors, records, structures, or hash tables."
+ (pcase sexp
+ (`(edebug-after ,_before-form ,_after-index ,form)
+ form)
+ (`(lambda ,args (edebug-enter ',_sym ,_arglist
+ (function (lambda nil . ,body))))
+ `(lambda ,args ,@body))
+ (`(closure ,env ,args (edebug-enter ',_sym ,_arglist
+ (function (lambda nil . ,body))))
+ `(closure ,env ,args ,@body))
+ (`(edebug-enter ',_sym ,_args (function (lambda nil . ,body)))
+ (macroexp-progn body))
+ (_ sexp)))
(defun edebug-unwrap* (sexp)
"Return the SEXP recursively unwrapped."
+ (let ((ht (make-hash-table :test 'eq)))
+ (edebug--unwrap1 sexp ht)))
+
+(defun edebug--unwrap1 (sexp hash-table)
+ "Unwrap SEXP using HASH-TABLE of things already unwrapped.
+HASH-TABLE contains the results of unwrapping cons cells within
+SEXP, which are reused to avoid infinite loops when SEXP is or
+contains a circular object."
(let ((new-sexp (edebug-unwrap sexp)))
(while (not (eq sexp new-sexp))
(setq sexp new-sexp
new-sexp (edebug-unwrap sexp)))
(if (consp new-sexp)
- (mapcar #'edebug-unwrap* new-sexp)
+ (let ((result (gethash new-sexp hash-table nil)))
+ (unless result
+ (let ((remainder new-sexp)
+ current)
+ (setq result (cons nil nil)
+ current result)
+ (while
+ (progn
+ (puthash remainder current hash-table)
+ (setf (car current)
+ (edebug--unwrap1 (car remainder) hash-table))
+ (setq remainder (cdr remainder))
+ (cond
+ ((atom remainder)
+ (setf (cdr current)
+ (edebug--unwrap1 remainder hash-table))
+ nil)
+ ((gethash remainder hash-table nil)
+ (setf (cdr current) (gethash remainder hash-table nil))
+ nil)
+ (t (setq current
+ (setf (cdr current) (cons nil nil)))))))))
+ result)
new-sexp)))
@@ -1463,6 +1499,11 @@ expressions; a `progn' form will be returned enclosing these forms."
;; Helper for edebug-list-form
(let ((spec (get-edebug-spec head)))
(cond
+ ;; Treat cl-macrolet bindings like macros with no spec.
+ ((member head edebug--cl-macrolet-defs)
+ (if edebug-eval-macro-args
+ (edebug-forms cursor)
+ (edebug-sexps cursor)))
(spec
(cond
((consp spec)
@@ -1651,6 +1692,9 @@ expressions; a `progn' form will be returned enclosing these forms."
;; (function . edebug-match-function)
(lambda-expr . edebug-match-lambda-expr)
(cl-generic-method-args . edebug-match-cl-generic-method-args)
+ (cl-macrolet-expr . edebug-match-cl-macrolet-expr)
+ (cl-macrolet-name . edebug-match-cl-macrolet-name)
+ (cl-macrolet-body . edebug-match-cl-macrolet-body)
(&not . edebug-match-&not)
(&key . edebug-match-&key)
(place . edebug-match-place)
@@ -1954,6 +1998,43 @@ expressions; a `progn' form will be returned enclosing these forms."
(edebug-move-cursor cursor)
(list args)))
+(defvar edebug--cl-macrolet-defs nil
+ "List of symbols found within the bindings of enclosing `cl-macrolet' forms.")
+(defvar edebug--current-cl-macrolet-defs nil
+ "List of symbols found within the bindings of the current `cl-macrolet' form.")
+
+(defun edebug-match-cl-macrolet-expr (cursor)
+ "Match a `cl-macrolet' form at CURSOR."
+ (let (edebug--current-cl-macrolet-defs)
+ (edebug-match cursor
+ '((&rest (&define cl-macrolet-name cl-macro-list
+ cl-declarations-or-string
+ def-body))
+ cl-declarations cl-macrolet-body))))
+
+(defun edebug-match-cl-macrolet-name (cursor)
+ "Match the name in a `cl-macrolet' binding at CURSOR.
+Collect the names in `edebug--cl-macrolet-defs' where they
+will be checked by `edebug-list-form-args' and treated as
+macros without a spec."
+ (let ((name (edebug-top-element-required cursor "Expected name")))
+ (when (not (symbolp name))
+ (edebug-no-match cursor "Bad name:" name))
+ ;; Change edebug-def-name to avoid conflicts with
+ ;; names at global scope.
+ (setq edebug-def-name (gensym "edebug-anon"))
+ (edebug-move-cursor cursor)
+ (push name edebug--current-cl-macrolet-defs)
+ (list name)))
+
+(defun edebug-match-cl-macrolet-body (cursor)
+ "Match the body of a `cl-macrolet' expression at CURSOR.
+Put the definitions collected in `edebug--current-cl-macrolet-defs'
+into `edebug--cl-macrolet-defs' which is checked in `edebug-list-form-args'."
+ (let ((edebug--cl-macrolet-defs (nconc edebug--current-cl-macrolet-defs
+ edebug--cl-macrolet-defs)))
+ (edebug-match-body cursor)))
+
(defun edebug-match-arg (cursor)
;; set the def-args bound in edebug-defining-form
(let ((edebug-arg (edebug-top-element-required cursor "Expected arg")))
@@ -3611,7 +3692,7 @@ be installed in `emacs-lisp-mode-map'.")
;; misc
(define-key map "?" 'edebug-help)
- (define-key map "d" 'edebug-backtrace)
+ (define-key map "d" 'edebug-pop-to-backtrace)
(define-key map "-" 'negative-argument)
@@ -3869,8 +3950,10 @@ Global commands prefixed by `global-edebug-prefix':
;; (setq debugger 'debug) ; use the standard debugger
;; Note that debug and its utilities must be byte-compiled to work,
-;; since they depend on the backtrace looking a certain way. But
-;; edebug is not dependent on this, yet.
+;; since they depend on the backtrace looking a certain way. Edebug
+;; will work if not byte-compiled, but it will not be able correctly
+;; remove its instrumentation from backtraces unless it is
+;; byte-compiled.
(defun edebug (&optional arg-mode &rest args)
"Replacement for `debug'.
@@ -3900,49 +3983,136 @@ Otherwise call `debug' normally."
(apply #'debug arg-mode args)
))
-
-(defun edebug-backtrace ()
- "Display a non-working backtrace. Better than nothing..."
+;;; Backtrace buffer
+
+(defvar-local edebug-backtrace-frames nil
+ "Stack frames of the current Edebug Backtrace buffer without instrumentation.
+This should be a list of `edebug---frame' objects.")
+(defvar-local edebug-instrumented-backtrace-frames nil
+ "Stack frames of the current Edebug Backtrace buffer with instrumentation.
+This should be a list of `edebug---frame' objects.")
+
+;; Data structure for backtrace frames with information
+;; from Edebug instrumentation found in the backtrace.
+(cl-defstruct
+ (edebug--frame
+ (:constructor edebug--make-frame)
+ (:include backtrace-frame))
+ def-name before-index after-index)
+
+(defun edebug-pop-to-backtrace ()
+ "Display the current backtrace in a `backtrace-mode' window."
(interactive)
(if (or (not edebug-backtrace-buffer)
(null (buffer-name edebug-backtrace-buffer)))
(setq edebug-backtrace-buffer
- (generate-new-buffer "*Backtrace*"))
+ (generate-new-buffer "*Edebug Backtrace*"))
;; Else, could just display edebug-backtrace-buffer.
)
- (with-output-to-temp-buffer (buffer-name edebug-backtrace-buffer)
- (setq edebug-backtrace-buffer standard-output)
- (let ((print-escape-newlines t)
- (print-length 50) ; FIXME cf edebug-safe-prin1-to-string
- last-ok-point)
- (backtrace)
-
- ;; Clean up the backtrace.
- ;; Not quite right for current edebug scheme.
- (set-buffer edebug-backtrace-buffer)
- (setq truncate-lines t)
- (goto-char (point-min))
- (setq last-ok-point (point))
- (if t (progn
-
- ;; Delete interspersed edebug internals.
- (while (re-search-forward "^ (?edebug" nil t)
- (beginning-of-line)
- (cond
- ((looking-at "^ (edebug-after")
- ;; Previous lines may contain code, so just delete this line.
- (setq last-ok-point (point))
- (forward-line 1)
- (delete-region last-ok-point (point)))
-
- ((looking-at (if debugger-stack-frame-as-list
- "^ (edebug"
- "^ edebug"))
- (forward-line 1)
- (delete-region last-ok-point (point))
- )))
- )))))
+ (pop-to-buffer edebug-backtrace-buffer)
+ (unless (derived-mode-p 'backtrace-mode)
+ (backtrace-mode)
+ (add-hook 'backtrace-goto-source-functions 'edebug--backtrace-goto-source))
+ (setq edebug-instrumented-backtrace-frames
+ (backtrace-get-frames 'edebug-debugger
+ :constructor #'edebug--make-frame)
+ edebug-backtrace-frames (edebug--strip-instrumentation
+ edebug-instrumented-backtrace-frames)
+ backtrace-frames edebug-backtrace-frames)
+ (backtrace-print)
+ (goto-char (point-min)))
+
+(defun edebug--strip-instrumentation (frames)
+ "Return a new list of backtrace frames with instrumentation removed.
+Remove frames for Edebug's functions and the lambdas in
+`edebug-enter' wrappers. Fill in the def-name, before-index
+and after-index fields in both FRAMES and the returned list
+of deinstrumented frames, for those frames where the source
+code location is known."
+ (let (skip-next-lambda def-name before-index after-index results
+ (index (length frames)))
+ (dolist (frame (reverse frames))
+ (let ((new-frame (copy-edebug--frame frame))
+ (fun (edebug--frame-fun frame))
+ (args (edebug--frame-args frame)))
+ (cl-decf index)
+ (pcase fun
+ ('edebug-enter
+ (setq skip-next-lambda t
+ def-name (nth 0 args)))
+ ('edebug-after
+ (setq before-index (if (consp (nth 0 args))
+ (nth 1 (nth 0 args))
+ (nth 0 args))
+ after-index (nth 1 args)))
+ ((pred edebug--symbol-not-prefixed-p)
+ (edebug--unwrap-frame new-frame)
+ (edebug--add-source-info new-frame def-name before-index after-index)
+ (edebug--add-source-info frame def-name before-index after-index)
+ (push new-frame results)
+ (setq before-index nil
+ after-index nil))
+ (`(,(or 'lambda 'closure) . ,_)
+ (unless skip-next-lambda
+ (edebug--unwrap-frame new-frame)
+ (edebug--add-source-info frame def-name before-index after-index)
+ (edebug--add-source-info new-frame def-name before-index after-index)
+ (push new-frame results))
+ (setq before-index nil
+ after-index nil
+ skip-next-lambda nil)))))
+ results))
+
+(defun edebug--symbol-not-prefixed-p (sym)
+ "Return non-nil if SYM is a symbol not prefixed by \"edebug-\"."
+ (and (symbolp sym)
+ (not (string-prefix-p "edebug-" (symbol-name sym)))))
+
+(defun edebug--unwrap-frame (frame)
+ "Remove Edebug's instrumentation from FRAME.
+Strip it from the function and any unevaluated arguments."
+ (setf (edebug--frame-fun frame) (edebug-unwrap* (edebug--frame-fun frame)))
+ (unless (edebug--frame-evald frame)
+ (let (results)
+ (dolist (arg (edebug--frame-args frame))
+ (push (edebug-unwrap* arg) results))
+ (setf (edebug--frame-args frame) (nreverse results)))))
+
+(defun edebug--add-source-info (frame def-name before-index after-index)
+ "Update FRAME with the additional info needed by an edebug--frame.
+Save DEF-NAME, BEFORE-INDEX and AFTER-INDEX in FRAME."
+ (when (and before-index def-name)
+ (setf (edebug--frame-flags frame)
+ (plist-put (copy-sequence (edebug--frame-flags frame))
+ :source-available t)))
+ (setf (edebug--frame-def-name frame) (and before-index def-name))
+ (setf (edebug--frame-before-index frame) before-index)
+ (setf (edebug--frame-after-index frame) after-index))
+
+(defun edebug--backtrace-goto-source ()
+ (let* ((index (backtrace-get-index))
+ (frame (nth index backtrace-frames)))
+ (when (edebug--frame-def-name frame)
+ (let* ((data (get (edebug--frame-def-name frame) 'edebug))
+ (marker (nth 0 data))
+ (offsets (nth 2 data)))
+ (pop-to-buffer (marker-buffer marker))
+ (goto-char (+ (marker-position marker)
+ (aref offsets (edebug--frame-before-index frame))))))))
+
+(defun edebug-backtrace-show-instrumentation ()
+ "Show Edebug's instrumentation in an Edebug Backtrace buffer."
+ (interactive)
+ (unless (eq backtrace-frames edebug-instrumented-backtrace-frames)
+ (setq backtrace-frames edebug-instrumented-backtrace-frames)
+ (revert-buffer)))
+(defun edebug-backtrace-hide-instrumentation ()
+ "Hide Edebug's instrumentation in an Edebug Backtrace buffer."
+ (interactive)
+ (unless (eq backtrace-frames edebug-backtrace-frames)
+ (setq backtrace-frames edebug-backtrace-frames)
+ (revert-buffer)))
;;; Trace display
@@ -4116,7 +4286,7 @@ It is removed when you hit any char."
["Bounce to Current Point" edebug-bounce-point t]
["View Outside Windows" edebug-view-outside t]
["Previous Result" edebug-previous-result t]
- ["Show Backtrace" edebug-backtrace t]
+ ["Show Backtrace" edebug-pop-to-backtrace t]
["Display Freq Count" edebug-display-freq-count t])
("Eval"
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index cad21044f15..eb9695d0c12 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -60,6 +60,7 @@
(require 'cl-lib)
(require 'button)
(require 'debug)
+(require 'backtrace)
(require 'easymenu)
(require 'ewoc)
(require 'find-func)
@@ -677,13 +678,6 @@ and is displayed in front of the value of MESSAGE-FORM."
(cl-defstruct (ert-test-aborted-with-non-local-exit
(:include ert-test-result)))
-(defun ert--print-backtrace (backtrace do-xrefs)
- "Format the backtrace BACKTRACE to the current buffer."
- (let ((print-escape-newlines t)
- (print-level 8)
- (print-length 50))
- (debugger-insert-backtrace backtrace do-xrefs)))
-
;; A container for the state of the execution of a single test and
;; environment data needed during its execution.
(cl-defstruct ert--test-execution-info
@@ -732,7 +726,7 @@ run. ARGS are the arguments to `debugger'."
;; use.
;;
;; Grab the frames above the debugger.
- (backtrace (cdr (backtrace-frames debugger)))
+ (backtrace (cdr (backtrace-get-frames debugger)))
(infos (reverse ert--infos)))
(setf (ert--test-execution-info-result info)
(cl-ecase type
@@ -1406,9 +1400,8 @@ Returns the stats object."
(ert-test-result-with-condition
(message "Test %S backtrace:" (ert-test-name test))
(with-temp-buffer
- (ert--print-backtrace
- (ert-test-result-with-condition-backtrace result)
- nil)
+ (insert (backtrace-to-string
+ (ert-test-result-with-condition-backtrace result)))
(if (not ert-batch-backtrace-right-margin)
(message "%s"
(buffer-substring-no-properties (point-min)
@@ -2450,20 +2443,20 @@ To be used in the ERT results buffer."
(cl-etypecase result
(ert-test-passed (error "Test passed, no backtrace available"))
(ert-test-result-with-condition
- (let ((backtrace (ert-test-result-with-condition-backtrace result))
- (buffer (get-buffer-create "*ERT Backtrace*")))
+ (let ((buffer (get-buffer-create "*ERT Backtrace*")))
(pop-to-buffer buffer)
- (let ((inhibit-read-only t))
- (buffer-disable-undo)
- (erase-buffer)
- (ert-simple-view-mode)
- (set-buffer-multibyte t) ; mimic debugger-setup-buffer
- (setq truncate-lines t)
- (ert--print-backtrace backtrace t)
- (goto-char (point-min))
- (insert (substitute-command-keys "Backtrace for test `"))
- (ert-insert-test-name-button (ert-test-name test))
- (insert (substitute-command-keys "':\n"))))))))
+ (unless (derived-mode-p 'backtrace-mode)
+ (backtrace-mode))
+ (setq backtrace-insert-header-function
+ (lambda () (ert--insert-backtrace-header (ert-test-name test)))
+ backtrace-frames (ert-test-result-with-condition-backtrace result))
+ (backtrace-print)
+ (goto-char (point-min)))))))
+
+(defun ert--insert-backtrace-header (name)
+ (insert (substitute-command-keys "Backtrace for test `"))
+ (ert-insert-test-name-button name)
+ (insert (substitute-command-keys "':\n")))
(defun ert-results-pop-to-messages-for-test-at-point ()
"Display the part of the *Messages* buffer generated during the test at point.
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 4e5b1a7e4ff..afb7cbd1dd7 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -517,6 +517,16 @@ This will generate compile-time constants from BINDINGS."
(defvar lisp-cl-font-lock-keywords lisp-cl-font-lock-keywords-1
"Default expressions to highlight in Lisp modes.")
+;; Support backtrace mode.
+(defconst lisp-el-font-lock-keywords-for-backtraces lisp-el-font-lock-keywords
+ "Default highlighting from Emacs Lisp mod used in Backtrace mode.")
+(defconst lisp-el-font-lock-keywords-for-backtraces-1 lisp-el-font-lock-keywords-1
+ "Subdued highlighting from Emacs Lisp mode used in Backtrace mode.")
+(defconst lisp-el-font-lock-keywords-for-backtraces-2
+ (remove (assoc 'lisp--match-hidden-arg lisp-el-font-lock-keywords-2)
+ lisp-el-font-lock-keywords-2)
+ "Gaudy highlighting from Emacs Lisp mode used in Backtrace mode.")
+
(defun lisp-string-in-doc-position-p (listbeg startpos)
"Return true if a doc string may occur at STARTPOS inside a list.
LISTBEG is the position of the start of the innermost list
@@ -1196,7 +1206,21 @@ ENDPOS is encountered."
(if endpos endpos
;; Get error now if we don't have a complete sexp
;; after point.
- (save-excursion (forward-sexp 1) (point)))))
+ (save-excursion
+ (let ((eol (line-end-position)))
+ (forward-sexp 1)
+ ;; We actually look for a sexp which ends
+ ;; after the current line so that we properly
+ ;; indent things like #s(...). This might not
+ ;; be needed if Bug#15998 is fixed.
+ (condition-case ()
+ (while (and (< (point) eol) (not (eobp)))
+ (forward-sexp 1))
+ ;; But don't signal an error for incomplete
+ ;; sexps following the first complete sexp
+ ;; after point.
+ (scan-error nil)))
+ (point)))))
(save-excursion
(while (let ((indent (lisp-indent-calc-next parse-state))
(ppss (lisp-indent-state-ppss parse-state)))
diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el
index 61c04ff7b3e..a61c0adc8fb 100644
--- a/lisp/emacs-lisp/map-ynp.el
+++ b/lisp/emacs-lisp/map-ynp.el
@@ -257,10 +257,15 @@ C-g to quit (cancel the whole command);
;; either long or short answers.
;; For backward compatibility check if short y/n answers are preferred.
-(defcustom read-answer-short (eq (symbol-function 'yes-or-no-p) 'y-or-n-p)
- "If non-nil, accept short answers to the question."
- :type 'boolean
- :version "27.1"
+(defcustom read-answer-short 'auto
+ "If non-nil, `read-answer' accepts single-character answers.
+If t, accept short (single key-press) answers to the question.
+If nil, require long answers. If `auto', accept short answers if
+the function cell of `yes-or-no-p' is set to `y-or-on-p'."
+ :type '(choice (const :tag "Accept short answers" t)
+ (const :tag "Require long answer" nil)
+ (const :tag "Guess preference" auto))
+ :version "26.2"
:group 'minibuffer)
(defconst read-answer-map--memoize (make-hash-table :weakness 'key :test 'equal))
@@ -290,8 +295,9 @@ When `read-answer-short' is non-nil, accept short answers.
Return a long answer even in case of accepting short ones.
When `use-dialog-box' is t, pop up a dialog window to get user input."
- (custom-reevaluate-setting 'read-answer-short)
- (let* ((short read-answer-short)
+ (let* ((short (if (eq read-answer-short 'auto)
+ (eq (symbol-function 'yes-or-no-p) 'y-or-n-p)
+ read-answer-short))
(answers-with-help
(if (assoc "help" answers)
answers
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el
index 85e74f28ef0..bb759011513 100644
--- a/lisp/emacs-lisp/rx.el
+++ b/lisp/emacs-lisp/rx.el
@@ -1183,24 +1183,28 @@ enclosed in `(and ...)'.
(pcase-defmacro rx (&rest regexps)
- "Build a `pcase' pattern matching `rx' regexps.
-The REGEXPS are interpreted as by `rx'. The pattern matches if
-the regular expression so constructed matches EXPVAL, as if
-by `string-match'.
+ "Build a `pcase' pattern matching `rx' REGEXPS in sexp form.
+The REGEXPS are interpreted as in `rx'. The pattern matches any
+string that is a match for the regular expression so constructed,
+as if by `string-match'.
In addition to the usual `rx' constructs, REGEXPS can contain the
following constructs:
- (let VAR FORM...) creates a new explicitly numbered submatch
- that matches FORM and binds the match to
- VAR.
- (backref VAR) creates a backreference to the submatch
- introduced by a previous (let VAR ...)
- construct.
-
-The VARs are associated with explicitly numbered submatches
-starting from 1. Multiple occurrences of the same VAR refer to
-the same submatch.
+ (let REF SEXP...) creates a new explicitly named reference to
+ a submatch that matches regular expressions
+ SEXP, and binds the match to REF.
+ (backref REF) creates a backreference to the submatch
+ introduced by a previous (let REF ...)
+ construct. REF can be the same symbol
+ in the first argument of the corresponding
+ (let REF ...) construct, or it can be a
+ submatch number. It matches the referenced
+ submatch.
+
+The REFs are associated with explicitly named submatches starting
+from 1. Multiple occurrences of the same REF refer to the same
+submatch.
If a case matches, the match data is modified as usual so you can
use it in the case body, but you still have to pass the correct
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index e03a81c892a..20eb0d5d05c 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -211,7 +211,7 @@ The variable list SPEC is the same as in `if-let'."
(defsubst string-join (strings &optional separator)
"Join all STRINGS using SEPARATOR."
- (mapconcat 'identity strings separator))
+ (mapconcat #'identity strings separator))
(define-obsolete-function-alias 'string-reverse 'reverse "25.1")
@@ -219,17 +219,17 @@ The variable list SPEC is the same as in `if-let'."
"Trim STRING of leading string matching REGEXP.
REGEXP defaults to \"[ \\t\\n\\r]+\"."
- (if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+")"\\)") string)
- (replace-match "" t t string)
+ (if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+") "\\)") string)
+ (substring string (match-end 0))
string))
(defsubst string-trim-right (string &optional regexp)
"Trim STRING of trailing string matching REGEXP.
REGEXP defaults to \"[ \\t\\n\\r]+\"."
- (if (string-match (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'") string)
- (replace-match "" t t string)
- string))
+ (let ((i (string-match-p (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'")
+ string)))
+ (if i (substring string 0 i) string)))
(defsubst string-trim (string &optional trim-left trim-right)
"Trim STRING of leading and trailing strings matching TRIM-LEFT and TRIM-RIGHT.
diff --git a/lisp/env.el b/lisp/env.el
index e47eb57836f..7007ba33e58 100644
--- a/lisp/env.el
+++ b/lisp/env.el
@@ -113,11 +113,11 @@ Changes ENV by side-effect, and returns its new value."
(not keep-empty)
env
(stringp (car env))
- (string-match pattern (car env)))
+ (string-match-p pattern (car env)))
(cdr env)
;; Try to find existing entry for VARIABLE in ENV.
(while (and scan (stringp (car scan)))
- (when (string-match pattern (car scan))
+ (when (string-match-p pattern (car scan))
(if value
(setcar scan (concat variable "=" value))
(if keep-empty
@@ -184,7 +184,7 @@ a side-effect."
(setq variable (encode-coding-string variable locale-coding-system)))
(if (and value (multibyte-string-p value))
(setq value (encode-coding-string value locale-coding-system)))
- (if (string-match "=" variable)
+ (if (string-match-p "=" variable)
(error "Environment variable name `%s' contains `='" variable))
(if (string-equal "TZ" variable)
(set-time-zone-rule value))
diff --git a/lisp/epg-config.el b/lisp/epg-config.el
index 98f458d9962..fb866df3920 100644
--- a/lisp/epg-config.el
+++ b/lisp/epg-config.el
@@ -98,11 +98,14 @@ Note that the buffer name starts with a space."
:type 'boolean)
(defconst epg-gpg-minimum-version "1.4.3")
+(defconst epg-gpg2-minimum-version "2.1.6")
(defconst epg-config--program-alist
`((OpenPGP
epg-gpg-program
- ("gpg2" . "2.1.6") ("gpg" . ,epg-gpg-minimum-version))
+ ("gpg2" . ,epg-gpg2-minimum-version)
+ ("gpg" . ((,epg-gpg-minimum-version . "2.0")
+ ,epg-gpg2-minimum-version)))
(CMS
epg-gpgsm-program
("gpgsm" . "2.0.4")))
@@ -228,14 +231,26 @@ version requirement is met."
(epg-config--make-gpg-configuration epg-gpg-program))
;;;###autoload
-(defun epg-check-configuration (config &optional minimum-version)
- "Verify that a sufficient version of GnuPG is installed."
+(defun epg-check-configuration (config &optional req-versions)
+ "Verify that a sufficient version of GnuPG is installed.
+CONFIG should be a `epg-configuration' object (a plist).
+REQ-VERSIONS should be a list with elements of the form (MIN
+. MAX) where MIN and MAX are version strings indicating a
+semi-open range of acceptable versions. REQ-VERSIONS may also be
+a single minimum version string."
(let ((version (alist-get 'version config)))
(unless (stringp version)
(error "Undetermined version: %S" version))
- (unless (version<= (or minimum-version
- epg-gpg-minimum-version)
- version)
+ (catch 'version-ok
+ (pcase-dolist ((or `(,min . ,max)
+ (and min (let max nil)))
+ (if (listp req-versions) req-versions
+ (list req-versions)))
+ (when (and (version<= (or min epg-gpg-minimum-version)
+ version)
+ (or (null max)
+ (version< version max)))
+ (throw 'version-ok t)))
(error "Unsupported version: %s" version))))
;;;###autoload
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index ec380e67011..5180a0700db 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -407,6 +407,7 @@ in the minibuffer:
nil))))
(put 'eshell/cd 'eshell-no-numeric-conversions t)
+(put 'eshell/cd 'eshell-filename-arguments t)
(defun eshell-add-to-dir-ring (path)
"Add PATH to the last-dir-ring, if applicable."
@@ -470,6 +471,7 @@ in the minibuffer:
nil)
(put 'eshell/pushd 'eshell-no-numeric-conversions t)
+(put 'eshell/pushd 'eshell-filename-arguments t)
;;; popd [+n]
(defun eshell/popd (&rest args)
@@ -500,6 +502,7 @@ in the minibuffer:
nil)
(put 'eshell/popd 'eshell-no-numeric-conversions t)
+(put 'eshell/pop 'eshell-filename-arguments t)
(defun eshell/dirs (&optional if-verbose)
"Implementation of dirs in Lisp."
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index 900b28905b7..2b568a991a2 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -334,6 +334,7 @@ instead."
(apply 'eshell-do-ls args)))
(put 'eshell/ls 'eshell-no-numeric-conversions t)
+(put 'eshell/ls 'eshell-filename-arguments t)
(declare-function eshell-glob-regexp "em-glob" (pattern))
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index a18fb85507d..c912c15ac75 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -307,6 +307,7 @@ Remove (unlink) the FILE(s).")
nil))
(put 'eshell/rm 'eshell-no-numeric-conversions t)
+(put 'eshell/rm 'eshell-filename-arguments t)
(defun eshell/mkdir (&rest args)
"Implementation of mkdir in Lisp."
@@ -324,6 +325,7 @@ Create the DIRECTORY(ies), if they do not already exist.")
nil))
(put 'eshell/mkdir 'eshell-no-numeric-conversions t)
+(put 'eshell/mkdir 'eshell-filename-arguments t)
(defun eshell/rmdir (&rest args)
"Implementation of rmdir in Lisp."
@@ -340,6 +342,7 @@ Remove the DIRECTORY(ies), if they are empty.")
nil))
(put 'eshell/rmdir 'eshell-no-numeric-conversions t)
+(put 'eshell/rmdir 'eshell-filename-arguments t)
(defvar no-dereference)
@@ -524,6 +527,7 @@ Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
eshell-mv-overwrite-files))))
(put 'eshell/mv 'eshell-no-numeric-conversions t)
+(put 'eshell/mv 'eshell-filename-arguments t)
(defun eshell/cp (&rest args)
"Implementation of cp in Lisp."
@@ -561,6 +565,7 @@ Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.")
eshell-cp-overwrite-files preserve)))
(put 'eshell/cp 'eshell-no-numeric-conversions t)
+(put 'eshell/cp 'eshell-filename-arguments t)
(defun eshell/ln (&rest args)
"Implementation of ln in Lisp."
@@ -593,6 +598,7 @@ with `--symbolic'. When creating hard links, each TARGET must exist.")
eshell-ln-overwrite-files))))
(put 'eshell/ln 'eshell-no-numeric-conversions t)
+(put 'eshell/ln 'eshell-filename-arguments t)
(defun eshell/cat (&rest args)
"Implementation of cat in Lisp.
@@ -645,6 +651,7 @@ Concatenate FILE(s), or standard input, to standard output.")
(setq eshell-ensure-newline-p nil))))
(put 'eshell/cat 'eshell-no-numeric-conversions t)
+(put 'eshell/cat 'eshell-filename-arguments t)
;; special front-end functions for compilation-mode buffers
@@ -927,6 +934,8 @@ Summarize disk usage of each FILE, recursively for directories.")
(eshell-print (concat (eshell-du-size-string size)
"total\n"))))))))
+(put 'eshell/du 'eshell-filename-arguments t)
+
(defvar eshell-time-start nil)
(defun eshell-show-elapsed-time ()
@@ -1029,6 +1038,7 @@ Show wall-clock time elapsed during execution of COMMAND.")
nil)
(put 'eshell/diff 'eshell-no-numeric-conversions t)
+(put 'eshell/diff 'eshell-filename-arguments t)
(defvar locate-history-list)
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 61c0ebc71d0..92cac612d4c 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -1304,27 +1304,36 @@ messages, and errors."
"Insert Lisp OBJECT, using ARGS if a function."
(catch 'eshell-external ; deferred to an external command
(let* ((eshell-ensure-newline-p (eshell-interactive-output-p))
- (result
- (if (functionp object)
- (progn
- (setq eshell-last-arguments args
- eshell-last-command-name
- (concat "#<function " (symbol-name object) ">"))
- ;; if any of the arguments are flagged as numbers
- ;; waiting for conversion, convert them now
- (unless (get object 'eshell-no-numeric-conversions)
- (while args
- (let ((arg (car args)))
- (if (and (stringp arg)
- (> (length arg) 0)
- (not (text-property-not-all
- 0 (length arg) 'number t arg)))
- (setcar args (string-to-number arg))))
- (setq args (cdr args))))
- (eshell-apply object eshell-last-arguments))
- (setq eshell-last-arguments args
- eshell-last-command-name "#<Lisp object>")
- (eshell-eval object))))
+ (result
+ (if (functionp object)
+ (progn
+ (setq eshell-last-arguments args
+ eshell-last-command-name
+ (concat "#<function " (symbol-name object) ">"))
+ (let ((numeric (not (get object
+ 'eshell-no-numeric-conversions)))
+ (fname-args (get object 'eshell-filename-arguments)))
+ (when (or numeric fname-args)
+ (while args
+ (let ((arg (car args)))
+ (cond ((and numeric (stringp arg) (> (length arg) 0)
+ (text-property-any 0 (length arg)
+ 'number t arg))
+ ;; If any of the arguments are
+ ;; flagged as numbers waiting for
+ ;; conversion, convert them now.
+ (setcar args (string-to-number arg)))
+ ((and fname-args (stringp arg)
+ (string-equal arg "~"))
+ ;; If any of the arguments match "~",
+ ;; prepend "./" to treat it as a
+ ;; regular file name.
+ (setcar args (concat "./" arg)))))
+ (setq args (cdr args)))))
+ (eshell-apply object eshell-last-arguments))
+ (setq eshell-last-arguments args
+ eshell-last-command-name "#<Lisp object>")
+ (eshell-eval object))))
(if (and eshell-ensure-newline-p
(save-excursion
(goto-char eshell-last-output-end)
diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el
index ba5182deb45..244cc7ff1f3 100644
--- a/lisp/eshell/esh-ext.el
+++ b/lisp/eshell/esh-ext.el
@@ -259,6 +259,7 @@ Adds the given PATH to $PATH.")
(eshell-printn dir)))))
(put 'eshell/addpath 'eshell-no-numeric-conversions t)
+(put 'eshell/addpath 'eshell-filename-arguments t)
(defun eshell-script-interpreter (file)
"Extract the script to run from FILE, if it has #!<interp> in it.
diff --git a/lisp/files.el b/lisp/files.el
index eabb3c0e06c..940bacde230 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1830,7 +1830,7 @@ killed."
;; Don't use `find-file' because it may end up using another window
;; in some corner cases, e.g. when the selected window is
;; softly-dedicated.
- (let ((newbuf (find-file-noselect filename wildcards)))
+ (let ((newbuf (find-file-noselect filename nil nil wildcards)))
(switch-to-buffer newbuf)))
(when (eq obuf (current-buffer))
;; This executes if find-file gets an error
@@ -1954,7 +1954,7 @@ started Emacs, set `abbreviated-home-dir' to nil so it will be recalculated)."
(save-match-data
(string-match "^[a-zA-`]:/$" filename))))
(equal (get 'abbreviated-home-dir 'home)
- (expand-file-name "~")))
+ (save-match-data (expand-file-name "~"))))
(setq filename
(concat "~"
(match-string 1 filename)
@@ -5091,6 +5091,9 @@ Before and after saving the buffer, this function runs
(make-directory dir t)
(error "Canceled")))
(setq setmodes (basic-save-buffer-1)))))
+ ;; We are hunting a nasty error, which happens on hydra.
+ ;; Adding traces might help.
+ (if (getenv "BUG_32226") (message "BUG_32226"))
;; Now we have saved the current buffer. Let's make sure
;; that buffer-file-coding-system is fixed to what
;; actually used for saving by binding it locally.
@@ -5519,6 +5522,21 @@ raised."
(dolist (dir create-list)
(files--ensure-directory dir)))))))
+(defun make-empty-file (filename &optional parents)
+ "Create an empty file FILENAME.
+Optional arg PARENTS, if non-nil then creates parent dirs as needed.
+
+If called interactively, then PARENTS is non-nil."
+ (interactive
+ (let ((filename (read-file-name "Create empty file: ")))
+ (list filename t)))
+ (when (and (file-exists-p filename) (null parents))
+ (signal 'file-already-exists `("File exists" ,filename)))
+ (let ((paren-dir (file-name-directory filename)))
+ (when (and paren-dir (not (file-exists-p paren-dir)))
+ (make-directory paren-dir parents)))
+ (write-region "" nil filename nil 0))
+
(defconst directory-files-no-dot-files-regexp
"^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
"Regexp matching any file name except \".\" and \"..\".")
diff --git a/lisp/format.el b/lisp/format.el
index 5bf1be39475..49d3c718abc 100644
--- a/lisp/format.el
+++ b/lisp/format.el
@@ -539,6 +539,8 @@ Compare using `equal'."
(setq tail next)))
(cons acopy bcopy)))
+(define-obsolete-function-alias 'format-proper-list-p 'proper-list-p "27.1")
+
(defun format-reorder (items order)
"Arrange ITEMS to follow partial ORDER.
Elements of ITEMS equal to elements of ORDER will be rearranged
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index 055f02fb1ab..1b0dde94551 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -1626,6 +1626,12 @@ resources when reading email groups (and therefore stops
tracking), but allows loading external resources when reading
from NNTP newsgroups and the like.
+People controlling these external resources won't be able to tell
+that any one person in particular has read the message (since
+it's in a public venue, many people will end up loading that
+resource), but they'll be able to tell that somebody from your IP
+address has accessed the resource.
+
This can also be a function to be evaluated. If so, it will be
called with the group name as the parameter, and should return a
regexp."
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index e562b30170a..ceb98421665 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -4310,10 +4310,10 @@ If SELECT-ARTICLES, only select those articles from GROUP."
If FORCE-NEW is not nil, enter HEADER into the DEPENDENCIES table even
if it was already present.
-If `gnus-summary-ignore-duplicates' is nil then duplicate Message-IDs
-will not be entered in the DEPENDENCIES table. Otherwise duplicate
-Message-IDs will be renamed to a unique Message-ID before being
-entered.
+If `gnus-summary-ignore-duplicates' is non-nil then duplicate
+Message-IDs will not be entered in the DEPENDENCIES table.
+Otherwise duplicate Message-IDs will be renamed to a unique
+Message-ID before being entered.
Returns HEADER if it was entered in the DEPENDENCIES. Returns nil otherwise."
(let* ((id (mail-header-id header))
diff --git a/lisp/ielm.el b/lisp/ielm.el
index b4ad69e4c72..8d1efcdc3bf 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -612,17 +612,19 @@ Customized bindings may be defined in `ielm-map', which currently contains:
;;; User command
;;;###autoload
-(defun ielm nil
+(defun ielm (&optional buf-name)
"Interactively evaluate Emacs Lisp expressions.
-Switches to the buffer `*ielm*', or creates it if it does not exist.
+Switches to the buffer named BUF-NAME if provided (`*ielm*' by default),
+or creates it if it does not exist.
See `inferior-emacs-lisp-mode' for details."
(interactive)
- (let (old-point)
- (unless (comint-check-proc "*ielm*")
- (with-current-buffer (get-buffer-create "*ielm*")
+ (let (old-point
+ (buf-name (or buf-name "*ielm*")))
+ (unless (comint-check-proc buf-name)
+ (with-current-buffer (get-buffer-create buf-name)
(unless (zerop (buffer-size)) (setq old-point (point)))
(inferior-emacs-lisp-mode)))
- (pop-to-buffer-same-window "*ielm*")
+ (pop-to-buffer-same-window buf-name)
(when old-point (push-mark old-point))))
(provide 'ielm)
diff --git a/lisp/imenu.el b/lisp/imenu.el
index edca51e3ade..7285b105748 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -832,15 +832,14 @@ depending on PATTERNS."
(dolist (item index-alist)
(when (listp item)
(setcdr item (sort (cdr item) 'imenu--sort-by-position))))
- (let ((main-element (assq nil index-alist)))
- (nconc (delq main-element (delq 'dummy index-alist))
- (cdr main-element)))
;; Remove any empty menus. That can happen because of skipping
;; things inside comments or strings.
- (when (consp (car index-alist))
- (setq index-alist (cl-delete-if-not
- (lambda (it) (cdr it))
- index-alist)))))
+ (setq index-alist (cl-delete-if
+ (lambda (it) (and (consp it) (null (cdr it))))
+ index-alist))
+ (let ((main-element (assq nil index-alist)))
+ (nconc (delq main-element (delq 'dummy index-alist))
+ (cdr main-element)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
diff --git a/lisp/indent.el b/lisp/indent.el
index 450632174fc..73a7d0ef4eb 100644
--- a/lisp/indent.el
+++ b/lisp/indent.el
@@ -292,7 +292,8 @@ indentation by specifying a large negative ARG."
"Indent current line to COLUMN.
This function removes or adds spaces and tabs at beginning of line
only if necessary. It leaves point at end of indentation."
- (back-to-indentation)
+ (beginning-of-line 1)
+ (skip-chars-forward " \t")
(let ((cur-col (current-column)))
(cond ((< cur-col column)
(if (>= (- column (* (/ cur-col tab-width) tab-width)) tab-width)
@@ -303,8 +304,10 @@ only if necessary. It leaves point at end of indentation."
(delete-region (progn (move-to-column column t) (point))
;; The `move-to-column' call may replace
;; tabs with spaces, so we can't reuse the
- ;; previous `back-to-indentation' point.
- (progn (back-to-indentation) (point)))))))
+ ;; previous start point.
+ (progn (beginning-of-line 1)
+ (skip-chars-forward " \t")
+ (point)))))))
(defun current-left-margin ()
"Return the left margin to use for this line.
diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el
index a023d4fbc85..d4ade3cc4c0 100644
--- a/lisp/international/fontset.el
+++ b/lisp/international/fontset.el
@@ -79,7 +79,7 @@
("cns11643.92p7-0" . chinese-cns11643-7)
("big5" . big5)
("viscii" . viscii)
- ("tis620" . tis620-2533)
+ ("tis620" . thai-iso8859-11)
("microsoft-cp1251" . windows-1251)
("koi8-r" . koi8-r)
("jisx0213.2000-1" . japanese-jisx0213-1)
@@ -139,7 +139,7 @@
(cyrillic-iso8859-5 . iso-8859-5)
(greek-iso8859-7 . iso-8859-7)
(arabic-iso8859-6 . iso-8859-6)
- (thai-tis620 . tis620-2533)
+ (thai-tis620 . thai-iso8859-11)
(latin-jisx0201 . jisx0201)
(katakana-jisx0201 . jisx0201)
(chinese-big5-1 . big5)
@@ -1233,11 +1233,12 @@ Done when `mouse-set-font' is called."
(latin-iso8859-15 . latin)
(latin-iso8859-16 . latin)
(latin-jisx0201 . latin)
+ (thai-iso8859-11 . thai)
(thai-tis620 . thai)
(cyrillic-iso8859-5 . cyrillic)
(arabic-iso8859-6 . arabic)
- (greek-iso8859-7 . latin)
- (hebrew-iso8859-8 . latin)
+ (greek-iso8859-7 . greek)
+ (hebrew-iso8859-8 . hebrew)
(katakana-jisx0201 . kana)
(chinese-gb2312 . han)
(chinese-gbk . han)
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index cf6a8c78d09..2bde83f4eab 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -300,8 +300,7 @@ wrong, use this command again to toggle back to the right mode."
(cmd (key-binding keyseq))
prefix)
;; read-key-sequence ignores quit, so make an explicit check.
- ;; Like many places, this assumes quit == C-g, but it need not be.
- (if (equal last-input-event ?\C-g)
+ (if (equal last-input-event (nth 3 (current-input-mode)))
(keyboard-quit))
(when (memq cmd '(universal-argument digit-argument))
(call-interactively cmd)
@@ -314,16 +313,16 @@ wrong, use this command again to toggle back to the right mode."
(let ((current-prefix-arg prefix-arg)
;; Have to bind `last-command-event' here so that
;; `digit-argument', for instance, can compute the
- ;; prefix arg.
+ ;; `prefix-arg'.
(last-command-event (aref keyseq 0)))
(call-interactively cmd)))
;; This is the final call to `universal-argument-other-key', which
- ;; set's the final `prefix-arg.
+ ;; sets the final `prefix-arg'.
(let ((current-prefix-arg prefix-arg))
(call-interactively cmd))
- ;; Read the command to execute with the given prefix arg.
+ ;; Read the command to execute with the given `prefix-arg'.
(setq prefix prefix-arg
keyseq (read-key-sequence nil t)
cmd (key-binding keyseq)))
diff --git a/lisp/international/mule-conf.el b/lisp/international/mule-conf.el
index dc095707a2c..a635c677705 100644
--- a/lisp/international/mule-conf.el
+++ b/lisp/international/mule-conf.el
@@ -201,6 +201,7 @@
;; plus nbsp
(define-iso-single-byte-charset 'iso-8859-11 'thai-iso8859-11
"ISO/IEC 8859/11" "Latin/Thai" 166 ?T nil "8859-11")
+(define-charset-alias 'tis620-2533 'thai-iso8859-11)
;; 8859-12 doesn't (yet?) exist.
@@ -229,14 +230,6 @@
:code-space [32 127]
:code-offset #x0E00)
-;; Fixme: doc for this, c.f. above
-(define-charset 'tis620-2533
- "TIS620.2533"
- :short-name "TIS620.2533"
- :ascii-compatible-p t
- :code-space [0 255]
- :superset '(ascii eight-bit-control (thai-tis620 . 128)))
-
(define-charset 'jisx0201
"JISX0201"
:short-name "JISX0201"
diff --git a/lisp/international/mule-diag.el b/lisp/international/mule-diag.el
index 87a2e993bb4..c9829e352ec 100644
--- a/lisp/international/mule-diag.el
+++ b/lisp/international/mule-diag.el
@@ -355,7 +355,8 @@ meanings of these arguments."
(:iso-revision-number "ISO revision number: "
number-to-string)
(:supplementary-p
- "Used only as a parent of some other charset." nil)))
+ "Used only as a parent or a subset of some other charset,
+or provided just for backward compatibility." nil)))
(let ((val (get-charset-property charset (car elt))))
(when val
(if (cadr elt) (insert (cadr elt)))
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index eece836354c..ec15ccaaf76 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -1394,12 +1394,13 @@ Return the input string."
(generated-events nil) ;FIXME: What is this?
(input-method-function nil)
(modified-p (buffer-modified-p))
- last-command-event last-command this-command)
+ last-command-event last-command this-command inhibit-record)
(setq quail-current-key ""
quail-current-str ""
quail-translating t)
(if key
- (setq unread-command-events (cons key unread-command-events)))
+ (setq unread-command-events (cons key unread-command-events)
+ inhibit-record t))
(while quail-translating
(set-buffer-modified-p modified-p)
(quail-show-guidance)
@@ -1408,8 +1409,13 @@ Return the input string."
(or input-method-previous-message "")
quail-current-str
quail-guidance-str)))
+ ;; We inhibit record_char only for the first key,
+ ;; because it was already recorded before read_char
+ ;; called quail-input-method.
+ (inhibit--record-char inhibit-record)
(keyseq (read-key-sequence prompt nil nil t))
(cmd (lookup-key (quail-translation-keymap) keyseq)))
+ (setq inhibit-record nil)
(if (if key
(and (commandp cmd) (not (eq cmd 'quail-other-command)))
(eq cmd 'quail-self-insert-command))
@@ -1453,14 +1459,15 @@ Return the input string."
(generated-events nil) ;FIXME: What is this?
(input-method-function nil)
(modified-p (buffer-modified-p))
- last-command-event last-command this-command)
+ last-command-event last-command this-command inhibit-record)
(setq quail-current-key ""
quail-current-str ""
quail-translating t
quail-converting t
quail-conversion-str "")
(if key
- (setq unread-command-events (cons key unread-command-events)))
+ (setq unread-command-events (cons key unread-command-events)
+ inhibit-record t))
(while quail-converting
(set-buffer-modified-p modified-p)
(or quail-translating
@@ -1476,8 +1483,13 @@ Return the input string."
quail-conversion-str
quail-current-str
quail-guidance-str)))
+ ;; We inhibit record_char only for the first key,
+ ;; because it was already recorded before read_char
+ ;; called quail-input-method.
+ (inhibit--record-char inhibit-record)
(keyseq (read-key-sequence prompt nil nil t))
(cmd (lookup-key (quail-conversion-keymap) keyseq)))
+ (setq inhibit-record nil)
(if (if key (commandp cmd) (eq cmd 'quail-self-insert-command))
(progn
(setq last-command-event (aref keyseq (1- (length keyseq)))
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el
index b2ccea5c143..a137616ecae 100644
--- a/lisp/jsonrpc.el
+++ b/lisp/jsonrpc.el
@@ -6,7 +6,7 @@
;; Maintainer: João Távora <joaotavora@gmail.com>
;; Keywords: processes, languages, extensions
;; Package-Requires: ((emacs "25.2"))
-;; Version: 1.0.0
+;; Version: 1.0.2
;; This is an Elpa :core package. Don't use functionality that is not
;; compatible with Emacs 25.2.
@@ -74,7 +74,11 @@
:documentation "A hash table of request ID to continuation lambdas.")
(-events-buffer
:accessor jsonrpc--events-buffer
- :documentation "A buffer pretty-printing the JSON-RPC RPC events")
+ :documentation "A buffer pretty-printing the JSONRPC events")
+ (-events-buffer-scrollback-size
+ :initarg :events-buffer-scrollback-size
+ :accessor jsonrpc--events-buffer-scrollback-size
+ :documentation "If non-nil, maximum size of events buffer.")
(-deferred-actions
:initform (make-hash-table :test #'equal)
:accessor jsonrpc--deferred-actions
@@ -193,9 +197,7 @@ dispatcher in CONNECTION."
(when timer (cancel-timer timer)))
(remhash id (jsonrpc--request-continuations connection))
(if error (funcall (nth 1 continuations) error)
- (funcall (nth 0 continuations) result)))
- (;; An abnormal situation
- id (jsonrpc--warn "No continuation for id %s" id)))
+ (funcall (nth 0 continuations) result))))
(jsonrpc--call-deferred connection))))
@@ -256,17 +258,30 @@ Returns nil."
(apply #'jsonrpc--async-request-1 connection method params args)
nil)
-(cl-defun jsonrpc-request (connection method params &key deferred timeout)
+(cl-defun jsonrpc-request (connection
+ method params &key
+ deferred timeout
+ cancel-on-input
+ cancel-on-input-retval)
"Make a request to CONNECTION, wait for a reply.
Like `jsonrpc-async-request' for CONNECTION, METHOD and PARAMS,
-but synchronous, i.e. this function doesn't exit until anything
-interesting (success, error or timeout) happens. Furthermore, it
-only exits locally (returning the JSONRPC result object) if the
-request is successful, otherwise exit non-locally with an error
-of type `jsonrpc-error'.
+but synchronous.
-DEFERRED is passed to `jsonrpc-async-request', which see."
+Except in the case of a non-nil CANCEL-ON-INPUT (explained
+below), this function doesn't exit until anything interesting
+happens (success reply, error reply, or timeout). Furthermore,
+it only exits locally (returning the JSONRPC result object) if
+the request is successful, otherwise it exits non-locally with an
+error of type `jsonrpc-error'.
+
+DEFERRED is passed to `jsonrpc-async-request', which see.
+
+If CANCEL-ON-INPUT is non-nil and the user inputs something while
+the functino is waiting, then it exits immediately, returning
+CANCEL-ON-INPUT-RETVAL. Any future replies (normal or error) are
+ignored."
(let* ((tag (cl-gensym "jsonrpc-request-catch-tag")) id-and-timer
+ cancelled
(retval
(unwind-protect ; protect against user-quit, for example
(catch tag
@@ -274,19 +289,27 @@ DEFERRED is passed to `jsonrpc-async-request', which see."
id-and-timer
(jsonrpc--async-request-1
connection method params
- :success-fn (lambda (result) (throw tag `(done ,result)))
+ :success-fn (lambda (result)
+ (unless cancelled
+ (throw tag `(done ,result))))
:error-fn
(jsonrpc-lambda
(&key code message data)
- (throw tag `(error (jsonrpc-error-code . ,code)
- (jsonrpc-error-message . ,message)
- (jsonrpc-error-data . ,data))))
+ (unless cancelled
+ (throw tag `(error (jsonrpc-error-code . ,code)
+ (jsonrpc-error-message . ,message)
+ (jsonrpc-error-data . ,data)))))
:timeout-fn
(lambda ()
- (throw tag '(error (jsonrpc-error-message . "Timed out"))))
+ (unless cancelled
+ (throw tag '(error (jsonrpc-error-message . "Timed out")))))
:deferred deferred
:timeout timeout))
- (while t (accept-process-output nil 30)))
+ (cond (cancel-on-input
+ (while (sit-for 30))
+ (setq cancelled t)
+ `(cancelled ,cancel-on-input-retval))
+ (t (while t (accept-process-output nil 30)))))
(pcase-let* ((`(,id ,timer) id-and-timer))
(remhash id (jsonrpc--request-continuations connection))
(remhash (list deferred (current-buffer))
@@ -641,15 +664,26 @@ originated."
(if type
(format "-%s" subtype)))))
(goto-char (point-max))
- (let ((msg (format "%s%s%s %s:\n%s\n"
- type
- (if id (format " (id:%s)" id) "")
- (if error " ERROR" "")
- (current-time-string)
- (pp-to-string message))))
- (when error
- (setq msg (propertize msg 'face 'error)))
- (insert-before-markers msg))))))
+ (prog1
+ (let ((msg (format "%s%s%s %s:\n%s\n"
+ type
+ (if id (format " (id:%s)" id) "")
+ (if error " ERROR" "")
+ (current-time-string)
+ (pp-to-string message))))
+ (when error
+ (setq msg (propertize msg 'face 'error)))
+ (insert-before-markers msg))
+ ;; Trim the buffer if it's too large
+ (let ((max (jsonrpc--events-buffer-scrollback-size connection)))
+ (when max
+ (save-excursion
+ (goto-char (point-min))
+ (while (> (buffer-size) max)
+ (delete-region (point) (progn (forward-line 1)
+ (forward-sexp 1)
+ (forward-line 2)
+ (point))))))))))))
(provide 'jsonrpc)
;;; jsonrpc.el ends here
diff --git a/lisp/language/thai.el b/lisp/language/thai.el
index a896fe59fd1..c655845e95d 100644
--- a/lisp/language/thai.el
+++ b/lisp/language/thai.el
@@ -36,7 +36,7 @@
"8-bit encoding for ASCII (MSB=0) and Thai TIS620 (MSB=1)."
:coding-type 'charset
:mnemonic ?T
- :charset-list '(tis620-2533))
+ :charset-list '(thai-iso8859-11))
(define-coding-system-alias 'th-tis620 'thai-tis620)
(define-coding-system-alias 'tis620 'thai-tis620)
@@ -47,7 +47,7 @@
(charset thai-tis620)
(coding-system thai-tis620 iso-8859-11 cp874)
(coding-priority thai-tis620)
- (nonascii-translation . tis620-2533)
+ (nonascii-translation . iso-8859-11)
(input-method . "thai-kesmanee")
(unibyte-display . thai-tis620)
(features thai-util)
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index 5f26eba695e..3bd775f5152 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -176,12 +176,18 @@ Optional arg BUFFER-FILE overrides `buffer-file-name'.
\(fn &optional FILE-NAME BUFFER-FILE)" nil nil)
(autoload 'add-change-log-entry "add-log" "\
-Find change log file, and add an entry for today and an item for this file.
-Optional arg WHOAMI (interactive prefix) non-nil means prompt for user
-name and email (stored in `add-log-full-name' and `add-log-mailing-address').
-
-Second arg FILE-NAME is file name of the change log.
-If nil, use the value of `change-log-default-name'.
+Find ChangeLog buffer, add an entry for today and an item for this file.
+Optional arg WHOAMI (interactive prefix) non-nil means prompt for
+user name and email (stored in `add-log-full-name'
+and `add-log-mailing-address').
+
+Second arg CHANGELOG-FILE-NAME is the file name of the change log.
+If nil, use the value of `change-log-default-name'. If the file
+thus named exists, it is used for the new entry. If it doesn't
+exist, it is created, unless `add-log-dont-create-changelog-file' is t,
+in which case a suitably named buffer that doesn't visit any file
+is used for keeping entries pertaining to CHANGELOG-FILE-NAME's
+directory.
Third arg OTHER-WINDOW non-nil means visit in other window.
@@ -204,7 +210,7 @@ notices.
Today's date is calculated according to `add-log-time-zone-rule' if
non-nil, otherwise in local time.
-\(fn &optional WHOAMI FILE-NAME OTHER-WINDOW NEW-ENTRY PUT-NEW-ENTRY-ON-NEW-LINE)" t nil)
+\(fn &optional WHOAMI CHANGELOG-FILE-NAME OTHER-WINDOW NEW-ENTRY PUT-NEW-ENTRY-ON-NEW-LINE)" t nil)
(autoload 'add-change-log-entry-other-window "add-log" "\
Find change log file in other window and add entry and item.
@@ -577,9 +583,11 @@ Return t if `allout-mode' is active in current buffer.
(autoload 'allout-mode "allout" "\
Toggle Allout outline mode.
-With a prefix argument ARG, enable Allout outline mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Allout mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\\<allout-mode-map-value>
Allout outline mode is a minor mode that provides extensive
@@ -890,9 +898,11 @@ See `allout-widgets-mode' for allout widgets mode features.")
(autoload 'allout-widgets-mode "allout-widgets" "\
Toggle Allout Widgets mode.
-With a prefix argument ARG, enable Allout Widgets mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Allout-Widgets mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Allout Widgets mode is an extension of Allout mode that provides
graphical decoration of outline structure. It is meant to
@@ -1300,7 +1310,12 @@ Entering array mode calls the function `array-mode-hook'.
(autoload 'artist-mode "artist" "\
Toggle Artist mode.
-With argument ARG, turn Artist mode on if ARG is positive.
+
+If called interactively, enable Artist mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
Artist lets you draw lines, squares, rectangles and poly-lines,
ellipses and circles with your mouse and/or keyboard.
@@ -1571,9 +1586,6 @@ for a description of this minor mode.")
(autoload 'autoarg-mode "autoarg" "\
Toggle Autoarg mode, a global minor mode.
-With a prefix argument ARG, enable Autoarg mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
\\<autoarg-mode-map>
In Autoarg mode, digits are bound to `digit-argument', i.e. they
@@ -1607,9 +1619,11 @@ or call the function `autoarg-kp-mode'.")
(autoload 'autoarg-kp-mode "autoarg" "\
Toggle Autoarg-KP mode, a global minor mode.
-With a prefix argument ARG, enable Autoarg-KP mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Autoarg-Kp mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\\<autoarg-kp-mode-map>
This is similar to `autoarg-mode' but rebinds the keypad keys
@@ -1663,9 +1677,11 @@ or call the function `auto-insert-mode'.")
(autoload 'auto-insert-mode "autoinsert" "\
Toggle Auto-insert mode, a global minor mode.
-With a prefix argument ARG, enable Auto-insert mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Auto-Insert mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Auto-insert mode is enabled, when new files are created you can
insert a template for the file depending on the mode of the buffer.
@@ -1735,9 +1751,11 @@ should be non-nil).
(autoload 'auto-revert-mode "autorevert" "\
Toggle reverting buffer when the file changes (Auto-Revert Mode).
-With a prefix argument ARG, enable Auto-Revert Mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Auto-Revert mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Auto-Revert Mode is a minor mode that affects only the current
buffer. When enabled, it reverts the buffer when the file on
@@ -1762,9 +1780,11 @@ This function is designed to be added to hooks, for example:
(autoload 'auto-revert-tail-mode "autorevert" "\
Toggle reverting tail of buffer when the file grows.
-With a prefix argument ARG, enable Auto-Revert Tail Mode if ARG
-is positive, and disable it otherwise. If called from Lisp,
-enable the mode if ARG is omitted or nil.
+
+If called interactively, enable Auto-Revert-Tail mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Auto-Revert Tail Mode is enabled, the tail of the file is
constantly followed, as with the shell command `tail -f'. This
@@ -1803,9 +1823,11 @@ or call the function `global-auto-revert-mode'.")
(autoload 'global-auto-revert-mode "autorevert" "\
Toggle Global Auto-Revert Mode.
-With a prefix argument ARG, enable Global Auto-Revert Mode if ARG
-is positive, and disable it otherwise. If called from Lisp,
-enable the mode if ARG is omitted or nil.
+
+If called interactively, enable Global Auto-Revert mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Global Auto-Revert Mode is a global minor mode that reverts any
buffer associated with a file when the file changes on disk. Use
@@ -1921,9 +1943,11 @@ or call the function `display-battery-mode'.")
(autoload 'display-battery-mode "battery" "\
Toggle battery status display in mode line (Display Battery mode).
-With a prefix argument ARG, enable Display Battery mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Display-Battery mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
The text displayed in the mode line is controlled by
`battery-mode-line-format' and `battery-status-function'.
@@ -2331,7 +2355,7 @@ BOOKMARK is usually a bookmark name (a string). It can also be a
bookmark record, but this is usually only done by programmatic callers.
If DISPLAY-FUNC is non-nil, it is a function to invoke to display the
-bookmark. It defaults to `switch-to-buffer'. A typical value for
+bookmark. It defaults to `pop-to-buffer-same-window'. A typical value for
DISPLAY-FUNC would be `switch-to-buffer-other-window'.
\(fn BOOKMARK &optional DISPLAY-FUNC)" t nil)
@@ -2897,15 +2921,22 @@ columns on its right towards the left.
(autoload 'bug-reference-mode "bug-reference" "\
Toggle hyperlinking bug references in the buffer (Bug Reference mode).
-With a prefix argument ARG, enable Bug Reference mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Bug-Reference mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
(autoload 'bug-reference-prog-mode "bug-reference" "\
Like `bug-reference-mode', but only buttonize in comments and strings.
+If called interactively, enable Bug-Reference-Prog mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bug-reference" '("bug-reference-")))
@@ -4691,9 +4722,11 @@ Prefix argument is the same as for `checkdoc-defun'
(autoload 'checkdoc-minor-mode "checkdoc" "\
Toggle automatic docstring checking (Checkdoc minor mode).
-With a prefix argument ARG, enable Checkdoc minor mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Checkdoc minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
In Checkdoc minor mode, the usual bindings for `eval-defun' which is
bound to \\<checkdoc-minor-mode-map>\\[checkdoc-eval-defun] and `checkdoc-eval-current-buffer' are overridden to include
@@ -4933,6 +4966,11 @@ This can be needed when using code byte-compiled using the old
macro-expansion of `cl-defstruct' that used vectors objects instead
of record objects.
+If called interactively, enable Cl-Old-Struct-Compat mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cl-lib" '("cl-")))
@@ -5150,7 +5188,7 @@ REGEXP-GROUP is the regular expression group in REGEXP to use.
\(fn PROCESS COMMAND REGEXP REGEXP-GROUP)" nil nil)
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "comint" '("comint-" "send-invisible" "shell-strip-ctrl-m")))
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "comint" '("comint-")))
;;;***
@@ -5346,9 +5384,11 @@ Runs `compilation-mode-hook' with `run-mode-hooks' (which see).
(autoload 'compilation-shell-minor-mode "compile" "\
Toggle Compilation Shell minor mode.
-With a prefix argument ARG, enable Compilation Shell minor mode
-if ARG is positive, and disable it otherwise. If called from
-Lisp, enable the mode if ARG is omitted or nil.
+
+If called interactively, enable Compilation-Shell minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Compilation Shell minor mode is enabled, all the
error-parsing commands of the Compilation major mode are
@@ -5359,9 +5399,11 @@ See `compilation-mode'.
(autoload 'compilation-minor-mode "compile" "\
Toggle Compilation minor mode.
-With a prefix argument ARG, enable Compilation minor mode if ARG
-is positive, and disable it otherwise. If called from Lisp,
-enable the mode if ARG is omitted or nil.
+
+If called interactively, enable Compilation minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Compilation minor mode is enabled, all the error-parsing
commands of Compilation major mode are available. See
@@ -5394,9 +5436,11 @@ or call the function `dynamic-completion-mode'.")
(autoload 'dynamic-completion-mode "completion" "\
Toggle dynamic word-completion on or off.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Dynamic-Completion mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -5959,9 +6003,11 @@ or call the function `cua-mode'.")
(autoload 'cua-mode "cua-base" "\
Toggle Common User Access style editing (CUA mode).
-With a prefix argument ARG, enable CUA mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Cua mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
CUA mode is a global minor mode. When enabled, typed text
replaces the active selection, and you can use C-z, C-x, C-c, and
@@ -6006,6 +6052,11 @@ Enable CUA selection mode without the C-z/C-x/C-c/C-v bindings.
Toggle the region as rectangular.
Activates the region if needed. Only lasts until the region is deactivated.
+If called interactively, enable Cua-Rectangle-Mark mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cua-rect" '("cua-")))
@@ -6021,6 +6072,11 @@ Activates the region if needed. Only lasts until the region is deactivated.
(autoload 'cursor-intangible-mode "cursor-sensor" "\
Keep cursor outside of any `cursor-intangible' text property.
+If called interactively, enable Cursor-Intangible mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(autoload 'cursor-sensor-mode "cursor-sensor" "\
@@ -6031,6 +6087,11 @@ where WINDOW is the affected window, OLDPOS is the last known position of
the cursor and DIR can be `entered' or `left' depending on whether the cursor
is entering the area covered by the text-property property or leaving it.
+If called interactively, enable Cursor-Sensor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "cursor-sensor" '("cursor-sensor-")))
@@ -6421,16 +6482,17 @@ Mode used for cvs status output.
(autoload 'cwarn-mode "cwarn" "\
Minor mode that highlights suspicious C and C++ constructions.
+If called interactively, enable Cwarn mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
Suspicious constructs are highlighted using `font-lock-warning-face'.
Note, in addition to enabling this minor mode, the major mode must
be included in the variable `cwarn-configuration'. By default C and
C++ modes are included.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
-
\(fn &optional ARG)" t nil)
(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "24.1")
@@ -6849,12 +6911,11 @@ or call the function `delete-selection-mode'.")
(autoload 'delete-selection-mode "delsel" "\
Toggle Delete Selection mode.
-Interactively, with a prefix argument, enable
-Delete Selection mode if the prefix argument is positive,
-and disable it otherwise. If called from Lisp, toggle
-the mode if ARG is `toggle', disable the mode if ARG is
-a non-positive integer, and enable the mode otherwise
-\(including if ARG is omitted or nil or a positive integer).
+
+If called interactively, enable Delete-Selection mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Delete Selection mode is enabled, typed text replaces the selection
if the selection is active. Otherwise, typed text is just inserted at
@@ -7006,9 +7067,11 @@ or call the function `desktop-save-mode'.")
(autoload 'desktop-save-mode "desktop" "\
Toggle desktop saving (Desktop Save mode).
-With a prefix argument ARG, enable Desktop Save mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode if ARG
-is omitted or nil.
+
+If called interactively, enable Desktop-Save mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Desktop Save mode is enabled, the state of Emacs is saved from
one session to another. In particular, Emacs will save the desktop when
@@ -7371,9 +7434,11 @@ a diff with \\[diff-reverse-direction].
(autoload 'diff-minor-mode "diff-mode" "\
Toggle Diff minor mode.
-With a prefix argument ARG, enable Diff minor mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Diff minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\\{diff-minor-mode-map}
@@ -7549,9 +7614,11 @@ Keybindings:
(autoload 'dirtrack-mode "dirtrack" "\
Toggle directory tracking in shell buffers (Dirtrack mode).
-With a prefix argument ARG, enable Dirtrack mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Dirtrack mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
This method requires that your shell prompt contain the current
working directory at all times, and that you set the variable
@@ -7723,6 +7790,11 @@ in `.emacs'.
Toggle display of line numbers in the buffer.
This uses `display-line-numbers' internally.
+If called interactively, enable Display-Line-Numbers mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
To change the type of line numbers displayed by default,
customize `display-line-numbers-type'. To change the type while
the mode is on, set `display-line-numbers' directly.
@@ -7856,9 +7928,11 @@ to the next best mode.
(autoload 'doc-view-minor-mode "doc-view" "\
Toggle displaying buffer via Doc View (Doc View minor mode).
-With a prefix argument ARG, enable Doc View minor mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Doc-View minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
See the command `doc-view-mode' for more information on this mode.
@@ -7918,9 +7992,11 @@ Switch to *doctor* buffer and start giving psychotherapy.
(autoload 'double-mode "double" "\
Toggle special insertion on double keypresses (Double mode).
-With a prefix argument ARG, enable Double mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Double mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Double mode is enabled, some keys will insert different
strings when pressed twice. See `double-map' for details.
@@ -7975,7 +8051,9 @@ non-positive integer, and enables the mode otherwise (including
if the argument is omitted or nil or a positive integer).
If DOC is nil, give the mode command a basic doc-string
-documenting what its argument does.
+documenting what its argument does. If the word \"ARG\" does not
+appear in DOC, a paragraph is added to DOC explaining
+usage of the mode argument.
Optional INIT-VALUE is the initial value of the mode's variable.
Optional LIGHTER is displayed in the mode line when the mode is on.
@@ -8785,9 +8863,11 @@ or call the function `global-ede-mode'.")
(autoload 'global-ede-mode "ede" "\
Toggle global EDE (Emacs Development Environment) mode.
-With a prefix argument ARG, enable global EDE mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Global Ede mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
This global minor mode enables `ede-minor-mode' in all buffers in
an EDE controlled project.
@@ -9797,9 +9877,11 @@ or call the function `electric-pair-mode'.")
(autoload 'electric-pair-mode "elec-pair" "\
Toggle automatic parens pairing (Electric Pair mode).
-With a prefix argument ARG, enable Electric Pair mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Electric-Pair mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Electric Pair mode is a global minor mode. When enabled, typing
an open parenthesis automatically inserts the corresponding
@@ -9814,6 +9896,11 @@ To toggle the mode in a single buffer, use `electric-pair-local-mode'.
(autoload 'electric-pair-local-mode "elec-pair" "\
Toggle `electric-pair-mode' only in this buffer.
+If called interactively, enable Electric-Pair-Local mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "elec-pair" '("electric-pair-")))
@@ -10053,9 +10140,7 @@ displayed.
(autoload 'emacs-lock-mode "emacs-lock" "\
Toggle Emacs Lock mode in the current buffer.
If called with a plain prefix argument, ask for the locking mode
-to be used. With any other prefix ARG, turn mode on if ARG is
-positive, off otherwise. If called from Lisp, enable the mode if
-ARG is omitted or nil.
+to be used.
Initially, if the user does not pass an explicit locking mode, it
defaults to `emacs-lock-default-locking-mode' (which see);
@@ -10070,6 +10155,9 @@ When called from Elisp code, ARG can be any locking mode:
Other values are interpreted as usual.
+See also `emacs-lock-unlockable-modes', which exempts buffers under
+some major modes from being locked under some circumstances.
+
\(fn &optional ARG)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "emacs-lock" '("emacs-lock-" "toggle-emacs-lock")))
@@ -10161,9 +10249,10 @@ Minor mode for editing text/enriched files.
These are files with embedded formatting information in the MIME standard
text/enriched format.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+If called interactively, enable Enriched mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Turning the mode on or off runs `enriched-mode-hook'.
@@ -10432,9 +10521,11 @@ Encrypt marked files.
(autoload 'epa-mail-mode "epa-mail" "\
A minor-mode for composing encrypted/clearsigned mails.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable epa-mail mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -10497,9 +10588,11 @@ or call the function `epa-global-mail-mode'.")
(autoload 'epa-global-mail-mode "epa-mail" "\
Minor mode to hook EasyPG into Mail mode.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Epa-Global-Mail mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -10545,8 +10638,13 @@ Return a list of internal configuration parameters of `epg-gpg-program'.
(autoload 'epg-check-configuration "epg-config" "\
Verify that a sufficient version of GnuPG is installed.
+CONFIG should be a `epg-configuration' object (a plist).
+REQ-VERSIONS should be a list with elements of the form (MIN
+. MAX) where MIN and MAX are version strings indicating a
+semi-open range of acceptable versions. REQ-VERSIONS may also be
+a single minimum version string.
-\(fn CONFIG &optional MINIMUM-VERSION)" nil nil)
+\(fn CONFIG &optional REQ-VERSIONS)" nil nil)
(autoload 'epg-expand-group "epg-config" "\
Look at CONFIG and try to expand GROUP.
@@ -12087,10 +12185,14 @@ a top-level keymap, `text-scale-increase' or
(autoload 'buffer-face-mode "face-remap" "\
Minor mode for a buffer-specific default face.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil. When enabled, the face specified by the
-variable `buffer-face-mode-face' is used to display the buffer text.
+
+If called interactively, enable Buffer-Face mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
+When enabled, the face specified by the variable
+`buffer-face-mode-face' is used to display the buffer text.
\(fn &optional ARG)" t nil)
@@ -12972,9 +13074,11 @@ region is invalid.
(autoload 'flymake-mode "flymake" "\
Toggle Flymake mode on or off.
-With a prefix argument ARG, enable Flymake mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'.
+
+If called interactively, enable Flymake mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Flymake is an Emacs minor mode for on-the-fly syntax checking.
Flymake collects diagnostic information from multiple sources,
@@ -13060,9 +13164,11 @@ Turn on `flyspell-mode' for comments and strings.
(autoload 'flyspell-mode "flyspell" "\
Toggle on-the-fly spell checking (Flyspell mode).
-With a prefix argument ARG, enable Flyspell mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Flyspell mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Flyspell mode is a buffer-local minor mode. When enabled, it
spawns a single Ispell process and checks each word. The default
@@ -13110,6 +13216,9 @@ Turn Flyspell mode off.
(autoload 'flyspell-region "flyspell" "\
Flyspell text between BEG and END.
+Make sure `flyspell-mode' is turned on if you want the highlight
+of a misspelled word removed when you've corrected it.
+
\(fn BEG END)" t nil)
(autoload 'flyspell-buffer "flyspell" "\
@@ -13144,9 +13253,11 @@ Turn off Follow mode. Please see the function `follow-mode'.
(autoload 'follow-mode "follow" "\
Toggle Follow mode.
-With a prefix argument ARG, enable Follow mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Follow mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Follow mode is a minor mode that combines windows into one tall
virtual window. This is accomplished by two main techniques:
@@ -13267,9 +13378,11 @@ selected if the original window is the first one in the frame.
(autoload 'footnote-mode "footnote" "\
Toggle Footnote mode.
-With a prefix argument ARG, enable Footnote mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Footnote mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Footnote mode is a buffer-local minor mode. If enabled, it
provides footnote support for `message-mode'. To get started,
@@ -13691,6 +13804,11 @@ being transferred. This list may grow up to a size of
`gdb-debug-log-max' after which the oldest element (at the end of
the list) is deleted every time a new one is added (at the front).
+If called interactively, enable Gdb-Enable-Debug mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(autoload 'gdb "gdb-mi" "\
@@ -13859,10 +13977,14 @@ regular expression that can be used as an element of
(autoload 'glasses-mode "glasses" "\
Minor mode for making identifiers likeThis readable.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil. When this mode is active, it tries to
-add virtual separators (like underscores) at places they belong to.
+
+If called interactively, enable Glasses mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
+When this mode is active, it tries to add virtual
+separators (like underscores) at places they belong to.
\(fn &optional ARG)" t nil)
@@ -14469,6 +14591,11 @@ If FORCE is non-nil, replace the old ones.
(autoload 'gnus-mailing-list-mode "gnus-ml" "\
Minor mode for providing mailing-list commands.
+If called interactively, enable Gnus-Mailing-List mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\\{gnus-mailing-list-mode-map}
\(fn &optional ARG)" t nil)
@@ -14889,7 +15016,14 @@ number with fewer than this number of bits, the handshake is
rejected. (The smaller the prime number, the less secure the
key exchange is against man-in-the-middle attacks.)
-A value of nil says to use the default GnuTLS value.")
+A value of nil says to use the default GnuTLS value.
+
+The default value of this variable is such that virtually any
+connection can be established, whether this connection can be
+considered cryptographically \"safe\" or not. However, Emacs
+network security is handled at a higher level via
+`open-network-stream' and the Network Security Manager. See Info
+node `(emacs) Network Security'.")
(custom-autoload 'gnutls-min-prime-bits "gnutls" t)
@@ -14951,15 +15085,22 @@ Also fontifies the buffer appropriately (see `goto-address-fontify-p' and
(autoload 'goto-address-mode "goto-addr" "\
Minor mode to buttonize URLs and e-mail addresses in the current buffer.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Goto-Address mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
(autoload 'goto-address-prog-mode "goto-addr" "\
Like `goto-address-mode', but only for comments and strings.
+If called interactively, enable Goto-Address-Prog mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "goto-addr" '("goto-address-")))
@@ -15017,7 +15158,7 @@ List of hook functions run by `grep-process-setup' (see `run-hooks').")
(custom-autoload 'grep-setup-hook "grep" t)
-(defconst grep-regexp-alist `((,(concat "^\\(?:" "\\(?1:[^\0\n]+\\)\\(?3:\0\\)\\(?2:[0-9]+\\):" "\\|" "\\(?1:[^\n:]+?[^\n/:]\\):[\11 ]*\\(?2:[1-9][0-9]*\\)[\11 ]*:" "\\)") 1 2 (,(lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face 'grep-match-face))) (when mbeg (- mbeg beg))))) \, (lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face 'grep-match-face)) (mend (and mbeg (next-single-property-change mbeg 'font-lock-face nil end)))) (when mend (- mend beg)))))) nil nil (3 '(face nil display ":"))) ("^Binary file \\(.+\\) matches$" 1 nil nil 0 1)) "\
+(defconst grep-regexp-alist `((,(concat "^\\(?:" "\\(?1:[^\0\n]+\\)\\(?3:\0\\)\\(?2:[0-9]+\\):" "\\|" "\\(?1:" "\\(?:[a-zA-Z]:\\)?" "[^\n:]+?[^\n/:]\\):[\11 ]*\\(?2:[1-9][0-9]*\\)[\11 ]*:" "\\)") 1 2 (,(lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face 'grep-match-face))) (when mbeg (- mbeg beg))))) \, (lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face 'grep-match-face)) (mend (and mbeg (next-single-property-change mbeg 'font-lock-face nil end)))) (when mend (- mend beg)))))) nil nil (3 '(face nil display ":"))) ("^Binary file \\(.+\\) matches$" 1 nil nil 0 1)) "\
Regexp used to match grep hits.
See `compilation-error-regexp-alist' for format details.")
@@ -15259,9 +15400,11 @@ or call the function `gud-tooltip-mode'.")
(autoload 'gud-tooltip-mode "gud" "\
Toggle the display of GUD tooltips.
-With a prefix argument ARG, enable the feature if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-it if ARG is omitted or nil.
+
+If called interactively, enable Gud-Tooltip mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -15944,9 +16087,11 @@ This discards the buffer's undo information.
(autoload 'hi-lock-mode "hi-lock" "\
Toggle selective highlighting of patterns (Hi Lock mode).
-With a prefix argument ARG, enable Hi Lock mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Hi-Lock mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Hi Lock mode is automatically enabled when you invoke any of the
highlighting commands listed below, such as \\[highlight-regexp].
@@ -16114,9 +16259,11 @@ be found in variable `hi-lock-interactive-patterns'.
(autoload 'hide-ifdef-mode "hideif" "\
Toggle features to hide/show #ifdef blocks (Hide-Ifdef mode).
-With a prefix argument ARG, enable Hide-Ifdef mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Hide-Ifdef mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Hide-Ifdef mode is a buffer-local minor mode for use with C and
C-like major modes. When enabled, code within #ifdef constructs
@@ -16191,9 +16338,11 @@ whitespace. Case does not matter.")
(autoload 'hs-minor-mode "hideshow" "\
Minor mode to selectively hide/show code and comment blocks.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Hs minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When hideshow minor mode is on, the menu bar is augmented with hideshow
commands and the hideshow commands are enabled.
@@ -16227,9 +16376,11 @@ Unconditionally turn off `hs-minor-mode'.
(autoload 'highlight-changes-mode "hilit-chg" "\
Toggle highlighting changes in this buffer (Highlight Changes mode).
-With a prefix argument ARG, enable Highlight Changes mode if ARG
-is positive, and disable it otherwise. If called from Lisp,
-enable the mode if ARG is omitted or nil.
+
+If called interactively, enable Highlight-Changes mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Highlight Changes is enabled, changes are marked with a text
property. Normally they are displayed in a distinctive face, but
@@ -16250,9 +16401,11 @@ buffer with the contents of a file
(autoload 'highlight-changes-visible-mode "hilit-chg" "\
Toggle visibility of highlighting due to Highlight Changes mode.
-With a prefix argument ARG, enable Highlight Changes Visible mode
-if ARG is positive, and disable it otherwise. If called from
-Lisp, enable the mode if ARG is omitted or nil.
+
+If called interactively, enable Highlight-Changes-Visible mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Highlight Changes Visible mode only has an effect when Highlight
Changes mode is on. When enabled, the changed text is displayed
@@ -16395,9 +16548,11 @@ argument VERBOSE non-nil makes the function verbose.
(autoload 'hl-line-mode "hl-line" "\
Toggle highlighting of the current line (Hl-Line mode).
-With a prefix argument ARG, enable Hl-Line mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Hl-Line mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Hl-Line mode is a buffer-local minor mode. If
`hl-line-sticky-flag' is non-nil, Hl-Line mode highlights the
@@ -16425,9 +16580,11 @@ or call the function `global-hl-line-mode'.")
(autoload 'global-hl-line-mode "hl-line" "\
Toggle line highlighting in all buffers (Global Hl-Line mode).
-With a prefix argument ARG, enable Global Hl-Line mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Global Hl-Line mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
If `global-hl-line-sticky-flag' is non-nil, Global Hl-Line mode
highlights the line about the current buffer's point in all live
@@ -16841,9 +16998,11 @@ or call the function `icomplete-mode'.")
(autoload 'icomplete-mode "icomplete" "\
Toggle incremental minibuffer completion (Icomplete mode).
-With a prefix argument ARG, enable Icomplete mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Icomplete mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When this global minor mode is enabled, typing in the minibuffer
continuously displays a list of possible completions that match
@@ -17392,10 +17551,11 @@ DEF, if non-nil, is the default value.
(autoload 'ielm "ielm" "\
Interactively evaluate Emacs Lisp expressions.
-Switches to the buffer `*ielm*', or creates it if it does not exist.
+Switches to the buffer named BUF-NAME if provided (`*ielm*' by default),
+or creates it if it does not exist.
See `inferior-emacs-lisp-mode' for details.
-\(fn)" t nil)
+\(fn &optional BUF-NAME)" t nil)
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ielm" '("ielm-" "inferior-emacs-lisp-mode")))
@@ -17415,9 +17575,12 @@ See `inferior-emacs-lisp-mode' for details.
(autoload 'iimage-mode "iimage" "\
Toggle Iimage mode on or off.
-With a prefix argument ARG, enable Iimage mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'.
+
+If called interactively, enable Iimage mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\\{iimage-mode-map}
\(fn &optional ARG)" t nil)
@@ -17710,6 +17873,11 @@ Setup easy-to-use keybindings for the commands to be used in dired mode.
Note that n, p and <down> and <up> will be hijacked and bound to
`image-dired-dired-x-line'.
+If called interactively, enable Image-Dired minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(define-obsolete-function-alias 'image-dired-setup-dired-keybindings 'image-dired-minor-mode "26.1")
@@ -17813,9 +17981,11 @@ or call the function `auto-image-file-mode'.")
(autoload 'auto-image-file-mode "image-file" "\
Toggle visiting of image files as images (Auto Image File mode).
-With a prefix argument ARG, enable Auto Image File mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Auto-Image-File mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
An image file is one whose name has an extension in
`image-file-name-extensions', or matches a regexp in
@@ -17842,9 +18012,11 @@ Key bindings:
(autoload 'image-minor-mode "image-mode" "\
Toggle Image minor mode in this buffer.
-With a prefix argument ARG, enable Image minor mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Image minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Image minor mode provides the key \\<image-mode-map>\\[image-toggle-display],
to switch back to `image-mode' and display an image file as the
@@ -17907,9 +18079,9 @@ string (which specifies the title of a submenu into which the
matches are put).
REGEXP is a regular expression matching a definition construct
which is to be displayed in the menu. REGEXP may also be a
-function, called without arguments. It is expected to search
-backwards. It must return true and set `match-data' if it finds
-another element.
+function of no arguments. If REGEXP is a function, it is
+expected to search backwards, return non-nil if it finds a
+definition construct, and set `match-data' for that construct.
INDEX is an integer specifying which subexpression of REGEXP
matches the definition's name; this subexpression is displayed as
the menu item.
@@ -18824,9 +18996,11 @@ available on the net.
(autoload 'ispell-minor-mode "ispell" "\
Toggle last-word spell checking (Ispell minor mode).
-With a prefix argument ARG, enable Ispell minor mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable ISpell minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Ispell minor mode is a buffer-local minor mode. When enabled,
typing SPC or RET warns you if the previous word is incorrectly
@@ -19510,9 +19684,11 @@ generations (this defaults to 1).
(autoload 'linum-mode "linum" "\
Toggle display of line numbers in the left margin (Linum mode).
-With a prefix argument ARG, enable Linum mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Linum mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Linum mode is a buffer-local minor mode.
@@ -20085,9 +20261,11 @@ or call the function `mail-abbrevs-mode'.")
(autoload 'mail-abbrevs-mode "mailabbrev" "\
Toggle abbrev expansion of mail aliases (Mail Abbrevs mode).
-With a prefix argument ARG, enable Mail Abbrevs mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Mail-Abbrevs mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Mail Abbrevs mode is a global minor mode. When enabled,
abbrev-like expansion is performed when editing certain mail
@@ -20431,9 +20609,11 @@ Default bookmark handler for Man buffers.
(autoload 'master-mode "master" "\
Toggle Master mode.
-With a prefix argument ARG, enable Master mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Master mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Master mode is enabled, you can scroll the slave buffer
using the following commands:
@@ -20465,9 +20645,11 @@ or call the function `minibuffer-depth-indicate-mode'.")
(autoload 'minibuffer-depth-indicate-mode "mb-depth" "\
Toggle Minibuffer Depth Indication mode.
-With a prefix argument ARG, enable Minibuffer Depth Indication
-mode if ARG is positive, and disable it otherwise. If called
-from Lisp, enable the mode if ARG is omitted or nil.
+
+If called interactively, enable Minibuffer-Depth-Indicate mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Minibuffer Depth Indication mode is a global minor mode. When
enabled, any recursive use of the minibuffer will show the
@@ -21095,6 +21277,11 @@ or call the function `midnight-mode'.")
(autoload 'midnight-mode "midnight" "\
Non-nil means run `midnight-hook' at midnight.
+If called interactively, enable Midnight mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(autoload 'clean-buffer-list "midnight" "\
@@ -21137,9 +21324,11 @@ or call the function `minibuffer-electric-default-mode'.")
(autoload 'minibuffer-electric-default-mode "minibuf-eldef" "\
Toggle Minibuffer Electric Default mode.
-With a prefix argument ARG, enable Minibuffer Electric Default
-mode if ARG is positive, and disable it otherwise. If called
-from Lisp, enable the mode if ARG is omitted or nil.
+
+If called interactively, enable Minibuffer-Electric-Default mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Minibuffer Electric Default mode is a global minor mode. When
enabled, minibuffer prompts that show a default value only show
@@ -21722,9 +21911,11 @@ or call the function `msb-mode'.")
(autoload 'msb-mode "msb" "\
Toggle Msb mode.
-With a prefix argument ARG, enable Msb mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Msb mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
This mode overrides the binding(s) of `mouse-buffer-menu' to provide a
different buffer menu using the function `msb'.
@@ -23390,6 +23581,11 @@ modes. The following keys behave as if Org mode were active, if
the cursor is on a headline, or on a plain list item (both as
defined by Org mode).
+If called interactively, enable OrgStruct mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(autoload 'turn-on-orgstruct "org" "\
@@ -24302,9 +24498,11 @@ Turning on outline mode calls the value of `text-mode-hook' and then of
(autoload 'outline-minor-mode "outline" "\
Toggle Outline minor mode.
-With a prefix argument ARG, enable Outline minor mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Outline minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
See the command `outline-mode' for more information on this mode.
@@ -24579,9 +24777,11 @@ or call the function `show-paren-mode'.")
(autoload 'show-paren-mode "paren" "\
Toggle visualization of matching parens (Show Paren mode).
-With a prefix argument ARG, enable Show Paren mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Show-Paren mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Show Paren mode is a global minor mode. When enabled, any
matching parenthesis is highlighted in `show-paren-style' after
@@ -25300,9 +25500,11 @@ or call the function `pixel-scroll-mode'.")
(autoload 'pixel-scroll-mode "pixel-scroll" "\
A minor mode to scroll text pixel-by-pixel.
-With a prefix argument ARG, enable Pixel Scroll mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable Pixel Scroll mode
-if ARG is omitted or nil.
+
+If called interactively, enable Pixel-Scroll mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -26959,9 +27161,11 @@ or call the function `rcirc-track-minor-mode'.")
(autoload 'rcirc-track-minor-mode "rcirc" "\
Global minor mode for tracking activity in rcirc buffers.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Rcirc-Track minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -27005,9 +27209,11 @@ or call the function `recentf-mode'.")
(autoload 'recentf-mode "recentf" "\
Toggle \"Open Recent\" menu (Recentf mode).
-With a prefix argument ARG, enable Recentf mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-Recentf mode if ARG is omitted or nil.
+
+If called interactively, enable Recentf mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Recentf mode is enabled, a \"Open Recent\" submenu is
displayed in the \"File\" menu, containing a list of files that
@@ -27157,6 +27363,12 @@ with a prefix argument, prompt for START-AT and FORMAT.
(autoload 'rectangle-mark-mode "rect" "\
Toggle the region as rectangular.
+
+If called interactively, enable Rectangle-Mark mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
Activates the region if needed. Only lasts until the region is deactivated.
\(fn &optional ARG)" t nil)
@@ -27184,9 +27396,11 @@ Activates the region if needed. Only lasts until the region is deactivated.
(autoload 'refill-mode "refill" "\
Toggle automatic refilling (Refill mode).
-With a prefix argument ARG, enable Refill mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Refill mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Refill mode is a buffer-local minor mode. When enabled, the
current paragraph is refilled as you edit. Self-inserting
@@ -27216,6 +27430,11 @@ Turn on RefTeX mode.
(autoload 'reftex-mode "reftex" "\
Minor mode with distinct support for \\label, \\ref and \\cite in LaTeX.
+If called interactively, enable Reftex mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\\<reftex-mode-map>A Table of Contents of the entire (multifile) document with browsing
capabilities is available with `\\[reftex-toc]'.
@@ -27560,9 +27779,11 @@ first comment line visible (if point is in a comment).
(autoload 'reveal-mode "reveal" "\
Toggle uncloaking of invisible text near point (Reveal mode).
-With a prefix argument ARG, enable Reveal mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-Reveal mode if ARG is omitted or nil.
+
+If called interactively, enable Reveal mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Reveal mode is a buffer-local minor mode. When enabled, it
reveals invisible text around point.
@@ -27583,9 +27804,10 @@ or call the function `global-reveal-mode'.")
Toggle Reveal mode in all buffers (Global Reveal mode).
Reveal mode renders invisible text around point visible again.
-With a prefix argument ARG, enable Global Reveal mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+If called interactively, enable Global Reveal mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -28303,9 +28525,11 @@ highlighting.
(autoload 'rst-minor-mode "rst" "\
Toggle ReST minor mode.
-With a prefix argument ARG, enable ReST minor mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Rst minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When ReST minor mode is enabled, the ReST mode keybindings
are installed on top of the major mode bindings. Use this
@@ -28352,9 +28576,11 @@ Use the command `ruler-mode' to change this variable.")
(autoload 'ruler-mode "ruler-mode" "\
Toggle display of ruler in header line (Ruler mode).
-With a prefix argument ARG, enable Ruler mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Ruler mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -28738,9 +28964,11 @@ or call the function `savehist-mode'.")
(autoload 'savehist-mode "savehist" "\
Toggle saving of minibuffer history (Savehist mode).
-With a prefix argument ARG, enable Savehist mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Savehist mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Savehist mode is enabled, minibuffer history is saved
periodically and when exiting Emacs. When Savehist mode is
@@ -28775,6 +29003,11 @@ Non-nil means automatically save place in each file.
This means when you visit a file, point goes to the last place
where it was when you previously visited the same file.
+If called interactively, enable Save-Place mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(autoload 'save-place-local-mode "saveplace" "\
@@ -28783,8 +29016,10 @@ If this mode is enabled, point is recorded when you kill the buffer
or exit Emacs. Visiting this file again will go to that position,
even in a later Emacs session.
-If called with a prefix arg, the mode is enabled if and only if
-the argument is positive.
+If called interactively, enable Save-Place-Local mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
To save places automatically in all files, put this in your init
file:
@@ -28875,9 +29110,11 @@ or call the function `scroll-all-mode'.")
(autoload 'scroll-all-mode "scroll-all" "\
Toggle shared scrolling in same-frame windows (Scroll-All mode).
-With a prefix argument ARG, enable Scroll-All mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Scroll-All mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Scroll-All mode is enabled, scrolling commands invoked in
one window apply to all visible windows in the same frame.
@@ -28900,12 +29137,16 @@ one window apply to all visible windows in the same frame.
(autoload 'scroll-lock-mode "scroll-lock" "\
Buffer-local minor mode for pager-like scrolling.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil. When enabled, keys that normally move
-point by line or paragraph will scroll the buffer by the
-respective amount of lines instead and point will be kept
-vertically fixed relative to window boundaries during scrolling.
+
+If called interactively, enable Scroll-Lock mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
+When enabled, keys that normally move point by line or paragraph
+will scroll the buffer by the respective amount of lines instead
+and point will be kept vertically fixed relative to window
+boundaries during scrolling.
\(fn &optional ARG)" t nil)
@@ -28964,9 +29205,11 @@ or call the function `semantic-mode'.")
(autoload 'semantic-mode "semantic" "\
Toggle parser features (Semantic mode).
-With a prefix argument ARG, enable Semantic mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-Semantic mode if ARG is omitted or nil.
+
+If called interactively, enable Semantic mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
In Semantic mode, Emacs parses the buffers you visit for their
semantic content. This information is used by a variety of
@@ -29925,9 +30168,11 @@ or call the function `server-mode'.")
(autoload 'server-mode "server" "\
Toggle Server mode.
-With a prefix argument ARG, enable Server mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-Server mode if ARG is omitted or nil.
+
+If called interactively, enable Server mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Server mode runs a process that accepts commands from the
`emacsclient' program. See Info node `Emacs server' and
@@ -30550,9 +30795,12 @@ buffer names.
(autoload 'smerge-mode "smerge-mode" "\
Minor mode to simplify editing output from the diff3 program.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Smerge mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\\{smerge-mode-map}
\(fn &optional ARG)" t nil)
@@ -31865,9 +32113,11 @@ or call the function `strokes-mode'.")
(autoload 'strokes-mode "strokes" "\
Toggle Strokes mode, a global minor mode.
-With a prefix argument ARG, enable Strokes mode if ARG is
-positive, and disable it otherwise. If called from Lisp,
-enable the mode if ARG is omitted or nil.
+
+If called interactively, enable Strokes mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\\<strokes-mode-map>
Strokes are pictographic mouse gestures which invoke commands.
@@ -31934,9 +32184,11 @@ Studlify-case the current buffer.
(autoload 'subword-mode "subword" "\
Toggle subword movement and editing (Subword mode).
-With a prefix argument ARG, enable Subword mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Subword mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Subword mode is a buffer-local minor mode. Enabling it changes
the definition of a word so that word-based commands stop inside
@@ -31956,8 +32208,6 @@ called a `subword'. Here are some examples:
This mode changes the definition of a word so that word commands
treat nomenclature boundaries as word boundaries.
-\\{subword-mode-map}
-
\(fn &optional ARG)" t nil)
(defvar global-subword-mode nil "\
@@ -31984,9 +32234,11 @@ See `subword-mode' for more information on Subword mode.
(autoload 'superword-mode "subword" "\
Toggle superword movement and editing (Superword mode).
-With a prefix argument ARG, enable Superword mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Superword mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Superword mode is a buffer-local minor mode. Enabling it changes
the definition of words such that symbols characters are treated
@@ -32081,9 +32333,11 @@ or call the function `gpm-mouse-mode'.")
(autoload 'gpm-mouse-mode "t-mouse" "\
Toggle mouse support in GNU/Linux consoles (GPM Mouse mode).
-With a prefix argument ARG, enable GPM Mouse mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Gpm-Mouse mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
This allows the use of the mouse when operating on a GNU/Linux console,
in the same way as you can use the mouse under X11.
@@ -32481,6 +32735,11 @@ location is indicated by `table-word-continuation-char'. This
variable's value can be toggled by \\[table-fixed-width-mode] at
run-time.
+If called interactively, enable Table-Fixed-Width mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
\(fn &optional ARG)" t nil)
(autoload 'table-query-dimension "table" "\
@@ -33667,6 +33926,11 @@ This function is meant to be used as a `post-self-insert-hook'.
(autoload 'tildify-mode "tildify" "\
Adds electric behavior to space character.
+If called interactively, enable Tildify mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
When space is inserted into a buffer in a position where hard space is required
instead (determined by `tildify-space-pattern' and `tildify-space-predicates'),
that space character is replaced by a hard space specified by
@@ -33712,9 +33976,11 @@ or call the function `display-time-mode'.")
(autoload 'display-time-mode "time" "\
Toggle display of time, load level, and mail flag in mode lines.
-With a prefix argument ARG, enable Display Time mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-it if ARG is omitted or nil.
+
+If called interactively, enable Display-Time mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When Display Time mode is enabled, it updates every minute (you
can control the number of seconds between updates by customizing
@@ -34571,6 +34837,11 @@ or call the function `type-break-mode'.")
Enable or disable typing-break mode.
This is a minor mode, but it is global to all buffers by default.
+If called interactively, enable Type-Break mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
+
When this mode is enabled, the user is encouraged to take typing breaks at
appropriate intervals; either after a specified amount of time or when the
user has exceeded a keystroke threshold. When the time arrives, the user
@@ -34579,9 +34850,6 @@ again in a short period of time. The idea is to give the user enough time
to find a good breaking point in his or her work, but be sufficiently
annoying to discourage putting typing breaks off indefinitely.
-A negative prefix argument disables this mode.
-No argument or any non-negative argument enables it.
-
The user may enable or disable this mode by setting the variable of the
same name, though setting it in that way doesn't reschedule a break or
reset the keystroke counter.
@@ -35105,9 +35373,11 @@ or call the function `url-handler-mode'.")
(autoload 'url-handler-mode "url-handlers" "\
Toggle using `url' library for URL filenames (URL Handler mode).
-With a prefix argument ARG, enable URL Handler mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Url-Handler mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -37252,9 +37522,11 @@ own View-like bindings.
(autoload 'view-mode "view" "\
Toggle View mode, a minor mode for viewing text but not editing it.
-With a prefix argument ARG, enable View mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable View mode
-if ARG is omitted or nil.
+
+If called interactively, enable View mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
When View mode is enabled, commands that do not change the buffer
contents are available as usual. Kill commands insert text in
@@ -37628,9 +37900,11 @@ or call the function `which-function-mode'.")
(autoload 'which-function-mode "which-func" "\
Toggle mode line display of current function (Which Function mode).
-With a prefix argument ARG, enable Which Function mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Which-Function mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Which Function mode is a global minor mode. When enabled, the
current function name is continuously displayed in the mode line,
@@ -37648,11 +37922,11 @@ in certain major modes.
(autoload 'whitespace-mode "whitespace" "\
Toggle whitespace visualization (Whitespace mode).
-With a prefix argument ARG, enable Whitespace mode if ARG is
-positive, and disable it otherwise.
-If called from Lisp, also enables the mode if ARG is omitted or nil,
-and toggles it if ARG is `toggle'.
+If called interactively, enable Whitespace mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
See also `whitespace-style', `whitespace-newline' and
`whitespace-display-mappings'.
@@ -37661,11 +37935,11 @@ See also `whitespace-style', `whitespace-newline' and
(autoload 'whitespace-newline-mode "whitespace" "\
Toggle newline visualization (Whitespace Newline mode).
-With a prefix argument ARG, enable Whitespace Newline mode if ARG
-is positive, and disable it otherwise.
-If called from Lisp, also enables the mode if ARG is omitted or nil,
-and toggles it if ARG is `toggle'.
+If called interactively, enable Whitespace-Newline mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Use `whitespace-newline-mode' only for NEWLINE visualization
exclusively. For other visualizations, including NEWLINE
@@ -37688,11 +37962,11 @@ or call the function `global-whitespace-mode'.")
(autoload 'global-whitespace-mode "whitespace" "\
Toggle whitespace visualization globally (Global Whitespace mode).
-With a prefix argument ARG, enable Global Whitespace mode if ARG
-is positive, and disable it otherwise.
-If called from Lisp, also enables the mode if ARG is omitted or nil,
-and toggles it if ARG is `toggle'.
+If called interactively, enable Global Whitespace mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
See also `whitespace-style', `whitespace-newline' and
`whitespace-display-mappings'.
@@ -37711,11 +37985,11 @@ or call the function `global-whitespace-newline-mode'.")
(autoload 'global-whitespace-newline-mode "whitespace" "\
Toggle global newline visualization (Global Whitespace Newline mode).
-With a prefix argument ARG, enable Global Whitespace Newline mode
-if ARG is positive, and disable it otherwise.
-If called from Lisp, also enables the mode if ARG is omitted or nil,
-and toggles it if ARG is `toggle'.
+If called interactively, enable Global Whitespace-Newline mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Use `global-whitespace-newline-mode' only for NEWLINE
visualization exclusively. For other visualizations, including
@@ -38037,9 +38311,11 @@ Show widget browser for WIDGET in other window.
(autoload 'widget-minor-mode "wid-browse" "\
Minor mode for traversing widgets.
-With a prefix argument ARG, enable the mode if ARG is positive,
-and disable it otherwise. If called from Lisp, enable the mode
-if ARG is omitted or nil.
+
+If called interactively, enable Widget minor mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
\(fn &optional ARG)" t nil)
@@ -38161,9 +38437,11 @@ or call the function `winner-mode'.")
(autoload 'winner-mode "winner" "\
Toggle Winner mode on or off.
-With a prefix argument ARG, enable Winner mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'.
+
+If called interactively, enable Winner mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Winner mode is a global minor mode that records the changes in
the window configuration (i.e. how the frames are partitioned
@@ -38373,6 +38651,12 @@ With prefix argument, prompt for the identifier.
\(fn IDENTIFIER)" t nil)
+(autoload 'xref-find-definitions-at-mouse "xref" "\
+Find the definition of identifier at or around mouse click.
+This command is intended to be bound to a mouse event.
+
+\(fn EVENT)" t nil)
+
(autoload 'xref-find-apropos "xref" "\
Find all meaningful symbols that match PATTERN.
The argument has the same meaning as in `apropos'.
@@ -38425,9 +38709,11 @@ or call the function `xterm-mouse-mode'.")
(autoload 'xterm-mouse-mode "xt-mouse" "\
Toggle XTerm mouse mode.
-With a prefix argument ARG, enable XTerm mouse mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
+
+If called interactively, enable Xterm-Mouse mode if ARG is positive, and
+disable it if ARG is zero or negative. If called from Lisp,
+also enable the mode if ARG is omitted or nil, and toggle it
+if ARG is `toggle'; disable the mode otherwise.
Turn it on to use Emacs mouse commands, and off to use xterm mouse commands.
This works in terminal emulators compatible with xterm. It only
diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el
index 2b49fae2a6d..5c474b4b90c 100644
--- a/lisp/mh-e/mh-comp.el
+++ b/lisp/mh-e/mh-comp.el
@@ -77,6 +77,14 @@ Default is \"components\".
If not an absolute file name, the file is searched for first in the
user's MH directory, then in the system MH lib directory.")
+(defvar mh-dist-formfile "distcomps"
+ "Name of file to be used as a skeleton for redistributing messages.
+
+Default is \"distcomps\".
+
+If not an absolute file name, the file is searched for first in the
+user's MH directory, then in the system MH lib directory.")
+
(defvar mh-repl-formfile "replcomps"
"Name of file to be used as a skeleton for replying to messages.
@@ -413,7 +421,7 @@ See also `mh-send'."
(interactive (list (mh-get-msg-num t)))
(let* ((from-folder mh-current-folder)
(config (current-window-configuration))
- (components-file (mh-bare-components))
+ (components-file (mh-bare-components mh-comp-formfile))
(draft
(cond ((and mh-draft-folder (equal from-folder mh-draft-folder))
(pop-to-buffer (find-file-noselect (mh-msg-filename message))
@@ -649,15 +657,16 @@ Original message has headers FROM and SUBJECT."
(format mh-forward-subject-format from subject))
;;;###mh-autoload
-(defun mh-redistribute (to cc &optional message)
+(defun mh-redistribute (to cc identity &optional message)
"Redistribute a message.
This command is similar in function to forwarding mail, but it
does not allow you to edit the message, nor does it add your name
to the \"From\" header field. It appears to the recipient as if
the message had come from the original sender. When you run this
-command, you are prompted for the TO and CC recipients. The
-default MESSAGE is the current message.
+command, you are prompted for the TO and CC recipients. You are
+also prompted for the sending IDENTITY to use. The default
+MESSAGE is the current message.
Also investigate the command \\[mh-edit-again] for another way to
redistribute messages.
@@ -668,6 +677,9 @@ The hook `mh-annotate-msg-hook' is run after annotating the
message and scan line."
(interactive (list (mh-read-address "Redist-To: ")
(mh-read-address "Redist-Cc: ")
+ (if mh-identity-list
+ (mh-select-identity mh-identity-default)
+ nil)
(mh-get-msg-num t)))
(or message
(setq message (mh-get-msg-num t)))
@@ -677,14 +689,51 @@ message and scan line."
(if mh-redist-full-contents-flag
(mh-msg-filename message)
nil)
- nil)))
- (mh-goto-header-end 0)
- (insert "Resent-To: " to "\n")
- (if (not (equal cc "")) (insert "Resent-cc: " cc "\n"))
- (mh-clean-msg-header
- (point-min)
- "^Message-Id:\\|^Received:\\|^Return-Path:\\|^Sender:\\|^Date:\\|^From:"
- nil)
+ nil))
+ (from (mh-identity-field identity "From"))
+ (fcc (mh-identity-field identity "Fcc"))
+ (bcc (mh-identity-field identity "Bcc"))
+ comp-fcc comp-to comp-cc comp-bcc)
+ (if mh-redist-full-contents-flag
+ (mh-clean-msg-header
+ (point-min)
+ "^Message-Id:\\|^Received:\\|^Return-Path:\\|^Date:\\|^Resent-.*:"
+ nil))
+ ;; Read fields from the distcomps file and put them in our
+ ;; draft. For "To", "Cc", "Bcc", and "Fcc", multiple headers are
+ ;; combined into a single header with comma-separated entries.
+ ;; For "From", the first value wins, with the identity's "From"
+ ;; trumping anything in the distcomps file.
+ (let ((components-file (mh-bare-components mh-dist-formfile)))
+ (mh-mapc
+ (function
+ (lambda (header-field)
+ (let ((field (car header-field))
+ (value (cdr header-field))
+ (case-fold-search t))
+ (cond
+ ((string-match field "^Resent-Fcc$")
+ (setq comp-fcc value))
+ ((string-match field "^Resent-From$")
+ (or from
+ (setq from value)))
+ ((string-match field "^Resent-To$")
+ (setq comp-to value))
+ ((string-match field "^Resent-Cc$")
+ (setq comp-cc value))
+ ((string-match field "^Resent-Bcc$")
+ (setq comp-bcc value))
+ ((string-match field "^Resent-.*$")
+ (mh-insert-fields field value))))))
+ (mh-components-to-list components-file))
+ (delete-file components-file))
+ (mh-insert-fields "Resent-To:" (mapconcat 'identity (list to comp-to) ", ")
+ "Resent-Cc:" (mapconcat 'identity (list cc comp-cc) ", ")
+ "Resent-Fcc:" (mapconcat 'identity (list fcc
+ comp-fcc) ", ")
+ "Resent-Bcc:" (mapconcat 'identity (list bcc
+ comp-bcc) ", ")
+ "Resent-From:" from)
(save-buffer)
(message "Redistributing...")
(let ((env "mhdist=1"))
@@ -702,7 +751,8 @@ message and scan line."
;; Annotate...
(mh-annotate-msg message folder mh-note-dist
"-component" "Resent:"
- "-text" (format "\"%s %s\"" to cc)))
+ "-text" (format "\"To: %s Cc: %s From: %s\""
+ to cc from)))
(kill-buffer draft)
(message "Redistributing...done"))))
@@ -898,7 +948,7 @@ CONFIG is the window configuration before sending mail."
(message "Composing a message...")
(let ((draft (mh-read-draft
"message"
- (mh-bare-components)
+ (mh-bare-components mh-comp-formfile)
t)))
(mh-insert-fields "To:" to "Subject:" subject "Cc:" cc)
(goto-char (point-max))
@@ -908,23 +958,25 @@ CONFIG is the window configuration before sending mail."
(mh-letter-mode-message)
(mh-letter-adjust-point))))
-(defun mh-bare-components ()
- "Generate a temporary, clean components file and return its path."
- ;; Let comp(1) create the skeleton for us. This is particularly
+(defun mh-bare-components (formfile)
+ "Generate a temporary, clean components file from FORMFILE.
+Return the path to the temporary file."
+ ;; Let comp(1) create the skeleton for us. This is particularly
;; important with nmh-1.5, because its default "components" needs
- ;; some processing before it can be used. Unfortunately, comp(1)
- ;; doesn't have a -build option. So, to avoid the possibility of
- ;; clobbering an existing draft, create a temporary directory and
- ;; use it as the drafts folder. Then copy the skeleton to a regular
- ;; temp file, and return the regular temp file.
+ ;; some processing before it can be used. Unfortunately, comp(1)
+ ;; didn't have a -build option until later versions of nmh. So, to
+ ;; avoid the possibility of clobbering an existing draft, create
+ ;; a temporary directory and use it as the drafts folder. Then
+ ;; copy the skeleton to a regular temp file, and return the
+ ;; regular temp file.
(let (new
(temp-folder (make-temp-file
(concat mh-user-path "draftfolder.") t)))
(mh-exec-cmd "comp" "-nowhatnowproc"
"-draftfolder" (format "+%s"
(file-name-nondirectory temp-folder))
- (if (stringp mh-comp-formfile)
- (list "-form" mh-comp-formfile)))
+ (if (stringp formfile)
+ (list "-form" formfile)))
(setq new (make-temp-file "comp."))
(rename-file (concat temp-folder "/" "1") new t)
;; The temp folder could contain various metadata files. Rather
diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el
index 661d0ec7569..3574f8c801d 100644
--- a/lisp/mh-e/mh-funcs.el
+++ b/lisp/mh-e/mh-funcs.el
@@ -357,6 +357,8 @@ Arguments are IGNORED (for `revert-buffer')."
(yes-or-no-p "Undo all commands in folder? "))
(setq mh-delete-list nil
mh-refile-list nil
+ mh-blacklist nil
+ mh-whitelist nil
mh-seq-list nil
mh-next-direction 'forward)
(with-mh-folder-updating (nil)
diff --git a/lisp/mh-e/mh-identity.el b/lisp/mh-e/mh-identity.el
index fd7c2b83fe7..a1eb22ff18e 100644
--- a/lisp/mh-e/mh-identity.el
+++ b/lisp/mh-e/mh-identity.el
@@ -132,6 +132,33 @@ valid header field."
'mh-identity-handler-default))
;;;###mh-autoload
+(defun mh-select-identity (default)
+ "Prompt for and return an identity.
+If DEFAULT is non-nil, it will be used if the user doesn't enter a
+different identity.
+
+See `mh-identity-list'."
+ (let (identity)
+ (setq identity
+ (completing-read
+ "Identity: "
+ (cons '("None")
+ (mapcar 'list (mapcar 'car mh-identity-list)))
+ nil t default nil default))
+ (if (eq identity "None")
+ nil
+ identity)))
+
+;;;###mh-autoload
+(defun mh-identity-field (identity field)
+ "Return the specified FIELD of the given IDENTITY.
+
+See `mh-identity-list'."
+ (let* ((pers-list (cadr (assoc identity mh-identity-list)))
+ (value (cdr (assoc field pers-list))))
+ value))
+
+;;;###mh-autoload
(defun mh-insert-identity (identity &optional maybe-insert)
"Insert fields specified by given IDENTITY.
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index 5b63e0c34df..108e368373f 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -583,7 +583,7 @@ If ARG is non-nil, instead prompt for connection parameters."
(setq-local rcirc-connection-info
(list server port nick user-name full-name startup-channels
- password encryption))
+ password encryption server-alias))
(setq-local rcirc-process process)
(setq-local rcirc-server server)
(setq-local rcirc-server-name
diff --git a/lisp/net/rlogin.el b/lisp/net/rlogin.el
index 3bfc4d7f356..015e04f4075 100644
--- a/lisp/net/rlogin.el
+++ b/lisp/net/rlogin.el
@@ -1,4 +1,4 @@
-;;; rlogin.el --- remote login interface
+;;; rlogin.el --- remote login interface -*- lexical-binding:t -*-
;; Copyright (C) 1992-1995, 1997-1998, 2001-2018 Free Software
;; Foundation, Inc.
@@ -30,9 +30,9 @@
;; tracking and the sending of some special characters.
;; If you wish for rlogin mode to prompt you in the minibuffer for
-;; passwords when a password prompt appears, just enter m-x send-invisible
-;; and type in your line, or add `comint-watch-for-password-prompt' to
-;; `comint-output-filter-functions'.
+;; passwords when a password prompt appears, just enter
+;; M-x comint-send-invisible and type in your line (or tweak
+;; `comint-password-prompt-regexp' to match your password prompt).
;;; Code:
diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el
index 17f83082f8d..f5de05dc3d7 100644
--- a/lisp/net/soap-client.el
+++ b/lisp/net/soap-client.el
@@ -685,14 +685,17 @@ This is a specialization of `soap-decode-type' for
(anyType (soap-decode-any-type node))
(Array (soap-decode-array node))))))
-(defun soap-type-of (element)
- "Return the type of ELEMENT."
- ;; Support Emacs < 26 byte-code running in Emacs >= 26 sessions
- ;; (Bug#31742).
- (let ((type (type-of element)))
- (if (eq type 'vector)
- (aref element 0) ; For Emacs 25 and earlier.
- type)))
+(defalias 'soap-type-of
+ (if (eq 'soap-xs-basic-type (type-of (make-soap-xs-basic-type)))
+ ;; `type-of' in Emacs ≥ 26 already does what we need.
+ #'type-of
+ ;; For Emacs < 26, use our own function.
+ (lambda (element)
+ "Return the type of ELEMENT."
+ (if (vectorp element)
+ (aref element 0) ;Assume this vector is actually a struct!
+ ;; This should never happen.
+ (type-of element)))))
;; Register methods for `soap-xs-basic-type'
(let ((tag (soap-type-of (make-soap-xs-basic-type))))
@@ -2881,6 +2884,8 @@ reference multiRef parts which are external to RESPONSE-NODE."
;;;; SOAP type encoding
+;; FIXME: Use `cl-defmethod' (but this requires Emacs-25).
+
(defun soap-encode-attributes (value type)
"Encode XML attributes for VALUE according to TYPE.
This is a generic function which determines the attribute encoder
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 1f40339c271..84af410de07 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -49,9 +49,9 @@
;; The user option `tramp-gvfs-methods' contains the list of supported
;; connection methods. Per default, these are "afp", "dav", "davs",
-;; "gdrive", "owncloud" and "sftp".
+;; "gdrive", "nextcloud" and "sftp".
-;; "gdrive" and "owncloud" connection methods require a respective
+;; "gdrive" and "nextcloud" connection methods require a respective
;; account in GNOME Online Accounts, with enabled "Files" service.
;; Other possible connection methods are "ftp", "http", "https" and
@@ -121,7 +121,7 @@
;;;###tramp-autoload
(defcustom tramp-gvfs-methods
- '("afp" "dav" "davs" "gdrive" "owncloud" "sftp")
+ '("afp" "dav" "davs" "gdrive" "nextcloud" "sftp")
"List of methods for remote files, accessed with GVFS."
:group 'tramp
:version "27.1"
@@ -132,11 +132,11 @@
(const "gdrive")
(const "http")
(const "https")
- (const "owncloud")
+ (const "nextcloud")
(const "sftp")
(const "smb"))))
-(defconst tramp-goa-methods '("gdrive" "owncloud")
+(defconst tramp-goa-methods '("gdrive" "nextcloud")
"List of methods which require registration at GNOME Online Accounts.")
;; Remove GNOME Online Accounts methods if not supported.
@@ -511,11 +511,11 @@ It has been changed in GVFS 1.14.")
":[[:blank:]]+\\(.*\\)$")
"Regexp to parse GVFS file system attributes with `gvfs-info'.")
-(defconst tramp-gvfs-owncloud-default-prefix "/remote.php/webdav"
+(defconst tramp-gvfs-nextcloud-default-prefix "/remote.php/webdav"
"Default prefix for owncloud / nextcloud methods.")
-(defconst tramp-gvfs-owncloud-default-prefix-regexp
- (concat (regexp-quote tramp-gvfs-owncloud-default-prefix) "$")
+(defconst tramp-gvfs-nextcloud-default-prefix-regexp
+ (concat (regexp-quote tramp-gvfs-nextcloud-default-prefix) "$")
"Regexp of default prefix for owncloud / nextcloud methods.")
@@ -1380,7 +1380,7 @@ file-notify events."
(with-parsed-tramp-file-name filename nil
(when (string-equal "gdrive" method)
(setq method "google-drive"))
- (when (string-equal "owncloud" method)
+ (when (string-equal "nextcloud" method)
(setq method "davs"
localname
(concat (tramp-gvfs-get-remote-prefix v) localname)))
@@ -1543,8 +1543,8 @@ file-notify events."
(setq method "davs"))
(when (and (string-equal "davs" method)
(string-match
- tramp-gvfs-owncloud-default-prefix-regexp prefix))
- (setq method "owncloud"))
+ tramp-gvfs-nextcloud-default-prefix-regexp prefix))
+ (setq method "nextcloud"))
(when (string-equal "google-drive" method)
(setq method "gdrive"))
(when (and (string-equal "http" method) (stringp uri))
@@ -1633,8 +1633,8 @@ file-notify events."
(setq method "davs"))
(when (and (string-equal "davs" method)
(string-match
- tramp-gvfs-owncloud-default-prefix-regexp prefix))
- (setq method "owncloud"))
+ tramp-gvfs-nextcloud-default-prefix-regexp prefix))
+ (setq method "nextcloud"))
(when (string-equal "google-drive" method)
(setq method "gdrive"))
(when (and (string-equal "http" method) (stringp uri))
@@ -1688,7 +1688,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
(localname (tramp-file-name-unquote-localname vec))
(share (when (string-match "^/?\\([^/]+\\)" localname)
(match-string 1 localname)))
- (ssl (if (string-match "^davs\\|^owncloud" method) "true" "false"))
+ (ssl (if (string-match "^davs\\|^nextcloud" method) "true" "false"))
(mount-spec
`(:array
,@(cond
@@ -1696,7 +1696,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
(list (tramp-gvfs-mount-spec-entry "type" "smb-share")
(tramp-gvfs-mount-spec-entry "server" host)
(tramp-gvfs-mount-spec-entry "share" share)))
- ((string-match "^dav\\|^owncloud" method)
+ ((string-match "^dav\\|^nextcloud" method)
(list (tramp-gvfs-mount-spec-entry "type" "dav")
(tramp-gvfs-mount-spec-entry "host" host)
(tramp-gvfs-mount-spec-entry "ssl" ssl)))
@@ -1707,6 +1707,9 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
((string-equal "gdrive" method)
(list (tramp-gvfs-mount-spec-entry "type" "google-drive")
(tramp-gvfs-mount-spec-entry "host" host)))
+ ((string-equal "nextcloud" method)
+ (list (tramp-gvfs-mount-spec-entry "type" "owncloud")
+ (tramp-gvfs-mount-spec-entry "host" host)))
((string-match "^http" method)
(list (tramp-gvfs-mount-spec-entry "type" "http")
(tramp-gvfs-mount-spec-entry
@@ -1980,6 +1983,8 @@ VEC is used only for traces."
:port (match-string 3 identity)))
(when (string-equal (tramp-goa-name-method key) "google")
(setf (tramp-goa-name-method key) "gdrive"))
+ (when (string-equal (tramp-goa-name-method key) "owncloud")
+ (setf (tramp-goa-name-method key) "nextcloud"))
;; Cache all properties.
(dolist (prop (nconc account-properties files-properties))
(tramp-set-connection-property key (car prop) (cdr prop)))
@@ -2086,7 +2091,7 @@ This uses \"avahi-browse\" in case D-Bus is not enabled in Avahi."
;; * (Customizable) unmount when exiting Emacs. See tramp-archive.el.
;; * Host name completion for existing mount points (afp-server,
-;; smb-server, google-drive, owncloud) or via smb-network or network.
+;; smb-server, google-drive, nextcloud) or via smb-network or network.
;;
;; * Check, how two shares of the same SMB server can be mounted in
;; parallel.
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 2d253506dde..86e82d40929 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2547,7 +2547,11 @@ The method used must be an out-of-band method."
"Like `make-directory' for Tramp files."
(setq dir (expand-file-name dir))
(with-parsed-tramp-file-name dir nil
- (tramp-flush-directory-properties v (file-name-directory localname))
+ ;; When PARENTS is non-nil, DIR could be a chain of non-existent
+ ;; directories a/b/c/... Instead of checking, we simply flush the
+ ;; whole cache.
+ (tramp-flush-directory-properties
+ v (if parents "/" (file-name-directory localname)))
(save-excursion
(tramp-barf-unless-okay
v (format "%s %s"
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index d56b09a604d..1af2defd586 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3567,16 +3567,20 @@ support symbolic links."
;; First, we must replace environment variables.
(setq filename (tramp-replace-environment-variables filename))
(with-parsed-tramp-file-name filename nil
- ;; We do not want to replace environment variables, again.
+ ;; We do not want to replace environment variables, again. "//"
+ ;; has a special meaning at the beginning of a file name on
+ ;; Cygwin and MS-Windows, we must remove it.
(let (process-environment)
;; Ignore in LOCALNAME everything before "//" or "/~".
(when (stringp localname)
(if (string-match "//\\(/\\|~\\)" localname)
- (setq filename (substitute-in-file-name localname))
+ (setq filename
+ (replace-regexp-in-string
+ "\\`/+" "/" (substitute-in-file-name localname)))
(setq filename
(concat (file-remote-p filename)
- (tramp-run-real-handler
- 'substitute-in-file-name (list localname)))))))
+ (replace-regexp-in-string
+ "\\`/+" "/" (substitute-in-file-name localname)))))))
;; "/m:h:~" does not work for completion. We use "/m:h:~/".
(if (and (stringp localname) (string-equal "~" localname))
(concat filename "/")
diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el
index 0b83afcc590..9bc8768384e 100644
--- a/lisp/net/trampver.el
+++ b/lisp/net/trampver.el
@@ -69,7 +69,7 @@
("2.2.9-24.4" . "24.4") ("2.2.11-24.5" . "24.5")
("2.2.13.25.1" . "25.1") ("2.2.13.25.2" . "25.2")
("2.2.13.25.2" . "25.3")
- ("2.3.3.26.1" . "26.1")))
+ ("2.3.3.26.1" . "26.1") ("2.3.4.26.2" . "26.2")))
(add-hook 'tramp-unload-hook
(lambda ()
diff --git a/lisp/profiler.el b/lisp/profiler.el
index eaeb69793fb..41dea68bd13 100644
--- a/lisp/profiler.el
+++ b/lisp/profiler.el
@@ -105,13 +105,13 @@
"Format ENTRY in human readable string. ENTRY would be a
function name of a function itself."
(cond ((memq (car-safe entry) '(closure lambda))
- (format "#<lambda 0x%x>" (sxhash entry)))
+ (format "#<lambda %#x>" (sxhash entry)))
((byte-code-function-p entry)
- (format "#<compiled 0x%x>" (sxhash entry)))
+ (format "#<compiled %#x>" (sxhash entry)))
((or (subrp entry) (symbolp entry) (stringp entry))
(format "%s" entry))
(t
- (format "#<unknown 0x%x>" (sxhash entry)))))
+ (format "#<unknown %#x>" (sxhash entry)))))
(defun profiler-fixup-entry (entry)
(if (symbolp entry)
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 3961ea647cf..d1eb3c3d06f 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -12607,7 +12607,11 @@ comment at the start of cc-engine.el for more info."
(= (point) containing-sexp)))
(if (eq (point) (c-point 'boi))
(c-add-syntax 'brace-list-close (point))
- (setq lim (c-most-enclosing-brace state-cache (point)))
+ (setq lim (or (save-excursion
+ (and
+ (c-back-over-member-initializers)
+ (point)))
+ (c-most-enclosing-brace state-cache (point))))
(c-beginning-of-statement-1 lim nil nil t)
(c-add-stmt-syntax 'brace-list-close nil t lim paren-state)))
@@ -12636,7 +12640,11 @@ comment at the start of cc-engine.el for more info."
(goto-char containing-sexp))
(if (eq (point) (c-point 'boi))
(c-add-syntax 'brace-list-intro (point))
- (setq lim (c-most-enclosing-brace state-cache (point)))
+ (setq lim (or (save-excursion
+ (and
+ (c-back-over-member-initializers)
+ (point)))
+ (c-most-enclosing-brace state-cache (point))))
(c-beginning-of-statement-1 lim)
(c-add-stmt-syntax 'brace-list-intro nil t lim paren-state)))
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 58a58b46395..f694252c407 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -45,7 +45,7 @@ It has `lisp-mode-abbrev-table' as its parent."
"Syntax table used in `emacs-lisp-mode'.")
(defvar emacs-lisp-mode-map
- (let ((map (make-sparse-keymap "Emacs-Lisp"))
+ (let ((map (make-sparse-keymap))
(menu-map (make-sparse-keymap "Emacs-Lisp"))
(lint-map (make-sparse-keymap))
(prof-map (make-sparse-keymap))
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index 519b768ab40..0ededb1b155 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -374,7 +374,9 @@ Notice that using \\[next-error] or \\[compile-goto-error] modifies
;; to handle weird file names (with colons in them) as
;; well as possible. E.g., use [1-9][0-9]* rather than
;; [0-9]+ so as to accept ":034:" in file names.
- "\\(?1:[^\n:]+?[^\n/:]\\):[\t ]*\\(?2:[1-9][0-9]*\\)[\t ]*:"
+ "\\(?1:"
+ "\\(?:[a-zA-Z]:\\)?" ; Allow "C:..." for w32.
+ "[^\n:]+?[^\n/:]\\):[\t ]*\\(?2:[1-9][0-9]*\\)[\t ]*:"
"\\)")
1 2
;; Calculate column positions (col . end-col) of first grep match on a line
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index ce7127a3d77..24ad2ff6c75 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -1625,7 +1625,7 @@ not be expanded."
((integerp result)
(if (or (= 0 result) (= 1 result))
(message "%S <= `%s'" result exprstring)
- (message "%S (0x%x) <= `%s'" result result exprstring)))
+ (message "%S (%#x) <= `%s'" result result exprstring)))
((null result) (message "%S <= `%s'" 'false exprstring))
((eq t result) (message "%S <= `%s'" 'true exprstring))
(t (message "%S <= `%s'" result exprstring)))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index e39ff08739b..c55b69e33ec 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -526,9 +526,19 @@ The type returned can be `comment', `string' or `paren'."
font-lock-string-face)
font-lock-comment-face))
-(defvar python-font-lock-keywords
- ;; Keywords
- `(,(rx symbol-start
+(defvar python-font-lock-keywords-level-1
+ `((,(rx symbol-start "def" (1+ space) (group (1+ (or word ?_))))
+ (1 font-lock-function-name-face))
+ (,(rx symbol-start "class" (1+ space) (group (1+ (or word ?_))))
+ (1 font-lock-type-face)))
+ "Font lock keywords to use in python-mode for level 1 decoration.
+
+This is the minimum decoration level, including function and
+class declarations.")
+
+(defvar python-font-lock-keywords-level-2
+ `(,@python-font-lock-keywords-level-1
+ ,(rx symbol-start
(or
"and" "del" "from" "not" "while" "as" "elif" "global" "or" "with"
"assert" "else" "if" "pass" "yield" "break" "except" "import" "class"
@@ -548,12 +558,35 @@ The type returned can be `comment', `string' or `paren'."
;; Extra:
"self")
symbol-end)
- ;; functions
- (,(rx symbol-start "def" (1+ space) (group (1+ (or word ?_))))
- (1 font-lock-function-name-face))
- ;; classes
- (,(rx symbol-start "class" (1+ space) (group (1+ (or word ?_))))
- (1 font-lock-type-face))
+ ;; Builtins
+ (,(rx symbol-start
+ (or
+ "abs" "all" "any" "bin" "bool" "callable" "chr" "classmethod"
+ "compile" "complex" "delattr" "dict" "dir" "divmod" "enumerate"
+ "eval" "filter" "float" "format" "frozenset" "getattr" "globals"
+ "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance"
+ "issubclass" "iter" "len" "list" "locals" "map" "max" "memoryview"
+ "min" "next" "object" "oct" "open" "ord" "pow" "print" "property"
+ "range" "repr" "reversed" "round" "set" "setattr" "slice" "sorted"
+ "staticmethod" "str" "sum" "super" "tuple" "type" "vars" "zip"
+ "__import__"
+ ;; Python 2:
+ "basestring" "cmp" "execfile" "file" "long" "raw_input" "reduce"
+ "reload" "unichr" "unicode" "xrange" "apply" "buffer" "coerce"
+ "intern"
+ ;; Python 3:
+ "ascii" "bytearray" "bytes" "exec"
+ ;; Extra:
+ "__all__" "__doc__" "__name__" "__package__")
+ symbol-end) . font-lock-builtin-face))
+ "Font lock keywords to use in python-mode for level 2 decoration.
+
+This is the medium decoration level, including everything in
+`python-font-lock-keywords-level-1', as well as keywords and
+builtins.")
+
+(defvar python-font-lock-keywords-maximum-decoration
+ `(,@python-font-lock-keywords-level-2
;; Constants
(,(rx symbol-start
(or
@@ -596,27 +629,6 @@ The type returned can be `comment', `string' or `paren'."
"VMSError" "WindowsError"
)
symbol-end) . font-lock-type-face)
- ;; Builtins
- (,(rx symbol-start
- (or
- "abs" "all" "any" "bin" "bool" "callable" "chr" "classmethod"
- "compile" "complex" "delattr" "dict" "dir" "divmod" "enumerate"
- "eval" "filter" "float" "format" "frozenset" "getattr" "globals"
- "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance"
- "issubclass" "iter" "len" "list" "locals" "map" "max" "memoryview"
- "min" "next" "object" "oct" "open" "ord" "pow" "print" "property"
- "range" "repr" "reversed" "round" "set" "setattr" "slice" "sorted"
- "staticmethod" "str" "sum" "super" "tuple" "type" "vars" "zip"
- "__import__"
- ;; Python 2:
- "basestring" "cmp" "execfile" "file" "long" "raw_input" "reduce"
- "reload" "unichr" "unicode" "xrange" "apply" "buffer" "coerce"
- "intern"
- ;; Python 3:
- "ascii" "bytearray" "bytes" "exec"
- ;; Extra:
- "__all__" "__doc__" "__name__" "__package__")
- symbol-end) . font-lock-builtin-face)
;; assignments
;; support for a = b = c = 5
(,(lambda (limit)
@@ -640,7 +652,26 @@ The type returned can be `comment', `string' or `paren'."
(goto-char (match-end 1))
(python-syntax-context 'paren)))
res))
- (1 font-lock-variable-name-face nil nil))))
+ (1 font-lock-variable-name-face nil nil)))
+ "Font lock keywords to use in python-mode for maximum decoration.
+
+This decoration level includes everything in
+`python-font-lock-keywords-level-2', as well as constants,
+decorators, exceptions, and assignments.")
+
+(defvar python-font-lock-keywords
+ '(python-font-lock-keywords-level-1 ; When `font-lock-maximum-decoration' is nil.
+ python-font-lock-keywords-level-1 ; When `font-lock-maximum-decoration' is 1.
+ python-font-lock-keywords-level-2 ; When `font-lock-maximum-decoration' is 2.
+ python-font-lock-keywords-maximum-decoration ; When `font-lock-maximum-decoration'
+ ; is more than 1, or t (which it is,
+ ; by default).
+ )
+ "List of font lock keyword specifications to use in python-mode.
+
+Which one will be chosen depends on the value of
+`font-lock-maximum-decoration'.")
+
(defconst python-syntax-propertize-function
(syntax-propertize-rules
@@ -5325,7 +5356,7 @@ REPORT-FN is Flymake's callback function."
'python-nav-forward-sexp)
(set (make-local-variable 'font-lock-defaults)
- '(python-font-lock-keywords
+ `(,python-font-lock-keywords
nil nil nil nil
(font-lock-syntactic-face-function
. python-font-lock-syntactic-face-function)))
diff --git a/lisp/progmodes/subword.el b/lisp/progmodes/subword.el
index ed71b862cfd..685e171dd64 100644
--- a/lisp/progmodes/subword.el
+++ b/lisp/progmodes/subword.el
@@ -110,9 +110,7 @@ called a `subword'. Here are some examples:
NSGraphicsContext => \"NS\", \"Graphics\" and \"Context\"
This mode changes the definition of a word so that word commands
-treat nomenclature boundaries as word boundaries.
-
-\\{subword-mode-map}"
+treat nomenclature boundaries as word boundaries."
:lighter " ,"
(when subword-mode (superword-mode -1))
(subword-setup-buffer))
diff --git a/lisp/register.el b/lisp/register.el
index 77d84c047a9..e25f9fd5889 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -231,6 +231,7 @@ Interactively, reads the register using `register-read-with-preview'."
(defalias 'register-to-point 'jump-to-register)
(defun jump-to-register (register &optional delete)
"Move point to location stored in a register.
+Push the mark if jumping moves point, unless called in succession.
If the register contains a file name, find that file.
\(To put a file name in a register, you must use `set-register'.)
If the register contains a window configuration (one frame) or a frameset
@@ -390,7 +391,20 @@ Interactively, reads the register using `register-read-with-preview'."
(cl-defmethod register-val-describe ((val cons) verbose)
(cond
((window-configuration-p (car val))
- (princ "a window configuration."))
+ (let* ((stored-window-config (car val))
+ (window-config-frame (window-configuration-frame stored-window-config))
+ (current-frame (selected-frame)))
+ (princ (format "a window configuration: %s."
+ (if (frame-live-p window-config-frame)
+ (with-selected-frame window-config-frame
+ (save-window-excursion
+ (set-window-configuration stored-window-config)
+ (concat
+ (mapconcat (lambda (w) (buffer-name (window-buffer w)))
+ (window-list (selected-frame)) ", ")
+ (unless (eq current-frame window-config-frame)
+ " in another frame"))))
+ "dead frame")))))
((frame-configuration-p (car val))
(princ "a frame configuration."))
diff --git a/lisp/scroll-bar.el b/lisp/scroll-bar.el
index 4d1ad03fa5f..7efbfc77742 100644
--- a/lisp/scroll-bar.el
+++ b/lisp/scroll-bar.el
@@ -254,14 +254,22 @@ EVENT should be a scroll bar click or drag event."
(let* ((start-position (event-start event))
(window (nth 0 start-position))
(portion-whole (nth 2 start-position)))
- (save-excursion
- (with-current-buffer (window-buffer window)
- ;; Calculate position relative to the accessible part of the buffer.
- (goto-char (+ (point-min)
- (scroll-bar-scale portion-whole
- (- (point-max) (point-min)))))
- (vertical-motion 0 window)
- (set-window-start window (point))))))
+ ;; With 'scroll-bar-adjust-thumb-portion' nil and 'portion-whole'
+ ;; indicating that the buffer is fully visible, do not scroll the
+ ;; window since that might make it impossible to scroll it back
+ ;; with GTK's thumb (Bug#32002).
+ (when (or scroll-bar-adjust-thumb-portion
+ (not (numberp (car portion-whole)))
+ (not (numberp (cdr portion-whole)))
+ (/= (car portion-whole) (cdr portion-whole)))
+ (save-excursion
+ (with-current-buffer (window-buffer window)
+ ;; Calculate position relative to the accessible part of the buffer.
+ (goto-char (+ (point-min)
+ (scroll-bar-scale portion-whole
+ (- (point-max) (point-min)))))
+ (vertical-motion 0 window)
+ (set-window-start window (point)))))))
(defun scroll-bar-drag (event)
"Scroll the window by dragging the scroll bar slider.
diff --git a/lisp/shadowfile.el b/lisp/shadowfile.el
index 0095d6959ef..86280c38adf 100644
--- a/lisp/shadowfile.el
+++ b/lisp/shadowfile.el
@@ -25,37 +25,38 @@
;; This package helps you to keep identical copies of files in more than one
;; place - possibly on different machines. When you save a file, it checks
;; whether it is on the list of files with "shadows", and if so, it tries to
-;; copy it when you exit Emacs (or use the shadow-copy-files command).
+;; copy it when you exit Emacs (or use the `shadow-copy-files' command).
;; Installation & Use:
-;; Add clusters (if necessary) and file groups with shadow-define-cluster,
-;; shadow-define-literal-group, and shadow-define-regexp-group (see the
+;; Add clusters (if necessary) and file groups with `shadow-define-cluster',
+;; `shadow-define-literal-group', and `shadow-define-regexp-group' (see the
;; documentation for these functions for information on how and when to use
;; them). After doing this once, everything should be automatic.
-;; The lists of clusters and shadows are saved in a ~/.emacs.d/shadows
-;; (`shadow-info-file') file, so that they can be remembered from one
-;; Emacs session to another, even (as much as possible) if the Emacs
-;; session terminates abnormally. The files needing to be copied are
-;; stored in `shadow-todo-file'; if a file cannot be copied for any
-;; reason, it will stay on the list to be tried again next time. The
-;; `shadow-info-file' file should itself have shadows on all your accounts
-;; so that the information in it is consistent everywhere, but
-;; `shadow-todo-file' is local information and should have no shadows.
+;; The lists of clusters and shadows are saved in `shadow-info-file',
+;; so that they can be remembered from one Emacs session to another,
+;; even (as much as possible) if the Emacs session terminates
+;; abnormally. The files needing to be copied are stored in
+;; `shadow-todo-file'; if a file cannot be copied for any reason, it
+;; will stay on the list to be tried again next time. The
+;; `shadow-info-file' file should itself have shadows on all your
+;; accounts so that the information in it is consistent everywhere,
+;; but `shadow-todo-file' is local information and should have no
+;; shadows.
;; If you do not want to copy a particular file, you can answer "no" and
-;; be asked again next time you hit C-x 4 s or exit Emacs. If you do not
-;; want to be asked again, use shadow-cancel, and you will not be asked
+;; be asked again next time you hit "C-x 4 s" or exit Emacs. If you do not
+;; want to be asked again, use "M-x shadow-cancel", and you will not be asked
;; until you change the file and save it again. If you do not want to
;; shadow that file ever again, you can edit it out of the shadows
-;; buffer. Anytime you edit the shadows buffer, you must type M-x
-;; shadow-read-files to load in the new information, or your changes will
+;; buffer. Anytime you edit the shadows buffer, you must type "M-x
+;; shadow-read-files" to load in the new information, or your changes will
;; be overwritten!
;; Bugs & Warnings:
;;
-;; - It is bad to have two emacses both running shadowfile at the same
+;; - It is bad to have two Emacsen both running shadowfile at the same
;; time. It tries to detect this condition, but is not always successful.
;;
;; - You have to be careful not to edit a file in two locations
@@ -64,19 +65,16 @@
;;
;; - It ought to check modification times of both files to make sure
;; it is doing the right thing. This will have to wait until
-;; file-newer-than-file-p works between machines.
+;; `file-newer-than-file-p' works between machines.
;;
;; - It will not make directories for you, it just fails to copy files
;; that belong in non-existent directories.
-;;
-;; Please report any bugs to me (boris@gnu.org). Also let me know
-;; if you have suggestions or would like to be informed of updates.
;;; Code:
(require 'cl-lib)
-(require 'ange-ftp)
+(require 'tramp)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Variables
@@ -107,35 +105,35 @@ files that have been changed and need to be copied to other systems."
:type 'boolean
:group 'shadow)
-;; FIXME in a sense, this changed in 24.4 (addition of locate-user-emacs-file),
-;; but due to the weird way this variable is initialized to nil, it didn't
-;; literally change. Same for shadow-todo-file.
-(defcustom shadow-info-file nil
+(defcustom shadow-info-file (locate-user-emacs-file "shadows" ".shadows")
"File to keep shadow information in.
The `shadow-info-file' should be shadowed to all your accounts to
ensure consistency. Default: ~/.emacs.d/shadows"
- :type '(choice (const nil) file)
- :group 'shadow)
+ :type 'file
+ :group 'shadow
+ :version "26.2")
-(defcustom shadow-todo-file nil
+(defcustom shadow-todo-file
+ (locate-user-emacs-file "shadow_todo" ".shadow_todo")
"File to store the list of uncopied shadows in.
This means that if a remote system is down, or for any reason you cannot or
decide not to copy your shadow files at the end of one Emacs session, it will
remember and ask you again in your next Emacs session.
This file must NOT be shadowed to any other system, it is host-specific.
Default: ~/.emacs.d/shadow_todo"
- :type '(choice (const nil) file)
- :group 'shadow)
+ :type 'file
+ :group 'shadow
+ :version "26.2")
;;; The following two variables should in most cases initialize themselves
;;; correctly. They are provided as variables in case the defaults are wrong
;;; on your machine (and for efficiency).
-(defvar shadow-system-name (system-name)
- "The complete hostname of this machine.")
+(defvar shadow-system-name (concat "/" (system-name) ":")
+ "The identification for local files on this machine.")
-(defvar shadow-homedir nil
+(defvar shadow-homedir "~"
"Your home directory on this machine.")
;;;
@@ -186,12 +184,12 @@ created by `shadow-define-regexp-group'.")
(car list))
(defun shadow-regexp-superquote (string)
- "Like `regexp-quote', but includes the ^ and $.
+ "Like `regexp-quote', but includes the \\` and \\'.
This makes sure regexp matches nothing but STRING."
- (concat "^" (regexp-quote string) "$"))
+ (concat "\\`" (regexp-quote string) "\\'"))
(defun shadow-suffix (prefix string)
- "If PREFIX begins STRING, return the rest.
+ "If PREFIX begins with STRING, return the rest.
Return value is non-nil if PREFIX and STRING are `string=' up to the length of
PREFIX."
(let ((lp (length prefix))
@@ -204,70 +202,66 @@ PREFIX."
;;; Clusters and sites
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; I use the term `site' to refer to a string which may be the name of a
-;;; cluster or a literal hostname. All user-level commands should accept
-;;; either.
-
-(defun shadow-make-cluster (name primary regexp)
- "Create a shadow cluster.
-It is called NAME, uses the PRIMARY hostname and REGEXP matching all
-hosts in the cluster. The variable `shadow-clusters' associates the
-names of clusters to these structures. This function is for program
-use: to create clusters interactively, use `shadow-define-cluster'
-instead."
- (list name primary regexp))
-
-(defmacro shadow-cluster-name (cluster)
- "Return the name of the CLUSTER."
- (list 'elt cluster 0))
+;;; I use the term `site' to refer to a string which may be the
+;;; cluster identification "/name:", a remote identification
+;;; "/method:user@host:", or "/system-name:' (the value of
+;;; `shadow-system-name') for the location of local files. All
+;;; user-level commands should accept either.
-(defmacro shadow-cluster-primary (cluster)
- "Return the primary hostname of a CLUSTER."
- (list 'elt cluster 1))
-
-(defmacro shadow-cluster-regexp (cluster)
- "Return the regexp matching hosts in a CLUSTER."
- (list 'elt cluster 2))
+(cl-defstruct (shadow-cluster (:type list) :named) name primary regexp)
(defun shadow-set-cluster (name primary regexp)
"Put cluster NAME on the list of clusters.
Replace old definition, if any. PRIMARY and REGEXP are the
information defining the cluster. For interactive use, call
`shadow-define-cluster' instead."
- (let ((rest (cl-remove-if (lambda (x) (equal name (car x)))
+ (let ((rest (cl-remove-if (lambda (x) (equal name (shadow-cluster-name x)))
shadow-clusters)))
(setq shadow-clusters
- (cons (shadow-make-cluster name primary regexp)
+ (cons (make-shadow-cluster :name name :primary primary :regexp regexp)
rest))))
-(defmacro shadow-get-cluster (name)
+(defun shadow-get-cluster (name)
"Return cluster named NAME, or nil."
- (list 'assoc name 'shadow-clusters))
+ (shadow-find
+ (lambda (x) (string-equal (shadow-cluster-name x) name))
+ shadow-clusters))
+
+;;; SITES
+
+(defun shadow-site-name (site)
+ "Return name if SITE has the form \"/name:\", otherwise SITE."
+ (if (string-match "\\`/\\([-.[:word:]]+\\):\\'" site)
+ (match-string 1 site) site))
+
+(defun shadow-name-site (name)
+ "Return \"/name:\" if NAME has word syntax, otherwise NAME."
+ (if (string-match "\\`[-.[:word:]]+\\'" name)
+ (format "/%s:"name) name))
(defun shadow-site-primary (site)
- "If SITE is a cluster, return primary host, otherwise return SITE."
- (let ((c (shadow-get-cluster site)))
- (if c
- (shadow-cluster-primary c)
+ "If SITE is a cluster, return primary identification, otherwise return SITE."
+ (let ((cluster (shadow-get-cluster (shadow-site-name site))))
+ (if cluster
+ (shadow-cluster-primary cluster)
site)))
-;;; SITES
-
(defun shadow-site-cluster (site)
- "Given a SITE (hostname or cluster name), return cluster it is in, or nil."
- (or (assoc site shadow-clusters)
+ "Given a SITE, return cluster it is in, or nil."
+ (or (shadow-get-cluster (shadow-site-name site))
(shadow-find
- (function (lambda (x)
- (string-match (shadow-cluster-regexp x)
- site)))
+ (lambda (x)
+ (string-match (shadow-cluster-regexp x) (shadow-name-site site)))
shadow-clusters)))
(defun shadow-read-site ()
- "Read a cluster name or hostname from the minibuffer."
- (let ((ans (completing-read "Host or cluster name [RET when done]: "
+ "Read a cluster name or host identification from the minibuffer."
+ (let ((ans (completing-read "Host identification or cluster name: "
shadow-clusters)))
- (if (equal "" ans)
- nil
+ (when (or (shadow-get-cluster (shadow-site-name ans))
+ (string-equal ans shadow-system-name)
+ (string-equal ans (shadow-site-name shadow-system-name))
+ (setq ans (file-remote-p ans)))
ans)))
(defun shadow-site-match (site1 site2)
@@ -281,63 +275,88 @@ be matched against the primary of SITE2."
(string-match (shadow-cluster-regexp cluster1) primary2)
(string-equal site1 primary2)))))
-(defun shadow-get-user (site)
- "Return the default username for a SITE."
- (ange-ftp-get-user (shadow-site-primary site)))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Filename manipulation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun shadow-parse-fullname (fullname)
- "Parse FULLNAME into (site user path) list.
-Leave it alone if it already is one. Return nil if the argument is
-not a full ange-ftp pathname."
- (if (listp fullname)
- fullname
- (ange-ftp-ftp-name fullname)))
-
(defun shadow-parse-name (name)
- "Parse any NAME into (site user name) list.
-Argument can be a simple name, full ange-ftp name, or already a hup list."
- (or (shadow-parse-fullname name)
- (list shadow-system-name
- (user-login-name)
- name)))
-
-(defsubst shadow-make-fullname (host user name)
- "Make an ange-ftp style fullname out of HOST, USER (optional), and NAME.
-This is probably not as general as it ought to be."
- (concat "/"
- (if user (concat user "@"))
- host ":"
- name))
+ "Parse any NAME into a `tramp-file-name' structure.
+Argument can be a simple name, remote file name, or already a
+`tramp-file-name' structure."
+ (cond
+ ((null name) nil)
+ ((tramp-file-name-p name) name)
+ ((file-remote-p name) (tramp-dissect-file-name name))
+ ((shadow-local-file name)
+ (make-tramp-file-name
+ :host (shadow-site-name shadow-system-name)
+ :localname (shadow-local-file name)))
+ ;; Cluster name.
+ ((string-match "^/\\([^:/]+\\):\\([^:]*\\)$" name)
+ (let ((name (match-string 1 name))
+ (file (match-string 2 name)))
+ (when (shadow-get-cluster name)
+ (make-tramp-file-name :host name :localname file))))))
+
+(defsubst shadow-make-fullname (hup &optional host name)
+ "Make a Tramp style fullname out of HUP, a `tramp-file-name' structure.
+Replace HOST, and NAME when non-nil."
+ (let ((hup (copy-tramp-file-name hup)))
+ (when host (setf (tramp-file-name-host hup) host))
+ (when name (setf (tramp-file-name-localname hup) name))
+ (if (null (tramp-file-name-method hup))
+ (format
+ "/%s:%s" (tramp-file-name-host hup) (tramp-file-name-localname hup))
+ (tramp-make-tramp-file-name hup))))
(defun shadow-replace-name-component (fullname newname)
"Return FULLNAME with the name component changed to NEWNAME."
- (let ((hup (shadow-parse-fullname fullname)))
- (shadow-make-fullname (nth 0 hup) (nth 1 hup) newname)))
+ (concat (file-remote-p fullname) newname))
(defun shadow-local-file (file)
- "If FILE is at this site, remove /user@host part.
-If refers to a different system or a different user on this system,
-return nil."
- (let ((hup (shadow-parse-fullname file)))
- (cond ((null hup) file)
- ((and (shadow-site-match (nth 0 hup) shadow-system-name)
- (string-equal (nth 1 hup) (user-login-name)))
- (nth 2 hup))
- (t nil))))
+ "If FILE is not remote, return it.
+If it refers to a different system, return nil."
+ (cond
+ ((null file) nil)
+ ;; `tramp-file-name' structure.
+ ((and (tramp-file-name-p file) (null (tramp-file-name-method file)))
+ (tramp-file-name-localname file))
+ ((tramp-file-name-p file) nil)
+ ;; Local host name.
+ ((string-match
+ (format "^%s\\([^:]*\\)$" (regexp-quote shadow-system-name)) file)
+ (match-string 1 file))
+ ;; Cluster name.
+ ((and (string-match "^/\\([^:/]+\\):\\([^:]*\\)$" file)
+ (shadow-get-cluster (match-string 1 file)))
+ (let ((file (match-string 2 file))
+ (primary
+ (shadow-cluster-primary
+ (shadow-get-cluster (match-string 1 file)))))
+ (when (string-equal primary shadow-system-name) (setq primary nil))
+ (shadow-local-file (concat primary file))))
+ ;; Local name.
+ ((null (file-remote-p file)) file)))
(defun shadow-expand-cluster-in-file-name (file)
"If hostname part of FILE is a cluster, expand it to cluster's primary hostname.
Will return the name bare if it is a local file."
- (let ((hup (shadow-parse-name file)))
- (cond ((null hup) file)
- ((shadow-local-file hup))
- ((shadow-make-fullname (shadow-site-primary (nth 0 hup))
- (nth 1 hup)
- (nth 2 hup))))))
+ (when (stringp file)
+ (cond
+ ;; Local file.
+ ((shadow-local-file file))
+ ;; Cluster name.
+ ((string-match "^\\(/[^:/]+:\\)[^:]*$" file)
+ (let ((primary
+ (save-match-data
+ (shadow-cluster-primary
+ (shadow-get-cluster
+ (shadow-site-name (match-string 1 file)))))))
+ (if (not primary)
+ file
+ (setq file (replace-match primary nil nil file 1))
+ (or (shadow-local-file file) file))))
+ (t file))))
(defun shadow-expand-file-name (file &optional default)
"Expand file name and get FILE's true name."
@@ -352,46 +371,50 @@ true."
(homedir (if (shadow-local-file hup)
shadow-homedir
(file-name-as-directory
- (nth 2 (shadow-parse-fullname
- (expand-file-name
- (shadow-make-fullname
- (nth 0 hup) (nth 1 hup) "~")))))))
- (suffix (shadow-suffix homedir (nth 2 hup)))
- (cluster (shadow-site-cluster (nth 0 hup))))
+ (file-local-name
+ (expand-file-name (shadow-make-fullname hup nil "~"))))))
+ (suffix (shadow-suffix homedir (tramp-file-name-localname hup)))
+ (cluster (shadow-site-cluster (shadow-make-fullname hup nil ""))))
+ (when cluster
+ (setf (tramp-file-name-method hup) nil
+ (tramp-file-name-host hup) (shadow-cluster-name cluster)))
(shadow-make-fullname
- (if cluster
- (shadow-cluster-name cluster)
- (nth 0 hup))
- (nth 1 hup)
+ hup nil
(if suffix
- (concat "~/" suffix)
- (nth 2 hup)))))
+ (concat "~/" suffix)
+ (tramp-file-name-localname hup)))))
(defun shadow-same-site (pattern file)
"True if the site of PATTERN and of FILE are on the same site.
-If usernames are supplied, they must also match exactly. PATTERN and FILE may
-be lists of host, user, name, or ange-ftp file names. FILE may also be just a
-local filename."
- (let ((pattern-sup (shadow-parse-fullname pattern))
+PATTERN and FILE may be Tramp vectors, or remote file names.
+FILE may also be just a local filename."
+ (let ((pattern-sup (shadow-parse-name pattern))
(file-sup (shadow-parse-name file)))
(and
- (shadow-site-match (nth 0 pattern-sup) (nth 0 file-sup))
- (or (null (nth 1 pattern-sup))
- (string-equal (nth 1 pattern-sup) (nth 1 file-sup))))))
+ (shadow-site-match
+ (tramp-file-name-host pattern-sup) (tramp-file-name-host file-sup))
+ (or (null (tramp-file-name-user pattern-sup))
+ (string-equal
+ (tramp-file-name-user pattern-sup)
+ (tramp-file-name-user file-sup))))))
(defun shadow-file-match (pattern file &optional regexp)
"Return t if PATTERN matches FILE.
If REGEXP is supplied and non-nil, the file part of the pattern is a regular
-expression, otherwise it must match exactly. The sites and usernames must
-match---see `shadow-same-site'. The pattern must be in full ange-ftp format,
+expression, otherwise it must match exactly. The sites must
+match---see `shadow-same-site'. The pattern must be in full Tramp format,
but the file can be any valid filename. This function does not do any
filename expansion or contraction, you must do that yourself first."
- (let* ((pattern-sup (shadow-parse-fullname pattern))
+ (let* ((pattern-sup (shadow-parse-name pattern))
(file-sup (shadow-parse-name file)))
(and (shadow-same-site pattern-sup file-sup)
(if regexp
- (string-match (nth 2 pattern-sup) (nth 2 file-sup))
- (string-equal (nth 2 pattern-sup) (nth 2 file-sup))))))
+ (string-match
+ (tramp-file-name-localname pattern-sup)
+ (tramp-file-name-localname file-sup))
+ (string-equal
+ (tramp-file-name-localname pattern-sup)
+ (tramp-file-name-localname file-sup))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; User-level Commands
@@ -405,30 +428,34 @@ one of them is sufficient to update the file on all of them. Clusters are
defined by a name, the network address of a primary host (the one we copy
files to), and a regular expression that matches the hostnames of all the
sites in the cluster."
- (interactive (list (completing-read "Cluster name: " shadow-clusters () ())))
+ (interactive (list (completing-read "Cluster name: " shadow-clusters)))
(let* ((old (shadow-get-cluster name))
- (primary (read-string "Primary host: "
- (if old (shadow-cluster-primary old)
- name)))
- (regexp (let (try-regexp)
- (while (not
- (string-match
- (setq try-regexp
+ (primary (let (try-primary)
+ (while (not
+ (or
+ (string-equal
+ (setq try-primary
(read-string
- "Regexp matching all host names: "
- (if old (shadow-cluster-regexp old)
- (shadow-regexp-superquote primary))))
- primary))
- (message "Regexp doesn't include the primary host!")
- (sit-for 2))
- try-regexp))
-; (username (read-no-blanks-input
-; (format "Username (default %s): "
-; (shadow-get-user primary))
-; (if old (or (shadow-cluster-username old) "")
-; (user-login-name))))
- )
-; (if (string-equal "" username) (setq username nil))
+ "Primary host: "
+ (if old (shadow-cluster-primary old)
+ name)))
+ shadow-system-name)
+ (file-remote-p try-primary)))
+ (message "Not a valid primary!")
+ (sit-for 2))
+ try-primary))
+ (regexp (let (try-regexp)
+ (while (not
+ (string-match
+ (setq try-regexp
+ (read-string
+ "Regexp matching all host names: "
+ (if old (shadow-cluster-regexp old)
+ (shadow-regexp-superquote primary))))
+ primary))
+ (message "Regexp doesn't include the primary host!")
+ (sit-for 2))
+ try-regexp)))
(shadow-set-cluster name primary regexp)))
;;;###autoload
@@ -438,20 +465,14 @@ It may have different filenames on each site. When this file is edited, the
new version will be copied to each of the other locations. Sites can be
specific hostnames, or names of clusters (see `shadow-define-cluster')."
(interactive)
- (let* ((hup (shadow-parse-fullname
+ (let* ((hup (shadow-parse-name
(shadow-contract-file-name (buffer-file-name))))
- (name (nth 2 hup))
- user site group)
+ (name (tramp-file-name-localname hup))
+ site group)
(while (setq site (shadow-read-site))
- (setq user (read-string (format "Username (default %s): "
- (shadow-get-user site)))
- name (read-string "Filename: " name))
- (setq group (cons (shadow-make-fullname site
- (if (string-equal "" user)
- (shadow-get-user site)
- user)
- name)
- group)))
+ (setq name (read-string "Filename: " name)
+ hup (shadow-parse-name (shadow-contract-file-name name))
+ group (cons (shadow-make-fullname hup site) group)))
(setq shadow-literal-groups (cons group shadow-literal-groups)))
(shadow-write-info-file))
@@ -468,19 +489,12 @@ function). Each site can be either a hostname or the name of a cluster (see
"Filename regexp: "
(if (buffer-file-name)
(shadow-regexp-superquote
- (nth 2
- (shadow-parse-name
- (shadow-contract-file-name
- (buffer-file-name))))))))
- site sites usernames)
+ (file-local-name (buffer-file-name))))))
+ site sites)
(while (setq site (shadow-read-site))
- (setq sites (cons site sites))
- (setq usernames
- (cons (read-string (format "Username for %s: " site)
- (shadow-get-user site))
- usernames)))
+ (setq sites (cons site sites)))
(setq shadow-regexp-groups
- (cons (shadow-make-group regexp sites usernames)
+ (cons (shadow-make-group regexp sites)
shadow-regexp-groups))
(shadow-write-info-file)))
@@ -537,14 +551,14 @@ permanently, remove the group from `shadow-literal-groups' or
;;; Internal functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun shadow-make-group (regexp sites usernames)
+(defun shadow-make-group (regexp sites)
"Make a description of a file group---
-actually a list of regexp ange-ftp file names---from REGEXP (name of file to
-be shadowed), list of SITES, and corresponding list of USERNAMES for each
-site."
+actually a list of regexp Tramp file names---from REGEXP (name of file to
+be shadowed), and list of SITES"
(if sites
- (cons (shadow-make-fullname (car sites) (car usernames) regexp)
- (shadow-make-group regexp (cdr sites) (cdr usernames)))
+ (cons (shadow-make-fullname
+ (shadow-parse-name (shadow-site-primary (car sites))) nil regexp)
+ (shadow-make-group regexp (cdr sites)))
nil))
(defun shadow-copy-file (s)
@@ -601,7 +615,9 @@ Consider them as regular expressions if third arg REGEXP is true."
(car groups))))
(append (cond ((equal nonmatching (car groups)) nil)
(regexp
- (let ((realname (nth 2 (shadow-parse-fullname file))))
+ (let ((realname
+ (tramp-file-name-localname
+ (shadow-parse-name file))))
(mapcar
(function
(lambda (x)
@@ -612,17 +628,26 @@ Consider them as regular expressions if third arg REGEXP is true."
(defun shadow-add-to-todo ()
"If current buffer has shadows, add them to the list needing to be copied."
+ (message "shadow-add-to-todo 1 %s" (current-buffer))
+ (message "shadow-add-to-todo 2 %s" (buffer-file-name))
+ (message "shadow-add-to-todo 3 %s" (shadow-expand-file-name (buffer-file-name (current-buffer))))
+ (message "shadow-add-to-todo 4 %s" (shadow-shadows-of (shadow-expand-file-name (buffer-file-name (current-buffer)))))
(let ((shadows (shadow-shadows-of
(shadow-expand-file-name
(buffer-file-name (current-buffer))))))
(when shadows
+ (message "shadow-add-to-todo 5 %s" shadows)
+ (message "shadow-add-to-todo 6 %s" shadow-files-to-copy)
+ (message "shadow-add-to-todo 7 %s" (shadow-union shadows shadow-files-to-copy))
(setq shadow-files-to-copy
(shadow-union shadows shadow-files-to-copy))
(when (not shadow-inhibit-message)
(message "%s" (substitute-command-keys
"Use \\[shadow-copy-files] to update shadows."))
(sit-for 1))
- (shadow-write-todo-file)))
+ (message "shadow-add-to-todo 8")
+ (shadow-write-todo-file)
+ (message "shadow-add-to-todo 9")))
nil) ; Return nil for write-file-functions
(defun shadow-remove-from-todo (pair)
@@ -636,9 +661,8 @@ PAIR must be `eq' to one of the elements of that list."
Thus restores shadowfile's state from your last Emacs session.
Return t unless files were locked; then return nil."
(interactive)
- (if (and (fboundp 'file-locked-p)
- (or (stringp (file-locked-p shadow-info-file))
- (stringp (file-locked-p shadow-todo-file))))
+ (if (or (stringp (file-locked-p shadow-info-file))
+ (stringp (file-locked-p shadow-todo-file)))
(progn
(message "Shadowfile is running in another Emacs; can't have two.")
(beep)
@@ -647,7 +671,7 @@ Return t unless files were locked; then return nil."
(save-current-buffer
(when shadow-info-file
(set-buffer (setq shadow-info-buffer
- (find-file-noselect shadow-info-file)))
+ (find-file-noselect shadow-info-file 'nowarn)))
(when (and (not (buffer-modified-p))
(file-newer-than-file-p (make-auto-save-file-name)
shadow-info-file))
@@ -680,6 +704,7 @@ defined, the old hashtable info is invalid."
(if (not shadow-info-buffer)
(setq shadow-info-buffer (find-file-noselect shadow-info-file)))
(set-buffer shadow-info-buffer)
+ (setq buffer-read-only nil)
(delete-region (point-min) (point-max))
(shadow-insert-var 'shadow-clusters)
(shadow-insert-var 'shadow-literal-groups)
@@ -689,17 +714,26 @@ defined, the old hashtable info is invalid."
"Write out information to `shadow-todo-file'.
With non-nil argument also saves the buffer."
(save-excursion
+ (message "shadow-write-todo-file 1 %s" shadow-todo-buffer)
(if (not shadow-todo-buffer)
(setq shadow-todo-buffer (find-file-noselect shadow-todo-file)))
+ (message "shadow-write-todo-file 2 %s" shadow-todo-buffer)
(set-buffer shadow-todo-buffer)
+ (message "shadow-write-todo-file 3 %s" shadow-todo-buffer)
+ (setq buffer-read-only nil)
(delete-region (point-min) (point-max))
+ (message "shadow-write-todo-file 4 %s" shadow-todo-buffer)
(shadow-insert-var 'shadow-files-to-copy)
- (if save (shadow-save-todo-file))))
+ (message "shadow-write-todo-file 5 %s" save)
+ (if save (shadow-save-todo-file))
+ (message "shadow-write-todo-file 6 %s" save)))
(defun shadow-save-todo-file ()
+ (message "shadow-save-todo-file 1 %s" shadow-todo-buffer)
(if (and shadow-todo-buffer (buffer-modified-p shadow-todo-buffer))
(with-current-buffer shadow-todo-buffer
- (condition-case nil ; have to continue even in case of
+ (message "shadow-save-todo-file 2 %s" shadow-todo-buffer)
+ (condition-case nil ; have to continue even in case of
(basic-save-buffer) ; error, otherwise kill-emacs might
(error ; not work!
(message "WARNING: Can't save shadow todo file; it is locked!")
@@ -765,24 +799,6 @@ look for files that have been changed and need to be copied to other systems."
(kill-emacs)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Lucid Emacs compatibility
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; This is on hold until someone tells me about a working version of
-;; map-ynp for Lucid Emacs.
-
-;(when (string-match "Lucid" emacs-version)
-; (require 'symlink-fix)
-; (require 'ange-ftp)
-; (require 'map-ynp)
-; (if (not (fboundp 'file-truename))
-; (fset 'shadow-expand-file-name
-; (symbol-function 'symlink-expand-file-name)))
-; (if (not (fboundp 'ange-ftp-ftp-name))
-; (fset 'ange-ftp-ftp-name
-; (symbol-function 'ange-ftp-ftp-name))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Hook us up
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -790,18 +806,10 @@ look for files that have been changed and need to be copied to other systems."
(defun shadow-initialize ()
"Set up file shadowing."
(interactive)
- (if (null shadow-homedir)
- (setq shadow-homedir
- (file-name-as-directory (shadow-expand-file-name "~"))))
- (if (null shadow-info-file)
- (setq shadow-info-file
- ;; FIXME: Move defaults to their defcustom.
- (shadow-expand-file-name
- (locate-user-emacs-file "shadows" ".shadows"))))
- (if (null shadow-todo-file)
- (setq shadow-todo-file
- (shadow-expand-file-name
- (locate-user-emacs-file "shadow_todo" ".shadow_todo"))))
+ (setq shadow-homedir
+ (file-name-as-directory (shadow-expand-file-name shadow-homedir))
+ shadow-info-file (shadow-expand-file-name shadow-info-file)
+ shadow-todo-file (shadow-expand-file-name shadow-todo-file))
(if (not (shadow-read-files))
(progn
(message "Shadowfile information files not found - aborting")
diff --git a/lisp/shell.el b/lisp/shell.el
index fa6eee0f187..ac6f11aeb40 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -73,7 +73,7 @@
;; c-c c-o comint-delete-output Delete last batch of process output
;; c-c c-r comint-show-output Show last batch of process output
;; c-c c-l comint-dynamic-list-input-ring List input history
-;; send-invisible Read line w/o echo & send to proc
+;; comint-send-invisible Read line w/o echo & send to proc
;; comint-continue-subjob Useful if you accidentally suspend
;; top-level job
;; comint-mode-hook is the comint mode hook.
@@ -500,7 +500,7 @@ Shell buffers. It implements `shell-completion-execonly' for
the end of process to the end of the current line.
\\[comint-send-input] before end of process output copies the current line minus the prompt to
the end of the buffer and sends it (\\[comint-copy-old-input] just copies the current line).
-\\[send-invisible] reads a line of text without echoing it, and sends it to
+\\[comint-send-invisible] reads a line of text without echoing it, and sends it to
the shell. This is useful for entering passwords. Or, add the function
`comint-watch-for-password-prompt' to `comint-output-filter-functions'.
diff --git a/lisp/simple.el b/lisp/simple.el
index 6459531a4ec..8d770478aa9 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -8346,14 +8346,12 @@ LSHIFTBY is the numeric value of this modifier, in keyboard events.
PREFIX is the string that represents this modifier in an event type symbol."
(if (numberp event)
(cond ((eq symbol 'control)
- (if (and (<= (downcase event) ?z)
- (>= (downcase event) ?a))
- (- (downcase event) ?a -1)
- (if (and (<= (downcase event) ?Z)
- (>= (downcase event) ?A))
- (- (downcase event) ?A -1)
- (logior (lsh 1 lshiftby) event))))
+ (if (<= 64 (upcase event) 95)
+ (- (upcase event) 64)
+ (logior (lsh 1 lshiftby) event)))
((eq symbol 'shift)
+ ;; FIXME: Should we also apply this "upcase" behavior of shift
+ ;; to non-ascii letters?
(if (and (<= (downcase event) ?z)
(>= (downcase event) ?a))
(upcase event)
diff --git a/lisp/subr.el b/lisp/subr.el
index 10343e69db8..fbb3e49a35c 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -555,12 +555,6 @@ If N is omitted or nil, remove the last element."
(if (> n 0) (setcdr (nthcdr (- (1- m) n) list) nil))
list))))
-(defun proper-list-p (object)
- "Return OBJECT's length if it is a proper list, nil otherwise.
-A proper list is neither circular nor dotted (i.e., its last cdr
-is nil)."
- (and (listp object) (ignore-errors (length object))))
-
(defun delete-dups (list)
"Destructively remove `equal' duplicates from LIST.
Store the result in LIST and return it. LIST must be a proper list.
@@ -2305,7 +2299,7 @@ some sort of escape sequence, the ambiguity is resolved via `read-key-delay'."
If optional CONFIRM is non-nil, read the password twice to make sure.
Optional DEFAULT is a default password to use instead of empty input.
-This function echoes `.' for each character that the user types.
+This function echoes `*' for each character that the user types.
You could let-bind `read-hide-char' to another hiding character, though.
Once the caller uses the password, it can erase the password
@@ -2331,7 +2325,7 @@ by doing (clear-string STRING)."
beg)))
(dotimes (i (- end beg))
(put-text-property (+ i beg) (+ 1 i beg)
- 'display (string (or read-hide-char ?.))))))
+ 'display (string (or read-hide-char ?*))))))
minibuf)
(minibuffer-with-setup-hook
(lambda ()
@@ -2346,7 +2340,7 @@ by doing (clear-string STRING)."
(add-hook 'after-change-functions hide-chars-fun nil 'local))
(unwind-protect
(let ((enable-recursive-minibuffers t)
- (read-hide-char (or read-hide-char ?.)))
+ (read-hide-char (or read-hide-char ?*)))
(read-string prompt nil t default)) ; t = "no history"
(when (buffer-live-p minibuf)
(with-current-buffer minibuf
@@ -4693,25 +4687,6 @@ The properties used on SYMBOL are `composefunc', `sendfunc',
(put symbol 'hookvar (or hookvar 'mail-send-hook)))
-(defun backtrace--print-frame (evald func args flags)
- "Print a trace of a single stack frame to `standard-output'.
-EVALD, FUNC, ARGS, FLAGS are as in `mapbacktrace'."
- (princ (if (plist-get flags :debug-on-exit) "* " " "))
- (cond
- ((and evald (not debugger-stack-frame-as-list))
- (cl-prin1 func)
- (if args (cl-prin1 args) (princ "()")))
- (t
- (cl-prin1 (cons func args))))
- (princ "\n"))
-
-(defun backtrace ()
- "Print a trace of Lisp function calls currently active.
-Output stream used is value of `standard-output'."
- (let ((print-level (or print-level 8))
- (print-escape-control-characters t))
- (mapbacktrace #'backtrace--print-frame 'backtrace)))
-
(defun backtrace-frames (&optional base)
"Collect all frames of current backtrace into a list.
If non-nil, BASE should be a function, and frames before its
diff --git a/lisp/term.el b/lisp/term.el
index 121a22e7933..9f8f1f703a6 100644
--- a/lisp/term.el
+++ b/lisp/term.el
@@ -343,6 +343,7 @@
(eval-when-compile (require 'cl-lib))
(require 'ring)
(require 'ehelp)
+(require 'comint) ; Password regexp.
(declare-function ring-empty-p "ring" (ring))
(declare-function ring-ref "ring" (ring index))
@@ -2215,6 +2216,7 @@ filter and C-g is pressed, this function returns nil rather than a string).
Note that the keystrokes comprising the text can still be recovered
\(temporarily) with \\[view-lossage]. This may be a security bug for some
applications."
+ (declare (obsolete read-passwd "27.1"))
(let ((ans "")
(c 0)
(echo-keystrokes 0)
@@ -2255,12 +2257,10 @@ applications."
(defun term-send-invisible (str &optional proc)
"Read a string without echoing.
Then send it to the process running in the current buffer. A new-line
-is additionally sent. String is not saved on term input history list.
-Security bug: your string can still be temporarily recovered with
-\\[view-lossage]."
+is additionally sent. String is not saved on term input history list."
(interactive "P") ; Defeat snooping via C-x esc
(when (not (stringp str))
- (setq str (term-read-noecho "Non-echoed text: " t)))
+ (setq str (read-passwd "Non-echoed text: ")))
(when (not proc)
(setq proc (get-buffer-process (current-buffer))))
(if (not proc) (error "Current buffer has no process")
@@ -2269,6 +2269,16 @@ Security bug: your string can still be temporarily recovered with
(term-send-string proc str)
(term-send-string proc "\n")))
+;; TODO: Maybe combine this with `comint-watch-for-password-prompt'.
+(defun term-watch-for-password-prompt (string)
+ "Prompt in the minibuffer for password and send without echoing.
+Checks if STRING contains a password prompt as defined by
+`comint-password-prompt-regexp'."
+ (when (term-in-line-mode)
+ (when (let ((case-fold-search t))
+ (string-match comint-password-prompt-regexp string))
+ (term-send-invisible (read-passwd string)))))
+
;;; Low-level process communication
@@ -3054,6 +3064,8 @@ See `term-prompt-regexp'."
(term-handle-deferred-scroll))
(set-marker (process-mark proc) (point))
+ (when (stringp decoded-substring)
+ (term-watch-for-password-prompt decoded-substring))
(when save-point
(goto-char save-point)
(set-marker save-point nil))
diff --git a/lisp/term/tty-colors.el b/lisp/term/tty-colors.el
index ab9149e6b42..a776c830a25 100644
--- a/lisp/term/tty-colors.el
+++ b/lisp/term/tty-colors.el
@@ -824,10 +824,12 @@ A canonicalized color name is all-lower case, with any blanks removed."
(replace-regexp-in-string " +" "" (downcase color))
color)))
-(defun tty-color-24bit (rgb)
- "Return pixel value on 24-bit terminals. Return nil if RGB is
-nil or not on 24-bit terminal."
- (when (and rgb (= (display-color-cells) 16777216))
+(defun tty-color-24bit (rgb &optional display)
+ "Return 24-bit color pixel value for RGB value on DISPLAY.
+DISPLAY can be a display name or a frame, and defaults to the
+selected frame's display.
+If DISPLAY is not on a 24-but TTY terminal, return nil."
+ (when (and rgb (= (display-color-cells display) 16777216))
(let ((r (lsh (car rgb) -8))
(g (lsh (cadr rgb) -8))
(b (lsh (nth 2 rgb) -8)))
@@ -850,7 +852,7 @@ If FRAME is not specified or is nil, it defaults to the selected frame."
(error "Invalid specification for tty color \"%s\"" name))
(tty-modify-color-alist
(append (list (tty-color-canonicalize name)
- (or (tty-color-24bit rgb) index))
+ (or (tty-color-24bit rgb frame) index))
rgb)
frame))
@@ -1026,7 +1028,7 @@ might need to be approximated if it is not supported directly."
(or (assoc color (tty-color-alist frame))
(let ((rgb (tty-color-standard-values color)))
(and rgb
- (let ((pixel (tty-color-24bit rgb)))
+ (let ((pixel (tty-color-24bit rgb frame)))
(or (and pixel (cons color (cons pixel rgb)))
(tty-color-approximate rgb frame)))))))))
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 8ad6832880a..69bba100922 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -31,10 +31,10 @@
;;
;; To enable Flyspell in text representing computer programs, type
;; M-x flyspell-prog-mode.
-;; In that mode only text inside comments is checked.
+;; In that mode only text inside comments and strings is checked.
;;
;; Some user variables control the behavior of flyspell. They are
-;; those defined under the `User variables' comment.
+;; those defined under the `User configuration' comment.
;;; Code:
@@ -137,7 +137,10 @@ This variable specifies how far to search to find such a duplicate.
(defcustom flyspell-persistent-highlight t
"Non-nil means misspelled words remain highlighted until corrected.
If this variable is nil, only the most recently detected misspelled word
-is highlighted."
+is highlighted, and the highlight is turned off as soon as point moves
+off the misspelled word.
+
+Make sure this variable is non-nil if you use `flyspell-region'."
:group 'flyspell
:type 'boolean)
@@ -1371,7 +1374,10 @@ language."
;;* flyspell-small-region ... */
;;*---------------------------------------------------------------------*/
(defun flyspell-small-region (beg end)
- "Flyspell text between BEG and END."
+ "Flyspell text between BEG and END.
+
+This function is intended to work on small regions, as
+determined by `flyspell-large-region'."
(save-excursion
(if (> beg end)
(let ((old beg))
@@ -1642,7 +1648,10 @@ The buffer to mark them in is `flyspell-large-region-buffer'."
;;*---------------------------------------------------------------------*/
;;;###autoload
(defun flyspell-region (beg end)
- "Flyspell text between BEG and END."
+ "Flyspell text between BEG and END.
+
+Make sure `flyspell-mode' is turned on if you want the highlight
+of a misspelled word removed when you've corrected it."
(interactive "r")
(ispell-set-spellchecker-params) ; Initialize variables and dicts alists
(if (= beg end)
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index d80447e0a5b..e6f436fa1a1 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -2262,8 +2262,9 @@ Global `ispell-quit' set to start location to continue spell session."
(ispell-pdict-save ispell-silently-savep)
(message "%s"
(substitute-command-keys
- (concat "Spell-checking suspended;"
- " use C-u \\[ispell-word] to resume")))
+ (concat
+ "Spell-checking suspended; use "
+ "\\[universal-argument] \\[ispell-word] to resume")))
(setq ispell-quit start)
nil)
((= char ?q)
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index 11dbb8d5705..e7fe8ffe660 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -1030,7 +1030,9 @@ This is used to string together whole reference sets, like
("Hyperref" "hyperref"
(("\\autoref" ?a) ("\\autopageref" ?u)))
("Cleveref" "cleveref"
- (("\\cref" ?c) ("\\Cref" ?C) ("\\cpageref" ?d) ("\\Cpageref" ?D))))
+ (("\\cref" ?c) ("\\Cref" ?C) ("\\cpageref" ?d) ("\\Cpageref" ?D)))
+ ("AMSmath" "amsmath"
+ (("\\eqref" ?e))))
"Alist of reference styles.
Each element is a list of the style name, the name of the LaTeX
package associated with the style or t for any package, and an
@@ -1040,7 +1042,7 @@ the macro type is being prompted for. (See also
`reftex-ref-macro-prompt'.) The keys, represented as characters,
have to be unique."
:group 'reftex-referencing-labels
- :version "24.3"
+ :version "27.1"
:type '(alist :key-type (string :tag "Style name")
:value-type (group (choice :tag "Package"
(const :tag "Any package" t)
diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el
index 4612e95bb0e..7fcb3bc2b73 100644
--- a/lisp/thingatpt.el
+++ b/lisp/thingatpt.el
@@ -484,7 +484,7 @@ looks like an email address, \"ftp://\" if it starts with
(put 'url 'end-op (lambda () (end-of-thing 'url)))
-(put 'url 'beginning-op (lambda () (end-of-thing 'url)))
+(put 'url 'beginning-op (lambda () (beginning-of-thing 'url)))
;; The normal thingatpt mechanism doesn't work for complex regexps.
;; This should work for almost any regexp wherever we are in the
diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el
index 4d69aac454c..d6e85408608 100644
--- a/lisp/vc/add-log.el
+++ b/lisp/vc/add-log.el
@@ -744,6 +744,7 @@ Optional arg BUFFER-FILE overrides `buffer-file-name'."
file-name)
(defun add-log-file-name (buffer-file log-file)
+ "Compute file-name of BUFFER-FILE to be used in entries in LOG-FILE."
;; Never want to add a change log entry for the ChangeLog file itself.
(unless (or (null buffer-file) (string= buffer-file log-file))
(if add-log-file-name-function
@@ -767,15 +768,57 @@ Optional arg BUFFER-FILE overrides `buffer-file-name'."
(file-name-sans-versions buffer-file)
buffer-file))))
+(defcustom add-log-dont-create-changelog-file t
+ "If non-nil, don't create ChangeLog files for log entries.
+If a ChangeLog file does not already exist, a non-nil value
+means to put log entries in a suitably named buffer."
+ :type :boolean
+ :version "27.1")
+
+(put 'add-log-dont-create-changelog-file 'safe-local-variable 'booleanp)
+
+(defun add-log--pseudo-changelog-buffer-name (changelog-file-name)
+ "Compute a suitable name for a non-file visiting ChangeLog buffer.
+CHANGELOG-FILE-NAME is the file name of the actual ChangeLog file
+if it were to exist."
+ (format "*changes to %s*"
+ (abbreviate-file-name
+ (file-name-directory changelog-file-name))))
+
+(defun add-log--changelog-buffer-p (changelog-file-name buffer)
+ "Return non-nil if BUFFER holds a change log for CHANGELOG-FILE-NAME."
+ (with-current-buffer buffer
+ (if buffer-file-name
+ (equal buffer-file-name changelog-file-name)
+ (equal (add-log--pseudo-changelog-buffer-name changelog-file-name)
+ (buffer-name)))))
+
+(defun add-log-find-changelog-buffer (changelog-file-name)
+ "Find a ChangeLog buffer for CHANGELOG-FILE-NAME.
+Respect `add-log-use-pseudo-changelog', which see."
+ (if (or (file-exists-p changelog-file-name)
+ (not add-log-dont-create-changelog-file))
+ (find-file-noselect changelog-file-name)
+ (get-buffer-create
+ (add-log--pseudo-changelog-buffer-name changelog-file-name))))
+
;;;###autoload
-(defun add-change-log-entry (&optional whoami file-name other-window new-entry
+(defun add-change-log-entry (&optional whoami
+ changelog-file-name
+ other-window new-entry
put-new-entry-on-new-line)
- "Find change log file, and add an entry for today and an item for this file.
-Optional arg WHOAMI (interactive prefix) non-nil means prompt for user
-name and email (stored in `add-log-full-name' and `add-log-mailing-address').
-
-Second arg FILE-NAME is file name of the change log.
-If nil, use the value of `change-log-default-name'.
+ "Find ChangeLog buffer, add an entry for today and an item for this file.
+Optional arg WHOAMI (interactive prefix) non-nil means prompt for
+user name and email (stored in `add-log-full-name'
+and `add-log-mailing-address').
+
+Second arg CHANGELOG-FILE-NAME is the file name of the change log.
+If nil, use the value of `change-log-default-name'. If the file
+thus named exists, it is used for the new entry. If it doesn't
+exist, it is created, unless `add-log-dont-create-changelog-file' is t,
+in which case a suitably named buffer that doesn't visit any file
+is used for keeping entries pertaining to CHANGELOG-FILE-NAME's
+directory.
Third arg OTHER-WINDOW non-nil means visit in other window.
@@ -804,20 +847,28 @@ non-nil, otherwise in local time."
(change-log-version-number-search)))
(buf-file-name (funcall add-log-buffer-file-name-function))
(buffer-file (if buf-file-name (expand-file-name buf-file-name)))
- (file-name (expand-file-name (find-change-log file-name buffer-file)))
+ (changelog-file-name (expand-file-name (find-change-log
+ changelog-file-name
+ buffer-file)))
;; Set ITEM to the file name to use in the new item.
- (item (add-log-file-name buffer-file file-name)))
+ (item (add-log-file-name buffer-file changelog-file-name)))
- (unless (equal file-name buffer-file-name)
+ ;; don't add entries from the ChangeLog file/buffer to itself.
+ (unless (equal changelog-file-name buffer-file-name)
(cond
- ((equal file-name (buffer-file-name (window-buffer)))
+ ((add-log--changelog-buffer-p
+ changelog-file-name
+ (window-buffer))
;; If the selected window already shows the desired buffer don't show
;; it again (particularly important if other-window is true).
;; This is important for diff-add-change-log-entries-other-window.
(set-buffer (window-buffer)))
((or other-window (window-dedicated-p))
- (find-file-other-window file-name))
- (t (find-file file-name))))
+ (switch-to-buffer-other-window
+ (add-log-find-changelog-buffer changelog-file-name)))
+ (t
+ (switch-to-buffer
+ (add-log-find-changelog-buffer changelog-file-name)))))
(or (derived-mode-p 'change-log-mode)
(change-log-mode))
(undo-boundary)
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index ffbd9e5479a..b91a2ba45a4 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -96,6 +96,11 @@ when editing big diffs)."
:version "27.1"
:type 'boolean)
+(defcustom diff-font-lock-prettify nil
+ "If non-nil, font-lock will try and make the format prettier."
+ :version "27.1"
+ :type 'boolean)
+
(defvar diff-vc-backend nil
"The VC backend that created the current Diff buffer, if any.")
@@ -396,6 +401,7 @@ and the face `diff-added' for added lines.")
(1 font-lock-comment-delimiter-face)
(2 font-lock-comment-face))
("^[^-=+*!<>#].*\n" (0 'diff-context))
+ (,#'diff--font-lock-prettify)
(,#'diff--font-lock-refined)))
(defconst diff-font-lock-defaults
@@ -2195,6 +2201,35 @@ fixed, visit it in a buffer."
modified-buffers ", "))
(message "No trailing whitespace to delete.")))))
+
+;;; Prettifying from font-lock
+
+(defun diff--font-lock-prettify (limit)
+ ;; Mimicks the output of Magit's diff.
+ ;; FIXME: This has only been tested with Git's diff output.
+ (when diff-font-lock-prettify
+ (while (re-search-forward "^diff " limit t)
+ (when (save-excursion
+ (forward-line 0)
+ (looking-at (eval-when-compile
+ (concat "diff.*\n"
+ "\\(?:\\(?:new file\\|deleted\\).*\n\\)?"
+ "\\(?:index.*\n\\)?"
+ "--- \\(?:/dev/null\\|a/\\(.*\\)\\)\n"
+ "\\+\\+\\+ \\(?:/dev/null\\|b/\\(.*\\)\\)\n"))))
+ (put-text-property (match-beginning 0)
+ (or (match-beginning 2) (match-beginning 1))
+ 'display (propertize
+ (cond
+ ((null (match-beginning 1)) "new file ")
+ ((null (match-beginning 2)) "deleted ")
+ (t "modified "))
+ 'face '(diff-file-header diff-header)))
+ (unless (match-beginning 2)
+ (put-text-property (match-end 1) (1- (match-end 0))
+ 'display "")))))
+ nil)
+
;;; Support for converting a diff to diff3 markers via `wiggle'.
;; Wiggle can be found at http://neil.brown.name/wiggle/ or in your nearest
diff --git a/lisp/vc/diff.el b/lisp/vc/diff.el
index b850350cd8a..ac94586cace 100644
--- a/lisp/vc/diff.el
+++ b/lisp/vc/diff.el
@@ -226,8 +226,9 @@ With prefix arg, prompt for diff switches."
"View the differences between BUFFER and its associated file.
This requires the external program `diff' to be in your `exec-path'."
(interactive "bBuffer: ")
- (with-current-buffer (get-buffer (or buffer (current-buffer)))
- (diff buffer-file-name (current-buffer) nil 'noasync)))
+ (let ((buf (get-buffer (or buffer (current-buffer)))))
+ (with-current-buffer (or (buffer-base-buffer buf) buf)
+ (diff buffer-file-name (current-buffer) nil 'noasync))))
(provide 'diff)
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el
index 6ff782a6061..90860fbdcfe 100644
--- a/lisp/vc/log-edit.el
+++ b/lisp/vc/log-edit.el
@@ -913,8 +913,10 @@ where LOGBUFFER is the name of the ChangeLog buffer, and each
(setq change-log-default-name nil)
(find-change-log)))))
(when (or (find-buffer-visiting changelog-file-name)
- (file-exists-p changelog-file-name))
- (with-current-buffer (find-file-noselect changelog-file-name)
+ (file-exists-p changelog-file-name)
+ add-log-dont-create-changelog-file)
+ (with-current-buffer
+ (add-log-find-changelog-buffer changelog-file-name)
(unless (eq major-mode 'change-log-mode) (change-log-mode))
(goto-char (point-min))
(if (looking-at "\\s-*\n") (goto-char (match-end 0)))
diff --git a/lisp/w32-fns.el b/lisp/w32-fns.el
index 825420c4261..bdba32c8067 100644
--- a/lisp/w32-fns.el
+++ b/lisp/w32-fns.el
@@ -280,7 +280,7 @@ bit output with no translation."
(w32-add-charset-info "iso8859-13" 'w32-charset-baltic 1257)
(w32-add-charset-info "koi8-r" 'w32-charset-russian 20866)
(w32-add-charset-info "iso8859-5" 'w32-charset-russian 28595)
- (w32-add-charset-info "tis620-2533" 'w32-charset-thai 874)
+ (w32-add-charset-info "iso8859-11" 'w32-charset-thai 874)
(w32-add-charset-info "windows-1258" 'w32-charset-vietnamese 1258)
(w32-add-charset-info "ksc5601.1992" 'w32-charset-johab 1361)
(w32-add-charset-info "mac-roman" 'w32-charset-mac 10000)
diff --git a/lisp/wdired.el b/lisp/wdired.el
index bb60e777769..be0bde290ab 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -255,6 +255,7 @@ See `wdired-mode'."
(setq buffer-read-only nil)
(dired-unadvertise default-directory)
(add-hook 'kill-buffer-hook 'wdired-check-kill-buffer nil t)
+ (add-hook 'after-change-functions 'wdired--restore-dired-filename-prop nil t)
(setq major-mode 'wdired-mode)
(setq mode-name "Editable Dired")
(setq revert-buffer-function 'wdired-revert)
@@ -363,6 +364,7 @@ non-nil means return old filename."
(setq mode-name "Dired")
(dired-advertise)
(remove-hook 'kill-buffer-hook 'wdired-check-kill-buffer t)
+ (remove-hook 'after-change-functions 'wdired--restore-dired-filename-prop t)
(set (make-local-variable 'revert-buffer-function) 'dired-revert))
@@ -381,7 +383,6 @@ non-nil means return old filename."
(defun wdired-finish-edit ()
"Actually rename files based on your editing in the Dired buffer."
(interactive)
- (wdired-change-to-dired-mode)
(let ((changes nil)
(errors 0)
files-deleted
@@ -423,6 +424,11 @@ non-nil means return old filename."
(forward-line -1)))
(when files-renamed
(setq errors (+ errors (wdired-do-renames files-renamed))))
+ ;; We have to be in wdired-mode when wdired-do-renames is executed
+ ;; so that wdired--restore-dired-filename-prop runs, but we have
+ ;; to change back to dired-mode before reverting the buffer to
+ ;; avoid using wdired-revert, which changes back to wdired-mode.
+ (wdired-change-to-dired-mode)
(if changes
(progn
;; If we are displaying a single file (rather than the
@@ -543,19 +549,25 @@ and proceed depending on the answer."
(goto-char (point-max))
(forward-line -1)
(let ((done nil)
+ (failed t)
curr-filename)
(while (and (not done) (not (bobp)))
(setq curr-filename (wdired-get-filename nil t))
(if (equal curr-filename filename-ori)
- (progn
- (setq done t)
- (let ((inhibit-read-only t))
- (dired-move-to-filename)
- (search-forward (wdired-get-filename t) nil t)
- (replace-match (file-name-nondirectory filename-ori) t t))
- (dired-do-create-files-regexp
- (function dired-rename-file)
- "Move" 1 ".*" filename-new nil t))
+ (unwind-protect
+ (progn
+ (setq done t)
+ (let ((inhibit-read-only t))
+ (dired-move-to-filename)
+ (search-forward (wdired-get-filename t) nil t)
+ (replace-match (file-name-nondirectory filename-ori) t t))
+ (dired-do-create-files-regexp
+ (function dired-rename-file)
+ "Move" 1 ".*" filename-new nil t)
+ (setq failed nil))
+ ;; If user types C-g when prompted to change the file
+ ;; name, make sure we return to dired-mode.
+ (when failed (wdired-change-to-dired-mode)))
(forward-line -1))))))
;; marks a list of files for deletion
@@ -586,6 +598,25 @@ Optional arguments are ignored."
(not (y-or-n-p "Buffer changed. Discard changes and kill buffer? ")))
(error "Error")))
+;; Added to after-change-functions in wdired-change-to-wdired-mode to
+;; ensure that, on editing a file name, new characters get the
+;; dired-filename text property, which allows functions that look for
+;; this property (e.g. dired-isearch-filenames) to work in wdired-mode
+;; and also avoids an error with non-nil wdired-use-interactive-rename
+;; (bug#32173).
+(defun wdired--restore-dired-filename-prop (beg end _len)
+ (save-match-data
+ (save-excursion
+ (beginning-of-line)
+ (when (re-search-forward directory-listing-before-filename-regexp
+ (line-end-position) t)
+ (setq beg (point)
+ end (if (and (file-symlink-p (dired-get-filename))
+ (search-forward " -> " (line-end-position) t))
+ (goto-char (match-beginning 0))
+ (line-end-position)))
+ (put-text-property beg end 'dired-filename t)))))
+
(defun wdired-next-line (arg)
"Move down lines then position at filename or the current column.
See `wdired-use-dired-vertical-movement'. Optional prefix ARG