diff options
| author | Helmut Eller | 2026-04-04 20:59:46 +0200 |
|---|---|---|
| committer | Helmut Eller | 2026-04-04 20:59:46 +0200 |
| commit | 6eec001187e8551f32b6498e6dc60cdc58c2e515 (patch) | |
| tree | 13233de9f0a05ef86a51500e8b1870b75ff20c81 /lisp | |
| parent | e4ea27119e79012f9d651cb61d1115589d91ef39 (diff) | |
| parent | 01a9d78a7e4c7d7fa5b799e4fdc2caf77a012734 (diff) | |
| download | emacs-feature/igc3.tar.gz emacs-feature/igc3.zip | |
Merge branch 'master' into feature/igc3feature/igc3
Diffstat (limited to 'lisp')
64 files changed, 2669 insertions, 2406 deletions
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el index adaa901612a..15dfa2f358f 100644 --- a/lisp/auth-source-pass.el +++ b/lisp/auth-source-pass.el | |||
| @@ -85,6 +85,9 @@ HOST, USER, PORT, REQUIRE, and MAX." | |||
| 85 | ((null host) | 85 | ((null host) |
| 86 | ;; Do not build a result, as none will match when HOST is nil | 86 | ;; Do not build a result, as none will match when HOST is nil |
| 87 | nil) | 87 | nil) |
| 88 | ((not (file-directory-p auth-source-pass-filename)) | ||
| 89 | ;; Do nothing if the password-store folder doesn't exist. | ||
| 90 | nil) | ||
| 88 | (auth-source-pass-extra-query-keywords | 91 | (auth-source-pass-extra-query-keywords |
| 89 | (auth-source-pass--build-result-many host port user require max)) | 92 | (auth-source-pass--build-result-many host port user require max)) |
| 90 | (t | 93 | (t |
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index 52677f435ee..87d8ecade54 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el | |||
| @@ -1084,7 +1084,7 @@ even if it doesn't match the type.) | |||
| 1084 | \(fn [VARIABLE VALUE]...)" | 1084 | \(fn [VARIABLE VALUE]...)" |
| 1085 | (declare (debug setq)) | 1085 | (declare (debug setq)) |
| 1086 | (unless (evenp (length pairs)) | 1086 | (unless (evenp (length pairs)) |
| 1087 | (error "PAIRS must have an even number of variable/value members")) | 1087 | (signal 'wrong-number-of-arguments (list 'setopt (length pairs)))) |
| 1088 | (let ((expr nil)) | 1088 | (let ((expr nil)) |
| 1089 | (while pairs | 1089 | (while pairs |
| 1090 | (unless (symbolp (car pairs)) | 1090 | (unless (symbolp (car pairs)) |
| @@ -1100,12 +1100,54 @@ even if it doesn't match the type.) | |||
| 1100 | ;; Check that the type is correct. | 1100 | ;; Check that the type is correct. |
| 1101 | (when-let* ((type (get variable 'custom-type))) | 1101 | (when-let* ((type (get variable 'custom-type))) |
| 1102 | (unless (widget-apply (widget-convert type) :match value) | 1102 | (unless (widget-apply (widget-convert type) :match value) |
| 1103 | (warn "Value `%S' for variable `%s' does not match its type \"%s\"" | 1103 | (warn "Value does not match %S's type `%S': %S" variable type value))) |
| 1104 | value variable type))) | ||
| 1105 | (put variable 'custom-check-value (list value)) | 1104 | (put variable 'custom-check-value (list value)) |
| 1106 | (funcall (or (get variable 'custom-set) #'set-default) variable value)) | 1105 | (funcall (or (get variable 'custom-set) #'set-default) variable value)) |
| 1107 | 1106 | ||
| 1108 | ;;;###autoload | 1107 | ;;;###autoload |
| 1108 | (defmacro setopt-local (&rest pairs) | ||
| 1109 | "Set buffer local VARIABLE/VALUE pairs, and return the final VALUE. | ||
| 1110 | This is like `setq-local', but is meant for user options instead of | ||
| 1111 | plain variables. This means that `setopt-local' will execute any | ||
| 1112 | `custom-set' form associated with VARIABLE. Unlike `setopt', | ||
| 1113 | `setopt-local' does not affect a user option's global value. | ||
| 1114 | |||
| 1115 | Note that `setopt-local' will emit a warning if the type of a VALUE does | ||
| 1116 | not match the type of the corresponding VARIABLE as declared by | ||
| 1117 | `defcustom'. (VARIABLE will be assigned the value even if it doesn't | ||
| 1118 | match the type.) | ||
| 1119 | |||
| 1120 | Signal an error if a `custom-set' form does not support the | ||
| 1121 | `buffer-local' argument. | ||
| 1122 | |||
| 1123 | \(fn [VARIABLE VALUE]...)" | ||
| 1124 | (declare (debug setq)) | ||
| 1125 | (unless (evenp (length pairs)) | ||
| 1126 | (signal 'wrong-number-of-arguments (list 'setopt-local (length pairs)))) | ||
| 1127 | (let ((expr nil)) | ||
| 1128 | (while pairs | ||
| 1129 | (unless (symbolp (car pairs)) | ||
| 1130 | (error "Attempting to set a non-symbol: %s" (car pairs))) | ||
| 1131 | (push `(setopt--set-local ',(car pairs) ,(cadr pairs)) | ||
| 1132 | expr) | ||
| 1133 | (setq pairs (cddr pairs))) | ||
| 1134 | (macroexp-progn (nreverse expr)))) | ||
| 1135 | |||
| 1136 | ;;;###autoload | ||
| 1137 | (defun setopt--set-local (variable value) | ||
| 1138 | (custom-load-symbol variable) | ||
| 1139 | ;; Check that the type is correct. | ||
| 1140 | (when-let* ((type (get variable 'custom-type))) | ||
| 1141 | (unless (widget-apply (widget-convert type) :match value) | ||
| 1142 | (warn "Value does not match %S's type `%S': %S" variable type value))) | ||
| 1143 | (condition-case _ | ||
| 1144 | (funcall (or (get variable 'custom-set) | ||
| 1145 | (lambda (x v &optional _) (set-local x v))) | ||
| 1146 | variable value 'buffer-local) | ||
| 1147 | (wrong-number-of-arguments | ||
| 1148 | (error "The setter of %S does not support setopt-local" variable)))) | ||
| 1149 | |||
| 1150 | ;;;###autoload | ||
| 1109 | (defun customize-save-variable (variable value &optional comment) | 1151 | (defun customize-save-variable (variable value &optional comment) |
| 1110 | "Set the default for VARIABLE to VALUE, and save it for future sessions. | 1152 | "Set the default for VARIABLE to VALUE, and save it for future sessions. |
| 1111 | Return VALUE. | 1153 | Return VALUE. |
diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el index 0e3c8bf6a5f..9fe2904c415 100644 --- a/lisp/dabbrev.el +++ b/lisp/dabbrev.el | |||
| @@ -398,7 +398,11 @@ then it searches *all* buffers." | |||
| 398 | ;; Set it so `dabbrev-capf' won't reset the vars. | 398 | ;; Set it so `dabbrev-capf' won't reset the vars. |
| 399 | (setq dabbrev--last-abbrev-location (point-marker)) | 399 | (setq dabbrev--last-abbrev-location (point-marker)) |
| 400 | (let ((completion-at-point-functions '(dabbrev-capf))) | 400 | (let ((completion-at-point-functions '(dabbrev-capf))) |
| 401 | (completion-at-point))) | 401 | (unless (completion-at-point) |
| 402 | (user-error "No dynamic expansion for \"%s\" found%s" | ||
| 403 | (dabbrev--abbrev-at-point) | ||
| 404 | (if dabbrev--check-other-buffers | ||
| 405 | "" " in this-buffer"))))) | ||
| 402 | 406 | ||
| 403 | (defun dabbrev-capf () | 407 | (defun dabbrev-capf () |
| 404 | "Dabbrev completion function for `completion-at-point-functions'." | 408 | "Dabbrev completion function for `completion-at-point-functions'." |
diff --git a/lisp/desktop.el b/lisp/desktop.el index f478cf2307b..0cdd554e295 100644 --- a/lisp/desktop.el +++ b/lisp/desktop.el | |||
| @@ -775,6 +775,7 @@ if different)." | |||
| 775 | ;; Don't delete daemon's initial frame, or | 775 | ;; Don't delete daemon's initial frame, or |
| 776 | ;; we'll never be able to close the last | 776 | ;; we'll never be able to close the last |
| 777 | ;; client's frame (Bug#26912). | 777 | ;; client's frame (Bug#26912). |
| 778 | ;; Use `frame-initial-p'? | ||
| 778 | (and (daemonp) (eq frame terminal-frame)) | 779 | (and (daemonp) (eq frame terminal-frame)) |
| 779 | (frame-parameter frame 'desktop-dont-clear)) | 780 | (frame-parameter frame 'desktop-dont-clear)) |
| 780 | (delete-frame frame)) | 781 | (delete-frame frame)) |
| @@ -1067,9 +1068,8 @@ DIRNAME must be the directory in which the desktop file will be saved." | |||
| 1067 | (and (not (frame-parameter frame 'desktop-dont-save)) | 1068 | (and (not (frame-parameter frame 'desktop-dont-save)) |
| 1068 | ;; Don't save daemon initial frames, since we cannot (and don't | 1069 | ;; Don't save daemon initial frames, since we cannot (and don't |
| 1069 | ;; need to) restore them. | 1070 | ;; need to) restore them. |
| 1070 | (not (and (daemonp) | 1071 | (not (and (daemonp) ;; FIXME: Remove `daemonp'? |
| 1071 | (equal (terminal-name (frame-terminal frame)) | 1072 | (frame-initial-p frame))))) |
| 1072 | "initial_terminal"))))) | ||
| 1073 | 1073 | ||
| 1074 | (defconst desktop--app-id `(desktop . ,desktop-file-version)) | 1074 | (defconst desktop--app-id `(desktop . ,desktop-file-version)) |
| 1075 | 1075 | ||
| @@ -1260,7 +1260,7 @@ This function also sets `desktop-dirname' to nil." | |||
| 1260 | "True if calling `desktop-restore-frameset' will actually restore it." | 1260 | "True if calling `desktop-restore-frameset' will actually restore it." |
| 1261 | (and desktop-restore-frames desktop-saved-frameset | 1261 | (and desktop-restore-frames desktop-saved-frameset |
| 1262 | ;; Don't restore frames when the selected frame is the daemon's | 1262 | ;; Don't restore frames when the selected frame is the daemon's |
| 1263 | ;; initial frame. | 1263 | ;; initial frame. Use `frame-initial-p'? |
| 1264 | (not (and (daemonp) (eq (selected-frame) terminal-frame))) | 1264 | (not (and (daemonp) (eq (selected-frame) terminal-frame))) |
| 1265 | t)) | 1265 | t)) |
| 1266 | 1266 | ||
diff --git a/lisp/dired.el b/lisp/dired.el index 7f598433a9d..4aded86e40d 100644 --- a/lisp/dired.el +++ b/lisp/dired.el | |||
| @@ -649,6 +649,10 @@ The match starts at the beginning of the line and ends after the end | |||
| 649 | of the line. | 649 | of the line. |
| 650 | Subexpression 2 must end right before the \\n.") | 650 | Subexpression 2 must end right before the \\n.") |
| 651 | 651 | ||
| 652 | (defvar dired--ls-error-buffer nil | ||
| 653 | "Non-nil if the current dired invocation yields an `ls' error. | ||
| 654 | The non-nil value is the buffer containing the error message.") | ||
| 655 | |||
| 652 | 656 | ||
| 653 | ;;; Faces | 657 | ;;; Faces |
| 654 | 658 | ||
| @@ -1230,7 +1234,16 @@ Type \\[describe-mode] after entering Dired for more info. | |||
| 1230 | If DIRNAME is already in a Dired buffer, that buffer is used without refresh." | 1234 | If DIRNAME is already in a Dired buffer, that buffer is used without refresh." |
| 1231 | ;; Cannot use (interactive "D") because of wildcards. | 1235 | ;; Cannot use (interactive "D") because of wildcards. |
| 1232 | (interactive (dired-read-dir-and-switches "")) | 1236 | (interactive (dired-read-dir-and-switches "")) |
| 1233 | (pop-to-buffer-same-window (dired-noselect dirname switches))) | 1237 | (prog1 (pop-to-buffer-same-window (dired-noselect dirname switches)) |
| 1238 | (dired--display-ls-error))) | ||
| 1239 | |||
| 1240 | ;; This is needed to let clicks on the menu bar invoke Dired even if | ||
| 1241 | ;; some feature remaps the Dired command to another command. | ||
| 1242 | ;;;###autoload | ||
| 1243 | (defun dired-from-menubar (dirname &optional switches) | ||
| 1244 | "Edit an existing directory." | ||
| 1245 | (interactive (dired-read-dir-and-switches "")) | ||
| 1246 | (dired dirname switches)) | ||
| 1234 | 1247 | ||
| 1235 | ;;;###autoload (keymap-set ctl-x-4-map "d" #'dired-other-window) | 1248 | ;;;###autoload (keymap-set ctl-x-4-map "d" #'dired-other-window) |
| 1236 | ;;;###autoload | 1249 | ;;;###autoload |
| @@ -1240,21 +1253,24 @@ If this command needs to split the current window, it by default obeys | |||
| 1240 | the user options `split-height-threshold' and `split-width-threshold', | 1253 | the user options `split-height-threshold' and `split-width-threshold', |
| 1241 | when it decides whether to split the window horizontally or vertically." | 1254 | when it decides whether to split the window horizontally or vertically." |
| 1242 | (interactive (dired-read-dir-and-switches "in other window ")) | 1255 | (interactive (dired-read-dir-and-switches "in other window ")) |
| 1243 | (switch-to-buffer-other-window (dired-noselect dirname switches))) | 1256 | (prog1 (switch-to-buffer-other-window (dired-noselect dirname switches)) |
| 1257 | (dired--display-ls-error))) | ||
| 1244 | 1258 | ||
| 1245 | ;;;###autoload (keymap-set ctl-x-5-map "d" #'dired-other-frame) | 1259 | ;;;###autoload (keymap-set ctl-x-5-map "d" #'dired-other-frame) |
| 1246 | ;;;###autoload | 1260 | ;;;###autoload |
| 1247 | (defun dired-other-frame (dirname &optional switches) | 1261 | (defun dired-other-frame (dirname &optional switches) |
| 1248 | "\"Edit\" directory DIRNAME. Like `dired' but make a new frame." | 1262 | "\"Edit\" directory DIRNAME. Like `dired' but make a new frame." |
| 1249 | (interactive (dired-read-dir-and-switches "in other frame ")) | 1263 | (interactive (dired-read-dir-and-switches "in other frame ")) |
| 1250 | (switch-to-buffer-other-frame (dired-noselect dirname switches))) | 1264 | (prog1 (switch-to-buffer-other-frame (dired-noselect dirname switches)) |
| 1265 | (dired--display-ls-error))) | ||
| 1251 | 1266 | ||
| 1252 | ;;;###autoload (keymap-set tab-prefix-map "d" #'dired-other-tab) | 1267 | ;;;###autoload (keymap-set tab-prefix-map "d" #'dired-other-tab) |
| 1253 | ;;;###autoload | 1268 | ;;;###autoload |
| 1254 | (defun dired-other-tab (dirname &optional switches) | 1269 | (defun dired-other-tab (dirname &optional switches) |
| 1255 | "\"Edit\" directory DIRNAME. Like `dired' but make a new tab." | 1270 | "\"Edit\" directory DIRNAME. Like `dired' but make a new tab." |
| 1256 | (interactive (dired-read-dir-and-switches "in other tab ")) | 1271 | (interactive (dired-read-dir-and-switches "in other tab ")) |
| 1257 | (switch-to-buffer-other-tab (dired-noselect dirname switches))) | 1272 | (prog1 (switch-to-buffer-other-tab (dired-noselect dirname switches)) |
| 1273 | (dired--display-ls-error))) | ||
| 1258 | 1274 | ||
| 1259 | ;;;###autoload | 1275 | ;;;###autoload |
| 1260 | (defun dired-noselect (dir-or-list &optional switches) | 1276 | (defun dired-noselect (dir-or-list &optional switches) |
| @@ -1439,10 +1455,19 @@ The return value is the target column for the file names." | |||
| 1439 | (let ((failed t)) | 1455 | (let ((failed t)) |
| 1440 | (unwind-protect | 1456 | (unwind-protect |
| 1441 | (progn (dired-readin) | 1457 | (progn (dired-readin) |
| 1442 | (setq failed nil)) | 1458 | ;; Check for file entries (they are listed below the |
| 1443 | ;; dired-readin can fail if parent directories are inaccessible. | 1459 | ;; directory name and (if present) wildcard lines). |
| 1444 | ;; Don't leave an empty buffer around in that case. | 1460 | (while (and (skip-syntax-forward "\s") |
| 1445 | (if failed (kill-buffer buffer)))) | 1461 | (looking-at "\\(.+:$\\|wildcard\\)")) |
| 1462 | (forward-line)) | ||
| 1463 | (unless (eobp) | ||
| 1464 | (setq failed nil))) | ||
| 1465 | ;; No file entries indicates an `ls' error, and `dired-readin' | ||
| 1466 | ;; can fail if parent directories are inaccessible. In either | ||
| 1467 | ;; case don't leave the Dired buffer around. | ||
| 1468 | (when failed | ||
| 1469 | (kill-buffer buffer) | ||
| 1470 | (setq buffer nil)))) | ||
| 1446 | (goto-char (point-min)) | 1471 | (goto-char (point-min)) |
| 1447 | (dired-initial-position dirname)) | 1472 | (dired-initial-position dirname)) |
| 1448 | (when (consp dired-directory) | 1473 | (when (consp dired-directory) |
| @@ -4003,20 +4028,11 @@ Considers buffers closer to the car of `buffer-list' to be more recent." | |||
| 4003 | (not (memq buffer1 (memq buffer2 (buffer-list)))))) | 4028 | (not (memq buffer1 (memq buffer2 (buffer-list)))))) |
| 4004 | 4029 | ||
| 4005 | (defun dired--filename-with-newline-p () | 4030 | (defun dired--filename-with-newline-p () |
| 4006 | "Check if a file name in this directory has a newline. | 4031 | "Check whether a file name in this directory has a newline. |
| 4007 | Return non-nil if at least one file name in this directory contains | 4032 | Return non-nil if at least one file name in this directory contains a |
| 4008 | either a literal newline or the string \"\\n\")." | 4033 | newline character (regardless of whether Dired displays the character as |
| 4009 | (save-excursion | 4034 | a literal newline or as \"\\n\")." |
| 4010 | (goto-char (point-min)) | 4035 | (directory-files default-directory nil "\n")) |
| 4011 | (catch 'found | ||
| 4012 | (while (not (eobp)) | ||
| 4013 | (when (dired-move-to-filename) | ||
| 4014 | (let ((fn (buffer-substring-no-properties | ||
| 4015 | (point) (dired-move-to-end-of-filename)))) | ||
| 4016 | (when (or (memq 10 (seq-into fn 'list)) | ||
| 4017 | (string-search "\\n" fn)) | ||
| 4018 | (throw 'found t)))) | ||
| 4019 | (forward-line))))) | ||
| 4020 | 4036 | ||
| 4021 | (defun dired--remove-b-switch () | 4037 | (defun dired--remove-b-switch () |
| 4022 | "Remove all variants of the `b' switch from `dired-actual-switches'. | 4038 | "Remove all variants of the `b' switch from `dired-actual-switches'. |
| @@ -4094,6 +4110,13 @@ See `%s' for other alternatives and more information.")) | |||
| 4094 | (set-window-point (get-buffer-window) | 4110 | (set-window-point (get-buffer-window) |
| 4095 | (search-backward "Warning (dired)"))))) | 4111 | (search-backward "Warning (dired)"))))) |
| 4096 | 4112 | ||
| 4113 | (defun dired--display-ls-error () | ||
| 4114 | "Pop up a buffer displaying the current `ls' error, if any." | ||
| 4115 | (when dired--ls-error-buffer | ||
| 4116 | (let* ((errwin (display-buffer dired--ls-error-buffer))) | ||
| 4117 | (fit-window-to-buffer errwin)) | ||
| 4118 | (setq dired--ls-error-buffer nil))) | ||
| 4119 | |||
| 4097 | 4120 | ||
| 4098 | ;;; Deleting files | 4121 | ;;; Deleting files |
| 4099 | 4122 | ||
diff --git a/lisp/display-fill-column-indicator.el b/lisp/display-fill-column-indicator.el index 349a470ab41..b661f20e22a 100644 --- a/lisp/display-fill-column-indicator.el +++ b/lisp/display-fill-column-indicator.el | |||
| @@ -102,6 +102,7 @@ See Info node `Displaying Boundaries' for details." | |||
| 102 | (defun display-fill-column-indicator--turn-on () | 102 | (defun display-fill-column-indicator--turn-on () |
| 103 | "Turn on `display-fill-column-indicator-mode'." | 103 | "Turn on `display-fill-column-indicator-mode'." |
| 104 | (unless (or (minibufferp) | 104 | (unless (or (minibufferp) |
| 105 | ;; Use `frame-initial-p'? | ||
| 105 | (and (daemonp) (eq (selected-frame) terminal-frame))) | 106 | (and (daemonp) (eq (selected-frame) terminal-frame))) |
| 106 | (display-fill-column-indicator-mode))) | 107 | (display-fill-column-indicator-mode))) |
| 107 | 108 | ||
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index ce2d8ac47c4..7ed71346451 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el | |||
| @@ -1901,6 +1901,8 @@ See Info node `(elisp) Integer Basics'." | |||
| 1901 | sqlite-available-p sqlitep | 1901 | sqlite-available-p sqlitep |
| 1902 | ;; syntax.c | 1902 | ;; syntax.c |
| 1903 | standard-syntax-table syntax-table syntax-table-p | 1903 | standard-syntax-table syntax-table syntax-table-p |
| 1904 | ;; terminal.c | ||
| 1905 | frame-initial-p | ||
| 1904 | ;; thread.c | 1906 | ;; thread.c |
| 1905 | current-thread | 1907 | current-thread |
| 1906 | ;; timefns.c | 1908 | ;; timefns.c |
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index 3019ada1bbd..ec2aa0ad728 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el | |||
| @@ -195,8 +195,7 @@ the debugger will not be entered." | |||
| 195 | ;; backtrace to stdout. This happens for example while | 195 | ;; backtrace to stdout. This happens for example while |
| 196 | ;; handling an error in code from early-init.el with | 196 | ;; handling an error in code from early-init.el with |
| 197 | ;; --debug-init. | 197 | ;; --debug-init. |
| 198 | (and (eq t (framep (selected-frame))) | 198 | (frame-initial-p))) |
| 199 | (equal "initial_terminal" (terminal-name))))) | ||
| 200 | ;; Don't let `inhibit-message' get in our way (especially important if | 199 | ;; Don't let `inhibit-message' get in our way (especially important if |
| 201 | ;; `non-interactive-frame' evaluated to a non-nil value. | 200 | ;; `non-interactive-frame' evaluated to a non-nil value. |
| 202 | (inhibit-message nil) | 201 | (inhibit-message nil) |
diff --git a/lisp/emacs-lisp/shortdoc-doc.el b/lisp/emacs-lisp/shortdoc-doc.el new file mode 100644 index 00000000000..eb642c1600b --- /dev/null +++ b/lisp/emacs-lisp/shortdoc-doc.el | |||
| @@ -0,0 +1,1528 @@ | |||
| 1 | ;;; shortdoc-doc.el --- Builtin shortdoc groups -*- lexical-binding: t -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2020-2026 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Keywords: lisp, help | ||
| 6 | ;; Package: emacs | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 13 | ;; (at your option) any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 22 | |||
| 23 | ;;; Commentary: | ||
| 24 | |||
| 25 | ;; This file defines builtin Emacs shortdoc groups. | ||
| 26 | ;; | ||
| 27 | ;; If a shortdoc group describes builtin functions, functions from | ||
| 28 | ;; subr.el or simple.el or otherwise preloaded files, or functions from | ||
| 29 | ;; different files, then you should probably define it in this file. | ||
| 30 | ;; Otherwise, you might as well define the shortdoc group in the file | ||
| 31 | ;; where the documented functions live, like treesit.el does it. | ||
| 32 | |||
| 33 | ;;; Code: | ||
| 34 | |||
| 35 | (define-short-documentation-group alist | ||
| 36 | "Alist Basics" | ||
| 37 | (assoc | ||
| 38 | :eval (assoc 'foo '((foo . bar) (zot . baz)))) | ||
| 39 | (rassoc | ||
| 40 | :eval (rassoc 'bar '((foo . bar) (zot . baz)))) | ||
| 41 | (assq | ||
| 42 | :eval (assq 'foo '((foo . bar) (zot . baz)))) | ||
| 43 | (rassq | ||
| 44 | :eval (rassq 'bar '((foo . bar) (zot . baz)))) | ||
| 45 | (assoc-string | ||
| 46 | :eval (assoc-string "foo" '(("foo" . "bar") ("zot" "baz")))) | ||
| 47 | "Manipulating Alists" | ||
| 48 | (assoc-delete-all | ||
| 49 | :eval (assoc-delete-all "b" (list '("a" . a) '("b" . b) '("b" . c)))) | ||
| 50 | (assq-delete-all | ||
| 51 | :eval (assq-delete-all 2 (list '(1 . a) '(2 . b) '(2 . c)))) | ||
| 52 | (rassq-delete-all | ||
| 53 | :eval (rassq-delete-all 'b (list '(1 . a) '(2 . b) '(2 . c)))) | ||
| 54 | (alist-get | ||
| 55 | :eval (let ((foo '((bar . baz)))) | ||
| 56 | (setf (alist-get 'bar foo) 'zot) | ||
| 57 | foo)) | ||
| 58 | "Misc" | ||
| 59 | (assoc-default | ||
| 60 | :eval (assoc-default "foobar" '(("foo" . baz)) #'string-match)) | ||
| 61 | (copy-alist | ||
| 62 | :eval (let* ((old '((foo . bar))) | ||
| 63 | (new (copy-alist old))) | ||
| 64 | (eq old new))) | ||
| 65 | ;; FIXME: Outputs "\.rose" for the symbol `.rose'. It would be | ||
| 66 | ;; better if that could be cleaned up. | ||
| 67 | (let-alist | ||
| 68 | :eval (let ((colors '((rose . red) | ||
| 69 | (lily . white)))) | ||
| 70 | (let-alist colors | ||
| 71 | (if (eq .rose 'red) | ||
| 72 | .lily))))) | ||
| 73 | |||
| 74 | (define-short-documentation-group map | ||
| 75 | "Map Basics" | ||
| 76 | (mapp | ||
| 77 | :eval (mapp (list 'bar 1 'foo 2 'baz 3)) | ||
| 78 | :eval (mapp (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 79 | :eval (mapp [bar foo baz]) | ||
| 80 | :eval (mapp "this is a string") | ||
| 81 | :eval (mapp #s(hash-table data (bar 1 foo 2 baz 3))) | ||
| 82 | :eval (mapp '()) | ||
| 83 | :eval (mapp nil) | ||
| 84 | :eval (mapp (make-char-table 'shortdoc-test))) | ||
| 85 | (map-empty-p | ||
| 86 | :args (map) | ||
| 87 | :eval (map-empty-p nil) | ||
| 88 | :eval (map-empty-p []) | ||
| 89 | :eval (map-empty-p '())) | ||
| 90 | (map-elt | ||
| 91 | :args (map key) | ||
| 92 | :eval (map-elt (list 'bar 1 'foo 2 'baz 3) 'foo) | ||
| 93 | :eval (map-elt (list '(bar . 1) '(foo . 2) '(baz . 3)) 'foo) | ||
| 94 | :eval (map-elt [bar foo baz] 1) | ||
| 95 | :eval (map-elt #s(hash-table data (bar 1 foo 2 baz 3)) 'foo)) | ||
| 96 | (map-contains-key | ||
| 97 | :args (map key) | ||
| 98 | :eval (map-contains-key (list 'bar 1 'foo 2 'baz 3) 'foo) | ||
| 99 | :eval (map-contains-key (list '(bar . 1) '(foo . 2) '(baz . 3)) 'foo) | ||
| 100 | :eval (map-contains-key [bar foo baz] 1) | ||
| 101 | :eval (map-contains-key #s(hash-table data (bar 1 foo 2 baz 3)) 'foo)) | ||
| 102 | (map-put! | ||
| 103 | :args (map key value) | ||
| 104 | :eval | ||
| 105 | "(let ((map (list 'bar 1 'baz 3))) | ||
| 106 | (map-put! map 'foo 2) | ||
| 107 | map)" | ||
| 108 | ;; This signals map-not-inplace when used in shortdoc.el :-( | ||
| 109 | ;; :eval | ||
| 110 | ;; "(let ((map (list '(bar . 1) '(baz . 3)))) | ||
| 111 | ;; (map-put! map 'foo 2) | ||
| 112 | ;; map)" | ||
| 113 | :eval | ||
| 114 | "(let ((map [bar bot baz])) | ||
| 115 | (map-put! map 1 'foo) | ||
| 116 | map)" | ||
| 117 | :eval | ||
| 118 | "(let ((map #s(hash-table data (bar 1 baz 3)))) | ||
| 119 | (map-put! map 'foo 2) | ||
| 120 | map)") | ||
| 121 | (map-insert | ||
| 122 | :args (map key value) | ||
| 123 | :eval (map-insert (list 'bar 1 'baz 3 'foo 7) 'foo 2) | ||
| 124 | :eval (map-insert (list '(bar . 1) '(baz . 3) '(foo . 7)) 'foo 2) | ||
| 125 | :eval (map-insert [bar bot baz] 1 'foo) | ||
| 126 | :eval (map-insert #s(hash-table data (bar 1 baz 3 foo 7)) 'foo 2)) | ||
| 127 | (map-delete | ||
| 128 | :args (map key) | ||
| 129 | :eval (map-delete (list 'bar 1 'foo 2 'baz 3) 'foo) | ||
| 130 | :eval (map-delete (list '(bar . 1) '(foo . 2) '(baz . 3)) 'foo) | ||
| 131 | :eval (map-delete [bar foo baz] 1) | ||
| 132 | :eval (map-delete #s(hash-table data (bar 1 foo 2 baz 3)) 'foo)) | ||
| 133 | (map-keys | ||
| 134 | :eval (map-keys (list 'bar 1 'foo 2 'baz 3)) | ||
| 135 | :eval (map-keys (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 136 | :eval (map-keys [bar foo baz]) | ||
| 137 | :eval (map-keys #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 138 | (map-values | ||
| 139 | :args (map) | ||
| 140 | :eval (map-values (list 'bar 1 'foo 2 'baz 3)) | ||
| 141 | :eval (map-values (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 142 | :eval (map-values [bar foo baz]) | ||
| 143 | :eval (map-values #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 144 | (map-pairs | ||
| 145 | :eval (map-pairs (list 'bar 1 'foo 2 'baz 3)) | ||
| 146 | :eval (map-pairs (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 147 | :eval (map-pairs [bar foo baz]) | ||
| 148 | :eval (map-pairs #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 149 | (map-length | ||
| 150 | :args (map) | ||
| 151 | :eval (map-length (list 'bar 1 'foo 2 'baz 3)) | ||
| 152 | :eval (map-length (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 153 | :eval (map-length [bar foo baz]) | ||
| 154 | :eval (map-length #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 155 | (map-copy | ||
| 156 | :args (map) | ||
| 157 | :eval (map-copy (list 'bar 1 'foo 2 'baz 3)) | ||
| 158 | :eval (map-copy (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 159 | :eval (map-copy [bar foo baz]) | ||
| 160 | :eval (map-copy #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 161 | "Doing things to maps and their contents" | ||
| 162 | (map-apply | ||
| 163 | :args (function map) | ||
| 164 | :eval (map-apply #'+ (list '(1 . 2) '(3 . 4)))) | ||
| 165 | (map-do | ||
| 166 | :args (function map) | ||
| 167 | :eval | ||
| 168 | "(let ((map (list '(1 . 1) '(2 . 3))) | ||
| 169 | acc) | ||
| 170 | (map-do (lambda (k v) (push (+ k v) acc)) map) | ||
| 171 | (nreverse acc))") | ||
| 172 | (map-keys-apply | ||
| 173 | :eval (map-keys-apply #'1+ (list '(1 . 2) '(3 . 4)))) | ||
| 174 | (map-values-apply | ||
| 175 | :args (function map) | ||
| 176 | :eval (map-values-apply #'1+ (list '(1 . 2) '(3 . 4)))) | ||
| 177 | (map-filter | ||
| 178 | :eval (map-filter (lambda (k _) (oddp k)) (list '(1 . 2) '(4 . 6))) | ||
| 179 | :eval (map-filter (lambda (k v) (evenp (+ k v))) (list '(1 . 2) '(4 . 6)))) | ||
| 180 | (map-remove | ||
| 181 | :eval (map-remove (lambda (k _) (oddp k)) (list '(1 . 2) '(4 . 6))) | ||
| 182 | :eval (map-remove (lambda (k v) (evenp (+ k v))) (list '(1 . 2) '(4 . 6)))) | ||
| 183 | (map-some | ||
| 184 | :eval (map-some (lambda (k _) (oddp k)) (list '(1 . 2) '(4 . 6))) | ||
| 185 | :eval (map-some (lambda (k v) (evenp (+ k v))) (list '(1 . 2) '(4 . 6)))) | ||
| 186 | (map-every-p | ||
| 187 | :eval (map-every-p (lambda (k _) (oddp k)) (list '(1 . 2) '(4 . 6))) | ||
| 188 | :eval (map-every-p (lambda (k v) (evenp (+ k v))) (list '(1 . 3) '(4 . 6)))) | ||
| 189 | "Combining and changing maps" | ||
| 190 | (map-merge | ||
| 191 | :eval (map-merge 'alist '(1 2 3 4) #s(hash-table data (5 6 7 8))) | ||
| 192 | :eval (map-merge 'list '(1 2 3 4) #s(hash-table data (5 6 7 8))) | ||
| 193 | :eval (map-merge 'plist '(1 2 3 4) #s(hash-table data (5 6 7 8))) | ||
| 194 | :eval (map-merge 'hash-table '(1 2 3 4) #s(hash-table data (5 6 7 8)))) | ||
| 195 | (map-merge-with | ||
| 196 | :eval (map-merge-with 'alist #'max '(1 2 3 4) #s(hash-table data (1 1 3 5))) | ||
| 197 | :eval (map-merge-with 'alist #'min '(1 2 3 4) #s(hash-table data (1 1 3 5))) | ||
| 198 | :eval (map-merge-with 'hash-table #'min '(1 2 3 4) #s(hash-table data (1 1 3 5)))) | ||
| 199 | (map-into | ||
| 200 | :args (map type) | ||
| 201 | :eval (map-into #s(hash-table data '(5 6 7 8)) 'list) | ||
| 202 | :eval (map-into '((5 . 6) (7 . 8)) 'plist) | ||
| 203 | :eval (map-into '((5 . 6) (7 . 8)) 'hash-table))) | ||
| 204 | |||
| 205 | (define-short-documentation-group string | ||
| 206 | "Making Strings" | ||
| 207 | (make-string | ||
| 208 | :args (length init) | ||
| 209 | :eval "(make-string 5 ?x)") | ||
| 210 | (string | ||
| 211 | :eval "(string ?a ?b ?c)") | ||
| 212 | (concat | ||
| 213 | :eval (concat "foo" "bar" "zot")) | ||
| 214 | (string-join | ||
| 215 | :no-manual t | ||
| 216 | :eval (string-join '("foo" "bar" "zot") " ")) | ||
| 217 | (mapconcat | ||
| 218 | :eval (mapconcat (lambda (a) (concat "[" a "]")) | ||
| 219 | '("foo" "bar" "zot") " ")) | ||
| 220 | (string-pad | ||
| 221 | :eval (string-pad "foo" 5) | ||
| 222 | :eval (string-pad "foobar" 5) | ||
| 223 | :eval (string-pad "foo" 5 ?- t)) | ||
| 224 | (mapcar | ||
| 225 | :eval (mapcar #'identity "123")) | ||
| 226 | (format | ||
| 227 | :eval (format "This number is %d" 4)) | ||
| 228 | "Manipulating Strings" | ||
| 229 | (substring | ||
| 230 | :eval (substring "abcde" 1 3) | ||
| 231 | :eval (substring "abcde" 2) | ||
| 232 | :eval (substring "abcde" 1 -1) | ||
| 233 | :eval (substring "abcde" -4 4)) | ||
| 234 | (string-limit | ||
| 235 | :eval (string-limit "foobar" 3) | ||
| 236 | :eval (string-limit "foobar" 3 t) | ||
| 237 | :eval (string-limit "foobar" 10) | ||
| 238 | :eval (string-limit "fo好" 3 nil 'utf-8)) | ||
| 239 | (truncate-string-to-width | ||
| 240 | :eval (truncate-string-to-width "foobar" 3) | ||
| 241 | :eval (truncate-string-to-width "你好bar" 5)) | ||
| 242 | (split-string | ||
| 243 | :eval (split-string "foo bar") | ||
| 244 | :eval (split-string "|foo|bar|" "|") | ||
| 245 | :eval (split-string "|foo|bar|" "|" t)) | ||
| 246 | (split-string-and-unquote | ||
| 247 | :eval (split-string-and-unquote "foo \"bar zot\"")) | ||
| 248 | (split-string-shell-command | ||
| 249 | :eval (split-string-shell-command "ls /tmp/'foo bar'")) | ||
| 250 | (string-lines | ||
| 251 | :eval (string-lines "foo\n\nbar") | ||
| 252 | :eval (string-lines "foo\n\nbar" t)) | ||
| 253 | (string-replace | ||
| 254 | :eval (string-replace "foo" "bar" "foozot")) | ||
| 255 | (replace-regexp-in-string | ||
| 256 | :eval (replace-regexp-in-string "[a-z]+" "_" "*foo*")) | ||
| 257 | (string-trim | ||
| 258 | :args (string) | ||
| 259 | :doc "Trim STRING of leading and trailing white space." | ||
| 260 | :eval (string-trim " foo ")) | ||
| 261 | (string-trim-left | ||
| 262 | :eval (string-trim-left "oofoo" "o+")) | ||
| 263 | (string-trim-right | ||
| 264 | :eval (string-trim-right "barkss" "s+")) | ||
| 265 | (string-truncate-left | ||
| 266 | :no-manual t | ||
| 267 | :eval (string-truncate-left "longstring" 8)) | ||
| 268 | (string-remove-suffix | ||
| 269 | :no-manual t | ||
| 270 | :eval (string-remove-suffix "bar" "foobar")) | ||
| 271 | (string-remove-prefix | ||
| 272 | :no-manual t | ||
| 273 | :eval (string-remove-prefix "foo" "foobar")) | ||
| 274 | (string-chop-newline | ||
| 275 | :eval (string-chop-newline "foo\n")) | ||
| 276 | (string-clean-whitespace | ||
| 277 | :eval (string-clean-whitespace " foo bar ")) | ||
| 278 | (string-fill | ||
| 279 | :eval (string-fill "Three short words" 12) | ||
| 280 | :eval (string-fill "Long-word" 3)) | ||
| 281 | (reverse | ||
| 282 | :eval (reverse "foo")) | ||
| 283 | (substring-no-properties | ||
| 284 | :eval (substring-no-properties (propertize "foobar" 'face 'bold) 0 3)) | ||
| 285 | (try-completion | ||
| 286 | :eval (try-completion "foo" '("foobar" "foozot" "gazonk"))) | ||
| 287 | "Unicode Strings" | ||
| 288 | (string-glyph-split | ||
| 289 | :eval (string-glyph-split "Hello, 👼🏻🧑🏼🤝🧑🏻")) | ||
| 290 | (string-glyph-compose | ||
| 291 | :eval (string-glyph-compose "Å")) | ||
| 292 | (string-glyph-decompose | ||
| 293 | :eval (string-glyph-decompose "Å")) | ||
| 294 | "Predicates for Strings" | ||
| 295 | (string-equal | ||
| 296 | :eval (string-equal "abc" "abc") | ||
| 297 | :eval (string-equal "abc" "ABC")) | ||
| 298 | (string-equal-ignore-case | ||
| 299 | :eval (string-equal-ignore-case "foo" "FOO")) | ||
| 300 | (equal | ||
| 301 | :eval (equal "foo" "foo")) | ||
| 302 | (cl-equalp | ||
| 303 | :eval (cl-equalp "Foo" "foo")) | ||
| 304 | (stringp | ||
| 305 | :eval (stringp "a") | ||
| 306 | :eval (stringp 'a) | ||
| 307 | :eval "(stringp ?a)") | ||
| 308 | (string-or-null-p | ||
| 309 | :eval (string-or-null-p "a") | ||
| 310 | :eval (string-or-null-p nil)) | ||
| 311 | (char-or-string-p | ||
| 312 | :eval "(char-or-string-p ?a)" | ||
| 313 | :eval (char-or-string-p "a")) | ||
| 314 | (string-empty-p | ||
| 315 | :no-manual t | ||
| 316 | :eval (string-empty-p "")) | ||
| 317 | (string-blank-p | ||
| 318 | :no-manual t | ||
| 319 | :eval (string-blank-p " \n")) | ||
| 320 | (string-lessp | ||
| 321 | :eval (string-lessp "abc" "def") | ||
| 322 | :eval (string-lessp "pic4.png" "pic32.png") | ||
| 323 | :eval (string-lessp "1.1" "1.2")) | ||
| 324 | (string-greaterp | ||
| 325 | :eval (string-greaterp "foo" "bar")) | ||
| 326 | (string-version-lessp | ||
| 327 | :eval (string-version-lessp "pic4.png" "pic32.png") | ||
| 328 | :eval (string-version-lessp "1.9.3" "1.10.2")) | ||
| 329 | (string-collate-lessp | ||
| 330 | :eval (string-collate-lessp "abc" "abd")) | ||
| 331 | (string-prefix-p | ||
| 332 | :eval (string-prefix-p "foo" "foobar")) | ||
| 333 | (string-suffix-p | ||
| 334 | :eval (string-suffix-p "bar" "foobar")) | ||
| 335 | "Case Manipulation" | ||
| 336 | (upcase | ||
| 337 | :eval (upcase "foo")) | ||
| 338 | (downcase | ||
| 339 | :eval (downcase "FOObar")) | ||
| 340 | (capitalize | ||
| 341 | :eval (capitalize "foo bar zot")) | ||
| 342 | (upcase-initials | ||
| 343 | :eval (upcase-initials "The CAT in the hAt")) | ||
| 344 | "Converting Strings" | ||
| 345 | (string-to-number | ||
| 346 | :eval (string-to-number "42") | ||
| 347 | :eval (string-to-number "deadbeef" 16) | ||
| 348 | :eval (string-to-number "2.5e+03")) | ||
| 349 | (number-to-string | ||
| 350 | :eval (number-to-string 42)) | ||
| 351 | (char-uppercase-p | ||
| 352 | :eval "(char-uppercase-p ?A)" | ||
| 353 | :eval "(char-uppercase-p ?a)") | ||
| 354 | "Data About Strings" | ||
| 355 | (length | ||
| 356 | :eval (length "foo") | ||
| 357 | :eval (length "avocado: 🥑")) | ||
| 358 | (string-width | ||
| 359 | :eval (string-width "foo") | ||
| 360 | :eval (string-width "avocado: 🥑")) | ||
| 361 | (string-pixel-width | ||
| 362 | :eval (string-pixel-width "foo") | ||
| 363 | :eval (string-pixel-width "avocado: 🥑")) | ||
| 364 | (string-search | ||
| 365 | :eval (string-search "bar" "foobarzot")) | ||
| 366 | (assoc-string | ||
| 367 | :eval (assoc-string "foo" '(("a" 1) (foo 2)))) | ||
| 368 | (seq-position | ||
| 369 | :eval "(seq-position \"foobarzot\" ?z)")) | ||
| 370 | |||
| 371 | (define-short-documentation-group file-name | ||
| 372 | "File Name Manipulation" | ||
| 373 | (file-name-directory | ||
| 374 | :eval (file-name-directory "/tmp/foo") | ||
| 375 | :eval (file-name-directory "/tmp/foo/")) | ||
| 376 | (file-name-nondirectory | ||
| 377 | :eval (file-name-nondirectory "/tmp/foo") | ||
| 378 | :eval (file-name-nondirectory "/tmp/foo/")) | ||
| 379 | (file-name-sans-versions | ||
| 380 | :args (filename) | ||
| 381 | :eval (file-name-sans-versions "/tmp/foo~")) | ||
| 382 | (file-name-extension | ||
| 383 | :eval (file-name-extension "/tmp/foo.txt")) | ||
| 384 | (file-name-sans-extension | ||
| 385 | :eval (file-name-sans-extension "/tmp/foo.txt")) | ||
| 386 | (file-name-with-extension | ||
| 387 | :eval (file-name-with-extension "foo.txt" "bin") | ||
| 388 | :eval (file-name-with-extension "foo" "bin")) | ||
| 389 | (file-name-base | ||
| 390 | :eval (file-name-base "/tmp/foo.txt")) | ||
| 391 | (file-relative-name | ||
| 392 | :eval (file-relative-name "/tmp/foo" "/tmp")) | ||
| 393 | (file-name-split | ||
| 394 | :eval (file-name-split "/tmp/foo") | ||
| 395 | :eval (file-name-split "foo/bar")) | ||
| 396 | (make-temp-name | ||
| 397 | :eval (make-temp-name "/tmp/foo-")) | ||
| 398 | (file-name-concat | ||
| 399 | :eval (file-name-concat "/tmp/" "foo") | ||
| 400 | :eval (file-name-concat "/tmp" "foo") | ||
| 401 | :eval (file-name-concat "/tmp" "foo" "bar/" "zot") | ||
| 402 | :eval (file-name-concat "/tmp" "~")) | ||
| 403 | (expand-file-name | ||
| 404 | :eval (expand-file-name "foo" "/tmp/") | ||
| 405 | :eval (expand-file-name "foo" "/tmp///") | ||
| 406 | :eval (expand-file-name "foo" "/tmp/foo/.././") | ||
| 407 | :eval (expand-file-name "~" "/tmp/")) | ||
| 408 | (substitute-in-file-name | ||
| 409 | :eval (substitute-in-file-name "$HOME/foo")) | ||
| 410 | "Directory Functions" | ||
| 411 | (file-name-as-directory | ||
| 412 | :eval (file-name-as-directory "/tmp/foo")) | ||
| 413 | (directory-file-name | ||
| 414 | :eval (directory-file-name "/tmp/foo/")) | ||
| 415 | (abbreviate-file-name | ||
| 416 | :no-eval (abbreviate-file-name "/home/some-user") | ||
| 417 | :eg-result "~some-user") | ||
| 418 | (file-name-parent-directory | ||
| 419 | :eval (file-name-parent-directory "/foo/bar") | ||
| 420 | :eval (file-name-parent-directory "/foo/") | ||
| 421 | :eval (file-name-parent-directory "foo/bar") | ||
| 422 | :eval (file-name-parent-directory "foo")) | ||
| 423 | "Quoted File Names" | ||
| 424 | (file-name-quote | ||
| 425 | :args (name) | ||
| 426 | :eval (file-name-quote "/tmp/foo")) | ||
| 427 | (file-name-unquote | ||
| 428 | :args (name) | ||
| 429 | :eval (file-name-unquote "/:/tmp/foo")) | ||
| 430 | "Predicates" | ||
| 431 | (file-name-absolute-p | ||
| 432 | :eval (file-name-absolute-p "/tmp/foo") | ||
| 433 | :eval (file-name-absolute-p "foo")) | ||
| 434 | (directory-name-p | ||
| 435 | :eval (directory-name-p "/tmp/foo/")) | ||
| 436 | (file-name-quoted-p | ||
| 437 | :eval (file-name-quoted-p "/:/tmp/foo"))) | ||
| 438 | |||
| 439 | (define-short-documentation-group file | ||
| 440 | "Inserting Contents" | ||
| 441 | (insert-file-contents | ||
| 442 | :no-eval (insert-file-contents "/tmp/foo") | ||
| 443 | :eg-result ("/tmp/foo" 6)) | ||
| 444 | (insert-file-contents-literally | ||
| 445 | :no-eval (insert-file-contents-literally "/tmp/foo") | ||
| 446 | :eg-result ("/tmp/foo" 6)) | ||
| 447 | (find-file | ||
| 448 | :no-eval (find-file "/tmp/foo") | ||
| 449 | :eg-result-string "#<buffer foo>") | ||
| 450 | "Predicates" | ||
| 451 | (file-symlink-p | ||
| 452 | :no-eval (file-symlink-p "/tmp/foo") | ||
| 453 | :eg-result t) | ||
| 454 | (file-directory-p | ||
| 455 | :no-eval (file-directory-p "/tmp") | ||
| 456 | :eg-result t) | ||
| 457 | (file-regular-p | ||
| 458 | :no-eval (file-regular-p "/tmp/foo") | ||
| 459 | :eg-result t) | ||
| 460 | (file-exists-p | ||
| 461 | :no-eval (file-exists-p "/tmp/foo") | ||
| 462 | :eg-result t) | ||
| 463 | (file-readable-p | ||
| 464 | :no-eval (file-readable-p "/tmp/foo") | ||
| 465 | :eg-result t) | ||
| 466 | (file-writable-p | ||
| 467 | :no-eval (file-writable-p "/tmp/foo") | ||
| 468 | :eg-result t) | ||
| 469 | (file-accessible-directory-p | ||
| 470 | :no-eval (file-accessible-directory-p "/tmp") | ||
| 471 | :eg-result t) | ||
| 472 | (file-executable-p | ||
| 473 | :no-eval (file-executable-p "/bin/cat") | ||
| 474 | :eg-result t) | ||
| 475 | (file-newer-than-file-p | ||
| 476 | :no-eval (file-newer-than-file-p "/tmp/foo" "/tmp/bar") | ||
| 477 | :eg-result nil) | ||
| 478 | (file-has-changed-p | ||
| 479 | :no-eval (file-has-changed-p "/tmp/foo") | ||
| 480 | :eg-result t) | ||
| 481 | (file-equal-p | ||
| 482 | :no-eval (file-equal-p "/tmp/foo" "/tmp/bar") | ||
| 483 | :eg-result nil) | ||
| 484 | (file-in-directory-p | ||
| 485 | :no-eval (file-in-directory-p "/tmp/foo" "/tmp/") | ||
| 486 | :eg-result t) | ||
| 487 | (file-locked-p | ||
| 488 | :no-eval (file-locked-p "/tmp/foo") | ||
| 489 | :eg-result nil) | ||
| 490 | "Information" | ||
| 491 | (file-attributes | ||
| 492 | :no-eval* (file-attributes "/tmp")) | ||
| 493 | (file-truename | ||
| 494 | :no-eval (file-truename "/tmp/foo/bar") | ||
| 495 | :eg-result "/tmp/foo/zot") | ||
| 496 | (file-chase-links | ||
| 497 | :no-eval (file-chase-links "/tmp/foo/bar") | ||
| 498 | :eg-result "/tmp/foo/zot") | ||
| 499 | (vc-responsible-backend | ||
| 500 | :args (file &optional no-error) | ||
| 501 | :no-eval (vc-responsible-backend "/src/foo/bar.c") | ||
| 502 | :eg-result Git) | ||
| 503 | (file-acl | ||
| 504 | :no-eval (file-acl "/tmp/foo") | ||
| 505 | :eg-result "user::rw-\ngroup::r--\nother::r--\n") | ||
| 506 | (file-extended-attributes | ||
| 507 | :no-eval* (file-extended-attributes "/tmp/foo")) | ||
| 508 | (file-selinux-context | ||
| 509 | :no-eval* (file-selinux-context "/tmp/foo")) | ||
| 510 | (locate-file | ||
| 511 | :no-eval (locate-file "syslog" '("/var/log" "/usr/bin")) | ||
| 512 | :eg-result "/var/log/syslog") | ||
| 513 | (executable-find | ||
| 514 | :no-eval (executable-find "ls") | ||
| 515 | :eg-result "/usr/bin/ls") | ||
| 516 | "Creating" | ||
| 517 | (make-temp-file | ||
| 518 | :no-eval (make-temp-file "/tmp/foo-") | ||
| 519 | :eg-result "/tmp/foo-ZcXFMj") | ||
| 520 | (make-nearby-temp-file | ||
| 521 | :no-eval (make-nearby-temp-file "/tmp/foo-") | ||
| 522 | :eg-result "/tmp/foo-xe8iON") | ||
| 523 | (write-region | ||
| 524 | :no-value (write-region (point-min) (point-max) "/tmp/foo")) | ||
| 525 | "Directories" | ||
| 526 | (make-directory | ||
| 527 | :no-value (make-directory "/tmp/bar/zot/" t)) | ||
| 528 | (directory-files | ||
| 529 | :no-eval (directory-files "/tmp/") | ||
| 530 | :eg-result ("." ".." ".ICE-unix" ".Test-unix")) | ||
| 531 | (directory-files-recursively | ||
| 532 | :no-eval (directory-files-recursively "/tmp/" "\\.png\\'") | ||
| 533 | :eg-result ("/tmp/foo.png" "/tmp/zot.png" "/tmp/bar/foobar.png")) | ||
| 534 | (directory-files-and-attributes | ||
| 535 | :no-eval* (directory-files-and-attributes "/tmp/foo")) | ||
| 536 | (file-expand-wildcards | ||
| 537 | :no-eval (file-expand-wildcards "/tmp/*.png") | ||
| 538 | :eg-result ("/tmp/foo.png" "/tmp/zot.png") | ||
| 539 | :no-eval (file-expand-wildcards "/*/foo.png") | ||
| 540 | :eg-result ("/tmp/foo.png" "/var/foo.png")) | ||
| 541 | (locate-dominating-file | ||
| 542 | :no-eval (locate-dominating-file "foo.png" "/tmp/foo/bar/zot") | ||
| 543 | :eg-result "/tmp/foo.png") | ||
| 544 | (copy-directory | ||
| 545 | :no-value (copy-directory "/tmp/bar/" "/tmp/barcopy")) | ||
| 546 | (delete-directory | ||
| 547 | :no-value (delete-directory "/tmp/bar/")) | ||
| 548 | "File Operations" | ||
| 549 | (rename-file | ||
| 550 | :no-value (rename-file "/tmp/foo" "/tmp/newname")) | ||
| 551 | (copy-file | ||
| 552 | :no-value (copy-file "/tmp/foo" "/tmp/foocopy")) | ||
| 553 | (delete-file | ||
| 554 | :no-value (delete-file "/tmp/foo")) | ||
| 555 | (make-empty-file | ||
| 556 | :no-value (make-empty-file "/tmp/foo")) | ||
| 557 | (make-symbolic-link | ||
| 558 | :no-value (make-symbolic-link "/tmp/foo" "/tmp/foosymlink")) | ||
| 559 | (add-name-to-file | ||
| 560 | :no-value (add-name-to-file "/tmp/foo" "/tmp/bar")) | ||
| 561 | (set-file-modes | ||
| 562 | :no-value "(set-file-modes \"/tmp/foo\" #o644)") | ||
| 563 | (set-file-times | ||
| 564 | :no-value (set-file-times "/tmp/foo")) | ||
| 565 | "File Modes" | ||
| 566 | (set-default-file-modes | ||
| 567 | :no-value "(set-default-file-modes #o755)") | ||
| 568 | (default-file-modes | ||
| 569 | :no-eval (default-file-modes) | ||
| 570 | :eg-result-string "#o755") | ||
| 571 | (file-modes-symbolic-to-number | ||
| 572 | :no-eval (file-modes-symbolic-to-number "a+r") | ||
| 573 | :eg-result-string "#o444") | ||
| 574 | (file-modes-number-to-symbolic | ||
| 575 | :eval "(file-modes-number-to-symbolic #o444)") | ||
| 576 | (set-file-extended-attributes | ||
| 577 | :no-eval (set-file-extended-attributes | ||
| 578 | "/tmp/foo" '((acl . "group::rxx"))) | ||
| 579 | :eg-result t) | ||
| 580 | (set-file-selinux-context | ||
| 581 | :no-eval (set-file-selinux-context | ||
| 582 | "/tmp/foo" '(unconfined_u object_r user_home_t s0)) | ||
| 583 | :eg-result t) | ||
| 584 | (set-file-acl | ||
| 585 | :no-eval (set-file-acl "/tmp/foo" "group::rxx") | ||
| 586 | :eg-result t)) | ||
| 587 | |||
| 588 | (define-short-documentation-group hash-table | ||
| 589 | "Hash Table Basics" | ||
| 590 | (make-hash-table | ||
| 591 | :no-eval (make-hash-table) | ||
| 592 | :result-string "#s(hash-table ...)") | ||
| 593 | (puthash | ||
| 594 | :no-eval (puthash 'key "value" table)) | ||
| 595 | (gethash | ||
| 596 | :no-eval (gethash 'key table) | ||
| 597 | :eg-result "value") | ||
| 598 | (remhash | ||
| 599 | :no-eval (remhash 'key table) | ||
| 600 | :result nil) | ||
| 601 | (clrhash | ||
| 602 | :no-eval (clrhash table) | ||
| 603 | :result-string "#s(hash-table ...)") | ||
| 604 | (maphash | ||
| 605 | :no-eval (maphash (lambda (key value) (message value)) table) | ||
| 606 | :result nil) | ||
| 607 | "Other Hash Table Functions" | ||
| 608 | (hash-table-p | ||
| 609 | :eval (hash-table-p 123)) | ||
| 610 | (hash-table-contains-p | ||
| 611 | :no-eval (hash-table-contains-p 'key table)) | ||
| 612 | (copy-hash-table | ||
| 613 | :no-eval (copy-hash-table table) | ||
| 614 | :result-string "#s(hash-table ...)") | ||
| 615 | (hash-table-count | ||
| 616 | :no-eval (hash-table-count table) | ||
| 617 | :eg-result 15)) | ||
| 618 | |||
| 619 | (define-short-documentation-group list | ||
| 620 | "Making Lists" | ||
| 621 | (make-list | ||
| 622 | :eval (make-list 5 'a)) | ||
| 623 | (cons | ||
| 624 | :eval (cons 1 '(2 3 4))) | ||
| 625 | (list | ||
| 626 | :eval (list 1 2 3)) | ||
| 627 | (number-sequence | ||
| 628 | :eval (number-sequence 5 8)) | ||
| 629 | (ensure-list | ||
| 630 | :eval (ensure-list "foo") | ||
| 631 | :eval (ensure-list '(1 2 3)) | ||
| 632 | :eval (ensure-list '(1 . 2))) | ||
| 633 | (ensure-proper-list | ||
| 634 | :eval (ensure-proper-list "foo") | ||
| 635 | :eval (ensure-proper-list '(1 2 3)) | ||
| 636 | :eval (ensure-proper-list '(1 . 2))) | ||
| 637 | "Operations on Lists" | ||
| 638 | (append | ||
| 639 | :eval (append '("foo" "bar") '("zot"))) | ||
| 640 | (copy-tree | ||
| 641 | :eval (copy-tree '(1 (2 3) 4))) | ||
| 642 | (flatten-tree | ||
| 643 | :eval (flatten-tree '(1 (2 3) 4))) | ||
| 644 | (car | ||
| 645 | :eval (car '(one two three)) | ||
| 646 | :eval (car '(one . two)) | ||
| 647 | :eval (car nil)) | ||
| 648 | (cdr | ||
| 649 | :eval (cdr '(one two three)) | ||
| 650 | :eval (cdr '(one . two)) | ||
| 651 | :eval (cdr nil)) | ||
| 652 | (last | ||
| 653 | :eval (last '(one two three))) | ||
| 654 | (butlast | ||
| 655 | :eval (butlast '(one two three))) | ||
| 656 | (nbutlast | ||
| 657 | :eval (nbutlast (list 'one 'two 'three))) | ||
| 658 | (nth | ||
| 659 | :eval (nth 1 '(one two three))) | ||
| 660 | (nthcdr | ||
| 661 | :eval (nthcdr 1 '(one two three))) | ||
| 662 | (take | ||
| 663 | :eval (take 3 '(one two three four))) | ||
| 664 | (ntake | ||
| 665 | :eval (ntake 3 (list 'one 'two 'three 'four))) | ||
| 666 | (take-while | ||
| 667 | :eval (take-while #'numberp '(1 2 three 4 five))) | ||
| 668 | (drop-while | ||
| 669 | :eval (drop-while #'numberp '(1 2 three 4 five))) | ||
| 670 | (any | ||
| 671 | :eval (any #'symbolp '(1 2 three 4 five))) | ||
| 672 | (all | ||
| 673 | :eval (all #'symbolp '(one 2 three)) | ||
| 674 | :eval (all #'symbolp '(one two three))) | ||
| 675 | (elt | ||
| 676 | :eval (elt '(one two three) 1)) | ||
| 677 | (car-safe | ||
| 678 | :eval (car-safe '(one two three))) | ||
| 679 | (cdr-safe | ||
| 680 | :eval (cdr-safe '(one two three))) | ||
| 681 | (push | ||
| 682 | :no-eval* (push 'a list)) | ||
| 683 | (pop | ||
| 684 | :no-eval* (pop list)) | ||
| 685 | (setcar | ||
| 686 | :no-eval (setcar list 'c) | ||
| 687 | :result c) | ||
| 688 | (setcdr | ||
| 689 | :no-eval (setcdr list (list c)) | ||
| 690 | :result '(c)) | ||
| 691 | (nconc | ||
| 692 | :eval (nconc (list 1) (list 2 3 4))) | ||
| 693 | (delq | ||
| 694 | :eval (delq 'a (list 'a 'b 'c 'd))) | ||
| 695 | (delete | ||
| 696 | :eval (delete 2 (list 1 2 3 4)) | ||
| 697 | :eval (delete "a" (list "a" "b" "c" "d"))) | ||
| 698 | (remq | ||
| 699 | :eval (remq 'b '(a b c))) | ||
| 700 | (remove | ||
| 701 | :eval (remove 2 '(1 2 3 4)) | ||
| 702 | :eval (remove "a" '("a" "b" "c" "d"))) | ||
| 703 | (delete-dups | ||
| 704 | :eval (delete-dups (list 1 2 4 3 2 4))) | ||
| 705 | "Mapping Over Lists" | ||
| 706 | (mapcar | ||
| 707 | :eval (mapcar #'list '(1 2 3))) | ||
| 708 | (mapcan | ||
| 709 | :eval (mapcan #'list '(1 2 3))) | ||
| 710 | (mapc | ||
| 711 | :eval (mapc #'insert '("1" "2" "3"))) | ||
| 712 | (seq-reduce | ||
| 713 | :eval (seq-reduce #'+ '(1 2 3) 0)) | ||
| 714 | (mapconcat | ||
| 715 | :eval (mapconcat #'identity '("foo" "bar") "|")) | ||
| 716 | "Predicates" | ||
| 717 | (listp | ||
| 718 | :eval (listp '(1 2 3)) | ||
| 719 | :eval (listp nil) | ||
| 720 | :eval (listp '(1 . 2))) | ||
| 721 | (consp | ||
| 722 | :eval (consp '(1 2 3)) | ||
| 723 | :eval (consp nil)) | ||
| 724 | (proper-list-p | ||
| 725 | :eval (proper-list-p '(1 2 3)) | ||
| 726 | :eval (proper-list-p nil) | ||
| 727 | :eval (proper-list-p '(1 . 2))) | ||
| 728 | (null | ||
| 729 | :eval (null nil)) | ||
| 730 | (atom | ||
| 731 | :eval (atom 'a)) | ||
| 732 | (nlistp | ||
| 733 | :eval (nlistp '(1 2 3)) | ||
| 734 | :eval (nlistp t) | ||
| 735 | :eval (nlistp '(1 . 2))) | ||
| 736 | "Finding Elements" | ||
| 737 | (memq | ||
| 738 | :eval (memq 'b '(a b c))) | ||
| 739 | (memql | ||
| 740 | :eval (memql 2.0 '(1.0 2.0 3.0))) | ||
| 741 | (member | ||
| 742 | :eval (member 2 '(1 2 3)) | ||
| 743 | :eval (member "b" '("a" "b" "c"))) | ||
| 744 | (member-ignore-case | ||
| 745 | :eval (member-ignore-case "foo" '("bar" "Foo" "zot"))) | ||
| 746 | "Association Lists" | ||
| 747 | (assoc | ||
| 748 | :eval (assoc "b" '(("a" . 1) ("b" . 2)))) | ||
| 749 | (rassoc | ||
| 750 | :eval (rassoc "b" '((1 . "a") (2 . "b")))) | ||
| 751 | (assq | ||
| 752 | :eval (assq 'b '((a . 1) (b . 2)))) | ||
| 753 | (rassq | ||
| 754 | :eval (rassq 'b '((1 . a) (2 . b)))) | ||
| 755 | (assoc-string | ||
| 756 | :eval (assoc-string "foo" '(("a" 1) (foo 2)))) | ||
| 757 | (alist-get | ||
| 758 | :eval (alist-get 2 '((1 . a) (2 . b)))) | ||
| 759 | (assoc-default | ||
| 760 | :eval (assoc-default 2 '((1 . a) (2 . b) #'=))) | ||
| 761 | (copy-alist | ||
| 762 | :eval (copy-alist '((1 . a) (2 . b)))) | ||
| 763 | (assoc-delete-all | ||
| 764 | :eval (assoc-delete-all "b" (list '("a" . a) '("b" . b) '("b" . c)))) | ||
| 765 | (assq-delete-all | ||
| 766 | :eval (assq-delete-all 2 (list '(1 . a) '(2 . b) '(2 . c)))) | ||
| 767 | (rassq-delete-all | ||
| 768 | :eval (rassq-delete-all 'b (list '(1 . a) '(2 . b) '(2 . c)))) | ||
| 769 | "Property Lists" | ||
| 770 | (plist-get | ||
| 771 | :eval (plist-get '(a 1 b 2 c 3) 'b)) | ||
| 772 | (plist-put | ||
| 773 | :no-eval (setq plist (plist-put plist 'd 4)) | ||
| 774 | :eg-result (a 1 b 2 c 3 d 4)) | ||
| 775 | (plist-member | ||
| 776 | :eval (plist-member '(a 1 b 2 c 3) 'b)) | ||
| 777 | "Data About Lists" | ||
| 778 | (length | ||
| 779 | :eval (length '(a b c))) | ||
| 780 | (length< | ||
| 781 | :eval (length< '(a b c) 1)) | ||
| 782 | (length> | ||
| 783 | :eval (length> '(a b c) 1)) | ||
| 784 | (length= | ||
| 785 | :eval (length= '(a b c) 3)) | ||
| 786 | (safe-length | ||
| 787 | :eval (safe-length '(a b c)))) | ||
| 788 | |||
| 789 | (define-short-documentation-group symbol | ||
| 790 | "Making symbols" | ||
| 791 | (intern | ||
| 792 | :eval (intern "abc")) | ||
| 793 | (intern-soft | ||
| 794 | :eval (intern-soft "list") | ||
| 795 | :eval (intern-soft "Phooey!")) | ||
| 796 | (make-symbol | ||
| 797 | :eval (make-symbol "abc")) | ||
| 798 | (gensym | ||
| 799 | :no-eval (gensym) | ||
| 800 | :eg-result g37) | ||
| 801 | "Comparing symbols" | ||
| 802 | (eq | ||
| 803 | :eval (eq 'abc 'abc) | ||
| 804 | :eval (eq 'abc 'abd)) | ||
| 805 | (eql | ||
| 806 | :eval (eql 'abc 'abc)) | ||
| 807 | (equal | ||
| 808 | :eval (equal 'abc 'abc)) | ||
| 809 | "Name" | ||
| 810 | (symbol-name | ||
| 811 | :eval (symbol-name 'abc)) | ||
| 812 | "Obarrays" | ||
| 813 | (obarray-make | ||
| 814 | :eval (obarray-make)) | ||
| 815 | (obarrayp | ||
| 816 | :eval (obarrayp (obarray-make)) | ||
| 817 | :eval (obarrayp nil)) | ||
| 818 | (unintern | ||
| 819 | :no-eval (unintern "abc" my-obarray) | ||
| 820 | :eg-result t) | ||
| 821 | (mapatoms | ||
| 822 | :no-eval (mapatoms (lambda (symbol) (print symbol)) my-obarray)) | ||
| 823 | (obarray-clear | ||
| 824 | :no-eval (obarray-clear my-obarray))) | ||
| 825 | |||
| 826 | (define-short-documentation-group comparison | ||
| 827 | "General-purpose" | ||
| 828 | (eq | ||
| 829 | :eval (eq 'a 'a) | ||
| 830 | :eval "(eq ?A ?A)" | ||
| 831 | :eval (let ((x (list 'a "b" '(c) 4 5.0))) | ||
| 832 | (eq x x))) | ||
| 833 | (eql | ||
| 834 | :eval (eql 2 2) | ||
| 835 | :eval (eql 2.0 2.0) | ||
| 836 | :eval (eql 2.0 2)) | ||
| 837 | (equal | ||
| 838 | :eval (equal "abc" "abc") | ||
| 839 | :eval (equal 2.0 2.0) | ||
| 840 | :eval (equal 2.0 2) | ||
| 841 | :eval (equal '(a "b" (c) 4.0) '(a "b" (c) 4.0))) | ||
| 842 | (cl-equalp | ||
| 843 | :eval (cl-equalp 2 2.0) | ||
| 844 | :eval (cl-equalp "ABC" "abc")) | ||
| 845 | "Numeric" | ||
| 846 | (= | ||
| 847 | :args (number &rest numbers) | ||
| 848 | :eval (= 2 2) | ||
| 849 | :eval (= 2.0 2.0) | ||
| 850 | :eval (= 2.0 2) | ||
| 851 | :eval (= 4 4 4 4)) | ||
| 852 | (/= | ||
| 853 | :eval (/= 4 4)) | ||
| 854 | (< | ||
| 855 | :args (number &rest numbers) | ||
| 856 | :eval (< 4 4) | ||
| 857 | :eval (< 1 2 3)) | ||
| 858 | (<= | ||
| 859 | :args (number &rest numbers) | ||
| 860 | :eval (<= 4 4) | ||
| 861 | :eval (<= 1 2 2 3)) | ||
| 862 | (> | ||
| 863 | :args (number &rest numbers) | ||
| 864 | :eval (> 4 4) | ||
| 865 | :eval (> 3 2 1)) | ||
| 866 | (>= | ||
| 867 | :args (number &rest numbers) | ||
| 868 | :eval (>= 4 4) | ||
| 869 | :eval (>= 3 2 2 1)) | ||
| 870 | "String" | ||
| 871 | (string-equal | ||
| 872 | :eval (string-equal "abc" "abc") | ||
| 873 | :eval (string-equal "abc" "ABC")) | ||
| 874 | (string-equal-ignore-case | ||
| 875 | :eval (string-equal-ignore-case "abc" "ABC")) | ||
| 876 | (string-lessp | ||
| 877 | :eval (string-lessp "abc" "abd") | ||
| 878 | :eval (string-lessp "abc" "abc") | ||
| 879 | :eval (string-lessp "pic4.png" "pic32.png")) | ||
| 880 | (string-greaterp | ||
| 881 | :eval (string-greaterp "abd" "abc") | ||
| 882 | :eval (string-greaterp "abc" "abc")) | ||
| 883 | (string-version-lessp | ||
| 884 | :eval (string-version-lessp "pic4.png" "pic32.png") | ||
| 885 | :eval (string-version-lessp "1.9.3" "1.10.2")) | ||
| 886 | (string-collate-lessp | ||
| 887 | :eval (string-collate-lessp "abc" "abd"))) | ||
| 888 | |||
| 889 | (define-short-documentation-group vector | ||
| 890 | "Making Vectors" | ||
| 891 | (make-vector | ||
| 892 | :eval (make-vector 5 "foo")) | ||
| 893 | (vector | ||
| 894 | :eval (vector 1 "b" 3)) | ||
| 895 | "Operations on Vectors" | ||
| 896 | (vectorp | ||
| 897 | :eval (vectorp [1]) | ||
| 898 | :eval (vectorp "1")) | ||
| 899 | (vconcat | ||
| 900 | :eval (vconcat '(1 2) [3 4])) | ||
| 901 | (append | ||
| 902 | :eval (append [1 2] nil)) | ||
| 903 | (length | ||
| 904 | :eval (length [1 2 3])) | ||
| 905 | (seq-reduce | ||
| 906 | :eval (seq-reduce #'+ [1 2 3] 0)) | ||
| 907 | (seq-subseq | ||
| 908 | :eval (seq-subseq [1 2 3 4 5] 1 3) | ||
| 909 | :eval (seq-subseq [1 2 3 4 5] 1)) | ||
| 910 | (copy-tree | ||
| 911 | :eval (copy-tree [1 (2 3) [4 5]] t)) | ||
| 912 | "Mapping Over Vectors" | ||
| 913 | (mapcar | ||
| 914 | :eval (mapcar #'identity [1 2 3])) | ||
| 915 | (mapc | ||
| 916 | :eval (mapc #'insert ["1" "2" "3"]))) | ||
| 917 | |||
| 918 | (define-short-documentation-group regexp | ||
| 919 | "Matching Strings" | ||
| 920 | (replace-regexp-in-string | ||
| 921 | :eval (replace-regexp-in-string "[a-z]+" "_" "*foo*")) | ||
| 922 | (string-match-p | ||
| 923 | :eval (string-match-p "^[fo]+" "foobar")) | ||
| 924 | "Looking in Buffers" | ||
| 925 | (re-search-forward | ||
| 926 | :no-eval (re-search-forward "^foo$" nil t) | ||
| 927 | :eg-result 43) | ||
| 928 | (re-search-backward | ||
| 929 | :no-eval (re-search-backward "^foo$" nil t) | ||
| 930 | :eg-result 43) | ||
| 931 | (looking-at-p | ||
| 932 | :no-eval (looking-at-p "f[0-9]") | ||
| 933 | :eg-result t) | ||
| 934 | "Match Data" | ||
| 935 | (match-string | ||
| 936 | :eval (and (string-match "^\\([fo]+\\)b" "foobar") | ||
| 937 | (match-string 0 "foobar"))) | ||
| 938 | (match-beginning | ||
| 939 | :no-eval (match-beginning 1) | ||
| 940 | :eg-result 0) | ||
| 941 | (match-end | ||
| 942 | :no-eval (match-end 1) | ||
| 943 | :eg-result 3) | ||
| 944 | (save-match-data | ||
| 945 | :no-eval (save-match-data ...)) | ||
| 946 | "Replacing Match" | ||
| 947 | (replace-match | ||
| 948 | :no-eval (replace-match "new") | ||
| 949 | :eg-result nil) | ||
| 950 | (match-substitute-replacement | ||
| 951 | :no-eval (match-substitute-replacement "new") | ||
| 952 | :eg-result "new") | ||
| 953 | (replace-regexp-in-region | ||
| 954 | :no-value (replace-regexp-in-region "[0-9]+" "Num \\&")) | ||
| 955 | "Utilities" | ||
| 956 | (regexp-quote | ||
| 957 | :eval (regexp-quote "foo.*bar")) | ||
| 958 | (regexp-opt | ||
| 959 | :eval (regexp-opt '("foo" "bar"))) | ||
| 960 | (regexp-opt-depth | ||
| 961 | :eval (regexp-opt-depth "\\(a\\(b\\)\\)")) | ||
| 962 | (regexp-opt-charset | ||
| 963 | :eval (regexp-opt-charset '(?a ?b ?c ?d ?e))) | ||
| 964 | "The `rx' Structured Regexp Notation" | ||
| 965 | (rx | ||
| 966 | :eval (rx "IP=" (+ digit) (= 3 "." (+ digit)))) | ||
| 967 | (rx-to-string | ||
| 968 | :eval (rx-to-string '(| "foo" "bar"))) | ||
| 969 | (rx-define | ||
| 970 | :no-eval "(and (rx-define haskell-comment (seq \"--\" (zero-or-more nonl))) | ||
| 971 | (rx haskell-comment))" | ||
| 972 | :result "--.*") | ||
| 973 | (rx-let | ||
| 974 | :eval "(rx-let ((comma-separated (item) (seq item (0+ \",\" item))) | ||
| 975 | (number (1+ digit)) | ||
| 976 | (numbers (comma-separated number))) | ||
| 977 | (rx \"(\" numbers \")\"))" | ||
| 978 | :result "([[:digit:]]+\\(?:,[[:digit:]]+\\)*)") | ||
| 979 | (rx-let-eval | ||
| 980 | :eval "(rx-let-eval | ||
| 981 | '((ponder (x) (seq \"Where have all the \" x \" gone?\"))) | ||
| 982 | (rx-to-string | ||
| 983 | '(ponder (or \"flowers\" \"cars\" \"socks\"))))" | ||
| 984 | :result "\\(?:Where have all the \\(?:\\(?:car\\|flower\\|sock\\)s\\) gone\\?\\)")) | ||
| 985 | |||
| 986 | (define-short-documentation-group sequence | ||
| 987 | "Sequence Predicates" | ||
| 988 | (seq-contains-p | ||
| 989 | :eval (seq-contains-p '(a b c) 'b) | ||
| 990 | :eval (seq-contains-p '(a b c) 'd)) | ||
| 991 | (seq-every-p | ||
| 992 | :eval (seq-every-p #'numberp '(1 2 3))) | ||
| 993 | (seq-empty-p | ||
| 994 | :eval (seq-empty-p [])) | ||
| 995 | (seq-set-equal-p | ||
| 996 | :eval (seq-set-equal-p '(1 2 3) '(3 1 2))) | ||
| 997 | (seq-some | ||
| 998 | :eval (seq-some #'floatp '(1 2.0 3))) | ||
| 999 | "Building Sequences" | ||
| 1000 | (seq-concatenate | ||
| 1001 | :eval (seq-concatenate 'vector '(1 2) '(c d))) | ||
| 1002 | (seq-copy | ||
| 1003 | :eval (seq-copy '(a 2))) | ||
| 1004 | (seq-into | ||
| 1005 | :eval (seq-into '(1 2 3) 'vector)) | ||
| 1006 | "Utility Functions" | ||
| 1007 | (seq-count | ||
| 1008 | :eval (seq-count #'numberp '(1 b c 4))) | ||
| 1009 | (seq-elt | ||
| 1010 | :eval (seq-elt '(a b c) 1)) | ||
| 1011 | (seq-random-elt | ||
| 1012 | :no-eval (seq-random-elt '(a b c)) | ||
| 1013 | :eg-result c) | ||
| 1014 | (seq-find | ||
| 1015 | :eval (seq-find #'numberp '(a b 3 4 f 6))) | ||
| 1016 | (seq-position | ||
| 1017 | :eval (seq-position '(a b c) 'c)) | ||
| 1018 | (seq-positions | ||
| 1019 | :eval (seq-positions '(a b c a d) 'a) | ||
| 1020 | :eval (seq-positions '(a b c a d) 'z) | ||
| 1021 | :eval (seq-positions '(11 5 7 12 9 15) 10 #'>=)) | ||
| 1022 | (seq-length | ||
| 1023 | :eval (seq-length "abcde")) | ||
| 1024 | (seq-max | ||
| 1025 | :eval (seq-max [1 2 3])) | ||
| 1026 | (seq-min | ||
| 1027 | :eval (seq-min [1 2 3])) | ||
| 1028 | (seq-first | ||
| 1029 | :eval (seq-first [a b c])) | ||
| 1030 | (seq-rest | ||
| 1031 | :eval (seq-rest '[1 2 3])) | ||
| 1032 | (seq-reverse | ||
| 1033 | :eval (seq-reverse '(1 2 3))) | ||
| 1034 | (seq-sort | ||
| 1035 | :eval (seq-sort #'> '(1 2 3))) | ||
| 1036 | (seq-sort-by | ||
| 1037 | :eval (seq-sort-by (lambda (a) (/ 1.0 a)) #'< '(1 2 3))) | ||
| 1038 | "Mapping Over Sequences" | ||
| 1039 | (seq-map | ||
| 1040 | :eval (seq-map #'1+ '(1 2 3))) | ||
| 1041 | (seq-map-indexed | ||
| 1042 | :eval (seq-map-indexed (lambda (a i) (cons i a)) '(a b c))) | ||
| 1043 | (seq-mapcat | ||
| 1044 | :eval (seq-mapcat #'upcase '("a" "b" "c") 'string)) | ||
| 1045 | (seq-doseq | ||
| 1046 | :no-eval (seq-doseq (a '("foo" "bar")) (insert a)) | ||
| 1047 | :eg-result ("foo" "bar")) | ||
| 1048 | (seq-do | ||
| 1049 | :no-eval (seq-do (lambda (a) (insert a)) '("foo" "bar")) | ||
| 1050 | :eg-result ("foo" "bar")) | ||
| 1051 | (seq-do-indexed | ||
| 1052 | :no-eval (seq-do-indexed | ||
| 1053 | (lambda (a index) (message "%s:%s" index a)) | ||
| 1054 | '("foo" "bar")) | ||
| 1055 | :eg-result nil) | ||
| 1056 | (seq-reduce | ||
| 1057 | :eval (seq-reduce #'* [1 2 3] 2)) | ||
| 1058 | "Excerpting Sequences" | ||
| 1059 | (seq-drop | ||
| 1060 | :eval (seq-drop '(a b c) 2)) | ||
| 1061 | (seq-drop-while | ||
| 1062 | :eval (seq-drop-while #'numberp '(1 2 c d 5))) | ||
| 1063 | (seq-filter | ||
| 1064 | :eval (seq-filter #'numberp '(a b 3 4 f 6))) | ||
| 1065 | (seq-keep | ||
| 1066 | :eval (seq-keep #'car-safe '((1 2) 3 t (a . b)))) | ||
| 1067 | (seq-remove | ||
| 1068 | :eval (seq-remove #'numberp '(1 2 c d 5))) | ||
| 1069 | (seq-remove-at-position | ||
| 1070 | :eval (seq-remove-at-position '(a b c d e) 3) | ||
| 1071 | :eval (seq-remove-at-position [a b c d e] 0)) | ||
| 1072 | (seq-group-by | ||
| 1073 | :eval (seq-group-by #'natnump '(-1 2 3 -4 -5 6))) | ||
| 1074 | (seq-union | ||
| 1075 | :eval (seq-union '(1 2 3) '(3 5))) | ||
| 1076 | (seq-difference | ||
| 1077 | :eval (seq-difference '(1 2 3) '(2 3 4))) | ||
| 1078 | (seq-intersection | ||
| 1079 | :eval (seq-intersection '(1 2 3) '(2 3 4))) | ||
| 1080 | (seq-partition | ||
| 1081 | :eval (seq-partition '(a b c d e f g h) 3)) | ||
| 1082 | (seq-subseq | ||
| 1083 | :eval (seq-subseq '(a b c d e) 2 4)) | ||
| 1084 | (seq-take | ||
| 1085 | :eval (seq-take '(a b c d e) 3)) | ||
| 1086 | (seq-split | ||
| 1087 | :eval (seq-split [0 1 2 3 5] 2)) | ||
| 1088 | (seq-take-while | ||
| 1089 | :eval (seq-take-while #'integerp [1 2 3.0 4])) | ||
| 1090 | (seq-uniq | ||
| 1091 | :eval (seq-uniq '(a b d b a c)))) | ||
| 1092 | |||
| 1093 | (define-short-documentation-group buffer | ||
| 1094 | "Buffer Basics" | ||
| 1095 | (current-buffer | ||
| 1096 | :no-eval (current-buffer) | ||
| 1097 | :eg-result-string "#<buffer shortdoc.el>") | ||
| 1098 | (bufferp | ||
| 1099 | :eval (bufferp 23)) | ||
| 1100 | (buffer-live-p | ||
| 1101 | :no-eval (buffer-live-p some-buffer) | ||
| 1102 | :eg-result t) | ||
| 1103 | (buffer-modified-p | ||
| 1104 | :eval (buffer-modified-p (current-buffer))) | ||
| 1105 | (buffer-name | ||
| 1106 | :eval (buffer-name)) | ||
| 1107 | (window-buffer | ||
| 1108 | :eval (window-buffer)) | ||
| 1109 | "Selecting Buffers" | ||
| 1110 | (get-buffer-create | ||
| 1111 | :no-eval (get-buffer-create "*foo*") | ||
| 1112 | :eg-result-string "#<buffer *foo*>") | ||
| 1113 | (pop-to-buffer | ||
| 1114 | :no-eval (pop-to-buffer "*foo*") | ||
| 1115 | :eg-result-string "#<buffer *foo*>") | ||
| 1116 | (with-current-buffer | ||
| 1117 | :no-eval* (with-current-buffer buffer (buffer-size))) | ||
| 1118 | "Points and Positions" | ||
| 1119 | (point | ||
| 1120 | :eval (point)) | ||
| 1121 | (point-min | ||
| 1122 | :eval (point-min)) | ||
| 1123 | (point-max | ||
| 1124 | :eval (point-max)) | ||
| 1125 | (pos-bol | ||
| 1126 | :eval (pos-bol)) | ||
| 1127 | (pos-eol | ||
| 1128 | :eval (pos-eol)) | ||
| 1129 | (bolp | ||
| 1130 | :eval (bolp)) | ||
| 1131 | (eolp | ||
| 1132 | :eval (eolp)) | ||
| 1133 | (line-beginning-position | ||
| 1134 | :eval (line-beginning-position)) | ||
| 1135 | (line-end-position | ||
| 1136 | :eval (line-end-position)) | ||
| 1137 | (buffer-size | ||
| 1138 | :eval (buffer-size)) | ||
| 1139 | (bobp | ||
| 1140 | :eval (bobp)) | ||
| 1141 | (eobp | ||
| 1142 | :eval (eobp)) | ||
| 1143 | "Moving Around" | ||
| 1144 | (goto-char | ||
| 1145 | :no-eval (goto-char (point-max)) | ||
| 1146 | :eg-result 342) | ||
| 1147 | (search-forward | ||
| 1148 | :no-eval (search-forward "some-string" nil t) | ||
| 1149 | :eg-result 245) | ||
| 1150 | (re-search-forward | ||
| 1151 | :no-eval (re-search-forward "some-s.*g" nil t) | ||
| 1152 | :eg-result 245) | ||
| 1153 | (forward-line | ||
| 1154 | :no-eval (forward-line 1) | ||
| 1155 | :eg-result 0 | ||
| 1156 | :no-eval (forward-line -2) | ||
| 1157 | :eg-result 0) | ||
| 1158 | "Strings from Buffers" | ||
| 1159 | (buffer-string | ||
| 1160 | :no-eval* (buffer-string)) | ||
| 1161 | (buffer-substring | ||
| 1162 | :eval (buffer-substring (point-min) (+ (point-min) 10))) | ||
| 1163 | (buffer-substring-no-properties | ||
| 1164 | :eval (buffer-substring-no-properties (point-min) (+ (point-min) 10))) | ||
| 1165 | (following-char | ||
| 1166 | :no-eval (following-char) | ||
| 1167 | :eg-result 67) | ||
| 1168 | (preceding-char | ||
| 1169 | :no-eval (preceding-char) | ||
| 1170 | :eg-result 38) | ||
| 1171 | (char-after | ||
| 1172 | :eval (char-after 45)) | ||
| 1173 | (char-before | ||
| 1174 | :eval (char-before 13)) | ||
| 1175 | (get-byte | ||
| 1176 | :no-eval (get-byte 45) | ||
| 1177 | :eg-result-string "#xff") | ||
| 1178 | "Altering Buffers" | ||
| 1179 | (delete-region | ||
| 1180 | :no-value (delete-region (point-min) (point-max))) | ||
| 1181 | (erase-buffer | ||
| 1182 | :no-value (erase-buffer)) | ||
| 1183 | (delete-line | ||
| 1184 | :no-value (delete-line)) | ||
| 1185 | (insert | ||
| 1186 | :no-value (insert "This string will be inserted in the buffer\n")) | ||
| 1187 | (subst-char-in-region | ||
| 1188 | :no-eval "(subst-char-in-region (point-min) (point-max) ?+ ?-)") | ||
| 1189 | (replace-string-in-region | ||
| 1190 | :no-value (replace-string-in-region "foo" "bar")) | ||
| 1191 | "Locking" | ||
| 1192 | (lock-buffer | ||
| 1193 | :no-value (lock-buffer "/tmp/foo")) | ||
| 1194 | (unlock-buffer | ||
| 1195 | :no-value (unlock-buffer))) | ||
| 1196 | |||
| 1197 | (define-short-documentation-group overlay | ||
| 1198 | "Predicates" | ||
| 1199 | (overlayp | ||
| 1200 | :no-eval (overlayp some-overlay) | ||
| 1201 | :eg-result t) | ||
| 1202 | "Creation and Deletion" | ||
| 1203 | (make-overlay | ||
| 1204 | :args (beg end &optional buffer) | ||
| 1205 | :no-eval (make-overlay 1 10) | ||
| 1206 | :eg-result-string "#<overlay from 1 to 10 in *foo*>") | ||
| 1207 | (delete-overlay | ||
| 1208 | :no-eval (delete-overlay foo) | ||
| 1209 | :eg-result t) | ||
| 1210 | "Searching Overlays" | ||
| 1211 | (overlays-at | ||
| 1212 | :no-eval (overlays-at 15) | ||
| 1213 | :eg-result-string "(#<overlay from 1 to 10 in *foo*>)") | ||
| 1214 | (overlays-in | ||
| 1215 | :no-eval (overlays-in 1 30) | ||
| 1216 | :eg-result-string "(#<overlay from 1 to 10 in *foo*>)") | ||
| 1217 | (next-overlay-change | ||
| 1218 | :no-eval (next-overlay-change 1) | ||
| 1219 | :eg-result 20) | ||
| 1220 | (previous-overlay-change | ||
| 1221 | :no-eval (previous-overlay-change 30) | ||
| 1222 | :eg-result 20) | ||
| 1223 | "Overlay Properties" | ||
| 1224 | (overlay-start | ||
| 1225 | :no-eval (overlay-start foo) | ||
| 1226 | :eg-result 1) | ||
| 1227 | (overlay-end | ||
| 1228 | :no-eval (overlay-end foo) | ||
| 1229 | :eg-result 10) | ||
| 1230 | (overlay-put | ||
| 1231 | :no-eval (overlay-put foo 'happy t) | ||
| 1232 | :eg-result t) | ||
| 1233 | (overlay-get | ||
| 1234 | :no-eval (overlay-get foo 'happy) | ||
| 1235 | :eg-result t) | ||
| 1236 | (overlay-buffer | ||
| 1237 | :no-eval (overlay-buffer foo)) | ||
| 1238 | "Moving Overlays" | ||
| 1239 | (move-overlay | ||
| 1240 | :no-eval (move-overlay foo 5 20) | ||
| 1241 | :eg-result-string "#<overlay from 5 to 20 in *foo*>")) | ||
| 1242 | |||
| 1243 | (define-short-documentation-group process | ||
| 1244 | (make-process | ||
| 1245 | :no-eval (make-process :name "foo" :command '("cat" "/tmp/foo")) | ||
| 1246 | :eg-result-string "#<process foo>") | ||
| 1247 | (processp | ||
| 1248 | :eval (processp t)) | ||
| 1249 | (process-status | ||
| 1250 | :no-eval (process-status process) | ||
| 1251 | :eg-result exit) | ||
| 1252 | (delete-process | ||
| 1253 | :no-value (delete-process process)) | ||
| 1254 | (kill-process | ||
| 1255 | :no-value (kill-process process)) | ||
| 1256 | (set-process-sentinel | ||
| 1257 | :no-value (set-process-sentinel process (lambda (proc string)))) | ||
| 1258 | (process-buffer | ||
| 1259 | :no-eval (process-buffer process) | ||
| 1260 | :eg-result-string "#<buffer *foo*>") | ||
| 1261 | (get-buffer-process | ||
| 1262 | :no-eval (get-buffer-process buffer) | ||
| 1263 | :eg-result-string "#<process foo>") | ||
| 1264 | (process-live-p | ||
| 1265 | :no-eval (process-live-p process) | ||
| 1266 | :eg-result t)) | ||
| 1267 | |||
| 1268 | (define-short-documentation-group number | ||
| 1269 | "Arithmetic" | ||
| 1270 | (+ | ||
| 1271 | :args (&rest numbers) | ||
| 1272 | :eval (+ 1 2) | ||
| 1273 | :eval (+ 1 2 3 4)) | ||
| 1274 | (- | ||
| 1275 | :args (&rest numbers) | ||
| 1276 | :eval (- 3 2) | ||
| 1277 | :eval (- 6 3 2)) | ||
| 1278 | (* | ||
| 1279 | :args (&rest numbers) | ||
| 1280 | :eval (* 3 4 5)) | ||
| 1281 | (/ | ||
| 1282 | :eval (/ 10 5) | ||
| 1283 | :eval (/ 10 6) | ||
| 1284 | :eval (/ 10.0 6) | ||
| 1285 | :eval (/ 10.0 3 3)) | ||
| 1286 | (% | ||
| 1287 | :eval (% 10 5) | ||
| 1288 | :eval (% 10 6)) | ||
| 1289 | (mod | ||
| 1290 | :eval (mod 10 5) | ||
| 1291 | :eval (mod 10 6) | ||
| 1292 | :eval (mod 10.5 6)) | ||
| 1293 | (1+ | ||
| 1294 | :eval (1+ 2) | ||
| 1295 | :eval (let ((x 2)) (1+ x) x)) | ||
| 1296 | (1- | ||
| 1297 | :eval (1- 4) | ||
| 1298 | :eval (let ((x 4)) (1- x) x)) | ||
| 1299 | (incf | ||
| 1300 | :eval (let ((x 2)) (incf x) x) | ||
| 1301 | :eval (let ((x 2)) (incf x 2) x)) | ||
| 1302 | (decf | ||
| 1303 | :eval (let ((x 4)) (decf x) x) | ||
| 1304 | :eval (let ((x 4)) (decf x 2) x)) | ||
| 1305 | "Predicates" | ||
| 1306 | (= | ||
| 1307 | :args (number &rest numbers) | ||
| 1308 | :eval (= 4 4) | ||
| 1309 | :eval (= 4.0 4.0) | ||
| 1310 | :eval (= 4 4.0) | ||
| 1311 | :eval (= 4 4 4 4)) | ||
| 1312 | (eql | ||
| 1313 | :eval (eql 4 4) | ||
| 1314 | :eval (eql 4.0 4.0)) | ||
| 1315 | (/= | ||
| 1316 | :eval (/= 4 4)) | ||
| 1317 | (< | ||
| 1318 | :args (number &rest numbers) | ||
| 1319 | :eval (< 4 4) | ||
| 1320 | :eval (< 1 2 3)) | ||
| 1321 | (<= | ||
| 1322 | :args (number &rest numbers) | ||
| 1323 | :eval (<= 4 4) | ||
| 1324 | :eval (<= 1 2 2 3)) | ||
| 1325 | (> | ||
| 1326 | :args (number &rest numbers) | ||
| 1327 | :eval (> 4 4) | ||
| 1328 | :eval (> 3 2 1)) | ||
| 1329 | (>= | ||
| 1330 | :args (number &rest numbers) | ||
| 1331 | :eval (>= 4 4) | ||
| 1332 | :eval (>= 3 2 2 1)) | ||
| 1333 | (zerop | ||
| 1334 | :eval (zerop 0)) | ||
| 1335 | (natnump | ||
| 1336 | :eval (natnump -1) | ||
| 1337 | :eval (natnump 0) | ||
| 1338 | :eval (natnump 23)) | ||
| 1339 | (plusp | ||
| 1340 | :eval (plusp 0) | ||
| 1341 | :eval (plusp 1)) | ||
| 1342 | (minusp | ||
| 1343 | :eval (minusp 0) | ||
| 1344 | :eval (minusp -1)) | ||
| 1345 | (oddp | ||
| 1346 | :eval (oddp 3)) | ||
| 1347 | (evenp | ||
| 1348 | :eval (evenp 6)) | ||
| 1349 | (bignump | ||
| 1350 | :eval (bignump 4) | ||
| 1351 | :eval (bignump (expt 2 90))) | ||
| 1352 | (fixnump | ||
| 1353 | :eval (fixnump 4) | ||
| 1354 | :eval (fixnump (expt 2 90))) | ||
| 1355 | (floatp | ||
| 1356 | :eval (floatp 5.4)) | ||
| 1357 | (integerp | ||
| 1358 | :eval (integerp 5.4)) | ||
| 1359 | (numberp | ||
| 1360 | :eval (numberp "5.4")) | ||
| 1361 | (cl-digit-char-p | ||
| 1362 | :eval (cl-digit-char-p ?5 10) | ||
| 1363 | :eval (cl-digit-char-p ?f 16)) | ||
| 1364 | "Operations" | ||
| 1365 | (max | ||
| 1366 | :args (number &rest numbers) | ||
| 1367 | :eval (max 7 9 3)) | ||
| 1368 | (min | ||
| 1369 | :args (number &rest numbers) | ||
| 1370 | :eval (min 7 9 3)) | ||
| 1371 | (abs | ||
| 1372 | :eval (abs -4)) | ||
| 1373 | (float | ||
| 1374 | :eval (float 2)) | ||
| 1375 | (truncate | ||
| 1376 | :eval (truncate 1.2) | ||
| 1377 | :eval (truncate -1.2) | ||
| 1378 | :eval (truncate 5.4 2)) | ||
| 1379 | (floor | ||
| 1380 | :eval (floor 1.2) | ||
| 1381 | :eval (floor -1.2) | ||
| 1382 | :eval (floor 5.4 2)) | ||
| 1383 | (ceiling | ||
| 1384 | :eval (ceiling 1.2) | ||
| 1385 | :eval (ceiling -1.2) | ||
| 1386 | :eval (ceiling 5.4 2)) | ||
| 1387 | (round | ||
| 1388 | :eval (round 1.2) | ||
| 1389 | :eval (round -1.2) | ||
| 1390 | :eval (round 5.4 2)) | ||
| 1391 | (random | ||
| 1392 | :eval (random 6)) | ||
| 1393 | "Bit Operations" | ||
| 1394 | (ash | ||
| 1395 | :eval (ash 1 4) | ||
| 1396 | :eval (ash 16 -1)) | ||
| 1397 | (logand | ||
| 1398 | :no-eval "(logand #b10 #b111)" | ||
| 1399 | :result-string "#b10") | ||
| 1400 | (logior | ||
| 1401 | :eval (logior 4 16)) | ||
| 1402 | (logxor | ||
| 1403 | :eval (logxor 4 16)) | ||
| 1404 | (lognot | ||
| 1405 | :eval (lognot 5)) | ||
| 1406 | (logcount | ||
| 1407 | :eval (logcount 5)) | ||
| 1408 | "Floating Point" | ||
| 1409 | (isnan | ||
| 1410 | :eval (isnan 5.0)) | ||
| 1411 | (frexp | ||
| 1412 | :eval (frexp 5.7)) | ||
| 1413 | (ldexp | ||
| 1414 | :eval (ldexp 0.7125 3)) | ||
| 1415 | (logb | ||
| 1416 | :eval (logb 10.5)) | ||
| 1417 | (ffloor | ||
| 1418 | :eval (ffloor 1.2)) | ||
| 1419 | (fceiling | ||
| 1420 | :eval (fceiling 1.2)) | ||
| 1421 | (ftruncate | ||
| 1422 | :eval (ftruncate 1.2)) | ||
| 1423 | (fround | ||
| 1424 | :eval (fround 1.2)) | ||
| 1425 | "Standard Math Functions" | ||
| 1426 | (sin | ||
| 1427 | :eval (sin float-pi)) | ||
| 1428 | (cos | ||
| 1429 | :eval (cos float-pi)) | ||
| 1430 | (tan | ||
| 1431 | :eval (tan float-pi)) | ||
| 1432 | (asin | ||
| 1433 | :eval (asin float-pi)) | ||
| 1434 | (acos | ||
| 1435 | :eval (acos float-pi)) | ||
| 1436 | (atan | ||
| 1437 | :eval (atan float-pi)) | ||
| 1438 | (exp | ||
| 1439 | :eval (exp 4)) | ||
| 1440 | (log | ||
| 1441 | :eval (log 54.59)) | ||
| 1442 | (expt | ||
| 1443 | :eval (expt 2 16)) | ||
| 1444 | (sqrt | ||
| 1445 | :eval (sqrt -1))) | ||
| 1446 | |||
| 1447 | (define-short-documentation-group text-properties | ||
| 1448 | "Examining Text Properties" | ||
| 1449 | (get-text-property | ||
| 1450 | :eval (get-text-property 0 'foo (propertize "x" 'foo t))) | ||
| 1451 | (get-char-property | ||
| 1452 | :eval (get-char-property 0 'foo (propertize "x" 'foo t))) | ||
| 1453 | (get-pos-property | ||
| 1454 | :eval (get-pos-property 0 'foo (propertize "x" 'foo t))) | ||
| 1455 | (get-char-property-and-overlay | ||
| 1456 | :eval (get-char-property-and-overlay 0 'foo (propertize "x" 'foo t))) | ||
| 1457 | (text-properties-at | ||
| 1458 | :eval (text-properties-at (point))) | ||
| 1459 | "Changing Text Properties" | ||
| 1460 | (put-text-property | ||
| 1461 | :eval (let ((s (copy-sequence "abc"))) (put-text-property 0 1 'foo t s) s) | ||
| 1462 | :no-eval (put-text-property (point) (1+ (point)) 'face 'error)) | ||
| 1463 | (add-text-properties | ||
| 1464 | :no-eval (add-text-properties (point) (1+ (point)) '(face error))) | ||
| 1465 | (remove-text-properties | ||
| 1466 | :no-eval (remove-text-properties (point) (1+ (point)) '(face nil))) | ||
| 1467 | (remove-list-of-text-properties | ||
| 1468 | :no-eval (remove-list-of-text-properties (point) (1+ (point)) '(face font-lock-face))) | ||
| 1469 | (set-text-properties | ||
| 1470 | :no-eval (set-text-properties (point) (1+ (point)) '(face error))) | ||
| 1471 | (add-face-text-property | ||
| 1472 | :no-eval (add-face-text-property START END '(:foreground "green"))) | ||
| 1473 | (propertize | ||
| 1474 | :eval (propertize "foo" 'face 'italic 'mouse-face 'bold-italic)) | ||
| 1475 | "Searching for Text Properties" | ||
| 1476 | (next-property-change | ||
| 1477 | :no-eval (next-property-change (point) (current-buffer))) | ||
| 1478 | (previous-property-change | ||
| 1479 | :no-eval (previous-property-change (point) (current-buffer))) | ||
| 1480 | (next-single-property-change | ||
| 1481 | :no-eval (next-single-property-change (point) 'face (current-buffer))) | ||
| 1482 | (previous-single-property-change | ||
| 1483 | :no-eval (previous-single-property-change (point) 'face (current-buffer))) | ||
| 1484 | ;; TODO: There are some more that could be added here. | ||
| 1485 | (text-property-search-forward | ||
| 1486 | :no-eval (text-property-search-forward 'face nil t)) | ||
| 1487 | (text-property-search-backward | ||
| 1488 | :no-eval (text-property-search-backward 'face nil t))) | ||
| 1489 | |||
| 1490 | (define-short-documentation-group keymaps | ||
| 1491 | "Defining keymaps or adding bindings to existing keymaps" | ||
| 1492 | (define-keymap | ||
| 1493 | :no-eval (define-keymap "C-c C-c" #'quit-buffer) | ||
| 1494 | :no-eval (define-keymap :keymap ctl-x-map | ||
| 1495 | "C-r" #'recentf-open | ||
| 1496 | "k" #'kill-current-buffer)) | ||
| 1497 | (defvar-keymap | ||
| 1498 | :no-eval (defvar-keymap my-keymap "C-c C-c" #'quit-buffer)) | ||
| 1499 | "Setting keys" | ||
| 1500 | (keymap-set | ||
| 1501 | :no-eval (keymap-set map "C-c C-c" #'quit-buffer)) | ||
| 1502 | (keymap-local-set | ||
| 1503 | :no-eval (keymap-local-set "C-c C-c" #'quit-buffer)) | ||
| 1504 | (keymap-global-set | ||
| 1505 | :no-eval (keymap-global-set "C-c C-c" #'quit-buffer)) | ||
| 1506 | (keymap-unset | ||
| 1507 | :no-eval (keymap-unset map "C-c C-c")) | ||
| 1508 | (keymap-local-unset | ||
| 1509 | :no-eval (keymap-local-unset "C-c C-c")) | ||
| 1510 | (keymap-global-unset | ||
| 1511 | :no-eval (keymap-global-unset "C-c C-c")) | ||
| 1512 | (keymap-substitute | ||
| 1513 | :no-eval (keymap-substitute map "C-c C-c" "M-a")) | ||
| 1514 | (keymap-set-after | ||
| 1515 | :no-eval (keymap-set-after map "<separator-2>" menu-bar-separator)) | ||
| 1516 | "Predicates" | ||
| 1517 | (keymapp | ||
| 1518 | :eval (keymapp (define-keymap))) | ||
| 1519 | (key-valid-p | ||
| 1520 | :eval (key-valid-p "C-c C-c") | ||
| 1521 | :eval (key-valid-p "C-cC-c")) | ||
| 1522 | "Lookup" | ||
| 1523 | (keymap-lookup | ||
| 1524 | :eval (keymap-lookup (current-global-map) "C-x x g"))) | ||
| 1525 | |||
| 1526 | (provide 'shortdoc-doc) | ||
| 1527 | |||
| 1528 | ;;; shortdoc-doc.el ends here | ||
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index ea6910c60fc..e8ba6ededc0 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el | |||
| @@ -25,8 +25,8 @@ | |||
| 25 | ;; This package lists functions based on various groupings. | 25 | ;; This package lists functions based on various groupings. |
| 26 | ;; | 26 | ;; |
| 27 | ;; For instance, `string-trim' and `mapconcat' are `string' functions, | 27 | ;; For instance, `string-trim' and `mapconcat' are `string' functions, |
| 28 | ;; so `M-x shortdoc RET string RET' will give an overview of functions | 28 | ;; so `M-x shortdoc RET string RET' will give an overview of these and |
| 29 | ;; that operate on strings. | 29 | ;; other functions that operate on strings. |
| 30 | ;; | 30 | ;; |
| 31 | ;; The documentation groups are created with the | 31 | ;; The documentation groups are created with the |
| 32 | ;; `define-short-documentation-group' macro. | 32 | ;; `define-short-documentation-group' macro. |
| @@ -50,23 +50,109 @@ | |||
| 50 | '((t :inherit variable-pitch)) | 50 | '((t :inherit variable-pitch)) |
| 51 | "Face used for a section.") | 51 | "Face used for a section.") |
| 52 | 52 | ||
| 53 | ;;;###autoload | 53 | |
| 54 | (defun shortdoc--check (group functions) | 54 | ;; Almost all past Emacs versions (but see note on Emacs 30 below) |
| 55 | (let ((keywords '( :no-manual :args :eval :no-eval :no-value :no-eval* | 55 | ;; understand the following shortdoc group structure: |
| 56 | :result :result-string :eg-result :eg-result-string :doc))) | 56 | ;; |
| 57 | (dolist (f functions) | 57 | ;; (SYMBOL ;; shortdoc group name |
| 58 | (when (consp f) | 58 | ;; (:group [:KEYWORD VALUE ...]) ;; group properties |
| 59 | (dolist (x f) | 59 | ;; STRING ;; shortdoc section title |
| 60 | (when (and (keywordp x) (not (memq x keywords))) | 60 | ;; (:section [:KEYWORD VALUE ...]) ;; section properties |
| 61 | (error "Shortdoc %s function `%s': bad keyword `%s'" | 61 | ;; |
| 62 | group (car f) x))))))) | 62 | ;; (SYMBOL ;; shortdoc item |
| 63 | ;; [:KEYWORD VALUE ...]) ;; item properties | ||
| 64 | ;; ([:item] FORM ;; generalized shortdoc item | ||
| 65 | ;; [:KEYWORD VALUE ...])) ;; item properties | ||
| 66 | ;; | ||
| 67 | ;; Where: | ||
| 68 | ;; - a group definition must contain at least one section title or item; | ||
| 69 | ;; - group and section properties must occur at most once after the | ||
| 70 | ;; group name and a section title, respectively; | ||
| 71 | ;; - the leading `:item' keyword of a generalized shortdoc item may be | ||
| 72 | ;; omitted if the shortdoc group is not intended to be used on Emacs | ||
| 73 | ;; versions older than Emacs 32; | ||
| 74 | ;; - the group, secion, or item properties may be empty. | ||
| 75 | ;; | ||
| 76 | ;; That does not mean that any such shortdoc group is meaningful. And | ||
| 77 | ;; that does not mean that past Emacs version actually use all the bits | ||
| 78 | ;; available in such a definition. But they will not error out when | ||
| 79 | ;; processing a definition with the format layed out above, they will | ||
| 80 | ;; simply silently ignore those bits unknown to them (specifically | ||
| 81 | ;; unknown keywords) and attempt to make the best out of the rest. | ||
| 82 | ;; | ||
| 83 | ;; Why is this important? Because it gives package authors a guarantee | ||
| 84 | ;; that they can use shortdoc features of newer Emacs versions without | ||
| 85 | ;; older Emacs versions breaking on them. | ||
| 86 | ;; | ||
| 87 | ;; So Emacs developers, please | ||
| 88 | ;; | ||
| 89 | ;; - stick to above structure when extending shortdoc.el (so that past | ||
| 90 | ;; Emacs versions can grok your extensions without breaking); and | ||
| 91 | ;; | ||
| 92 | ;; - do not impose any additional restrictions on the format described | ||
| 93 | ;; above and on the allowed keywords (so that you do not limit the | ||
| 94 | ;; options of future Emacs versions). | ||
| 95 | ;; | ||
| 96 | ;; Emacs 30, for example, had introduced some restrictions on item | ||
| 97 | ;; property keywords. As a result, we need that hack mentioned in the | ||
| 98 | ;; "boilerplate template for Emacs package authors" above. | ||
| 99 | |||
| 100 | (defun shortdoc--keyword-plist-p (object) | ||
| 101 | "Return non-nil if OBJECT is a plist with keywords as property names." | ||
| 102 | (let ((ok (proper-list-p object))) | ||
| 103 | (while (and ok object) | ||
| 104 | (setq ok (and (keywordp (car object)) (cdr object)) | ||
| 105 | object (cddr object))) | ||
| 106 | ok)) | ||
| 107 | |||
| 108 | (defun shortdoc--check (group definition) | ||
| 109 | "Ensure that (GROUP DEFINITION) is a valid shortdoc group definition. | ||
| 110 | Signal an error if that is not the case." | ||
| 111 | (unless (symbolp group) | ||
| 112 | (signal 'wrong-type-argument (list 'symbolp group))) | ||
| 113 | (unless (proper-list-p definition) | ||
| 114 | (signal 'wrong-type-argument (list 'proper-list-p definition))) | ||
| 115 | (let ((has-content nil) | ||
| 116 | entry keyword type | ||
| 117 | (prev-type 'group-name)) | ||
| 118 | (while definition | ||
| 119 | (setq entry (car definition) | ||
| 120 | keyword (car-safe entry) | ||
| 121 | type (cond | ||
| 122 | ((and (eq keyword :group) | ||
| 123 | (shortdoc--keyword-plist-p (cdr entry))) | ||
| 124 | 'group-properties) | ||
| 125 | ((stringp entry) 'section-title) | ||
| 126 | ((and (eq keyword :section) | ||
| 127 | (shortdoc--keyword-plist-p (cdr entry))) | ||
| 128 | 'section-properties) | ||
| 129 | ((and (eq keyword :item) | ||
| 130 | (shortdoc--keyword-plist-p entry)) | ||
| 131 | 'item-definition) | ||
| 132 | ((and (consp entry) | ||
| 133 | (shortdoc--keyword-plist-p (cdr entry))) | ||
| 134 | 'item-definition) | ||
| 135 | (t 'invalid))) | ||
| 136 | (cond ((memq type '(section-title item-definition)) | ||
| 137 | (setq has-content t)) | ||
| 138 | ((and (eq type 'group-properties) | ||
| 139 | (eq prev-type 'group-name))) | ||
| 140 | ((and (eq type 'section-properties) | ||
| 141 | (eq prev-type 'section-title))) | ||
| 142 | (t | ||
| 143 | (error "Shortdoc group %s with invalid entry %S" | ||
| 144 | group entry))) | ||
| 145 | (setq prev-type type | ||
| 146 | definition (cdr definition))) | ||
| 147 | (unless has-content | ||
| 148 | (error "Shortdoc group %s without content" group)))) | ||
| 63 | 149 | ||
| 64 | ;;;###autoload | 150 | ;;;###autoload |
| 65 | (progn | 151 | (defvar shortdoc--groups nil) |
| 66 | (defvar shortdoc--groups nil) | ||
| 67 | 152 | ||
| 68 | (defmacro define-short-documentation-group (group &rest functions) | 153 | ;;;###autoload |
| 69 | "Add GROUP to the list of defined documentation groups. | 154 | (defmacro define-short-documentation-group (group &rest functions) |
| 155 | "Add GROUP to the list of defined documentation groups. | ||
| 70 | FUNCTIONS is a list of elements on the form: | 156 | FUNCTIONS is a list of elements on the form: |
| 71 | 157 | ||
| 72 | (FUNC | 158 | (FUNC |
| @@ -128,1504 +214,28 @@ execution of the documented form depends on some conditions. | |||
| 128 | A FUNC form can have any number of `:no-eval' (or `:no-value'), | 214 | A FUNC form can have any number of `:no-eval' (or `:no-value'), |
| 129 | `:no-eval*', `:result', `:result-string', `:eg-result' and | 215 | `:no-eval*', `:result', `:result-string', `:eg-result' and |
| 130 | `:eg-result-string' properties." | 216 | `:eg-result-string' properties." |
| 131 | (declare (indent defun)) | 217 | (declare (indent defun)) |
| 132 | (shortdoc--check group functions) | 218 | (let ((err |
| 133 | `(progn | 219 | (condition-case err |
| 134 | (setq shortdoc--groups (delq (assq ',group shortdoc--groups) | 220 | (progn (shortdoc--check group functions) nil) |
| 135 | shortdoc--groups)) | 221 | (error err))) |
| 136 | (push (cons ',group ',functions) shortdoc--groups)))) | 222 | (exp |
| 137 | 223 | `(progn | |
| 138 | (define-short-documentation-group alist | 224 | (setq shortdoc--groups (delq (assq ',group shortdoc--groups) |
| 139 | "Alist Basics" | 225 | shortdoc--groups)) |
| 140 | (assoc | 226 | (push (cons ',group ',functions) shortdoc--groups)))) |
| 141 | :eval (assoc 'foo '((foo . bar) (zot . baz)))) | 227 | (if (null err) |
| 142 | (rassoc | 228 | exp |
| 143 | :eval (rassoc 'bar '((foo . bar) (zot . baz)))) | 229 | (macroexp-warn-and-return |
| 144 | (assq | 230 | (error-message-string err) exp nil t)))) |
| 145 | :eval (assq 'foo '((foo . bar) (zot . baz)))) | 231 | |
| 146 | (rassq | 232 | ;; FIXME: As long as we do not have a better mechanism to load shortdoc |
| 147 | :eval (rassq 'bar '((foo . bar) (zot . baz)))) | 233 | ;; definitions on demand, we must require `shortdoc-doc' after above |
| 148 | (assoc-string | 234 | ;; macro to avoid loading cycles. But at least we do not require |
| 149 | :eval (assoc-string "foo" '(("foo" . "bar") ("zot" "baz")))) | 235 | ;; `shortdoc-doc' while compiling this file, only when loading it. |
| 150 | "Manipulating Alists" | 236 | (if t (require 'shortdoc-doc)) |
| 151 | (assoc-delete-all | 237 | |
| 152 | :eval (assoc-delete-all "b" (list '("a" . a) '("b" . b) '("b" . c)))) | 238 | |
| 153 | (assq-delete-all | ||
| 154 | :eval (assq-delete-all 2 (list '(1 . a) '(2 . b) '(2 . c)))) | ||
| 155 | (rassq-delete-all | ||
| 156 | :eval (rassq-delete-all 'b (list '(1 . a) '(2 . b) '(2 . c)))) | ||
| 157 | (alist-get | ||
| 158 | :eval (let ((foo '((bar . baz)))) | ||
| 159 | (setf (alist-get 'bar foo) 'zot) | ||
| 160 | foo)) | ||
| 161 | "Misc" | ||
| 162 | (assoc-default | ||
| 163 | :eval (assoc-default "foobar" '(("foo" . baz)) #'string-match)) | ||
| 164 | (copy-alist | ||
| 165 | :eval (let* ((old '((foo . bar))) | ||
| 166 | (new (copy-alist old))) | ||
| 167 | (eq old new))) | ||
| 168 | ;; FIXME: Outputs "\.rose" for the symbol `.rose'. It would be | ||
| 169 | ;; better if that could be cleaned up. | ||
| 170 | (let-alist | ||
| 171 | :eval (let ((colors '((rose . red) | ||
| 172 | (lily . white)))) | ||
| 173 | (let-alist colors | ||
| 174 | (if (eq .rose 'red) | ||
| 175 | .lily))))) | ||
| 176 | |||
| 177 | (define-short-documentation-group map | ||
| 178 | "Map Basics" | ||
| 179 | (mapp | ||
| 180 | :eval (mapp (list 'bar 1 'foo 2 'baz 3)) | ||
| 181 | :eval (mapp (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 182 | :eval (mapp [bar foo baz]) | ||
| 183 | :eval (mapp "this is a string") | ||
| 184 | :eval (mapp #s(hash-table data (bar 1 foo 2 baz 3))) | ||
| 185 | :eval (mapp '()) | ||
| 186 | :eval (mapp nil) | ||
| 187 | :eval (mapp (make-char-table 'shortdoc-test))) | ||
| 188 | (map-empty-p | ||
| 189 | :args (map) | ||
| 190 | :eval (map-empty-p nil) | ||
| 191 | :eval (map-empty-p []) | ||
| 192 | :eval (map-empty-p '())) | ||
| 193 | (map-elt | ||
| 194 | :args (map key) | ||
| 195 | :eval (map-elt (list 'bar 1 'foo 2 'baz 3) 'foo) | ||
| 196 | :eval (map-elt (list '(bar . 1) '(foo . 2) '(baz . 3)) 'foo) | ||
| 197 | :eval (map-elt [bar foo baz] 1) | ||
| 198 | :eval (map-elt #s(hash-table data (bar 1 foo 2 baz 3)) 'foo)) | ||
| 199 | (map-contains-key | ||
| 200 | :args (map key) | ||
| 201 | :eval (map-contains-key (list 'bar 1 'foo 2 'baz 3) 'foo) | ||
| 202 | :eval (map-contains-key (list '(bar . 1) '(foo . 2) '(baz . 3)) 'foo) | ||
| 203 | :eval (map-contains-key [bar foo baz] 1) | ||
| 204 | :eval (map-contains-key #s(hash-table data (bar 1 foo 2 baz 3)) 'foo)) | ||
| 205 | (map-put! | ||
| 206 | (map key value) | ||
| 207 | :eval | ||
| 208 | "(let ((map (list 'bar 1 'baz 3))) | ||
| 209 | (map-put! map 'foo 2) | ||
| 210 | map)" | ||
| 211 | ;; This signals map-not-inplace when used in shortdoc.el :-( | ||
| 212 | ;; :eval | ||
| 213 | ;; "(let ((map (list '(bar . 1) '(baz . 3)))) | ||
| 214 | ;; (map-put! map 'foo 2) | ||
| 215 | ;; map)" | ||
| 216 | :eval | ||
| 217 | "(let ((map [bar bot baz])) | ||
| 218 | (map-put! map 1 'foo) | ||
| 219 | map)" | ||
| 220 | :eval | ||
| 221 | "(let ((map #s(hash-table data (bar 1 baz 3)))) | ||
| 222 | (map-put! map 'foo 2) | ||
| 223 | map)") | ||
| 224 | (map-insert | ||
| 225 | :args (map key value) | ||
| 226 | :eval (map-insert (list 'bar 1 'baz 3 'foo 7) 'foo 2) | ||
| 227 | :eval (map-insert (list '(bar . 1) '(baz . 3) '(foo . 7)) 'foo 2) | ||
| 228 | :eval (map-insert [bar bot baz] 1 'foo) | ||
| 229 | :eval (map-insert #s(hash-table data (bar 1 baz 3 foo 7)) 'foo 2)) | ||
| 230 | (map-delete | ||
| 231 | :args (map key) | ||
| 232 | :eval (map-delete (list 'bar 1 'foo 2 'baz 3) 'foo) | ||
| 233 | :eval (map-delete (list '(bar . 1) '(foo . 2) '(baz . 3)) 'foo) | ||
| 234 | :eval (map-delete [bar foo baz] 1) | ||
| 235 | :eval (map-delete #s(hash-table data (bar 1 foo 2 baz 3)) 'foo)) | ||
| 236 | (map-keys | ||
| 237 | :eval (map-keys (list 'bar 1 'foo 2 'baz 3)) | ||
| 238 | :eval (map-keys (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 239 | :eval (map-keys [bar foo baz]) | ||
| 240 | :eval (map-keys #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 241 | (map-values | ||
| 242 | :args (map) | ||
| 243 | :eval (map-values (list 'bar 1 'foo 2 'baz 3)) | ||
| 244 | :eval (map-values (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 245 | :eval (map-values [bar foo baz]) | ||
| 246 | :eval (map-values #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 247 | (map-pairs | ||
| 248 | :eval (map-pairs (list 'bar 1 'foo 2 'baz 3)) | ||
| 249 | :eval (map-pairs (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 250 | :eval (map-pairs [bar foo baz]) | ||
| 251 | :eval (map-pairs #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 252 | (map-length | ||
| 253 | :args (map) | ||
| 254 | :eval (map-length (list 'bar 1 'foo 2 'baz 3)) | ||
| 255 | :eval (map-length (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 256 | :eval (map-length [bar foo baz]) | ||
| 257 | :eval (map-length #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 258 | (map-copy | ||
| 259 | :args (map) | ||
| 260 | :eval (map-copy (list 'bar 1 'foo 2 'baz 3)) | ||
| 261 | :eval (map-copy (list '(bar . 1) '(foo . 2) '(baz . 3))) | ||
| 262 | :eval (map-copy [bar foo baz]) | ||
| 263 | :eval (map-copy #s(hash-table data (bar 1 foo 2 baz 3)))) | ||
| 264 | "Doing things to maps and their contents" | ||
| 265 | (map-apply | ||
| 266 | :args (function map) | ||
| 267 | :eval (map-apply #'+ (list '(1 . 2) '(3 . 4)))) | ||
| 268 | (map-do | ||
| 269 | :args (function map) | ||
| 270 | :eval | ||
| 271 | "(let ((map (list '(1 . 1) '(2 . 3))) | ||
| 272 | acc) | ||
| 273 | (map-do (lambda (k v) (push (+ k v) acc)) map) | ||
| 274 | (nreverse acc))") | ||
| 275 | (map-keys-apply | ||
| 276 | :eval (map-keys-apply #'1+ (list '(1 . 2) '(3 . 4)))) | ||
| 277 | (map-values-apply | ||
| 278 | :args (function map) | ||
| 279 | :eval (map-values-apply #'1+ (list '(1 . 2) '(3 . 4)))) | ||
| 280 | (map-filter | ||
| 281 | :eval (map-filter (lambda (k _) (oddp k)) (list '(1 . 2) '(4 . 6))) | ||
| 282 | :eval (map-filter (lambda (k v) (evenp (+ k v))) (list '(1 . 2) '(4 . 6)))) | ||
| 283 | (map-remove | ||
| 284 | :eval (map-remove (lambda (k _) (oddp k)) (list '(1 . 2) '(4 . 6))) | ||
| 285 | :eval (map-remove (lambda (k v) (evenp (+ k v))) (list '(1 . 2) '(4 . 6)))) | ||
| 286 | (map-some | ||
| 287 | :eval (map-some (lambda (k _) (oddp k)) (list '(1 . 2) '(4 . 6))) | ||
| 288 | :eval (map-some (lambda (k v) (evenp (+ k v))) (list '(1 . 2) '(4 . 6)))) | ||
| 289 | (map-every-p | ||
| 290 | :eval (map-every-p (lambda (k _) (oddp k)) (list '(1 . 2) '(4 . 6))) | ||
| 291 | :eval (map-every-p (lambda (k v) (evenp (+ k v))) (list '(1 . 3) '(4 . 6)))) | ||
| 292 | "Combining and changing maps" | ||
| 293 | (map-merge | ||
| 294 | :eval (map-merge 'alist '(1 2 3 4) #s(hash-table data (5 6 7 8))) | ||
| 295 | :eval (map-merge 'list '(1 2 3 4) #s(hash-table data (5 6 7 8))) | ||
| 296 | :eval (map-merge 'plist '(1 2 3 4) #s(hash-table data (5 6 7 8))) | ||
| 297 | :eval (map-merge 'hash-table '(1 2 3 4) #s(hash-table data (5 6 7 8)))) | ||
| 298 | (map-merge-with | ||
| 299 | :eval (map-merge-with 'alist #'max '(1 2 3 4) #s(hash-table data (1 1 3 5))) | ||
| 300 | :eval (map-merge-with 'alist #'min '(1 2 3 4) #s(hash-table data (1 1 3 5))) | ||
| 301 | :eval (map-merge-with 'hash-table #'min '(1 2 3 4) #s(hash-table data (1 1 3 5)))) | ||
| 302 | (map-into | ||
| 303 | :args (map type) | ||
| 304 | :eval (map-into #s(hash-table data '(5 6 7 8)) 'list) | ||
| 305 | :eval (map-into '((5 . 6) (7 . 8)) 'plist) | ||
| 306 | :eval (map-into '((5 . 6) (7 . 8)) 'hash-table))) | ||
| 307 | |||
| 308 | (define-short-documentation-group string | ||
| 309 | "Making Strings" | ||
| 310 | (make-string | ||
| 311 | :args (length init) | ||
| 312 | :eval "(make-string 5 ?x)") | ||
| 313 | (string | ||
| 314 | :eval "(string ?a ?b ?c)") | ||
| 315 | (concat | ||
| 316 | :eval (concat "foo" "bar" "zot")) | ||
| 317 | (string-join | ||
| 318 | :no-manual t | ||
| 319 | :eval (string-join '("foo" "bar" "zot") " ")) | ||
| 320 | (mapconcat | ||
| 321 | :eval (mapconcat (lambda (a) (concat "[" a "]")) | ||
| 322 | '("foo" "bar" "zot") " ")) | ||
| 323 | (string-pad | ||
| 324 | :eval (string-pad "foo" 5) | ||
| 325 | :eval (string-pad "foobar" 5) | ||
| 326 | :eval (string-pad "foo" 5 ?- t)) | ||
| 327 | (mapcar | ||
| 328 | :eval (mapcar #'identity "123")) | ||
| 329 | (format | ||
| 330 | :eval (format "This number is %d" 4)) | ||
| 331 | "Manipulating Strings" | ||
| 332 | (substring | ||
| 333 | :eval (substring "abcde" 1 3) | ||
| 334 | :eval (substring "abcde" 2) | ||
| 335 | :eval (substring "abcde" 1 -1) | ||
| 336 | :eval (substring "abcde" -4 4)) | ||
| 337 | (string-limit | ||
| 338 | :eval (string-limit "foobar" 3) | ||
| 339 | :eval (string-limit "foobar" 3 t) | ||
| 340 | :eval (string-limit "foobar" 10) | ||
| 341 | :eval (string-limit "fo好" 3 nil 'utf-8)) | ||
| 342 | (truncate-string-to-width | ||
| 343 | :eval (truncate-string-to-width "foobar" 3) | ||
| 344 | :eval (truncate-string-to-width "你好bar" 5)) | ||
| 345 | (split-string | ||
| 346 | :eval (split-string "foo bar") | ||
| 347 | :eval (split-string "|foo|bar|" "|") | ||
| 348 | :eval (split-string "|foo|bar|" "|" t)) | ||
| 349 | (split-string-and-unquote | ||
| 350 | :eval (split-string-and-unquote "foo \"bar zot\"")) | ||
| 351 | (split-string-shell-command | ||
| 352 | :eval (split-string-shell-command "ls /tmp/'foo bar'")) | ||
| 353 | (string-lines | ||
| 354 | :eval (string-lines "foo\n\nbar") | ||
| 355 | :eval (string-lines "foo\n\nbar" t)) | ||
| 356 | (string-replace | ||
| 357 | :eval (string-replace "foo" "bar" "foozot")) | ||
| 358 | (replace-regexp-in-string | ||
| 359 | :eval (replace-regexp-in-string "[a-z]+" "_" "*foo*")) | ||
| 360 | (string-trim | ||
| 361 | :args (string) | ||
| 362 | :doc "Trim STRING of leading and trailing white space." | ||
| 363 | :eval (string-trim " foo ")) | ||
| 364 | (string-trim-left | ||
| 365 | :eval (string-trim-left "oofoo" "o+")) | ||
| 366 | (string-trim-right | ||
| 367 | :eval (string-trim-right "barkss" "s+")) | ||
| 368 | (string-truncate-left | ||
| 369 | :no-manual t | ||
| 370 | :eval (string-truncate-left "longstring" 8)) | ||
| 371 | (string-remove-suffix | ||
| 372 | :no-manual t | ||
| 373 | :eval (string-remove-suffix "bar" "foobar")) | ||
| 374 | (string-remove-prefix | ||
| 375 | :no-manual t | ||
| 376 | :eval (string-remove-prefix "foo" "foobar")) | ||
| 377 | (string-chop-newline | ||
| 378 | :eval (string-chop-newline "foo\n")) | ||
| 379 | (string-clean-whitespace | ||
| 380 | :eval (string-clean-whitespace " foo bar ")) | ||
| 381 | (string-fill | ||
| 382 | :eval (string-fill "Three short words" 12) | ||
| 383 | :eval (string-fill "Long-word" 3)) | ||
| 384 | (reverse | ||
| 385 | :eval (reverse "foo")) | ||
| 386 | (substring-no-properties | ||
| 387 | :eval (substring-no-properties (propertize "foobar" 'face 'bold) 0 3)) | ||
| 388 | (try-completion | ||
| 389 | :eval (try-completion "foo" '("foobar" "foozot" "gazonk"))) | ||
| 390 | "Unicode Strings" | ||
| 391 | (string-glyph-split | ||
| 392 | :eval (string-glyph-split "Hello, 👼🏻🧑🏼🤝🧑🏻")) | ||
| 393 | (string-glyph-compose | ||
| 394 | :eval (string-glyph-compose "Å")) | ||
| 395 | (string-glyph-decompose | ||
| 396 | :eval (string-glyph-decompose "Å")) | ||
| 397 | "Predicates for Strings" | ||
| 398 | (string-equal | ||
| 399 | :eval (string-equal "abc" "abc") | ||
| 400 | :eval (string-equal "abc" "ABC")) | ||
| 401 | (string-equal-ignore-case | ||
| 402 | :eval (string-equal-ignore-case "foo" "FOO")) | ||
| 403 | (equal | ||
| 404 | :eval (equal "foo" "foo")) | ||
| 405 | (cl-equalp | ||
| 406 | :eval (cl-equalp "Foo" "foo")) | ||
| 407 | (stringp | ||
| 408 | :eval (stringp "a") | ||
| 409 | :eval (stringp 'a) | ||
| 410 | :eval "(stringp ?a)") | ||
| 411 | (string-or-null-p | ||
| 412 | :eval (string-or-null-p "a") | ||
| 413 | :eval (string-or-null-p nil)) | ||
| 414 | (char-or-string-p | ||
| 415 | :eval "(char-or-string-p ?a)" | ||
| 416 | :eval (char-or-string-p "a")) | ||
| 417 | (string-empty-p | ||
| 418 | :no-manual t | ||
| 419 | :eval (string-empty-p "")) | ||
| 420 | (string-blank-p | ||
| 421 | :no-manual t | ||
| 422 | :eval (string-blank-p " \n")) | ||
| 423 | (string-lessp | ||
| 424 | :eval (string-lessp "abc" "def") | ||
| 425 | :eval (string-lessp "pic4.png" "pic32.png") | ||
| 426 | :eval (string-lessp "1.1" "1.2")) | ||
| 427 | (string-greaterp | ||
| 428 | :eval (string-greaterp "foo" "bar")) | ||
| 429 | (string-version-lessp | ||
| 430 | :eval (string-version-lessp "pic4.png" "pic32.png") | ||
| 431 | :eval (string-version-lessp "1.9.3" "1.10.2")) | ||
| 432 | (string-collate-lessp | ||
| 433 | :eval (string-collate-lessp "abc" "abd")) | ||
| 434 | (string-prefix-p | ||
| 435 | :eval (string-prefix-p "foo" "foobar")) | ||
| 436 | (string-suffix-p | ||
| 437 | :eval (string-suffix-p "bar" "foobar")) | ||
| 438 | "Case Manipulation" | ||
| 439 | (upcase | ||
| 440 | :eval (upcase "foo")) | ||
| 441 | (downcase | ||
| 442 | :eval (downcase "FOObar")) | ||
| 443 | (capitalize | ||
| 444 | :eval (capitalize "foo bar zot")) | ||
| 445 | (upcase-initials | ||
| 446 | :eval (upcase-initials "The CAT in the hAt")) | ||
| 447 | "Converting Strings" | ||
| 448 | (string-to-number | ||
| 449 | :eval (string-to-number "42") | ||
| 450 | :eval (string-to-number "deadbeef" 16) | ||
| 451 | :eval (string-to-number "2.5e+03")) | ||
| 452 | (number-to-string | ||
| 453 | :eval (number-to-string 42)) | ||
| 454 | (char-uppercase-p | ||
| 455 | :eval "(char-uppercase-p ?A)" | ||
| 456 | :eval "(char-uppercase-p ?a)") | ||
| 457 | "Data About Strings" | ||
| 458 | (length | ||
| 459 | :eval (length "foo") | ||
| 460 | :eval (length "avocado: 🥑")) | ||
| 461 | (string-width | ||
| 462 | :eval (string-width "foo") | ||
| 463 | :eval (string-width "avocado: 🥑")) | ||
| 464 | (string-pixel-width | ||
| 465 | :eval (string-pixel-width "foo") | ||
| 466 | :eval (string-pixel-width "avocado: 🥑")) | ||
| 467 | (string-search | ||
| 468 | :eval (string-search "bar" "foobarzot")) | ||
| 469 | (assoc-string | ||
| 470 | :eval (assoc-string "foo" '(("a" 1) (foo 2)))) | ||
| 471 | (seq-position | ||
| 472 | :eval "(seq-position \"foobarzot\" ?z)")) | ||
| 473 | |||
| 474 | (define-short-documentation-group file-name | ||
| 475 | "File Name Manipulation" | ||
| 476 | (file-name-directory | ||
| 477 | :eval (file-name-directory "/tmp/foo") | ||
| 478 | :eval (file-name-directory "/tmp/foo/")) | ||
| 479 | (file-name-nondirectory | ||
| 480 | :eval (file-name-nondirectory "/tmp/foo") | ||
| 481 | :eval (file-name-nondirectory "/tmp/foo/")) | ||
| 482 | (file-name-sans-versions | ||
| 483 | :args (filename) | ||
| 484 | :eval (file-name-sans-versions "/tmp/foo~")) | ||
| 485 | (file-name-extension | ||
| 486 | :eval (file-name-extension "/tmp/foo.txt")) | ||
| 487 | (file-name-sans-extension | ||
| 488 | :eval (file-name-sans-extension "/tmp/foo.txt")) | ||
| 489 | (file-name-with-extension | ||
| 490 | :eval (file-name-with-extension "foo.txt" "bin") | ||
| 491 | :eval (file-name-with-extension "foo" "bin")) | ||
| 492 | (file-name-base | ||
| 493 | :eval (file-name-base "/tmp/foo.txt")) | ||
| 494 | (file-relative-name | ||
| 495 | :eval (file-relative-name "/tmp/foo" "/tmp")) | ||
| 496 | (file-name-split | ||
| 497 | :eval (file-name-split "/tmp/foo") | ||
| 498 | :eval (file-name-split "foo/bar")) | ||
| 499 | (make-temp-name | ||
| 500 | :eval (make-temp-name "/tmp/foo-")) | ||
| 501 | (file-name-concat | ||
| 502 | :eval (file-name-concat "/tmp/" "foo") | ||
| 503 | :eval (file-name-concat "/tmp" "foo") | ||
| 504 | :eval (file-name-concat "/tmp" "foo" "bar/" "zot") | ||
| 505 | :eval (file-name-concat "/tmp" "~")) | ||
| 506 | (expand-file-name | ||
| 507 | :eval (expand-file-name "foo" "/tmp/") | ||
| 508 | :eval (expand-file-name "foo" "/tmp///") | ||
| 509 | :eval (expand-file-name "foo" "/tmp/foo/.././") | ||
| 510 | :eval (expand-file-name "~" "/tmp/")) | ||
| 511 | (substitute-in-file-name | ||
| 512 | :eval (substitute-in-file-name "$HOME/foo")) | ||
| 513 | "Directory Functions" | ||
| 514 | (file-name-as-directory | ||
| 515 | :eval (file-name-as-directory "/tmp/foo")) | ||
| 516 | (directory-file-name | ||
| 517 | :eval (directory-file-name "/tmp/foo/")) | ||
| 518 | (abbreviate-file-name | ||
| 519 | :no-eval (abbreviate-file-name "/home/some-user") | ||
| 520 | :eg-result "~some-user") | ||
| 521 | (file-name-parent-directory | ||
| 522 | :eval (file-name-parent-directory "/foo/bar") | ||
| 523 | :eval (file-name-parent-directory "/foo/") | ||
| 524 | :eval (file-name-parent-directory "foo/bar") | ||
| 525 | :eval (file-name-parent-directory "foo")) | ||
| 526 | "Quoted File Names" | ||
| 527 | (file-name-quote | ||
| 528 | :args (name) | ||
| 529 | :eval (file-name-quote "/tmp/foo")) | ||
| 530 | (file-name-unquote | ||
| 531 | :args (name) | ||
| 532 | :eval (file-name-unquote "/:/tmp/foo")) | ||
| 533 | "Predicates" | ||
| 534 | (file-name-absolute-p | ||
| 535 | :eval (file-name-absolute-p "/tmp/foo") | ||
| 536 | :eval (file-name-absolute-p "foo")) | ||
| 537 | (directory-name-p | ||
| 538 | :eval (directory-name-p "/tmp/foo/")) | ||
| 539 | (file-name-quoted-p | ||
| 540 | :eval (file-name-quoted-p "/:/tmp/foo"))) | ||
| 541 | |||
| 542 | (define-short-documentation-group file | ||
| 543 | "Inserting Contents" | ||
| 544 | (insert-file-contents | ||
| 545 | :no-eval (insert-file-contents "/tmp/foo") | ||
| 546 | :eg-result ("/tmp/foo" 6)) | ||
| 547 | (insert-file-contents-literally | ||
| 548 | :no-eval (insert-file-contents-literally "/tmp/foo") | ||
| 549 | :eg-result ("/tmp/foo" 6)) | ||
| 550 | (find-file | ||
| 551 | :no-eval (find-file "/tmp/foo") | ||
| 552 | :eg-result-string "#<buffer foo>") | ||
| 553 | "Predicates" | ||
| 554 | (file-symlink-p | ||
| 555 | :no-eval (file-symlink-p "/tmp/foo") | ||
| 556 | :eg-result t) | ||
| 557 | (file-directory-p | ||
| 558 | :no-eval (file-directory-p "/tmp") | ||
| 559 | :eg-result t) | ||
| 560 | (file-regular-p | ||
| 561 | :no-eval (file-regular-p "/tmp/foo") | ||
| 562 | :eg-result t) | ||
| 563 | (file-exists-p | ||
| 564 | :no-eval (file-exists-p "/tmp/foo") | ||
| 565 | :eg-result t) | ||
| 566 | (file-readable-p | ||
| 567 | :no-eval (file-readable-p "/tmp/foo") | ||
| 568 | :eg-result t) | ||
| 569 | (file-writable-p | ||
| 570 | :no-eval (file-writable-p "/tmp/foo") | ||
| 571 | :eg-result t) | ||
| 572 | (file-accessible-directory-p | ||
| 573 | :no-eval (file-accessible-directory-p "/tmp") | ||
| 574 | :eg-result t) | ||
| 575 | (file-executable-p | ||
| 576 | :no-eval (file-executable-p "/bin/cat") | ||
| 577 | :eg-result t) | ||
| 578 | (file-newer-than-file-p | ||
| 579 | :no-eval (file-newer-than-file-p "/tmp/foo" "/tmp/bar") | ||
| 580 | :eg-result nil) | ||
| 581 | (file-has-changed-p | ||
| 582 | :no-eval (file-has-changed-p "/tmp/foo") | ||
| 583 | :eg-result t) | ||
| 584 | (file-equal-p | ||
| 585 | :no-eval (file-equal-p "/tmp/foo" "/tmp/bar") | ||
| 586 | :eg-result nil) | ||
| 587 | (file-in-directory-p | ||
| 588 | :no-eval (file-in-directory-p "/tmp/foo" "/tmp/") | ||
| 589 | :eg-result t) | ||
| 590 | (file-locked-p | ||
| 591 | :no-eval (file-locked-p "/tmp/foo") | ||
| 592 | :eg-result nil) | ||
| 593 | "Information" | ||
| 594 | (file-attributes | ||
| 595 | :no-eval* (file-attributes "/tmp")) | ||
| 596 | (file-truename | ||
| 597 | :no-eval (file-truename "/tmp/foo/bar") | ||
| 598 | :eg-result "/tmp/foo/zot") | ||
| 599 | (file-chase-links | ||
| 600 | :no-eval (file-chase-links "/tmp/foo/bar") | ||
| 601 | :eg-result "/tmp/foo/zot") | ||
| 602 | (vc-responsible-backend | ||
| 603 | :args (file &optional no-error) | ||
| 604 | :no-eval (vc-responsible-backend "/src/foo/bar.c") | ||
| 605 | :eg-result Git) | ||
| 606 | (file-acl | ||
| 607 | :no-eval (file-acl "/tmp/foo") | ||
| 608 | :eg-result "user::rw-\ngroup::r--\nother::r--\n") | ||
| 609 | (file-extended-attributes | ||
| 610 | :no-eval* (file-extended-attributes "/tmp/foo")) | ||
| 611 | (file-selinux-context | ||
| 612 | :no-eval* (file-selinux-context "/tmp/foo")) | ||
| 613 | (locate-file | ||
| 614 | :no-eval (locate-file "syslog" '("/var/log" "/usr/bin")) | ||
| 615 | :eg-result "/var/log/syslog") | ||
| 616 | (executable-find | ||
| 617 | :no-eval (executable-find "ls") | ||
| 618 | :eg-result "/usr/bin/ls") | ||
| 619 | "Creating" | ||
| 620 | (make-temp-file | ||
| 621 | :no-eval (make-temp-file "/tmp/foo-") | ||
| 622 | :eg-result "/tmp/foo-ZcXFMj") | ||
| 623 | (make-nearby-temp-file | ||
| 624 | :no-eval (make-nearby-temp-file "/tmp/foo-") | ||
| 625 | :eg-result "/tmp/foo-xe8iON") | ||
| 626 | (write-region | ||
| 627 | :no-value (write-region (point-min) (point-max) "/tmp/foo")) | ||
| 628 | "Directories" | ||
| 629 | (make-directory | ||
| 630 | :no-value (make-directory "/tmp/bar/zot/" t)) | ||
| 631 | (directory-files | ||
| 632 | :no-eval (directory-files "/tmp/") | ||
| 633 | :eg-result ("." ".." ".ICE-unix" ".Test-unix")) | ||
| 634 | (directory-files-recursively | ||
| 635 | :no-eval (directory-files-recursively "/tmp/" "\\.png\\'") | ||
| 636 | :eg-result ("/tmp/foo.png" "/tmp/zot.png" "/tmp/bar/foobar.png")) | ||
| 637 | (directory-files-and-attributes | ||
| 638 | :no-eval* (directory-files-and-attributes "/tmp/foo")) | ||
| 639 | (file-expand-wildcards | ||
| 640 | :no-eval (file-expand-wildcards "/tmp/*.png") | ||
| 641 | :eg-result ("/tmp/foo.png" "/tmp/zot.png") | ||
| 642 | :no-eval (file-expand-wildcards "/*/foo.png") | ||
| 643 | :eg-result ("/tmp/foo.png" "/var/foo.png")) | ||
| 644 | (locate-dominating-file | ||
| 645 | :no-eval (locate-dominating-file "foo.png" "/tmp/foo/bar/zot") | ||
| 646 | :eg-result "/tmp/foo.png") | ||
| 647 | (copy-directory | ||
| 648 | :no-value (copy-directory "/tmp/bar/" "/tmp/barcopy")) | ||
| 649 | (delete-directory | ||
| 650 | :no-value (delete-directory "/tmp/bar/")) | ||
| 651 | "File Operations" | ||
| 652 | (rename-file | ||
| 653 | :no-value (rename-file "/tmp/foo" "/tmp/newname")) | ||
| 654 | (copy-file | ||
| 655 | :no-value (copy-file "/tmp/foo" "/tmp/foocopy")) | ||
| 656 | (delete-file | ||
| 657 | :no-value (delete-file "/tmp/foo")) | ||
| 658 | (make-empty-file | ||
| 659 | :no-value (make-empty-file "/tmp/foo")) | ||
| 660 | (make-symbolic-link | ||
| 661 | :no-value (make-symbolic-link "/tmp/foo" "/tmp/foosymlink")) | ||
| 662 | (add-name-to-file | ||
| 663 | :no-value (add-name-to-file "/tmp/foo" "/tmp/bar")) | ||
| 664 | (set-file-modes | ||
| 665 | :no-value "(set-file-modes \"/tmp/foo\" #o644)") | ||
| 666 | (set-file-times | ||
| 667 | :no-value (set-file-times "/tmp/foo")) | ||
| 668 | "File Modes" | ||
| 669 | (set-default-file-modes | ||
| 670 | :no-value "(set-default-file-modes #o755)") | ||
| 671 | (default-file-modes | ||
| 672 | :no-eval (default-file-modes) | ||
| 673 | :eg-result-string "#o755") | ||
| 674 | (file-modes-symbolic-to-number | ||
| 675 | :no-eval (file-modes-symbolic-to-number "a+r") | ||
| 676 | :eg-result-string "#o444") | ||
| 677 | (file-modes-number-to-symbolic | ||
| 678 | :eval "(file-modes-number-to-symbolic #o444)") | ||
| 679 | (set-file-extended-attributes | ||
| 680 | :no-eval (set-file-extended-attributes | ||
| 681 | "/tmp/foo" '((acl . "group::rxx"))) | ||
| 682 | :eg-result t) | ||
| 683 | (set-file-selinux-context | ||
| 684 | :no-eval (set-file-selinux-context | ||
| 685 | "/tmp/foo" '(unconfined_u object_r user_home_t s0)) | ||
| 686 | :eg-result t) | ||
| 687 | (set-file-acl | ||
| 688 | :no-eval (set-file-acl "/tmp/foo" "group::rxx") | ||
| 689 | :eg-result t)) | ||
| 690 | |||
| 691 | (define-short-documentation-group hash-table | ||
| 692 | "Hash Table Basics" | ||
| 693 | (make-hash-table | ||
| 694 | :no-eval (make-hash-table) | ||
| 695 | :result-string "#s(hash-table ...)") | ||
| 696 | (puthash | ||
| 697 | :no-eval (puthash 'key "value" table)) | ||
| 698 | (gethash | ||
| 699 | :no-eval (gethash 'key table) | ||
| 700 | :eg-result "value") | ||
| 701 | (remhash | ||
| 702 | :no-eval (remhash 'key table) | ||
| 703 | :result nil) | ||
| 704 | (clrhash | ||
| 705 | :no-eval (clrhash table) | ||
| 706 | :result-string "#s(hash-table ...)") | ||
| 707 | (maphash | ||
| 708 | :no-eval (maphash (lambda (key value) (message value)) table) | ||
| 709 | :result nil) | ||
| 710 | "Other Hash Table Functions" | ||
| 711 | (hash-table-p | ||
| 712 | :eval (hash-table-p 123)) | ||
| 713 | (hash-table-contains-p | ||
| 714 | :no-eval (hash-table-contains-p 'key table)) | ||
| 715 | (copy-hash-table | ||
| 716 | :no-eval (copy-hash-table table) | ||
| 717 | :result-string "#s(hash-table ...)") | ||
| 718 | (hash-table-count | ||
| 719 | :no-eval (hash-table-count table) | ||
| 720 | :eg-result 15)) | ||
| 721 | |||
| 722 | (define-short-documentation-group list | ||
| 723 | "Making Lists" | ||
| 724 | (make-list | ||
| 725 | :eval (make-list 5 'a)) | ||
| 726 | (cons | ||
| 727 | :eval (cons 1 '(2 3 4))) | ||
| 728 | (list | ||
| 729 | :eval (list 1 2 3)) | ||
| 730 | (number-sequence | ||
| 731 | :eval (number-sequence 5 8)) | ||
| 732 | (ensure-list | ||
| 733 | :eval (ensure-list "foo") | ||
| 734 | :eval (ensure-list '(1 2 3)) | ||
| 735 | :eval (ensure-list '(1 . 2))) | ||
| 736 | (ensure-proper-list | ||
| 737 | :eval (ensure-proper-list "foo") | ||
| 738 | :eval (ensure-proper-list '(1 2 3)) | ||
| 739 | :eval (ensure-proper-list '(1 . 2))) | ||
| 740 | "Operations on Lists" | ||
| 741 | (append | ||
| 742 | :eval (append '("foo" "bar") '("zot"))) | ||
| 743 | (copy-tree | ||
| 744 | :eval (copy-tree '(1 (2 3) 4))) | ||
| 745 | (flatten-tree | ||
| 746 | :eval (flatten-tree '(1 (2 3) 4))) | ||
| 747 | (car | ||
| 748 | :eval (car '(one two three)) | ||
| 749 | :eval (car '(one . two)) | ||
| 750 | :eval (car nil)) | ||
| 751 | (cdr | ||
| 752 | :eval (cdr '(one two three)) | ||
| 753 | :eval (cdr '(one . two)) | ||
| 754 | :eval (cdr nil)) | ||
| 755 | (last | ||
| 756 | :eval (last '(one two three))) | ||
| 757 | (butlast | ||
| 758 | :eval (butlast '(one two three))) | ||
| 759 | (nbutlast | ||
| 760 | :eval (nbutlast (list 'one 'two 'three))) | ||
| 761 | (nth | ||
| 762 | :eval (nth 1 '(one two three))) | ||
| 763 | (nthcdr | ||
| 764 | :eval (nthcdr 1 '(one two three))) | ||
| 765 | (take | ||
| 766 | :eval (take 3 '(one two three four))) | ||
| 767 | (ntake | ||
| 768 | :eval (ntake 3 (list 'one 'two 'three 'four))) | ||
| 769 | (take-while | ||
| 770 | :eval (take-while #'numberp '(1 2 three 4 five))) | ||
| 771 | (drop-while | ||
| 772 | :eval (drop-while #'numberp '(1 2 three 4 five))) | ||
| 773 | (any | ||
| 774 | :eval (any #'symbolp '(1 2 three 4 five))) | ||
| 775 | (all | ||
| 776 | :eval (all #'symbolp '(one 2 three)) | ||
| 777 | :eval (all #'symbolp '(one two three))) | ||
| 778 | (elt | ||
| 779 | :eval (elt '(one two three) 1)) | ||
| 780 | (car-safe | ||
| 781 | :eval (car-safe '(one two three))) | ||
| 782 | (cdr-safe | ||
| 783 | :eval (cdr-safe '(one two three))) | ||
| 784 | (push | ||
| 785 | :no-eval* (push 'a list)) | ||
| 786 | (pop | ||
| 787 | :no-eval* (pop list)) | ||
| 788 | (setcar | ||
| 789 | :no-eval (setcar list 'c) | ||
| 790 | :result c) | ||
| 791 | (setcdr | ||
| 792 | :no-eval (setcdr list (list c)) | ||
| 793 | :result '(c)) | ||
| 794 | (nconc | ||
| 795 | :eval (nconc (list 1) (list 2 3 4))) | ||
| 796 | (delq | ||
| 797 | :eval (delq 'a (list 'a 'b 'c 'd))) | ||
| 798 | (delete | ||
| 799 | :eval (delete 2 (list 1 2 3 4)) | ||
| 800 | :eval (delete "a" (list "a" "b" "c" "d"))) | ||
| 801 | (remq | ||
| 802 | :eval (remq 'b '(a b c))) | ||
| 803 | (remove | ||
| 804 | :eval (remove 2 '(1 2 3 4)) | ||
| 805 | :eval (remove "a" '("a" "b" "c" "d"))) | ||
| 806 | (delete-dups | ||
| 807 | :eval (delete-dups (list 1 2 4 3 2 4))) | ||
| 808 | "Mapping Over Lists" | ||
| 809 | (mapcar | ||
| 810 | :eval (mapcar #'list '(1 2 3))) | ||
| 811 | (mapcan | ||
| 812 | :eval (mapcan #'list '(1 2 3))) | ||
| 813 | (mapc | ||
| 814 | :eval (mapc #'insert '("1" "2" "3"))) | ||
| 815 | (seq-reduce | ||
| 816 | :eval (seq-reduce #'+ '(1 2 3) 0)) | ||
| 817 | (mapconcat | ||
| 818 | :eval (mapconcat #'identity '("foo" "bar") "|")) | ||
| 819 | "Predicates" | ||
| 820 | (listp | ||
| 821 | :eval (listp '(1 2 3)) | ||
| 822 | :eval (listp nil) | ||
| 823 | :eval (listp '(1 . 2))) | ||
| 824 | (consp | ||
| 825 | :eval (consp '(1 2 3)) | ||
| 826 | :eval (consp nil)) | ||
| 827 | (proper-list-p | ||
| 828 | :eval (proper-list-p '(1 2 3)) | ||
| 829 | :eval (proper-list-p nil) | ||
| 830 | :eval (proper-list-p '(1 . 2))) | ||
| 831 | (null | ||
| 832 | :eval (null nil)) | ||
| 833 | (atom | ||
| 834 | :eval (atom 'a)) | ||
| 835 | (nlistp | ||
| 836 | :eval (nlistp '(1 2 3)) | ||
| 837 | :eval (nlistp t) | ||
| 838 | :eval (nlistp '(1 . 2))) | ||
| 839 | "Finding Elements" | ||
| 840 | (memq | ||
| 841 | :eval (memq 'b '(a b c))) | ||
| 842 | (memql | ||
| 843 | :eval (memql 2.0 '(1.0 2.0 3.0))) | ||
| 844 | (member | ||
| 845 | :eval (member 2 '(1 2 3)) | ||
| 846 | :eval (member "b" '("a" "b" "c"))) | ||
| 847 | (member-ignore-case | ||
| 848 | :eval (member-ignore-case "foo" '("bar" "Foo" "zot"))) | ||
| 849 | "Association Lists" | ||
| 850 | (assoc | ||
| 851 | :eval (assoc "b" '(("a" . 1) ("b" . 2)))) | ||
| 852 | (rassoc | ||
| 853 | :eval (rassoc "b" '((1 . "a") (2 . "b")))) | ||
| 854 | (assq | ||
| 855 | :eval (assq 'b '((a . 1) (b . 2)))) | ||
| 856 | (rassq | ||
| 857 | :eval (rassq 'b '((1 . a) (2 . b)))) | ||
| 858 | (assoc-string | ||
| 859 | :eval (assoc-string "foo" '(("a" 1) (foo 2)))) | ||
| 860 | (alist-get | ||
| 861 | :eval (alist-get 2 '((1 . a) (2 . b)))) | ||
| 862 | (assoc-default | ||
| 863 | :eval (assoc-default 2 '((1 . a) (2 . b) #'=))) | ||
| 864 | (copy-alist | ||
| 865 | :eval (copy-alist '((1 . a) (2 . b)))) | ||
| 866 | (assoc-delete-all | ||
| 867 | :eval (assoc-delete-all "b" (list '("a" . a) '("b" . b) '("b" . c)))) | ||
| 868 | (assq-delete-all | ||
| 869 | :eval (assq-delete-all 2 (list '(1 . a) '(2 . b) '(2 . c)))) | ||
| 870 | (rassq-delete-all | ||
| 871 | :eval (rassq-delete-all 'b (list '(1 . a) '(2 . b) '(2 . c)))) | ||
| 872 | "Property Lists" | ||
| 873 | (plist-get | ||
| 874 | :eval (plist-get '(a 1 b 2 c 3) 'b)) | ||
| 875 | (plist-put | ||
| 876 | :no-eval (setq plist (plist-put plist 'd 4)) | ||
| 877 | :eg-result (a 1 b 2 c 3 d 4)) | ||
| 878 | (plist-member | ||
| 879 | :eval (plist-member '(a 1 b 2 c 3) 'b)) | ||
| 880 | "Data About Lists" | ||
| 881 | (length | ||
| 882 | :eval (length '(a b c))) | ||
| 883 | (length< | ||
| 884 | :eval (length< '(a b c) 1)) | ||
| 885 | (length> | ||
| 886 | :eval (length> '(a b c) 1)) | ||
| 887 | (length= | ||
| 888 | :eval (length= '(a b c) 3)) | ||
| 889 | (safe-length | ||
| 890 | :eval (safe-length '(a b c)))) | ||
| 891 | |||
| 892 | (define-short-documentation-group symbol | ||
| 893 | "Making symbols" | ||
| 894 | (intern | ||
| 895 | :eval (intern "abc")) | ||
| 896 | (intern-soft | ||
| 897 | :eval (intern-soft "list") | ||
| 898 | :eval (intern-soft "Phooey!")) | ||
| 899 | (make-symbol | ||
| 900 | :eval (make-symbol "abc")) | ||
| 901 | (gensym | ||
| 902 | :no-eval (gensym) | ||
| 903 | :eg-result g37) | ||
| 904 | "Comparing symbols" | ||
| 905 | (eq | ||
| 906 | :eval (eq 'abc 'abc) | ||
| 907 | :eval (eq 'abc 'abd)) | ||
| 908 | (eql | ||
| 909 | :eval (eql 'abc 'abc)) | ||
| 910 | (equal | ||
| 911 | :eval (equal 'abc 'abc)) | ||
| 912 | "Name" | ||
| 913 | (symbol-name | ||
| 914 | :eval (symbol-name 'abc)) | ||
| 915 | "Obarrays" | ||
| 916 | (obarray-make | ||
| 917 | :eval (obarray-make)) | ||
| 918 | (obarrayp | ||
| 919 | :eval (obarrayp (obarray-make)) | ||
| 920 | :eval (obarrayp nil)) | ||
| 921 | (unintern | ||
| 922 | :no-eval (unintern "abc" my-obarray) | ||
| 923 | :eg-result t) | ||
| 924 | (mapatoms | ||
| 925 | :no-eval (mapatoms (lambda (symbol) (print symbol)) my-obarray)) | ||
| 926 | (obarray-clear | ||
| 927 | :no-eval (obarray-clear my-obarray))) | ||
| 928 | |||
| 929 | (define-short-documentation-group comparison | ||
| 930 | "General-purpose" | ||
| 931 | (eq | ||
| 932 | :eval (eq 'a 'a) | ||
| 933 | :eval "(eq ?A ?A)" | ||
| 934 | :eval (let ((x (list 'a "b" '(c) 4 5.0))) | ||
| 935 | (eq x x))) | ||
| 936 | (eql | ||
| 937 | :eval (eql 2 2) | ||
| 938 | :eval (eql 2.0 2.0) | ||
| 939 | :eval (eql 2.0 2)) | ||
| 940 | (equal | ||
| 941 | :eval (equal "abc" "abc") | ||
| 942 | :eval (equal 2.0 2.0) | ||
| 943 | :eval (equal 2.0 2) | ||
| 944 | :eval (equal '(a "b" (c) 4.0) '(a "b" (c) 4.0))) | ||
| 945 | (cl-equalp | ||
| 946 | :eval (cl-equalp 2 2.0) | ||
| 947 | :eval (cl-equalp "ABC" "abc")) | ||
| 948 | "Numeric" | ||
| 949 | (= | ||
| 950 | :args (number &rest numbers) | ||
| 951 | :eval (= 2 2) | ||
| 952 | :eval (= 2.0 2.0) | ||
| 953 | :eval (= 2.0 2) | ||
| 954 | :eval (= 4 4 4 4)) | ||
| 955 | (/= | ||
| 956 | :eval (/= 4 4)) | ||
| 957 | (< | ||
| 958 | :args (number &rest numbers) | ||
| 959 | :eval (< 4 4) | ||
| 960 | :eval (< 1 2 3)) | ||
| 961 | (<= | ||
| 962 | :args (number &rest numbers) | ||
| 963 | :eval (<= 4 4) | ||
| 964 | :eval (<= 1 2 2 3)) | ||
| 965 | (> | ||
| 966 | :args (number &rest numbers) | ||
| 967 | :eval (> 4 4) | ||
| 968 | :eval (> 3 2 1)) | ||
| 969 | (>= | ||
| 970 | :args (number &rest numbers) | ||
| 971 | :eval (>= 4 4) | ||
| 972 | :eval (>= 3 2 2 1)) | ||
| 973 | "String" | ||
| 974 | (string-equal | ||
| 975 | :eval (string-equal "abc" "abc") | ||
| 976 | :eval (string-equal "abc" "ABC")) | ||
| 977 | (string-equal-ignore-case | ||
| 978 | :eval (string-equal-ignore-case "abc" "ABC")) | ||
| 979 | (string-lessp | ||
| 980 | :eval (string-lessp "abc" "abd") | ||
| 981 | :eval (string-lessp "abc" "abc") | ||
| 982 | :eval (string-lessp "pic4.png" "pic32.png")) | ||
| 983 | (string-greaterp | ||
| 984 | :eval (string-greaterp "abd" "abc") | ||
| 985 | :eval (string-greaterp "abc" "abc")) | ||
| 986 | (string-version-lessp | ||
| 987 | :eval (string-version-lessp "pic4.png" "pic32.png") | ||
| 988 | :eval (string-version-lessp "1.9.3" "1.10.2")) | ||
| 989 | (string-collate-lessp | ||
| 990 | :eval (string-collate-lessp "abc" "abd"))) | ||
| 991 | |||
| 992 | (define-short-documentation-group vector | ||
| 993 | "Making Vectors" | ||
| 994 | (make-vector | ||
| 995 | :eval (make-vector 5 "foo")) | ||
| 996 | (vector | ||
| 997 | :eval (vector 1 "b" 3)) | ||
| 998 | "Operations on Vectors" | ||
| 999 | (vectorp | ||
| 1000 | :eval (vectorp [1]) | ||
| 1001 | :eval (vectorp "1")) | ||
| 1002 | (vconcat | ||
| 1003 | :eval (vconcat '(1 2) [3 4])) | ||
| 1004 | (append | ||
| 1005 | :eval (append [1 2] nil)) | ||
| 1006 | (length | ||
| 1007 | :eval (length [1 2 3])) | ||
| 1008 | (seq-reduce | ||
| 1009 | :eval (seq-reduce #'+ [1 2 3] 0)) | ||
| 1010 | (seq-subseq | ||
| 1011 | :eval (seq-subseq [1 2 3 4 5] 1 3) | ||
| 1012 | :eval (seq-subseq [1 2 3 4 5] 1)) | ||
| 1013 | (copy-tree | ||
| 1014 | :eval (copy-tree [1 (2 3) [4 5]] t)) | ||
| 1015 | "Mapping Over Vectors" | ||
| 1016 | (mapcar | ||
| 1017 | :eval (mapcar #'identity [1 2 3])) | ||
| 1018 | (mapc | ||
| 1019 | :eval (mapc #'insert ["1" "2" "3"]))) | ||
| 1020 | |||
| 1021 | (define-short-documentation-group regexp | ||
| 1022 | "Matching Strings" | ||
| 1023 | (replace-regexp-in-string | ||
| 1024 | :eval (replace-regexp-in-string "[a-z]+" "_" "*foo*")) | ||
| 1025 | (string-match-p | ||
| 1026 | :eval (string-match-p "^[fo]+" "foobar")) | ||
| 1027 | "Looking in Buffers" | ||
| 1028 | (re-search-forward | ||
| 1029 | :no-eval (re-search-forward "^foo$" nil t) | ||
| 1030 | :eg-result 43) | ||
| 1031 | (re-search-backward | ||
| 1032 | :no-eval (re-search-backward "^foo$" nil t) | ||
| 1033 | :eg-result 43) | ||
| 1034 | (looking-at-p | ||
| 1035 | :no-eval (looking-at-p "f[0-9]") | ||
| 1036 | :eg-result t) | ||
| 1037 | "Match Data" | ||
| 1038 | (match-string | ||
| 1039 | :eval (and (string-match "^\\([fo]+\\)b" "foobar") | ||
| 1040 | (match-string 0 "foobar"))) | ||
| 1041 | (match-beginning | ||
| 1042 | :no-eval (match-beginning 1) | ||
| 1043 | :eg-result 0) | ||
| 1044 | (match-end | ||
| 1045 | :no-eval (match-end 1) | ||
| 1046 | :eg-result 3) | ||
| 1047 | (save-match-data | ||
| 1048 | :no-eval (save-match-data ...)) | ||
| 1049 | "Replacing Match" | ||
| 1050 | (replace-match | ||
| 1051 | :no-eval (replace-match "new") | ||
| 1052 | :eg-result nil) | ||
| 1053 | (match-substitute-replacement | ||
| 1054 | :no-eval (match-substitute-replacement "new") | ||
| 1055 | :eg-result "new") | ||
| 1056 | (replace-regexp-in-region | ||
| 1057 | :no-value (replace-regexp-in-region "[0-9]+" "Num \\&")) | ||
| 1058 | "Utilities" | ||
| 1059 | (regexp-quote | ||
| 1060 | :eval (regexp-quote "foo.*bar")) | ||
| 1061 | (regexp-opt | ||
| 1062 | :eval (regexp-opt '("foo" "bar"))) | ||
| 1063 | (regexp-opt-depth | ||
| 1064 | :eval (regexp-opt-depth "\\(a\\(b\\)\\)")) | ||
| 1065 | (regexp-opt-charset | ||
| 1066 | :eval (regexp-opt-charset '(?a ?b ?c ?d ?e))) | ||
| 1067 | "The `rx' Structured Regexp Notation" | ||
| 1068 | (rx | ||
| 1069 | :eval (rx "IP=" (+ digit) (= 3 "." (+ digit)))) | ||
| 1070 | (rx-to-string | ||
| 1071 | :eval (rx-to-string '(| "foo" "bar"))) | ||
| 1072 | (rx-define | ||
| 1073 | :no-eval "(and (rx-define haskell-comment (seq \"--\" (zero-or-more nonl))) | ||
| 1074 | (rx haskell-comment))" | ||
| 1075 | :result "--.*") | ||
| 1076 | (rx-let | ||
| 1077 | :eval "(rx-let ((comma-separated (item) (seq item (0+ \",\" item))) | ||
| 1078 | (number (1+ digit)) | ||
| 1079 | (numbers (comma-separated number))) | ||
| 1080 | (rx \"(\" numbers \")\"))" | ||
| 1081 | :result "([[:digit:]]+\\(?:,[[:digit:]]+\\)*)") | ||
| 1082 | (rx-let-eval | ||
| 1083 | :eval "(rx-let-eval | ||
| 1084 | '((ponder (x) (seq \"Where have all the \" x \" gone?\"))) | ||
| 1085 | (rx-to-string | ||
| 1086 | '(ponder (or \"flowers\" \"cars\" \"socks\"))))" | ||
| 1087 | :result "\\(?:Where have all the \\(?:\\(?:car\\|flower\\|sock\\)s\\) gone\\?\\)")) | ||
| 1088 | |||
| 1089 | (define-short-documentation-group sequence | ||
| 1090 | "Sequence Predicates" | ||
| 1091 | (seq-contains-p | ||
| 1092 | :eval (seq-contains-p '(a b c) 'b) | ||
| 1093 | :eval (seq-contains-p '(a b c) 'd)) | ||
| 1094 | (seq-every-p | ||
| 1095 | :eval (seq-every-p #'numberp '(1 2 3))) | ||
| 1096 | (seq-empty-p | ||
| 1097 | :eval (seq-empty-p [])) | ||
| 1098 | (seq-set-equal-p | ||
| 1099 | :eval (seq-set-equal-p '(1 2 3) '(3 1 2))) | ||
| 1100 | (seq-some | ||
| 1101 | :eval (seq-some #'floatp '(1 2.0 3))) | ||
| 1102 | "Building Sequences" | ||
| 1103 | (seq-concatenate | ||
| 1104 | :eval (seq-concatenate 'vector '(1 2) '(c d))) | ||
| 1105 | (seq-copy | ||
| 1106 | :eval (seq-copy '(a 2))) | ||
| 1107 | (seq-into | ||
| 1108 | :eval (seq-into '(1 2 3) 'vector)) | ||
| 1109 | "Utility Functions" | ||
| 1110 | (seq-count | ||
| 1111 | :eval (seq-count #'numberp '(1 b c 4))) | ||
| 1112 | (seq-elt | ||
| 1113 | :eval (seq-elt '(a b c) 1)) | ||
| 1114 | (seq-random-elt | ||
| 1115 | :no-eval (seq-random-elt '(a b c)) | ||
| 1116 | :eg-result c) | ||
| 1117 | (seq-find | ||
| 1118 | :eval (seq-find #'numberp '(a b 3 4 f 6))) | ||
| 1119 | (seq-position | ||
| 1120 | :eval (seq-position '(a b c) 'c)) | ||
| 1121 | (seq-positions | ||
| 1122 | :eval (seq-positions '(a b c a d) 'a) | ||
| 1123 | :eval (seq-positions '(a b c a d) 'z) | ||
| 1124 | :eval (seq-positions '(11 5 7 12 9 15) 10 #'>=)) | ||
| 1125 | (seq-length | ||
| 1126 | :eval (seq-length "abcde")) | ||
| 1127 | (seq-max | ||
| 1128 | :eval (seq-max [1 2 3])) | ||
| 1129 | (seq-min | ||
| 1130 | :eval (seq-min [1 2 3])) | ||
| 1131 | (seq-first | ||
| 1132 | :eval (seq-first [a b c])) | ||
| 1133 | (seq-rest | ||
| 1134 | :eval (seq-rest '[1 2 3])) | ||
| 1135 | (seq-reverse | ||
| 1136 | :eval (seq-reverse '(1 2 3))) | ||
| 1137 | (seq-sort | ||
| 1138 | :eval (seq-sort #'> '(1 2 3))) | ||
| 1139 | (seq-sort-by | ||
| 1140 | :eval (seq-sort-by (lambda (a) (/ 1.0 a)) #'< '(1 2 3))) | ||
| 1141 | "Mapping Over Sequences" | ||
| 1142 | (seq-map | ||
| 1143 | :eval (seq-map #'1+ '(1 2 3))) | ||
| 1144 | (seq-map-indexed | ||
| 1145 | :eval (seq-map-indexed (lambda (a i) (cons i a)) '(a b c))) | ||
| 1146 | (seq-mapcat | ||
| 1147 | :eval (seq-mapcat #'upcase '("a" "b" "c") 'string)) | ||
| 1148 | (seq-doseq | ||
| 1149 | :no-eval (seq-doseq (a '("foo" "bar")) (insert a)) | ||
| 1150 | :eg-result ("foo" "bar")) | ||
| 1151 | (seq-do | ||
| 1152 | :no-eval (seq-do (lambda (a) (insert a)) '("foo" "bar")) | ||
| 1153 | :eg-result ("foo" "bar")) | ||
| 1154 | (seq-do-indexed | ||
| 1155 | :no-eval (seq-do-indexed | ||
| 1156 | (lambda (a index) (message "%s:%s" index a)) | ||
| 1157 | '("foo" "bar")) | ||
| 1158 | :eg-result nil) | ||
| 1159 | (seq-reduce | ||
| 1160 | :eval (seq-reduce #'* [1 2 3] 2)) | ||
| 1161 | "Excerpting Sequences" | ||
| 1162 | (seq-drop | ||
| 1163 | :eval (seq-drop '(a b c) 2)) | ||
| 1164 | (seq-drop-while | ||
| 1165 | :eval (seq-drop-while #'numberp '(1 2 c d 5))) | ||
| 1166 | (seq-filter | ||
| 1167 | :eval (seq-filter #'numberp '(a b 3 4 f 6))) | ||
| 1168 | (seq-keep | ||
| 1169 | :eval (seq-keep #'car-safe '((1 2) 3 t (a . b)))) | ||
| 1170 | (seq-remove | ||
| 1171 | :eval (seq-remove #'numberp '(1 2 c d 5))) | ||
| 1172 | (seq-remove-at-position | ||
| 1173 | :eval (seq-remove-at-position '(a b c d e) 3) | ||
| 1174 | :eval (seq-remove-at-position [a b c d e] 0)) | ||
| 1175 | (seq-group-by | ||
| 1176 | :eval (seq-group-by #'natnump '(-1 2 3 -4 -5 6))) | ||
| 1177 | (seq-union | ||
| 1178 | :eval (seq-union '(1 2 3) '(3 5))) | ||
| 1179 | (seq-difference | ||
| 1180 | :eval (seq-difference '(1 2 3) '(2 3 4))) | ||
| 1181 | (seq-intersection | ||
| 1182 | :eval (seq-intersection '(1 2 3) '(2 3 4))) | ||
| 1183 | (seq-partition | ||
| 1184 | :eval (seq-partition '(a b c d e f g h) 3)) | ||
| 1185 | (seq-subseq | ||
| 1186 | :eval (seq-subseq '(a b c d e) 2 4)) | ||
| 1187 | (seq-take | ||
| 1188 | :eval (seq-take '(a b c d e) 3)) | ||
| 1189 | (seq-split | ||
| 1190 | :eval (seq-split [0 1 2 3 5] 2)) | ||
| 1191 | (seq-take-while | ||
| 1192 | :eval (seq-take-while #'integerp [1 2 3.0 4])) | ||
| 1193 | (seq-uniq | ||
| 1194 | :eval (seq-uniq '(a b d b a c)))) | ||
| 1195 | |||
| 1196 | (define-short-documentation-group buffer | ||
| 1197 | "Buffer Basics" | ||
| 1198 | (current-buffer | ||
| 1199 | :no-eval (current-buffer) | ||
| 1200 | :eg-result-string "#<buffer shortdoc.el>") | ||
| 1201 | (bufferp | ||
| 1202 | :eval (bufferp 23)) | ||
| 1203 | (buffer-live-p | ||
| 1204 | :no-eval (buffer-live-p some-buffer) | ||
| 1205 | :eg-result t) | ||
| 1206 | (buffer-modified-p | ||
| 1207 | :eval (buffer-modified-p (current-buffer))) | ||
| 1208 | (buffer-name | ||
| 1209 | :eval (buffer-name)) | ||
| 1210 | (window-buffer | ||
| 1211 | :eval (window-buffer)) | ||
| 1212 | "Selecting Buffers" | ||
| 1213 | (get-buffer-create | ||
| 1214 | :no-eval (get-buffer-create "*foo*") | ||
| 1215 | :eg-result-string "#<buffer *foo*>") | ||
| 1216 | (pop-to-buffer | ||
| 1217 | :no-eval (pop-to-buffer "*foo*") | ||
| 1218 | :eg-result-string "#<buffer *foo*>") | ||
| 1219 | (with-current-buffer | ||
| 1220 | :no-eval* (with-current-buffer buffer (buffer-size))) | ||
| 1221 | "Points and Positions" | ||
| 1222 | (point | ||
| 1223 | :eval (point)) | ||
| 1224 | (point-min | ||
| 1225 | :eval (point-min)) | ||
| 1226 | (point-max | ||
| 1227 | :eval (point-max)) | ||
| 1228 | (pos-bol | ||
| 1229 | :eval (pos-bol)) | ||
| 1230 | (pos-eol | ||
| 1231 | :eval (pos-eol)) | ||
| 1232 | (bolp | ||
| 1233 | :eval (bolp)) | ||
| 1234 | (eolp | ||
| 1235 | :eval (eolp)) | ||
| 1236 | (line-beginning-position | ||
| 1237 | :eval (line-beginning-position)) | ||
| 1238 | (line-end-position | ||
| 1239 | :eval (line-end-position)) | ||
| 1240 | (buffer-size | ||
| 1241 | :eval (buffer-size)) | ||
| 1242 | (bobp | ||
| 1243 | :eval (bobp)) | ||
| 1244 | (eobp | ||
| 1245 | :eval (eobp)) | ||
| 1246 | "Moving Around" | ||
| 1247 | (goto-char | ||
| 1248 | :no-eval (goto-char (point-max)) | ||
| 1249 | :eg-result 342) | ||
| 1250 | (search-forward | ||
| 1251 | :no-eval (search-forward "some-string" nil t) | ||
| 1252 | :eg-result 245) | ||
| 1253 | (re-search-forward | ||
| 1254 | :no-eval (re-search-forward "some-s.*g" nil t) | ||
| 1255 | :eg-result 245) | ||
| 1256 | (forward-line | ||
| 1257 | :no-eval (forward-line 1) | ||
| 1258 | :eg-result 0 | ||
| 1259 | :no-eval (forward-line -2) | ||
| 1260 | :eg-result 0) | ||
| 1261 | "Strings from Buffers" | ||
| 1262 | (buffer-string | ||
| 1263 | :no-eval* (buffer-string)) | ||
| 1264 | (buffer-substring | ||
| 1265 | :eval (buffer-substring (point-min) (+ (point-min) 10))) | ||
| 1266 | (buffer-substring-no-properties | ||
| 1267 | :eval (buffer-substring-no-properties (point-min) (+ (point-min) 10))) | ||
| 1268 | (following-char | ||
| 1269 | :no-eval (following-char) | ||
| 1270 | :eg-result 67) | ||
| 1271 | (preceding-char | ||
| 1272 | :no-eval (preceding-char) | ||
| 1273 | :eg-result 38) | ||
| 1274 | (char-after | ||
| 1275 | :eval (char-after 45)) | ||
| 1276 | (char-before | ||
| 1277 | :eval (char-before 13)) | ||
| 1278 | (get-byte | ||
| 1279 | :no-eval (get-byte 45) | ||
| 1280 | :eg-result-string "#xff") | ||
| 1281 | "Altering Buffers" | ||
| 1282 | (delete-region | ||
| 1283 | :no-value (delete-region (point-min) (point-max))) | ||
| 1284 | (erase-buffer | ||
| 1285 | :no-value (erase-buffer)) | ||
| 1286 | (delete-line | ||
| 1287 | :no-value (delete-line)) | ||
| 1288 | (insert | ||
| 1289 | :no-value (insert "This string will be inserted in the buffer\n")) | ||
| 1290 | (subst-char-in-region | ||
| 1291 | :no-eval "(subst-char-in-region (point-min) (point-max) ?+ ?-)") | ||
| 1292 | (replace-string-in-region | ||
| 1293 | :no-value (replace-string-in-region "foo" "bar")) | ||
| 1294 | "Locking" | ||
| 1295 | (lock-buffer | ||
| 1296 | :no-value (lock-buffer "/tmp/foo")) | ||
| 1297 | (unlock-buffer | ||
| 1298 | :no-value (unlock-buffer))) | ||
| 1299 | |||
| 1300 | (define-short-documentation-group overlay | ||
| 1301 | "Predicates" | ||
| 1302 | (overlayp | ||
| 1303 | :no-eval (overlayp some-overlay) | ||
| 1304 | :eg-result t) | ||
| 1305 | "Creation and Deletion" | ||
| 1306 | (make-overlay | ||
| 1307 | :args (beg end &optional buffer) | ||
| 1308 | :no-eval (make-overlay 1 10) | ||
| 1309 | :eg-result-string "#<overlay from 1 to 10 in *foo*>") | ||
| 1310 | (delete-overlay | ||
| 1311 | :no-eval (delete-overlay foo) | ||
| 1312 | :eg-result t) | ||
| 1313 | "Searching Overlays" | ||
| 1314 | (overlays-at | ||
| 1315 | :no-eval (overlays-at 15) | ||
| 1316 | :eg-result-string "(#<overlay from 1 to 10 in *foo*>)") | ||
| 1317 | (overlays-in | ||
| 1318 | :no-eval (overlays-in 1 30) | ||
| 1319 | :eg-result-string "(#<overlay from 1 to 10 in *foo*>)") | ||
| 1320 | (next-overlay-change | ||
| 1321 | :no-eval (next-overlay-change 1) | ||
| 1322 | :eg-result 20) | ||
| 1323 | (previous-overlay-change | ||
| 1324 | :no-eval (previous-overlay-change 30) | ||
| 1325 | :eg-result 20) | ||
| 1326 | "Overlay Properties" | ||
| 1327 | (overlay-start | ||
| 1328 | :no-eval (overlay-start foo) | ||
| 1329 | :eg-result 1) | ||
| 1330 | (overlay-end | ||
| 1331 | :no-eval (overlay-end foo) | ||
| 1332 | :eg-result 10) | ||
| 1333 | (overlay-put | ||
| 1334 | :no-eval (overlay-put foo 'happy t) | ||
| 1335 | :eg-result t) | ||
| 1336 | (overlay-get | ||
| 1337 | :no-eval (overlay-get foo 'happy) | ||
| 1338 | :eg-result t) | ||
| 1339 | (overlay-buffer | ||
| 1340 | :no-eval (overlay-buffer foo)) | ||
| 1341 | "Moving Overlays" | ||
| 1342 | (move-overlay | ||
| 1343 | :no-eval (move-overlay foo 5 20) | ||
| 1344 | :eg-result-string "#<overlay from 5 to 20 in *foo*>")) | ||
| 1345 | |||
| 1346 | (define-short-documentation-group process | ||
| 1347 | (make-process | ||
| 1348 | :no-eval (make-process :name "foo" :command '("cat" "/tmp/foo")) | ||
| 1349 | :eg-result-string "#<process foo>") | ||
| 1350 | (processp | ||
| 1351 | :eval (processp t)) | ||
| 1352 | (process-status | ||
| 1353 | :no-eval (process-status process) | ||
| 1354 | :eg-result exit) | ||
| 1355 | (delete-process | ||
| 1356 | :no-value (delete-process process)) | ||
| 1357 | (kill-process | ||
| 1358 | :no-value (kill-process process)) | ||
| 1359 | (set-process-sentinel | ||
| 1360 | :no-value (set-process-sentinel process (lambda (proc string)))) | ||
| 1361 | (process-buffer | ||
| 1362 | :no-eval (process-buffer process) | ||
| 1363 | :eg-result-string "#<buffer *foo*>") | ||
| 1364 | (get-buffer-process | ||
| 1365 | :no-eval (get-buffer-process buffer) | ||
| 1366 | :eg-result-string "#<process foo>") | ||
| 1367 | (process-live-p | ||
| 1368 | :no-eval (process-live-p process) | ||
| 1369 | :eg-result t)) | ||
| 1370 | |||
| 1371 | (define-short-documentation-group number | ||
| 1372 | "Arithmetic" | ||
| 1373 | (+ | ||
| 1374 | :args (&rest numbers) | ||
| 1375 | :eval (+ 1 2) | ||
| 1376 | :eval (+ 1 2 3 4)) | ||
| 1377 | (- | ||
| 1378 | :args (&rest numbers) | ||
| 1379 | :eval (- 3 2) | ||
| 1380 | :eval (- 6 3 2)) | ||
| 1381 | (* | ||
| 1382 | :args (&rest numbers) | ||
| 1383 | :eval (* 3 4 5)) | ||
| 1384 | (/ | ||
| 1385 | :eval (/ 10 5) | ||
| 1386 | :eval (/ 10 6) | ||
| 1387 | :eval (/ 10.0 6) | ||
| 1388 | :eval (/ 10.0 3 3)) | ||
| 1389 | (% | ||
| 1390 | :eval (% 10 5) | ||
| 1391 | :eval (% 10 6)) | ||
| 1392 | (mod | ||
| 1393 | :eval (mod 10 5) | ||
| 1394 | :eval (mod 10 6) | ||
| 1395 | :eval (mod 10.5 6)) | ||
| 1396 | (1+ | ||
| 1397 | :eval (1+ 2) | ||
| 1398 | :eval (let ((x 2)) (1+ x) x)) | ||
| 1399 | (1- | ||
| 1400 | :eval (1- 4) | ||
| 1401 | :eval (let ((x 4)) (1- x) x)) | ||
| 1402 | (incf | ||
| 1403 | :eval (let ((x 2)) (incf x) x) | ||
| 1404 | :eval (let ((x 2)) (incf x 2) x)) | ||
| 1405 | (decf | ||
| 1406 | :eval (let ((x 4)) (decf x) x) | ||
| 1407 | :eval (let ((x 4)) (decf x 2)) x) | ||
| 1408 | "Predicates" | ||
| 1409 | (= | ||
| 1410 | :args (number &rest numbers) | ||
| 1411 | :eval (= 4 4) | ||
| 1412 | :eval (= 4.0 4.0) | ||
| 1413 | :eval (= 4 4.0) | ||
| 1414 | :eval (= 4 4 4 4)) | ||
| 1415 | (eql | ||
| 1416 | :eval (eql 4 4) | ||
| 1417 | :eval (eql 4.0 4.0)) | ||
| 1418 | (/= | ||
| 1419 | :eval (/= 4 4)) | ||
| 1420 | (< | ||
| 1421 | :args (number &rest numbers) | ||
| 1422 | :eval (< 4 4) | ||
| 1423 | :eval (< 1 2 3)) | ||
| 1424 | (<= | ||
| 1425 | :args (number &rest numbers) | ||
| 1426 | :eval (<= 4 4) | ||
| 1427 | :eval (<= 1 2 2 3)) | ||
| 1428 | (> | ||
| 1429 | :args (number &rest numbers) | ||
| 1430 | :eval (> 4 4) | ||
| 1431 | :eval (> 3 2 1)) | ||
| 1432 | (>= | ||
| 1433 | :args (number &rest numbers) | ||
| 1434 | :eval (>= 4 4) | ||
| 1435 | :eval (>= 3 2 2 1)) | ||
| 1436 | (zerop | ||
| 1437 | :eval (zerop 0)) | ||
| 1438 | (natnump | ||
| 1439 | :eval (natnump -1) | ||
| 1440 | :eval (natnump 0) | ||
| 1441 | :eval (natnump 23)) | ||
| 1442 | (plusp | ||
| 1443 | :eval (plusp 0) | ||
| 1444 | :eval (plusp 1)) | ||
| 1445 | (minusp | ||
| 1446 | :eval (minusp 0) | ||
| 1447 | :eval (minusp -1)) | ||
| 1448 | (oddp | ||
| 1449 | :eval (oddp 3)) | ||
| 1450 | (evenp | ||
| 1451 | :eval (evenp 6)) | ||
| 1452 | (bignump | ||
| 1453 | :eval (bignump 4) | ||
| 1454 | :eval (bignump (expt 2 90))) | ||
| 1455 | (fixnump | ||
| 1456 | :eval (fixnump 4) | ||
| 1457 | :eval (fixnump (expt 2 90))) | ||
| 1458 | (floatp | ||
| 1459 | :eval (floatp 5.4)) | ||
| 1460 | (integerp | ||
| 1461 | :eval (integerp 5.4)) | ||
| 1462 | (numberp | ||
| 1463 | :eval (numberp "5.4")) | ||
| 1464 | (cl-digit-char-p | ||
| 1465 | :eval (cl-digit-char-p ?5 10) | ||
| 1466 | :eval (cl-digit-char-p ?f 16)) | ||
| 1467 | "Operations" | ||
| 1468 | (max | ||
| 1469 | :args (number &rest numbers) | ||
| 1470 | :eval (max 7 9 3)) | ||
| 1471 | (min | ||
| 1472 | :args (number &rest numbers) | ||
| 1473 | :eval (min 7 9 3)) | ||
| 1474 | (abs | ||
| 1475 | :eval (abs -4)) | ||
| 1476 | (float | ||
| 1477 | :eval (float 2)) | ||
| 1478 | (truncate | ||
| 1479 | :eval (truncate 1.2) | ||
| 1480 | :eval (truncate -1.2) | ||
| 1481 | :eval (truncate 5.4 2)) | ||
| 1482 | (floor | ||
| 1483 | :eval (floor 1.2) | ||
| 1484 | :eval (floor -1.2) | ||
| 1485 | :eval (floor 5.4 2)) | ||
| 1486 | (ceiling | ||
| 1487 | :eval (ceiling 1.2) | ||
| 1488 | :eval (ceiling -1.2) | ||
| 1489 | :eval (ceiling 5.4 2)) | ||
| 1490 | (round | ||
| 1491 | :eval (round 1.2) | ||
| 1492 | :eval (round -1.2) | ||
| 1493 | :eval (round 5.4 2)) | ||
| 1494 | (random | ||
| 1495 | :eval (random 6)) | ||
| 1496 | "Bit Operations" | ||
| 1497 | (ash | ||
| 1498 | :eval (ash 1 4) | ||
| 1499 | :eval (ash 16 -1)) | ||
| 1500 | (logand | ||
| 1501 | :no-eval "(logand #b10 #b111)" | ||
| 1502 | :result-string "#b10") | ||
| 1503 | (logior | ||
| 1504 | :eval (logior 4 16)) | ||
| 1505 | (logxor | ||
| 1506 | :eval (logxor 4 16)) | ||
| 1507 | (lognot | ||
| 1508 | :eval (lognot 5)) | ||
| 1509 | (logcount | ||
| 1510 | :eval (logcount 5)) | ||
| 1511 | "Floating Point" | ||
| 1512 | (isnan | ||
| 1513 | :eval (isnan 5.0)) | ||
| 1514 | (frexp | ||
| 1515 | :eval (frexp 5.7)) | ||
| 1516 | (ldexp | ||
| 1517 | :eval (ldexp 0.7125 3)) | ||
| 1518 | (logb | ||
| 1519 | :eval (logb 10.5)) | ||
| 1520 | (ffloor | ||
| 1521 | :eval (ffloor 1.2)) | ||
| 1522 | (fceiling | ||
| 1523 | :eval (fceiling 1.2)) | ||
| 1524 | (ftruncate | ||
| 1525 | :eval (ftruncate 1.2)) | ||
| 1526 | (fround | ||
| 1527 | :eval (fround 1.2)) | ||
| 1528 | "Standard Math Functions" | ||
| 1529 | (sin | ||
| 1530 | :eval (sin float-pi)) | ||
| 1531 | (cos | ||
| 1532 | :eval (cos float-pi)) | ||
| 1533 | (tan | ||
| 1534 | :eval (tan float-pi)) | ||
| 1535 | (asin | ||
| 1536 | :eval (asin float-pi)) | ||
| 1537 | (acos | ||
| 1538 | :eval (acos float-pi)) | ||
| 1539 | (atan | ||
| 1540 | :eval (atan float-pi)) | ||
| 1541 | (exp | ||
| 1542 | :eval (exp 4)) | ||
| 1543 | (log | ||
| 1544 | :eval (log 54.59)) | ||
| 1545 | (expt | ||
| 1546 | :eval (expt 2 16)) | ||
| 1547 | (sqrt | ||
| 1548 | :eval (sqrt -1))) | ||
| 1549 | |||
| 1550 | (define-short-documentation-group text-properties | ||
| 1551 | "Examining Text Properties" | ||
| 1552 | (get-text-property | ||
| 1553 | :eval (get-text-property 0 'foo (propertize "x" 'foo t))) | ||
| 1554 | (get-char-property | ||
| 1555 | :eval (get-char-property 0 'foo (propertize "x" 'foo t))) | ||
| 1556 | (get-pos-property | ||
| 1557 | :eval (get-pos-property 0 'foo (propertize "x" 'foo t))) | ||
| 1558 | (get-char-property-and-overlay | ||
| 1559 | :eval (get-char-property-and-overlay 0 'foo (propertize "x" 'foo t))) | ||
| 1560 | (text-properties-at | ||
| 1561 | :eval (text-properties-at (point))) | ||
| 1562 | "Changing Text Properties" | ||
| 1563 | (put-text-property | ||
| 1564 | :eval (let ((s (copy-sequence "abc"))) (put-text-property 0 1 'foo t s) s) | ||
| 1565 | :no-eval (put-text-property (point) (1+ (point)) 'face 'error)) | ||
| 1566 | (add-text-properties | ||
| 1567 | :no-eval (add-text-properties (point) (1+ (point)) '(face error))) | ||
| 1568 | (remove-text-properties | ||
| 1569 | :no-eval (remove-text-properties (point) (1+ (point)) '(face nil))) | ||
| 1570 | (remove-list-of-text-properties | ||
| 1571 | :no-eval (remove-list-of-text-properties (point) (1+ (point)) '(face font-lock-face))) | ||
| 1572 | (set-text-properties | ||
| 1573 | :no-eval (set-text-properties (point) (1+ (point)) '(face error))) | ||
| 1574 | (add-face-text-property | ||
| 1575 | :no-eval (add-face-text-property START END '(:foreground "green"))) | ||
| 1576 | (propertize | ||
| 1577 | :eval (propertize "foo" 'face 'italic 'mouse-face 'bold-italic)) | ||
| 1578 | "Searching for Text Properties" | ||
| 1579 | (next-property-change | ||
| 1580 | :no-eval (next-property-change (point) (current-buffer))) | ||
| 1581 | (previous-property-change | ||
| 1582 | :no-eval (previous-property-change (point) (current-buffer))) | ||
| 1583 | (next-single-property-change | ||
| 1584 | :no-eval (next-single-property-change (point) 'face (current-buffer))) | ||
| 1585 | (previous-single-property-change | ||
| 1586 | :no-eval (previous-single-property-change (point) 'face (current-buffer))) | ||
| 1587 | ;; TODO: There are some more that could be added here. | ||
| 1588 | (text-property-search-forward | ||
| 1589 | :no-eval (text-property-search-forward 'face nil t)) | ||
| 1590 | (text-property-search-backward | ||
| 1591 | :no-eval (text-property-search-backward 'face nil t))) | ||
| 1592 | |||
| 1593 | (define-short-documentation-group keymaps | ||
| 1594 | "Defining keymaps or adding bindings to existing keymaps" | ||
| 1595 | (define-keymap | ||
| 1596 | :no-eval (define-keymap "C-c C-c" #'quit-buffer) | ||
| 1597 | :no-eval (define-keymap :keymap ctl-x-map | ||
| 1598 | "C-r" #'recentf-open | ||
| 1599 | "k" #'kill-current-buffer)) | ||
| 1600 | (defvar-keymap | ||
| 1601 | :no-eval (defvar-keymap my-keymap "C-c C-c" #'quit-buffer)) | ||
| 1602 | "Setting keys" | ||
| 1603 | (keymap-set | ||
| 1604 | :no-eval (keymap-set map "C-c C-c" #'quit-buffer)) | ||
| 1605 | (keymap-local-set | ||
| 1606 | :no-eval (keymap-local-set "C-c C-c" #'quit-buffer)) | ||
| 1607 | (keymap-global-set | ||
| 1608 | :no-eval (keymap-global-set "C-c C-c" #'quit-buffer)) | ||
| 1609 | (keymap-unset | ||
| 1610 | :no-eval (keymap-unset map "C-c C-c")) | ||
| 1611 | (keymap-local-unset | ||
| 1612 | :no-eval (keymap-local-unset "C-c C-c")) | ||
| 1613 | (keymap-global-unset | ||
| 1614 | :no-eval (keymap-global-unset "C-c C-c")) | ||
| 1615 | (keymap-substitute | ||
| 1616 | :no-eval (keymap-substitute map "C-c C-c" "M-a")) | ||
| 1617 | (keymap-set-after | ||
| 1618 | :no-eval (keymap-set-after map "<separator-2>" menu-bar-separator)) | ||
| 1619 | "Predicates" | ||
| 1620 | (keymapp | ||
| 1621 | :eval (keymapp (define-keymap))) | ||
| 1622 | (key-valid-p | ||
| 1623 | :eval (key-valid-p "C-c C-c") | ||
| 1624 | :eval (key-valid-p "C-cC-c")) | ||
| 1625 | "Lookup" | ||
| 1626 | (keymap-lookup | ||
| 1627 | :eval (keymap-lookup (current-global-map) "C-x x g"))) | ||
| 1628 | |||
| 1629 | ;;;###autoload | 239 | ;;;###autoload |
| 1630 | (defun shortdoc-display-group (group &optional function same-window) | 240 | (defun shortdoc-display-group (group &optional function same-window) |
| 1631 | "Pop to a buffer with short documentation summary for functions in GROUP. | 241 | "Pop to a buffer with short documentation summary for functions in GROUP. |
| @@ -1650,6 +260,9 @@ If SAME-WINDOW, don't pop to a new window." | |||
| 1650 | (text-property-search-forward 'shortdoc-function function t) | 260 | (text-property-search-forward 'shortdoc-function function t) |
| 1651 | (beginning-of-line))) | 261 | (beginning-of-line))) |
| 1652 | 262 | ||
| 263 | ;;;###autoload | ||
| 264 | (defalias 'shortdoc #'shortdoc-display-group) | ||
| 265 | |||
| 1653 | (defun shortdoc--insert-group-in-buffer (group &optional buf) | 266 | (defun shortdoc--insert-group-in-buffer (group &optional buf) |
| 1654 | "Insert a short documentation summary for functions in GROUP in buffer BUF. | 267 | "Insert a short documentation summary for functions in GROUP in buffer BUF. |
| 1655 | BUF defaults to the current buffer if nil or omitted." | 268 | BUF defaults to the current buffer if nil or omitted." |
| @@ -1685,9 +298,6 @@ BUF defaults to the current buffer if nil or omitted." | |||
| 1685 | (shortdoc--display-function data)))) | 298 | (shortdoc--display-function data)))) |
| 1686 | (cdr (assq group shortdoc--groups)))))) | 299 | (cdr (assq group shortdoc--groups)))))) |
| 1687 | 300 | ||
| 1688 | ;;;###autoload | ||
| 1689 | (defalias 'shortdoc #'shortdoc-display-group) | ||
| 1690 | |||
| 1691 | (defun shortdoc--display-function (data) | 301 | (defun shortdoc--display-function (data) |
| 1692 | (let ((function (pop data)) | 302 | (let ((function (pop data)) |
| 1693 | (start-section (point)) | 303 | (start-section (point)) |
| @@ -1875,6 +485,10 @@ Example: | |||
| 1875 | (shortdoc-add-function | 485 | (shortdoc-add-function |
| 1876 | \\='file \"Predicates\" | 486 | \\='file \"Predicates\" |
| 1877 | \\='(file-locked-p :no-eval (file-locked-p \"/tmp\")))" | 487 | \\='(file-locked-p :no-eval (file-locked-p \"/tmp\")))" |
| 488 | ;; Rely on `shortdoc--check' checking GROUP. | ||
| 489 | (unless (stringp section) | ||
| 490 | (signal 'wrong-type-argument (list 'stringp section))) | ||
| 491 | (shortdoc--check group (list section elem)) | ||
| 1878 | (let ((glist (assq group shortdoc--groups))) | 492 | (let ((glist (assq group shortdoc--groups))) |
| 1879 | (unless glist | 493 | (unless glist |
| 1880 | (setq glist (list group)) | 494 | (setq glist (list group)) |
diff --git a/lisp/emacs-lisp/warnings.el b/lisp/emacs-lisp/warnings.el index ddf3b594e12..7db316acda7 100644 --- a/lisp/emacs-lisp/warnings.el +++ b/lisp/emacs-lisp/warnings.el | |||
| @@ -372,6 +372,7 @@ entirely by setting `warning-suppress-types' or | |||
| 372 | (if (bolp) | 372 | (if (bolp) |
| 373 | (forward-char -1)) | 373 | (forward-char -1)) |
| 374 | (message "%s" (buffer-substring start (point)))))) | 374 | (message "%s" (buffer-substring start (point)))))) |
| 375 | ;; Use `frame-initial-p'? | ||
| 375 | ((and (daemonp) (eq (selected-frame) terminal-frame)) | 376 | ((and (daemonp) (eq (selected-frame) terminal-frame)) |
| 376 | ;; Display daemon startup warnings on the first client frame. | 377 | ;; Display daemon startup warnings on the first client frame. |
| 377 | (letrec ((afterfun | 378 | (letrec ((afterfun |
diff --git a/lisp/epa-file.el b/lisp/epa-file.el index b2a89907867..95202851544 100644 --- a/lisp/epa-file.el +++ b/lisp/epa-file.el | |||
| @@ -232,7 +232,22 @@ encryption is used." | |||
| 232 | (epa-file-decode-and-insert | 232 | (epa-file-decode-and-insert |
| 233 | string file visit beg end replace)))) | 233 | string file visit beg end replace)))) |
| 234 | (if visit | 234 | (if visit |
| 235 | (set-visited-file-modtime)))) | 235 | (set-visited-file-modtime))) |
| 236 | ;; The decoded file could still need another massage from a | ||
| 237 | ;; file name handler, for example a file like | ||
| 238 | ;; "folder.sym.tar.gz.gpg". (Bug#80641) | ||
| 239 | (when (find-file-name-handler | ||
| 240 | (file-name-sans-extension file) | ||
| 241 | 'insert-file-contents) | ||
| 242 | (let ((tmpfile | ||
| 243 | (make-temp-file | ||
| 244 | nil nil | ||
| 245 | (file-name-extension (file-name-base file) 'period)))) | ||
| 246 | (let (file-name-handler-alist) (write-region nil nil tmpfile)) | ||
| 247 | (erase-buffer) | ||
| 248 | (insert-file-contents tmpfile) | ||
| 249 | (setq length (- (point-max) (point-min))) | ||
| 250 | (delete-file tmpfile)))) | ||
| 236 | (if (and local-copy | 251 | (if (and local-copy |
| 237 | (file-exists-p local-copy)) | 252 | (file-exists-p local-copy)) |
| 238 | (delete-file local-copy))) | 253 | (delete-file local-copy))) |
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el index f5ea63ae764..6306df3fa2a 100644 --- a/lisp/erc/erc-track.el +++ b/lisp/erc/erc-track.el | |||
| @@ -1006,7 +1006,7 @@ Failing that, choose the first face in both NEW-FACES and NORMALS." | |||
| 1006 | (dolist (candidate (cdr ranks)) | 1006 | (dolist (candidate (cdr ranks)) |
| 1007 | (when (and (not (equal candidate choice)) | 1007 | (when (and (not (equal candidate choice)) |
| 1008 | (gethash candidate (car new-faces)) | 1008 | (gethash candidate (car new-faces)) |
| 1009 | (gethash choice normals)) | 1009 | (gethash candidate normals)) |
| 1010 | (throw 'face candidate))) | 1010 | (throw 'face candidate))) |
| 1011 | ;; Otherwise, go with any "normal" face other than | 1011 | ;; Otherwise, go with any "normal" face other than |
| 1012 | ;; `choice' in the region. | 1012 | ;; `choice' in the region. |
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 572b73188e3..6facb7966b0 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el | |||
| @@ -1693,11 +1693,18 @@ time `erc-mode-hook' runs for any connection." | |||
| 1693 | (declare (indent 1)) | 1693 | (declare (indent 1)) |
| 1694 | (cl-assert (stringp (car args))) | 1694 | (cl-assert (stringp (car args))) |
| 1695 | (if (derived-mode-p 'erc-mode) | 1695 | (if (derived-mode-p 'erc-mode) |
| 1696 | (unless (or (erc-with-server-buffer ; needs `erc-server-process' | 1696 | (unless |
| 1697 | (apply #'erc-button--display-error-notice-with-keys | 1697 | (or (erc-with-server-buffer ; needs `erc-server-process' |
| 1698 | (current-buffer) args) | 1698 | (let ((fn |
| 1699 | t) | 1699 | (lambda (buffer) |
| 1700 | erc--target) ; unlikely | 1700 | (erc-with-buffer (buffer) |
| 1701 | (apply #'erc-button--display-error-notice-with-keys | ||
| 1702 | buffer args))))) | ||
| 1703 | (if erc--msg-props | ||
| 1704 | (run-at-time nil nil fn (current-buffer)) | ||
| 1705 | (funcall fn (current-buffer)))) | ||
| 1706 | t) | ||
| 1707 | erc--target) ; unlikely | ||
| 1701 | (let (hook) | 1708 | (let (hook) |
| 1702 | (setq hook | 1709 | (setq hook |
| 1703 | (lambda (_) | 1710 | (lambda (_) |
diff --git a/lisp/files.el b/lisp/files.el index f9af75187cb..e05a4b99497 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -1790,7 +1790,10 @@ If DIR-FLAG is non-nil, create a new empty directory instead of a file. | |||
| 1790 | If SUFFIX is non-nil, add that at the end of the file name. | 1790 | If SUFFIX is non-nil, add that at the end of the file name. |
| 1791 | 1791 | ||
| 1792 | If TEXT is a string, insert it into the new file; DIR-FLAG should be nil. | 1792 | If TEXT is a string, insert it into the new file; DIR-FLAG should be nil. |
| 1793 | Otherwise the file will be empty." | 1793 | Otherwise the file will be empty. |
| 1794 | |||
| 1795 | On Posix systems, the file/directory is created with access mode bits | ||
| 1796 | that limit access to the current user." | ||
| 1794 | (let ((absolute-prefix | 1797 | (let ((absolute-prefix |
| 1795 | (if (or (zerop (length prefix)) (member prefix '("." ".."))) | 1798 | (if (or (zerop (length prefix)) (member prefix '("." ".."))) |
| 1796 | (concat (file-name-as-directory temporary-file-directory) prefix) | 1799 | (concat (file-name-as-directory temporary-file-directory) prefix) |
| @@ -8320,41 +8323,24 @@ Valid wildcards are `*', `?', `[abc]' and `[a-z]'." | |||
| 8320 | (forward-line -1)) | 8323 | (forward-line -1)) |
| 8321 | (if (let ((case-fold-search nil)) (looking-at "//DIRED//")) | 8324 | (if (let ((case-fold-search nil)) (looking-at "//DIRED//")) |
| 8322 | (let ((end (line-end-position)) | 8325 | (let ((end (line-end-position)) |
| 8323 | (linebeg (point)) | 8326 | (linebeg (point))) |
| 8324 | error-lines) | 8327 | ;; Read the numeric positions of file names. |
| 8325 | ;; Find all the lines that are error messages, | ||
| 8326 | ;; and record the bounds of each one. | ||
| 8327 | (goto-char beg) | ||
| 8328 | (while (< (point) linebeg) | ||
| 8329 | (or (eql (following-char) ?\s) | ||
| 8330 | (push (list (point) (line-end-position)) error-lines)) | ||
| 8331 | (forward-line 1)) | ||
| 8332 | (setq error-lines (nreverse error-lines)) | ||
| 8333 | ;; Now read the numeric positions of file names. | ||
| 8334 | (goto-char linebeg) | 8328 | (goto-char linebeg) |
| 8335 | (forward-word-strictly 1) | 8329 | (forward-word-strictly 1) |
| 8336 | (forward-char 3) | 8330 | (forward-char 3) |
| 8337 | (while (< (point) end) | 8331 | (while (< (point) end) |
| 8338 | (let ((start (insert-directory-adj-pos | 8332 | (let ((start (+ beg (read (current-buffer)))) |
| 8339 | (+ beg (read (current-buffer))) | 8333 | (end (+ beg (read (current-buffer))))) |
| 8340 | error-lines)) | 8334 | (when (memq (char-after end) '(?\n ?\s ?/ ?* ?@ ?% ?= ?|)) |
| 8341 | (end (insert-directory-adj-pos | 8335 | ;; End is followed by \n or by output of -F. |
| 8342 | (+ beg (read (current-buffer))) | 8336 | (put-text-property start end 'dired-filename t)))) |
| 8343 | error-lines))) | ||
| 8344 | (if (memq (char-after end) '(?\n ?\s ?/ ?* ?@ ?% ?= ?|)) | ||
| 8345 | ;; End is followed by \n or by output of -F. | ||
| 8346 | (put-text-property start end 'dired-filename t) | ||
| 8347 | ;; It seems that we can't trust ls's output as to | ||
| 8348 | ;; byte positions of filenames. | ||
| 8349 | (put-text-property beg (point) 'dired-filename nil) | ||
| 8350 | (end-of-line)))) | ||
| 8351 | (goto-char end) | 8337 | (goto-char end) |
| 8352 | (beginning-of-line) | 8338 | (beginning-of-line) |
| 8353 | (delete-region (point) (progn (forward-line 1) (point)))) | 8339 | (delete-region (point) (progn (forward-line 1) (point)))) |
| 8354 | ;; Take care of the case where the ls output contains a | 8340 | ;; Take care of the case where the ls output contains a |
| 8355 | ;; "//DIRED-OPTIONS//"-line, but no "//DIRED//"-line | 8341 | ;; "//DIRED-OPTIONS//"-line, but no "//DIRED//"-line |
| 8356 | ;; and we went one line too far back (see above). | 8342 | ;; and we went one line too far back (see above). |
| 8357 | (forward-line 1)) | 8343 | (unless (bobp) (forward-line 1))) |
| 8358 | (if (let ((case-fold-search nil)) (looking-at "//DIRED-OPTIONS//")) | 8344 | (if (let ((case-fold-search nil)) (looking-at "//DIRED-OPTIONS//")) |
| 8359 | (delete-region (point) (progn (forward-line 1) (point)))))) | 8345 | (delete-region (point) (progn (forward-line 1) (point)))))) |
| 8360 | 8346 | ||
| @@ -8363,12 +8349,12 @@ Valid wildcards are `*', `?', `[abc]' and `[a-z]'." | |||
| 8363 | ;; FULL-DIRECTORY-P is nil. | 8349 | ;; FULL-DIRECTORY-P is nil. |
| 8364 | ;; The single line of output must display FILE's name as it was | 8350 | ;; The single line of output must display FILE's name as it was |
| 8365 | ;; given, namely, an absolute path name. | 8351 | ;; given, namely, an absolute path name. |
| 8366 | ;; - must insert exactly one line for each file if WILDCARD or | 8352 | ;; - must insert exactly one entry for each file if WILDCARD or |
| 8367 | ;; FULL-DIRECTORY-P is t, plus one optional "total" line | 8353 | ;; FULL-DIRECTORY-P is t, plus one optional "total" line |
| 8368 | ;; before the file lines, plus optional text after the file lines. | 8354 | ;; before the file lines, plus optional text after the file lines. |
| 8369 | ;; Lines are delimited by "\n", so filenames containing "\n" are not | 8355 | ;; Entries are delimited by "\n", but file names containing "\n" are |
| 8370 | ;; allowed. | 8356 | ;; allowed and by default the "\n" is displayed as a literal newline. |
| 8371 | ;; File lines should display the basename. | 8357 | ;; File entries should display the basename. |
| 8372 | ;; - must be consistent with | 8358 | ;; - must be consistent with |
| 8373 | ;; - functions dired-move-to-filename, (these two define what a file line is) | 8359 | ;; - functions dired-move-to-filename, (these two define what a file line is) |
| 8374 | ;; dired-move-to-end-of-filename, | 8360 | ;; dired-move-to-end-of-filename, |
| @@ -8410,10 +8396,10 @@ normally equivalent short `-D' option is just passed on to | |||
| 8410 | (declare-function ls-lisp--insert-directory "ls-lisp") | 8396 | (declare-function ls-lisp--insert-directory "ls-lisp") |
| 8411 | (ls-lisp--insert-directory file switches wildcard full-directory-p)) | 8397 | (ls-lisp--insert-directory file switches wildcard full-directory-p)) |
| 8412 | (t | 8398 | (t |
| 8413 | (let (result (beg (point))) | 8399 | (let ((beg (point)) |
| 8400 | (errfile (make-temp-file "lserr"))) | ||
| 8414 | 8401 | ||
| 8415 | ;; Read the actual directory using `insert-directory-program'. | 8402 | ;; Read the actual directory using `insert-directory-program'. |
| 8416 | ;; RESULT gets the status code. | ||
| 8417 | (let* (;; We at first read by no-conversion, then after | 8403 | (let* (;; We at first read by no-conversion, then after |
| 8418 | ;; putting text property `dired-filename, decode one | 8404 | ;; putting text property `dired-filename, decode one |
| 8419 | ;; bunch by one to preserve that property. | 8405 | ;; bunch by one to preserve that property. |
| @@ -8423,143 +8409,88 @@ normally equivalent short `-D' option is just passed on to | |||
| 8423 | (and enable-multibyte-characters | 8409 | (and enable-multibyte-characters |
| 8424 | (or file-name-coding-system | 8410 | (or file-name-coding-system |
| 8425 | default-file-name-coding-system)))) | 8411 | default-file-name-coding-system)))) |
| 8426 | (setq result | 8412 | (if wildcard |
| 8427 | (if wildcard | 8413 | ;; If the wildcard is just in the file part, then run ls in |
| 8428 | ;; If the wildcard is just in the file part, then run ls in | 8414 | ;; the directory part of the file pattern using the last |
| 8429 | ;; the directory part of the file pattern using the last | 8415 | ;; component as argument. Otherwise, run ls in the longest |
| 8430 | ;; component as argument. Otherwise, run ls in the longest | 8416 | ;; subdirectory of the directory part free of wildcards; use |
| 8431 | ;; subdirectory of the directory part free of wildcards; use | 8417 | ;; the remaining of the file pattern as argument. |
| 8432 | ;; the remaining of the file pattern as argument. | 8418 | (let* ((dir-wildcard |
| 8433 | (let* ((dir-wildcard (insert-directory-wildcard-in-dir-p file)) | 8419 | (insert-directory-wildcard-in-dir-p file)) |
| 8434 | (default-directory | 8420 | (default-directory |
| 8435 | (cond (dir-wildcard (car dir-wildcard)) | 8421 | (cond (dir-wildcard (car dir-wildcard)) |
| 8436 | (t | 8422 | (t |
| 8437 | (if (file-name-absolute-p file) | 8423 | (if (file-name-absolute-p file) |
| 8438 | (file-name-directory file) | 8424 | (file-name-directory file) |
| 8439 | (file-name-directory (expand-file-name file)))))) | 8425 | (file-name-directory |
| 8440 | (pattern (if dir-wildcard (cdr dir-wildcard) (file-name-nondirectory file)))) | 8426 | (expand-file-name file)))))) |
| 8441 | ;; NB since switches is passed to the shell, be | 8427 | (pattern (if dir-wildcard |
| 8442 | ;; careful of malicious values, eg "-l;reboot". | 8428 | (cdr dir-wildcard) |
| 8443 | ;; See eg dired-safe-switches-p. | 8429 | (file-name-nondirectory file)))) |
| 8444 | (call-process | 8430 | ;; NB since switches is passed to the shell, be |
| 8445 | shell-file-name nil t nil | 8431 | ;; careful of malicious values, eg "-l;reboot". |
| 8446 | shell-command-switch | 8432 | ;; See eg dired-safe-switches-p. |
| 8447 | (concat (if (memq system-type '(ms-dos windows-nt)) | 8433 | (call-process |
| 8448 | "" | 8434 | shell-file-name nil (list t errfile) nil |
| 8449 | "\\") ; Disregard Unix shell aliases! | 8435 | shell-command-switch |
| 8450 | insert-directory-program | 8436 | (concat (if (memq system-type '(ms-dos windows-nt)) |
| 8451 | " -d " | 8437 | "" |
| 8452 | ;; Quote switches that require quoting | 8438 | "\\") ; Disregard Unix shell aliases! |
| 8453 | ;; such as "--block-size='1". But don't | 8439 | insert-directory-program |
| 8454 | ;; quote switches that use patterns | 8440 | " -d " |
| 8455 | ;; such as "--ignore=PATTERN" (bug#71935). | 8441 | ;; Quote switches that require quoting |
| 8456 | (mapconcat #'shell-quote-wildcard-pattern | 8442 | ;; such as "--block-size='1". But don't |
| 8457 | (if (stringp switches) | 8443 | ;; quote switches that use patterns |
| 8458 | (split-string-and-unquote switches) | 8444 | ;; such as "--ignore=PATTERN" (bug#71935). |
| 8459 | switches) | 8445 | (mapconcat #'shell-quote-wildcard-pattern |
| 8460 | " ") | 8446 | (if (stringp switches) |
| 8461 | " -- " | 8447 | (split-string-and-unquote switches) |
| 8462 | ;; Quote some characters that have | 8448 | switches) |
| 8463 | ;; special meanings in shells; but | 8449 | " ") |
| 8464 | ;; don't quote the wildcards--we want | 8450 | " -- " |
| 8465 | ;; them to be special. We also | 8451 | ;; Quote some characters that have |
| 8466 | ;; currently don't quote the quoting | 8452 | ;; special meanings in shells; but |
| 8467 | ;; characters in case people want to | 8453 | ;; don't quote the wildcards--we want |
| 8468 | ;; use them explicitly to quote | 8454 | ;; them to be special. We also |
| 8469 | ;; wildcard characters. | 8455 | ;; currently don't quote the quoting |
| 8470 | (shell-quote-wildcard-pattern pattern)))) | 8456 | ;; characters in case people want to |
| 8471 | ;; SunOS 4.1.3, SVr4 and others need the "." to list the | 8457 | ;; use them explicitly to quote |
| 8472 | ;; directory if FILE is a symbolic link. | 8458 | ;; wildcard characters. |
| 8473 | (unless full-directory-p | 8459 | (shell-quote-wildcard-pattern pattern)))) |
| 8474 | (setq switches | 8460 | ;; SunOS 4.1.3, SVr4 and others need the "." to list the |
| 8475 | (cond | 8461 | ;; directory if FILE is a symbolic link. |
| 8476 | ((stringp switches) (concat switches " -d")) | 8462 | (unless full-directory-p |
| 8477 | ((member "-d" switches) switches) | 8463 | (setq switches |
| 8478 | (t (append switches '("-d")))))) | 8464 | (cond |
| 8479 | (if (string-match "\\`~" file) | 8465 | ((stringp switches) (concat switches " -d")) |
| 8480 | (setq file (expand-file-name file))) | 8466 | ((member "-d" switches) switches) |
| 8481 | (apply #'call-process | 8467 | (t (append switches '("-d")))))) |
| 8482 | insert-directory-program nil t nil | 8468 | (if (string-match "\\`~" file) |
| 8483 | (append | 8469 | (setq file (expand-file-name file))) |
| 8484 | (if (listp switches) switches | 8470 | (apply #'call-process |
| 8485 | (unless (equal switches "") | 8471 | insert-directory-program nil (list t errfile) nil |
| 8486 | ;; Split the switches at any spaces so we can | 8472 | (append |
| 8487 | ;; pass separate options as separate args. | 8473 | (if (listp switches) switches |
| 8488 | (split-string-and-unquote switches))) | 8474 | (unless (equal switches "") |
| 8489 | ;; Avoid lossage if FILE starts with `-'. | 8475 | ;; Split the switches at any spaces so we can |
| 8490 | '("--") | 8476 | ;; pass separate options as separate args. |
| 8491 | (list file)))))) | 8477 | (split-string-and-unquote switches))) |
| 8492 | 8478 | ;; Avoid lossage if FILE starts with `-'. | |
| 8493 | ;; If we got "//DIRED//" in the output, it means we got a real | 8479 | '("--") |
| 8494 | ;; directory listing, even if `ls' returned nonzero. | 8480 | (list file))))) |
| 8495 | ;; So ignore any errors. | 8481 | |
| 8496 | (when (if (stringp switches) | 8482 | ;; If `ls' emits an error message, copy it to a buffer that will |
| 8497 | (string-match "--dired\\>" switches) | 8483 | ;; be displayed when a Dired invocation results in the `ls' |
| 8498 | (member "--dired" switches)) | 8484 | ;; error. |
| 8499 | (save-excursion | 8485 | (when (> (file-attribute-size (file-attributes errfile)) 0) |
| 8500 | (let ((case-fold-search nil)) | 8486 | (defvar dired--ls-error-buffer) ; Pacify byte-compiler. |
| 8501 | (forward-line -2) | 8487 | (let ((errbuf (get-buffer-create "*ls error*"))) |
| 8502 | (when (looking-at "//SUBDIRED//") | 8488 | (with-current-buffer errbuf |
| 8503 | (forward-line -1)) | 8489 | (erase-buffer) |
| 8504 | (if (looking-at "//DIRED//") | 8490 | (insert-file-contents errfile)) |
| 8505 | (setq result 0))))) | 8491 | (setq dired--ls-error-buffer errbuf))) |
| 8506 | 8492 | (delete-file errfile) | |
| 8507 | (when (and (not (eq 0 result)) | 8493 | |
| 8508 | (eq insert-directory-ls-version 'unknown)) | ||
| 8509 | ;; The first time ls returns an error, | ||
| 8510 | ;; find the version numbers of ls, | ||
| 8511 | ;; and set insert-directory-ls-version | ||
| 8512 | ;; to > if it is more than 5.2.1, < if it is less, nil if it | ||
| 8513 | ;; is equal or if the info cannot be obtained. | ||
| 8514 | ;; (That can mean it isn't GNU ls.) | ||
| 8515 | (let ((version-out | ||
| 8516 | (with-temp-buffer | ||
| 8517 | (call-process "ls" nil t nil "--version") | ||
| 8518 | (buffer-string)))) | ||
| 8519 | (setq insert-directory-ls-version | ||
| 8520 | (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out) | ||
| 8521 | (let* ((version (match-string 1 version-out)) | ||
| 8522 | (split (split-string version "[.]")) | ||
| 8523 | (numbers (mapcar #'string-to-number split)) | ||
| 8524 | (min '(5 2 1)) | ||
| 8525 | comparison) | ||
| 8526 | (while (and (not comparison) (or numbers min)) | ||
| 8527 | (cond ((null min) | ||
| 8528 | (setq comparison #'>)) | ||
| 8529 | ((null numbers) | ||
| 8530 | (setq comparison #'<)) | ||
| 8531 | ((> (car numbers) (car min)) | ||
| 8532 | (setq comparison #'>)) | ||
| 8533 | ((< (car numbers) (car min)) | ||
| 8534 | (setq comparison #'<)) | ||
| 8535 | (t | ||
| 8536 | (setq numbers (cdr numbers) | ||
| 8537 | min (cdr min))))) | ||
| 8538 | (or comparison #'=)) | ||
| 8539 | nil)))) | ||
| 8540 | |||
| 8541 | ;; For GNU ls versions 5.2.2 and up, ignore minor errors. | ||
| 8542 | (when (and (eq 1 result) (eq insert-directory-ls-version #'>)) | ||
| 8543 | (setq result 0)) | ||
| 8544 | |||
| 8545 | ;; If `insert-directory-program' failed, signal an error. | ||
| 8546 | (unless (eq 0 result) | ||
| 8547 | ;; Delete the error message it may have output. | ||
| 8548 | (delete-region beg (point)) | ||
| 8549 | ;; On non-Posix systems, we cannot open a directory, so | ||
| 8550 | ;; don't even try, because that will always result in | ||
| 8551 | ;; the ubiquitous "Access denied". Instead, show the | ||
| 8552 | ;; command line so the user can try to guess what went wrong. | ||
| 8553 | (if (and (file-directory-p file) | ||
| 8554 | (memq system-type '(ms-dos windows-nt))) | ||
| 8555 | (error | ||
| 8556 | "Reading directory: \"%s %s -- %s\" exited with status %s" | ||
| 8557 | insert-directory-program | ||
| 8558 | (if (listp switches) (concat switches) switches) | ||
| 8559 | file result) | ||
| 8560 | ;; Unix. Access the file to get a suitable error. | ||
| 8561 | (access-file file "Reading directory") | ||
| 8562 | (error "Listing directory failed but `access-file' worked"))) | ||
| 8563 | (insert-directory-clean beg switches) | 8494 | (insert-directory-clean beg switches) |
| 8564 | ;; Now decode what read if necessary. | 8495 | ;; Now decode what read if necessary. |
| 8565 | (let ((coding (or coding-system-for-read | 8496 | (let ((coding (or coding-system-for-read |
| @@ -8594,18 +8525,6 @@ normally equivalent short `-D' option is just passed on to | |||
| 8594 | (put-text-property pos (point) | 8525 | (put-text-property pos (point) |
| 8595 | 'dired-filename t)))))))))))) | 8526 | 'dired-filename t)))))))))))) |
| 8596 | 8527 | ||
| 8597 | (defun insert-directory-adj-pos (pos error-lines) | ||
| 8598 | "Convert `ls --dired' file name position value POS to a buffer position. | ||
| 8599 | File name position values returned in ls --dired output | ||
| 8600 | count only stdout; they don't count the error messages sent to stderr. | ||
| 8601 | So this function converts to them to real buffer positions. | ||
| 8602 | ERROR-LINES is a list of buffer positions of error message lines, | ||
| 8603 | of the form (START END)." | ||
| 8604 | (while (and error-lines (< (caar error-lines) pos)) | ||
| 8605 | (setq pos (+ pos (- (nth 1 (car error-lines)) (nth 0 (car error-lines))))) | ||
| 8606 | (pop error-lines)) | ||
| 8607 | pos) | ||
| 8608 | |||
| 8609 | (defun insert-directory-safely (file switches | 8528 | (defun insert-directory-safely (file switches |
| 8610 | &optional wildcard full-directory-p) | 8529 | &optional wildcard full-directory-p) |
| 8611 | "Insert directory listing for FILE, formatted according to SWITCHES. | 8530 | "Insert directory listing for FILE, formatted according to SWITCHES. |
diff --git a/lisp/frame.el b/lisp/frame.el index da48e695297..85b58cee070 100644 --- a/lisp/frame.el +++ b/lisp/frame.el | |||
| @@ -493,6 +493,7 @@ there (in decreasing order of priority)." | |||
| 493 | (setq parms (append initial-frame-alist window-system-frame-alist | 493 | (setq parms (append initial-frame-alist window-system-frame-alist |
| 494 | default-frame-alist parms nil)) | 494 | default-frame-alist parms nil)) |
| 495 | ;; Don't enable tab-bar in daemon's initial frame. | 495 | ;; Don't enable tab-bar in daemon's initial frame. |
| 496 | ;; Use `frame-initial-p'? | ||
| 496 | (when (and (daemonp) (eq (selected-frame) terminal-frame)) | 497 | (when (and (daemonp) (eq (selected-frame) terminal-frame)) |
| 497 | (setq parms (delq (assq 'tab-bar-lines parms) parms))) | 498 | (setq parms (delq (assq 'tab-bar-lines parms) parms))) |
| 498 | parms)) | 499 | parms)) |
diff --git a/lisp/frameset.el b/lisp/frameset.el index e11a1da7e9b..0dde10869fd 100644 --- a/lisp/frameset.el +++ b/lisp/frameset.el | |||
| @@ -1370,12 +1370,10 @@ All keyword parameters default to nil." | |||
| 1370 | ;; frame, as that would only trigger | 1370 | ;; frame, as that would only trigger |
| 1371 | ;; warnings. | 1371 | ;; warnings. |
| 1372 | (not | 1372 | (not |
| 1373 | (and (daemonp) | 1373 | (and (daemonp) ;; FIXME: Remove `daemonp'? |
| 1374 | (equal (terminal-name (frame-terminal | 1374 | (frame-initial-p frame)))) |
| 1375 | frame)) | 1375 | (delete-frame frame))) |
| 1376 | "initial_terminal")))) | 1376 | cleanup-frames))) |
| 1377 | (delete-frame frame))) | ||
| 1378 | cleanup-frames))) | ||
| 1379 | (maphash (lambda (frame _action) (push frame map)) frameset--action-map) | 1377 | (maphash (lambda (frame _action) (push frame map)) frameset--action-map) |
| 1380 | (dolist (frame (sort map | 1378 | (dolist (frame (sort map |
| 1381 | ;; Minibufferless frames must go first to avoid | 1379 | ;; Minibufferless frames must go first to avoid |
diff --git a/lisp/gnus/gnus-delay.el b/lisp/gnus/gnus-delay.el index b8fefabacbb..d3088b4001f 100644 --- a/lisp/gnus/gnus-delay.el +++ b/lisp/gnus/gnus-delay.el | |||
| @@ -70,6 +70,9 @@ DELAY is a string, giving the length of the time. Possible values are: | |||
| 70 | * YYYY-MM-DD for a specific date. The time of day is given by the | 70 | * YYYY-MM-DD for a specific date. The time of day is given by the |
| 71 | variable `gnus-delay-default-hour', minute and second are zero. | 71 | variable `gnus-delay-default-hour', minute and second are zero. |
| 72 | 72 | ||
| 73 | * YYYY-MM-DD hh:mm(:ss) for a specific date and time. If seconds are left | ||
| 74 | out, they will be zero. | ||
| 75 | |||
| 73 | * hh:mm for a specific time. Use 24h format. If it is later than this | 76 | * hh:mm for a specific time. Use 24h format. If it is later than this |
| 74 | time, then the deadline is tomorrow, else today. | 77 | time, then the deadline is tomorrow, else today. |
| 75 | 78 | ||
| @@ -82,8 +85,21 @@ generated when the article is sent." | |||
| 82 | message-mode) | 85 | message-mode) |
| 83 | ;; Allow spell checking etc. | 86 | ;; Allow spell checking etc. |
| 84 | (run-hooks 'message-send-hook) | 87 | (run-hooks 'message-send-hook) |
| 85 | (let (num unit year month day hour minute deadline) ;; days | 88 | (let (num unit year month day hour minute deadline second) ;; days |
| 86 | (cond ((string-match | 89 | (cond ((string-match |
| 90 | "\\([0-9][0-9][0-9]?[0-9]?\\)-\\([0-9]+\\)-\\([0-9]+\\) \\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\):?\\([0-9]\\{2\\}\\)?" | ||
| 91 | delay) | ||
| 92 | (setq year (string-to-number (match-string 1 delay)) | ||
| 93 | month (string-to-number (match-string 2 delay)) | ||
| 94 | day (string-to-number (match-string 3 delay)) | ||
| 95 | hour (string-to-number (match-string 4 delay)) | ||
| 96 | minute (string-to-number (match-string 5 delay)) | ||
| 97 | second (if (match-string 6 delay) (string-to-number (match-string 6 delay)) 0)) | ||
| 98 | (setq deadline | ||
| 99 | (message-make-date | ||
| 100 | (encode-time second minute hour | ||
| 101 | day month year)))) | ||
| 102 | ((string-match | ||
| 87 | "\\([0-9][0-9][0-9]?[0-9]?\\)-\\([0-9]+\\)-\\([0-9]+\\)" | 103 | "\\([0-9][0-9][0-9]?[0-9]?\\)-\\([0-9]+\\)-\\([0-9]+\\)" |
| 88 | delay) | 104 | delay) |
| 89 | (setq year (string-to-number (match-string 1 delay)) | 105 | (setq year (string-to-number (match-string 1 delay)) |
diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el index ad1c4c2731a..0097f590b43 100644 --- a/lisp/gnus/gnus-icalendar.el +++ b/lisp/gnus/gnus-icalendar.el | |||
| @@ -36,6 +36,10 @@ | |||
| 36 | ;;; Code: | 36 | ;;; Code: |
| 37 | 37 | ||
| 38 | (require 'icalendar) | 38 | (require 'icalendar) |
| 39 | (require 'icalendar-parser) | ||
| 40 | (eval-when-compile (require 'icalendar-macs)) | ||
| 41 | (require 'icalendar-ast) | ||
| 42 | (require 'icalendar-utils) | ||
| 39 | (require 'eieio) | 43 | (require 'eieio) |
| 40 | (require 'gmm-utils) | 44 | (require 'gmm-utils) |
| 41 | (require 'mm-decode) | 45 | (require 'mm-decode) |
| @@ -82,8 +86,8 @@ | |||
| 82 | :type (or null t)) | 86 | :type (or null t)) |
| 83 | (recur :initarg :recur | 87 | (recur :initarg :recur |
| 84 | :accessor gnus-icalendar-event:recur | 88 | :accessor gnus-icalendar-event:recur |
| 85 | :initform "" | 89 | :initform nil |
| 86 | :type (or null string)) | 90 | :type (or null list)) |
| 87 | (uid :initarg :uid | 91 | (uid :initarg :uid |
| 88 | :accessor gnus-icalendar-event:uid | 92 | :accessor gnus-icalendar-event:uid |
| 89 | :type string) | 93 | :type string) |
| @@ -127,295 +131,212 @@ | |||
| 127 | 131 | ||
| 128 | (cl-defmethod gnus-icalendar-event:recurring-freq ((event gnus-icalendar-event)) | 132 | (cl-defmethod gnus-icalendar-event:recurring-freq ((event gnus-icalendar-event)) |
| 129 | "Return recurring frequency of EVENT." | 133 | "Return recurring frequency of EVENT." |
| 130 | (let ((rrule (gnus-icalendar-event:recur event))) | 134 | (ical:recur-freq (gnus-icalendar-event:recur event))) |
| 131 | (string-match "FREQ=\\([[:alpha:]]+\\)" rrule) | ||
| 132 | (match-string 1 rrule))) | ||
| 133 | 135 | ||
| 134 | (cl-defmethod gnus-icalendar-event:recurring-interval ((event gnus-icalendar-event)) | 136 | (cl-defmethod gnus-icalendar-event:recurring-interval ((event gnus-icalendar-event)) |
| 135 | "Return recurring interval of EVENT." | 137 | "Return recurring interval of EVENT." |
| 136 | (let ((rrule (gnus-icalendar-event:recur event)) | 138 | (ical:recur-interval-size (gnus-icalendar-event:recur event))) |
| 137 | (default-interval "1")) | ||
| 138 | |||
| 139 | (if (string-match "INTERVAL=\\([[:digit:]]+\\)" rrule) | ||
| 140 | (match-string 1 rrule) | ||
| 141 | default-interval))) | ||
| 142 | 139 | ||
| 143 | (cl-defmethod gnus-icalendar-event:recurring-days ((event gnus-icalendar-event)) | 140 | (cl-defmethod gnus-icalendar-event:recurring-days ((event gnus-icalendar-event)) |
| 144 | "Return, when available, the week day numbers on which the EVENT recurs." | 141 | "Return, when available, the week day numbers on which the EVENT recurs." |
| 145 | (let ((rrule (gnus-icalendar-event:recur event)) | 142 | (let ((rrule (gnus-icalendar-event:recur event))) |
| 146 | (weekday-map '(("SU" . 0) | 143 | (when rrule |
| 147 | ("MO" . 1) | 144 | (mapcar (lambda (el) (if (consp el) (car el) el)) |
| 148 | ("TU" . 2) | 145 | (ical:recur-by* 'BYDAY rrule))))) |
| 149 | ("WE" . 3) | ||
| 150 | ("TH" . 4) | ||
| 151 | ("FR" . 5) | ||
| 152 | ("SA" . 6)))) | ||
| 153 | (when (and rrule (string-match "BYDAY=\\([^;]+\\)" rrule)) | ||
| 154 | (let ((bydays (split-string (match-string 1 rrule) ","))) | ||
| 155 | (seq-map | ||
| 156 | (lambda (x) (cdr (assoc x weekday-map))) | ||
| 157 | (seq-filter (lambda (x) (string-match "^[A-Z]\\{2\\}$" x)) bydays)))))) | ||
| 158 | 146 | ||
| 159 | (cl-defmethod gnus-icalendar-event:start ((event gnus-icalendar-event)) | 147 | (cl-defmethod gnus-icalendar-event:start ((event gnus-icalendar-event)) |
| 160 | (format-time-string "%Y-%m-%d %H:%M" (gnus-icalendar-event:start-time event))) | 148 | (format-time-string "%Y-%m-%d %H:%M" (gnus-icalendar-event:start-time event))) |
| 161 | 149 | ||
| 162 | (defun gnus-icalendar-event--decode-datefield (event field zone-map) | 150 | (defun gnus-icalendar-event--find-attendee (attendees ids) |
| 163 | (let* ((dtdate (icalendar--get-event-property event field)) | 151 | "Return the first `icalendar-attendee' in ATTENDEES matching IDS. |
| 164 | (dtdate-zone (icalendar--find-time-zone | 152 | IDS should be a list of strings. The first attendee is returned whose |
| 165 | (icalendar--get-event-property-attributes | 153 | name (as `icalendar-cnparam') or email address (without \"mailto:\") |
| 166 | event field) zone-map)) | 154 | is a member of IDS." |
| 167 | (dtdate-dec (icalendar--decode-isodatetime dtdate nil dtdate-zone))) | 155 | (catch 'found |
| 168 | (when dtdate-dec (encode-time dtdate-dec)))) | 156 | (dolist (attendee attendees) |
| 169 | 157 | (ical:with-property attendee ((ical:cnparam :value name)) | |
| 170 | (defun gnus-icalendar-event--find-attendee (ical name-or-email) | 158 | (let ((email (ical:strip-mailto value))) |
| 171 | (let* ((event (car (icalendar--all-events ical))) | 159 | (when (or (member name ids) |
| 172 | (event-props (caddr event))) | 160 | (member email ids)) |
| 173 | (cl-labels ((attendee-name (att) (plist-get (cadr att) 'CN)) | 161 | (throw 'found attendee))))))) |
| 174 | (attendee-email | 162 | |
| 175 | (att) | 163 | (defun gnus-icalendar-event--attendees-by-type (attendees) |
| 176 | (replace-regexp-in-string "^.*MAILTO:" "" (caddr att))) | 164 | "Return lists of required and optional participants in ATTENDEES. |
| 177 | (attendee-prop-matches-p | 165 | ATTENDEES must be a list of `icalendar-attendee' nodes. The returned |
| 178 | (prop) | 166 | list has the form (REQUIRED OPTIONAL), where each is a list of |
| 179 | (and (eq (car prop) 'ATTENDEE) | 167 | `icalendar-attendee' nodes." |
| 180 | (or (member (attendee-name prop) name-or-email) | 168 | (let (required optional) |
| 181 | (let ((att-email (attendee-email prop))) | 169 | (dolist (attendee attendees) |
| 182 | (gnus-icalendar-find-if | 170 | (ical:with-property attendee ((ical:roleparam :value role)) |
| 183 | (lambda (str-or-fun) | 171 | (when (or (null role) ; "REQ-PARTICIPANT" is the default |
| 184 | (if (functionp str-or-fun) | 172 | (equal role "REQ-PARTICIPANT")) |
| 185 | (funcall str-or-fun att-email) | 173 | (push attendee required)) |
| 186 | (string-match str-or-fun att-email))) | 174 | (when (equal role "OPT-PARTICIPANT") |
| 187 | name-or-email)))))) | 175 | (push attendee optional)))) |
| 188 | (gnus-icalendar-find-if #'attendee-prop-matches-p event-props)))) | 176 | (list (nreverse required) |
| 189 | 177 | (nreverse optional)))) | |
| 190 | (defun gnus-icalendar-event--get-attendee-names (ical) | 178 | |
| 191 | (let* ((event (car (icalendar--all-events ical))) | 179 | (defun gnus-icalendar-event-from-ical (vcalendar &optional ids) |
| 192 | (attendee-props (seq-filter | 180 | "Initialize an event instance with the first `icalendar-vevent' in VCALENDAR. |
| 193 | (lambda (p) (eq (car p) 'ATTENDEE)) | 181 | IDS should be a list of strings representing names and email addresses |
| 194 | (caddr event)))) | 182 | by which to identify an `icalendar-attendee' in the event as the |
| 195 | 183 | recipient." | |
| 196 | (cl-labels | 184 | (ical:with-component vcalendar |
| 197 | ((attendee-role (prop) | 185 | ((ical:vevent vevent) |
| 198 | ;; RFC5546: default ROLE is REQ-PARTICIPANT | 186 | (ical:method :value method)) |
| 199 | (and prop | 187 | (ical:with-component vevent |
| 200 | (or (plist-get (cadr prop) 'ROLE) | 188 | ((ical:organizer :value organizer) |
| 201 | "REQ-PARTICIPANT"))) | 189 | (ical:attendee :all attendees) |
| 202 | (attendee-name | 190 | (ical:summary :value summary) |
| 203 | (prop) | 191 | (ical:description :value description) |
| 204 | (or (plist-get (cadr prop) 'CN) | 192 | (ical:dtstart :value dtstart) |
| 205 | (replace-regexp-in-string "^.*MAILTO:" "" (caddr prop)))) | 193 | (ical:dtend :value dtend) |
| 206 | (attendees-by-type (type) | 194 | (ical:location :value location) |
| 207 | (seq-filter | 195 | (ical:rrule :value rrule) |
| 208 | (lambda (p) (string= (attendee-role p) type)) | 196 | (ical:uid :value uid)) |
| 209 | attendee-props)) | 197 | |
| 210 | (attendee-names-by-type | 198 | (let* ((attendee (when ids (gnus-icalendar-event--find-attendee attendees ids))) |
| 211 | (type) | 199 | (rsvp-p (ical:with-param-of attendee 'ical:rsvpparam)) |
| 212 | (mapcar #'attendee-name (attendees-by-type type)))) | ||
| 213 | (list | ||
| 214 | (attendee-names-by-type "REQ-PARTICIPANT") | ||
| 215 | (attendee-names-by-type "OPT-PARTICIPANT"))))) | ||
| 216 | |||
| 217 | (defun gnus-icalendar-event-from-ical (ical &optional attendee-name-or-email) | ||
| 218 | (let* ((event (car (icalendar--all-events ical))) | ||
| 219 | (organizer (replace-regexp-in-string | ||
| 220 | "^.*MAILTO:" "" | ||
| 221 | (or (icalendar--get-event-property event 'ORGANIZER) ""))) | ||
| 222 | (prop-map '((summary . SUMMARY) | ||
| 223 | (description . DESCRIPTION) | ||
| 224 | (location . LOCATION) | ||
| 225 | (recur . RRULE) | ||
| 226 | (uid . UID))) | ||
| 227 | (method (caddr (assoc 'METHOD (caddr (car (nreverse ical)))))) | ||
| 228 | (attendee (when attendee-name-or-email | ||
| 229 | (gnus-icalendar-event--find-attendee | ||
| 230 | ical attendee-name-or-email))) | ||
| 231 | (attendee-names (gnus-icalendar-event--get-attendee-names ical)) | ||
| 232 | ;; RFC5546: default ROLE is REQ-PARTICIPANT | 200 | ;; RFC5546: default ROLE is REQ-PARTICIPANT |
| 233 | (role (and attendee | 201 | (role (when attendee |
| 234 | (or (plist-get (cadr attendee) 'ROLE) | 202 | (or (ical:with-param-of attendee 'ical:roleparam) |
| 235 | "REQ-PARTICIPANT"))) | 203 | "REQ-PARTICIPANT"))) |
| 236 | (participation-type (pcase role | 204 | (participation-type (pcase role |
| 237 | ("REQ-PARTICIPANT" 'required) | 205 | ("REQ-PARTICIPANT" 'required) |
| 238 | ("OPT-PARTICIPANT" 'optional) | 206 | ("OPT-PARTICIPANT" 'optional) |
| 239 | (_ 'non-participant))) | 207 | (_ 'non-participant))) |
| 240 | (zone-map (icalendar--convert-all-timezones ical)) | 208 | (req/opt (gnus-icalendar-event--attendees-by-type attendees)) |
| 241 | (args | 209 | (args |
| 242 | (list :method method | 210 | (list :method method |
| 243 | :organizer organizer | 211 | :organizer (when organizer (ical:strip-mailto organizer)) |
| 244 | :start-time (gnus-icalendar-event--decode-datefield | 212 | :summary summary |
| 245 | event 'DTSTART zone-map) | 213 | :description description |
| 246 | :end-time (gnus-icalendar-event--decode-datefield | 214 | :location location |
| 247 | event 'DTEND zone-map) | 215 | :recur rrule |
| 248 | :rsvp (string= (plist-get (cadr attendee) 'RSVP) "TRUE") | 216 | :start-time (encode-time dtstart) |
| 217 | :end-time (encode-time dtend) | ||
| 218 | :rsvp rsvp-p | ||
| 249 | :participation-type participation-type | 219 | :participation-type participation-type |
| 250 | :req-participants (car attendee-names) | 220 | :req-participants (car req/opt) |
| 251 | :opt-participants (cadr attendee-names))) | 221 | :opt-participants (cadr req/opt) |
| 252 | (event-class | 222 | :uid (or uid ""))) ; UID must be a string |
| 253 | (cond | 223 | (event-class (pcase method |
| 254 | ((string= method "REQUEST") 'gnus-icalendar-event-request) | 224 | ("REQUEST" 'gnus-icalendar-event-request) |
| 255 | ((string= method "CANCEL") 'gnus-icalendar-event-cancel) | 225 | ("CANCEL" 'gnus-icalendar-event-cancel) |
| 256 | ((string= method "REPLY") 'gnus-icalendar-event-reply) | 226 | ("REPLY" 'gnus-icalendar-event-reply) |
| 257 | (t 'gnus-icalendar-event)))) | 227 | (_ 'gnus-icalendar-event)))) |
| 258 | (cl-labels | 228 | ;; Initialize and return the instance: |
| 259 | ((map-property | 229 | (apply |
| 260 | (prop) | 230 | #'make-instance |
| 261 | (let ((value (icalendar--get-event-property event prop))) | 231 | event-class |
| 262 | (when value | 232 | (cl-loop for slot in (eieio-class-slots event-class) |
| 263 | ;; ugly, but cannot get | 233 | for keyword = (intern |
| 264 | ;;replace-regexp-in-string work with "\\" as | 234 | (format ":%s" (eieio-slot-descriptor-name slot))) |
| 265 | ;;REP, plus we should also handle "\\;" | 235 | when (plist-member args keyword) |
| 266 | (string-replace | 236 | append (list keyword (plist-get args keyword)))))))) |
| 267 | "\\," "," | 237 | |
| 268 | (string-replace | 238 | (defun gnus-icalendar-event-from-buffer (buf &optional ids) |
| 269 | "\\n" "\n" (substring-no-properties value)))))) | ||
| 270 | (accumulate-args | ||
| 271 | (mapping) | ||
| 272 | (cl-destructuring-bind (slot . ical-property) mapping | ||
| 273 | (setq args (append (list | ||
| 274 | (intern (concat ":" (symbol-name slot))) | ||
| 275 | (map-property ical-property)) | ||
| 276 | args))))) | ||
| 277 | (mapc #'accumulate-args prop-map) | ||
| 278 | (apply | ||
| 279 | #'make-instance | ||
| 280 | event-class | ||
| 281 | (cl-loop for slot in (eieio-class-slots event-class) | ||
| 282 | for keyword = (intern | ||
| 283 | (format ":%s" (eieio-slot-descriptor-name slot))) | ||
| 284 | when (plist-member args keyword) | ||
| 285 | append (list keyword | ||
| 286 | (if (eq keyword :uid) | ||
| 287 | ;; The UID has to be a string. | ||
| 288 | (or (plist-get args keyword) "") | ||
| 289 | (plist-get args keyword)))))))) | ||
| 290 | |||
| 291 | (defun gnus-icalendar-event-from-buffer (buf &optional attendee-name-or-email) | ||
| 292 | "Parse RFC5545 iCalendar in buffer BUF and return an event object. | 239 | "Parse RFC5545 iCalendar in buffer BUF and return an event object. |
| 293 | 240 | ||
| 294 | Return a gnus-icalendar-event object representing the first event | 241 | Return a gnus-icalendar-event object representing the first event |
| 295 | contained in the invitation. Return nil for calendars without an | 242 | contained in the invitation. Return nil for calendars without an |
| 296 | event entry. | 243 | event entry. |
| 297 | 244 | ||
| 298 | ATTENDEE-NAME-OR-EMAIL is a list of strings that will be matched | 245 | IDS is a list of strings that identify the recipient |
| 299 | against the event's attendee names and emails. Invitation rsvp | 246 | `icalendar-attendee' by name or email address. Invitation rsvp status |
| 300 | status will be retrieved from the first matching attendee record." | 247 | will be retrieved from the first matching attendee record." |
| 301 | (let ((ical (with-current-buffer (icalendar--get-unfolded-buffer (get-buffer buf)) | 248 | (let ((vcalendar (ical:parse buf))) |
| 302 | (goto-char (point-min)) | 249 | (when vcalendar |
| 303 | (icalendar--read-element nil nil)))) | 250 | (gnus-icalendar-event-from-ical vcalendar ids)))) |
| 304 | |||
| 305 | (when ical | ||
| 306 | (gnus-icalendar-event-from-ical ical attendee-name-or-email)))) | ||
| 307 | 251 | ||
| 308 | ;;; | 252 | ;;; |
| 309 | ;;; gnus-icalendar-event-reply | 253 | ;;; gnus-icalendar-event-reply |
| 310 | ;;; | 254 | ;;; |
| 311 | 255 | ||
| 312 | (defun gnus-icalendar-event--build-reply-event-body (ical-request status identities &optional comment) | 256 | (defun gnus-icalendar-event--build-reply (vcalendar status ids &optional comment) |
| 257 | "Return an `icalendar-vcalendar' based on VCALENDAR with updated STATUS. | ||
| 258 | STATUS should one of \\='accepted, \\='declined, or \\='tentative. The | ||
| 259 | recipient whose participation status is updated to STATUS is identified | ||
| 260 | in EVENT by finding an `icalendar-attendee' whose name or email address | ||
| 261 | matches one of the strings in IDS. If no such attendee is found, a new | ||
| 262 | `icalendar-attendee' is added from the values of `user-mail-address' and | ||
| 263 | `user-full-name'. COMMENT, if provided, will be added as an | ||
| 264 | `icalendar-comment' to the returned event." | ||
| 313 | (let ((summary-status (capitalize (symbol-name status))) | 265 | (let ((summary-status (capitalize (symbol-name status))) |
| 314 | (attendee-status (upcase (symbol-name status))) | 266 | (attendee-status (upcase (symbol-name status))) |
| 315 | reply-event-lines) | 267 | recipient) |
| 316 | (cl-labels | 268 | (ical:with-component vcalendar |
| 317 | ((update-summary | 269 | ((ical:vtimezone :all tz-nodes) |
| 318 | (line) | 270 | (ical:vevent :first vevent)) |
| 319 | (if (string-match "^[^:]+:" line) | 271 | (ical:with-component vevent |
| 320 | (replace-match (format "\\&%s: " summary-status) t nil line) | 272 | ((ical:summary :value summary) |
| 321 | line)) | 273 | (ical:attendee :all attendees) |
| 322 | (update-comment | 274 | (ical:uid :value uid) |
| 323 | (line) | 275 | (ical:comment :value old-comment) |
| 324 | (if comment (format "COMMENT:%s" comment) | 276 | ;; The nodes below are copied unchanged to the reply. Not all |
| 325 | line)) | 277 | ;; of them are mandatory, but they are often present in other |
| 326 | (update-dtstamp () | 278 | ;; clients' replies. Can be helpful for debugging, too. |
| 327 | (format-time-string "DTSTAMP:%Y%m%dT%H%M%SZ" nil t)) | 279 | (ical:organizer :first organizer-node) |
| 328 | (attendee-matches-identity | 280 | (ical:dtstart :first dtstart-node) |
| 329 | (line) | 281 | (ical:dtend :first dtend-node) |
| 330 | (gnus-icalendar-find-if (lambda (name) (string-match-p name line)) | 282 | (ical:duration :first duration-node) |
| 331 | identities)) | 283 | (ical:location :first location-node) |
| 332 | (update-attendee-status | 284 | (ical:sequence :first sequence-node) |
| 333 | (line) | 285 | (ical:recurrence-id :first recid-node)) |
| 334 | (when (and (attendee-matches-identity line) | 286 | |
| 335 | (string-match "\\(PARTSTAT=\\)[^;]+" line)) | 287 | (setq recipient (gnus-icalendar-event--find-attendee attendees ids)) |
| 336 | (replace-match (format "\\1%s" attendee-status) t nil line))) | 288 | (if recipient |
| 337 | (process-event-line | 289 | (ical:with-property recipient |
| 338 | (line) | 290 | ((ical:partstatparam :first partstat-node)) |
| 339 | (when (string-match "^\\([^;:]+\\)" line) | 291 | (ical:ast-node-set-value partstat-node attendee-status)) |
| 340 | (let* ((key (match-string 0 line)) | 292 | ;; RFC5546 refers to uninvited attendees as "party crashers". |
| 341 | ;; NOTE: not all of the below fields are mandatory, | 293 | ;; This situation is common if the invitation is sent to a group |
| 342 | ;; but they are often present in other clients' | 294 | ;; of people via a mailing list. |
| 343 | ;; replies. Can be helpful for debugging, too. | 295 | (lwarn 'gnus-icalendar :warning |
| 344 | (new-line | 296 | "Could not find a matching event attendee; creating new.") |
| 345 | (cond | 297 | (setq recipient |
| 346 | ((string= key "ATTENDEE") (update-attendee-status line)) | 298 | (ical:make-property ical:attendee |
| 347 | ((string= key "SUMMARY") (update-summary line)) | 299 | (concat "mailto:" user-mail-address) |
| 348 | ((string= key "COMMENT") (update-comment line)) | 300 | (ical:partstatparam attendee-status) |
| 349 | ((string= key "DTSTAMP") (update-dtstamp)) | 301 | (ical:cnparam user-full-name))) |
| 350 | ((member key '("ORGANIZER" "DTSTART" "DTEND" | 302 | (push recipient attendees)) |
| 351 | "LOCATION" "DURATION" "SEQUENCE" | 303 | |
| 352 | "RECURRENCE-ID" "UID")) | 304 | ;; Build the reply: |
| 353 | line) | 305 | (ical:make-vcalendar |
| 354 | (t nil)))) | 306 | (ical:method "REPLY") |
| 355 | (when new-line | 307 | (@ tz-nodes) |
| 356 | (push new-line reply-event-lines)))))) | 308 | (ical:vevent |
| 357 | 309 | (ical:uid uid) | |
| 358 | (mapc #'process-event-line (split-string ical-request "\n")) | 310 | recid-node |
| 359 | 311 | sequence-node | |
| 360 | ;; RFC5546 refers to uninvited attendees as "party crashers". | 312 | organizer-node |
| 361 | ;; This situation is common if the invitation is sent to a group | 313 | dtstart-node |
| 362 | ;; of people via a mailing list. | 314 | dtend-node |
| 363 | (unless (gnus-icalendar-find-if (lambda (x) (string-match "^ATTENDEE" x)) | 315 | duration-node |
| 364 | reply-event-lines) | 316 | location-node |
| 365 | (lwarn 'gnus-icalendar :warning | 317 | (ical:summary |
| 366 | "Could not find an event attendee matching given identity") | 318 | (if (string-match "^[^:]+:" summary) |
| 367 | (push (format "ATTENDEE;RSVP=TRUE;PARTSTAT=%s;CN=%s:MAILTO:%s" | 319 | (replace-match (format "\\&%s: " summary-status) t nil summary) |
| 368 | attendee-status user-full-name user-mail-address) | 320 | summary)) |
| 369 | reply-event-lines)) | 321 | (ical:comment (or comment old-comment)) |
| 370 | 322 | (@ attendees))))))) | |
| 371 | ;; add comment line if not existing | 323 | |
| 372 | (when (and comment | 324 | (defun gnus-icalendar-event-reply-from-buffer (buf status ids |
| 373 | (not (gnus-icalendar-find-if | 325 | &optional comment) |
| 374 | (lambda (x) | ||
| 375 | (string-match "^COMMENT" x)) | ||
| 376 | reply-event-lines))) | ||
| 377 | (push (format "COMMENT:%s" comment) reply-event-lines)) | ||
| 378 | |||
| 379 | (mapconcat #'identity `("BEGIN:VEVENT" | ||
| 380 | ,@(nreverse reply-event-lines) | ||
| 381 | "END:VEVENT") | ||
| 382 | "\n")))) | ||
| 383 | |||
| 384 | (defun gnus-icalendar-event-reply-from-buffer (buf status identities &optional comment) | ||
| 385 | "Build a calendar event reply for request contained in BUF. | 326 | "Build a calendar event reply for request contained in BUF. |
| 386 | The reply will have STATUS (`accepted', `tentative' or `declined'). | 327 | The reply will have STATUS (`accepted', `tentative' or `declined'). The |
| 387 | The reply will be composed for attendees matching any entry | 328 | reply will be composed for attendees matching any entry in the |
| 388 | on the IDENTITIES list. | 329 | IDS list. Optional argument COMMENT will be placed in the |
| 389 | Optional argument COMMENT will be placed in the comment field of the | 330 | comment field of the reply." |
| 390 | reply. | 331 | (let (vcalendar reply) |
| 391 | " | 332 | (with-current-buffer (ical:unfolded-buffer-from-buffer (get-buffer buf)) |
| 392 | (cl-labels | 333 | (setq vcalendar (ical:parse)) |
| 393 | ((extract-block | 334 | (unless vcalendar |
| 394 | (blockname) | 335 | (error "Could not parse invitation; see buffer %s" |
| 395 | (save-excursion | 336 | (buffer-name (ical:error-buffer)))) |
| 396 | (let ((block-start-re (format "^BEGIN:%s" blockname)) | 337 | (setq reply |
| 397 | (block-end-re (format "^END:%s" blockname)) | 338 | (gnus-icalendar-event--build-reply vcalendar status ids comment)) |
| 398 | start) | 339 | (ical:print-calendar-node reply)))) |
| 399 | (when (re-search-forward block-start-re nil t) | ||
| 400 | (setq start (line-beginning-position)) | ||
| 401 | (re-search-forward block-end-re) | ||
| 402 | (buffer-substring-no-properties start (line-end-position))))))) | ||
| 403 | (let (zone event) | ||
| 404 | (with-current-buffer (icalendar--get-unfolded-buffer (get-buffer buf)) | ||
| 405 | (goto-char (point-min)) | ||
| 406 | (setq zone (extract-block "VTIMEZONE") | ||
| 407 | event (extract-block "VEVENT"))) | ||
| 408 | |||
| 409 | (when event | ||
| 410 | (let ((contents (list "BEGIN:VCALENDAR" | ||
| 411 | "METHOD:REPLY" | ||
| 412 | "PRODID:Gnus" | ||
| 413 | "VERSION:2.0" | ||
| 414 | zone | ||
| 415 | (gnus-icalendar-event--build-reply-event-body event status identities comment) | ||
| 416 | "END:VCALENDAR"))) | ||
| 417 | |||
| 418 | (mapconcat #'identity (delq nil contents) "\n")))))) | ||
| 419 | 340 | ||
| 420 | ;;; | 341 | ;;; |
| 421 | ;;; gnus-icalendar-org | 342 | ;;; gnus-icalendar-org |
| @@ -455,15 +376,17 @@ reply. | |||
| 455 | "Return `org-mode' timestamp repeater string for recurring EVENT. | 376 | "Return `org-mode' timestamp repeater string for recurring EVENT. |
| 456 | Return nil for non-recurring EVENT." | 377 | Return nil for non-recurring EVENT." |
| 457 | (when (gnus-icalendar-event:recurring-p event) | 378 | (when (gnus-icalendar-event:recurring-p event) |
| 458 | (let* ((freq-map '(("HOURLY" . "h") | 379 | (let* ((freq-map '((HOURLY . "h") |
| 459 | ("DAILY" . "d") | 380 | (DAILY . "d") |
| 460 | ("WEEKLY" . "w") | 381 | (WEEKLY . "w") |
| 461 | ("MONTHLY" . "m") | 382 | (MONTHLY . "m") |
| 462 | ("YEARLY" . "y"))) | 383 | (YEARLY . "y"))) |
| 463 | (org-freq (cdr (assoc (gnus-icalendar-event:recurring-freq event) freq-map)))) | 384 | (org-freq |
| 385 | (alist-get (gnus-icalendar-event:recurring-freq event) freq-map)) | ||
| 386 | (interval-size (gnus-icalendar-event:recurring-interval event))) | ||
| 464 | 387 | ||
| 465 | (when org-freq | 388 | (when org-freq |
| 466 | (format "+%s%s" (gnus-icalendar-event:recurring-interval event) org-freq))))) | 389 | (format "+%d%s" interval-size org-freq))))) |
| 467 | 390 | ||
| 468 | (defun gnus-icalendar--find-day (start-date end-date day) | 391 | (defun gnus-icalendar--find-day (start-date end-date day) |
| 469 | (let ((time-1-day 86400)) | 392 | (let ((time-1-day 86400)) |
| @@ -550,7 +473,18 @@ Return nil for non-recurring EVENT." | |||
| 550 | 473 | ||
| 551 | 474 | ||
| 552 | (defun gnus-icalendar--format-participant-list (participants) | 475 | (defun gnus-icalendar--format-participant-list (participants) |
| 553 | (mapconcat #'identity participants ", ")) | 476 | "Format PARTICIPANTS as a comma-separated list. |
| 477 | |||
| 478 | Each `icalendar-attendee' in PARTICIPANTS will be represented like | ||
| 479 | A. Person <a.person@example.domain> | ||
| 480 | or simply: <a.person@example.domain>, if no `icalendar-cnparam' is present." | ||
| 481 | (mapconcat | ||
| 482 | (lambda (attendee) | ||
| 483 | (ical:with-property attendee ((ical:cnparam :value cn)) | ||
| 484 | (if cn | ||
| 485 | (format "%s <%s>" cn value) | ||
| 486 | (format "<%s>" value)))) | ||
| 487 | participants ", ")) | ||
| 554 | 488 | ||
| 555 | ;; TODO: make the template customizable | 489 | ;; TODO: make the template customizable |
| 556 | (cl-defmethod gnus-icalendar-event->org-entry ((event gnus-icalendar-event) reply-status) | 490 | (cl-defmethod gnus-icalendar-event->org-entry ((event gnus-icalendar-event) reply-status) |
| @@ -1110,3 +1044,7 @@ means prompt for a comment to include in the reply." | |||
| 1110 | (provide 'gnus-icalendar) | 1044 | (provide 'gnus-icalendar) |
| 1111 | 1045 | ||
| 1112 | ;;; gnus-icalendar.el ends here | 1046 | ;;; gnus-icalendar.el ends here |
| 1047 | |||
| 1048 | ;; Local Variables: | ||
| 1049 | ;; read-symbol-shorthands: (("ical:" . "icalendar-")) | ||
| 1050 | ;; End: | ||
diff --git a/lisp/help.el b/lisp/help.el index 49d4659ab02..1576fb61dc8 100644 --- a/lisp/help.el +++ b/lisp/help.el | |||
| @@ -2356,11 +2356,13 @@ ARGLIST can also be t or a string of the form \"(FUN ARG1 ARG2 ...)\"." | |||
| 2356 | "Return a formal argument list for the function DEF. | 2356 | "Return a formal argument list for the function DEF. |
| 2357 | If PRESERVE-NAMES is non-nil, return a formal arglist that uses | 2357 | If PRESERVE-NAMES is non-nil, return a formal arglist that uses |
| 2358 | the same names as used in the original source code, when possible." | 2358 | the same names as used in the original source code, when possible." |
| 2359 | (let ((orig-def def) | 2359 | (let ((orig-def def)) |
| 2360 | ;; Advice wrappers have "catch all" args, so fetch the actual underlying | 2360 | (let ((seen nil)) |
| 2361 | ;; function to find the real arguments. | 2361 | ;; Advice wrappers have "catch all" args, so fetch the actual underlying |
| 2362 | (def (advice--cd*r | 2362 | ;; function to find the real arguments. Also follow aliases. |
| 2363 | (indirect-function def)))) ;; Follow aliases to other symbols. | 2363 | (while (not (memq def seen)) |
| 2364 | (push def seen) | ||
| 2365 | (setq def (advice--cd*r (indirect-function def))))) | ||
| 2364 | ;; If definition is a macro, find the function inside it. | 2366 | ;; If definition is a macro, find the function inside it. |
| 2365 | (if (eq (car-safe def) 'macro) (setq def (cdr def))) | 2367 | (if (eq (car-safe def) 'macro) (setq def (cdr def))) |
| 2366 | (cond | 2368 | (cond |
diff --git a/lisp/info.el b/lisp/info.el index 368255092a1..320ac7de65c 100644 --- a/lisp/info.el +++ b/lisp/info.el | |||
| @@ -1897,8 +1897,10 @@ of NODENAME; if none is found it then tries a case-insensitive match | |||
| 1897 | (if (equal nodename "") "Top" nodename) nil strict-case))) | 1897 | (if (equal nodename "") "Top" nodename) nil strict-case))) |
| 1898 | 1898 | ||
| 1899 | (defun Info-goto-node-web (node) | 1899 | (defun Info-goto-node-web (node) |
| 1900 | "Use `browse-url' to go to the gnu.org web server's version of NODE. | 1900 | "Use `browse-url' to go to the gnu.org Web server's version of NODE. |
| 1901 | By default, go to the current Info node." | 1901 | By default, go to the URL corresponding to the current Info node. |
| 1902 | |||
| 1903 | This uses `Info-url-for-node' to determine the URL that corresponds to NODE." | ||
| 1902 | (interactive (list (Info-read-node-name | 1904 | (interactive (list (Info-read-node-name |
| 1903 | "Go to node (default current page): " Info-current-node)) | 1905 | "Go to node (default current page): " Info-current-node)) |
| 1904 | Info-mode) | 1906 | Info-mode) |
| @@ -1924,7 +1926,10 @@ By default, go to the current Info node." | |||
| 1924 | (defun Info-url-for-node (node) | 1926 | (defun Info-url-for-node (node) |
| 1925 | "Return the URL corresponding to NODE. | 1927 | "Return the URL corresponding to NODE. |
| 1926 | 1928 | ||
| 1927 | NODE should be a string of the form \"(manual)Node\"." | 1929 | NODE should be a string of the form \"(manual)Node\". |
| 1930 | |||
| 1931 | The correspondence between Info manuals and their Web URLs is | ||
| 1932 | established by `Info-url-alist', which see." | ||
| 1928 | ;; GNU Texinfo skips whitespaces and newlines between the closing | 1933 | ;; GNU Texinfo skips whitespaces and newlines between the closing |
| 1929 | ;; parenthesis and the node-name, i.e. space, tab, line feed and | 1934 | ;; parenthesis and the node-name, i.e. space, tab, line feed and |
| 1930 | ;; carriage return. | 1935 | ;; carriage return. |
diff --git a/lisp/international/characters.el b/lisp/international/characters.el index ba994daa852..d19802c46fd 100644 --- a/lisp/international/characters.el +++ b/lisp/international/characters.el | |||
| @@ -1782,15 +1782,15 @@ Setup `char-width-table' appropriate for non-CJK language environment." | |||
| 1782 | (let ((c0-acronyms '("NUL" "SOH" "STX" "ETX" "EOT" "ENQ" "ACK" "BEL" | 1782 | (let ((c0-acronyms '("NUL" "SOH" "STX" "ETX" "EOT" "ENQ" "ACK" "BEL" |
| 1783 | "BS" nil nil "VT" "FF" "CR" "SO" "SI" | 1783 | "BS" nil nil "VT" "FF" "CR" "SO" "SI" |
| 1784 | "DLE" "DC1" "DC2" "DC3" "DC4" "NAK" "SYN" "ETB" | 1784 | "DLE" "DC1" "DC2" "DC3" "DC4" "NAK" "SYN" "ETB" |
| 1785 | "CAN" "EM" "SUB" "ESC" "FC" "GS" "RS" "US"))) | 1785 | "CAN" "EM" "SUB" "ESC" "FS" "GS" "RS" "US"))) |
| 1786 | (dotimes (i 32) | 1786 | (dotimes (i 32) |
| 1787 | (aset char-acronym-table i (car c0-acronyms)) | 1787 | (aset char-acronym-table i (car c0-acronyms)) |
| 1788 | (setq c0-acronyms (cdr c0-acronyms)))) | 1788 | (setq c0-acronyms (cdr c0-acronyms)))) |
| 1789 | 1789 | ||
| 1790 | (let ((c1-acronyms '("PAD" "HOP" "BPH" "NBH" "IND" "NEL" "SSA" "ESA" | 1790 | (let ((c1-acronyms '("PAD" "HOP" "BPH" "NBH" "IND" "NEL" "SSA" "ESA" |
| 1791 | "HTS" "HTJ" "VTS" "PLD" "PLU" "R1" "SS2" "SS1" | 1791 | "HTS" "HTJ" "VTS" "PLD" "PLU" "RI" "SS2" "SS3" |
| 1792 | "DCS" "PU1" "PU2" "STS" "CCH" "MW" "SPA" "EPA" | 1792 | "DCS" "PU1" "PU2" "STS" "CCH" "MW" "SPA" "EPA" |
| 1793 | "SOS" "SGCI" "SC1" "CSI" "ST" "OSC" "PM" "APC"))) | 1793 | "SOS" "SGCI" "SCI" "CSI" "ST" "OSC" "PM" "APC"))) |
| 1794 | (dotimes (i 32) | 1794 | (dotimes (i 32) |
| 1795 | (aset char-acronym-table (+ #x0080 i) (car c1-acronyms)) | 1795 | (aset char-acronym-table (+ #x0080 i) (car c1-acronyms)) |
| 1796 | (setq c1-acronyms (cdr c1-acronyms)))) | 1796 | (setq c1-acronyms (cdr c1-acronyms)))) |
diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index d8e779f7d8d..56a8134be81 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el | |||
| @@ -155,9 +155,13 @@ and also consults the `emoji-alternate-names' alist." | |||
| 155 | 155 | ||
| 156 | ;;;###autoload | 156 | ;;;###autoload |
| 157 | (defun emoji-list () | 157 | (defun emoji-list () |
| 158 | "List emojis and allow selecting and inserting one of them. | 158 | "List Emoji and allow selecting and inserting one of them. |
| 159 | If you are displaying Emoji on a text-only terminal, and some | ||
| 160 | of them look incorrect, or there are display artifacts when | ||
| 161 | scrolling the display, turn off `auto-composition-mode'. | ||
| 162 | |||
| 159 | Select the emoji by typing \\<emoji-list-mode-map>\\[emoji-list-select] on its picture. | 163 | Select the emoji by typing \\<emoji-list-mode-map>\\[emoji-list-select] on its picture. |
| 160 | The glyph will be inserted into the buffer that was current | 164 | The selected glyph will be inserted into the buffer that was current |
| 161 | when the command was invoked." | 165 | when the command was invoked." |
| 162 | (interactive) | 166 | (interactive) |
| 163 | (let ((buf (current-buffer))) | 167 | (let ((buf (current-buffer))) |
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el index fca00dd2fc7..e8930fd2d4e 100644 --- a/lisp/jsonrpc.el +++ b/lisp/jsonrpc.el | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | ;; Author: João Távora <joaotavora@gmail.com> | 5 | ;; Author: João Távora <joaotavora@gmail.com> |
| 6 | ;; Keywords: processes, languages, extensions | 6 | ;; Keywords: processes, languages, extensions |
| 7 | ;; Version: 1.0.27 | 7 | ;; Version: 1.0.28 |
| 8 | ;; Package-Requires: ((emacs "25.2")) | 8 | ;; Package-Requires: ((emacs "25.2")) |
| 9 | 9 | ||
| 10 | ;; This is a GNU ELPA :core package. Avoid functionality that is not | 10 | ;; This is a GNU ELPA :core package. Avoid functionality that is not |
diff --git a/lisp/kmacro.el b/lisp/kmacro.el index 982ae38f47d..b88c716f0b3 100644 --- a/lisp/kmacro.el +++ b/lisp/kmacro.el | |||
| @@ -219,7 +219,7 @@ macro to be executed before appending to it." | |||
| 219 | ;;;###autoload (autoload 'kmacro-keymap "kmacro" "Keymap for keyboard macro commands." t 'keymap) | 219 | ;;;###autoload (autoload 'kmacro-keymap "kmacro" "Keymap for keyboard macro commands." t 'keymap) |
| 220 | 220 | ||
| 221 | (if kmacro-call-mouse-event | 221 | (if kmacro-call-mouse-event |
| 222 | (global-set-key (vector kmacro-call-mouse-event) #'kmacro-end-call-mouse)) | 222 | (global-set-key (vector kmacro-call-mouse-event) #'kmacro-end-and-call-macro)) |
| 223 | 223 | ||
| 224 | 224 | ||
| 225 | ;;; Called from keyboard-quit | 225 | ;;; Called from keyboard-quit |
| @@ -742,8 +742,8 @@ With numeric ARG, repeat the macro that many times, | |||
| 742 | counting the definition just completed as the first repetition. | 742 | counting the definition just completed as the first repetition. |
| 743 | An argument of zero means repeat until error." | 743 | An argument of zero means repeat until error." |
| 744 | (interactive "p") | 744 | (interactive "p") |
| 745 | ;; Isearch may push the kmacro-end-macro key sequence onto the macro. | 745 | ;; Isearch may push the kmacro-end-macro key sequence onto the macro. |
| 746 | ;; Just ignore it when executing the macro. | 746 | ;; Just ignore it when executing the macro. FIXME: When?Why? |
| 747 | (unless executing-kbd-macro | 747 | (unless executing-kbd-macro |
| 748 | (end-kbd-macro arg #'kmacro-loop-setup-function) | 748 | (end-kbd-macro arg #'kmacro-loop-setup-function) |
| 749 | (when (and last-kbd-macro (= (length last-kbd-macro) 0)) | 749 | (when (and last-kbd-macro (= (length last-kbd-macro) 0)) |
| @@ -880,35 +880,25 @@ With \\[universal-argument], call second macro in macro ring." | |||
| 880 | 880 | ||
| 881 | 881 | ||
| 882 | ;;;###autoload | 882 | ;;;###autoload |
| 883 | (defun kmacro-end-and-call-macro (arg &optional no-repeat) | 883 | (defun kmacro-end-and-call-macro (arg &optional no-repeat event) |
| 884 | "Call last keyboard macro, ending it first if currently being defined. | 884 | "Call last keyboard macro, ending it first if currently being defined. |
| 885 | With numeric prefix ARG, repeat macro that many times. | 885 | With numeric prefix ARG, repeat macro that many times. |
| 886 | Zero argument means repeat until there is an error. | 886 | Zero argument means repeat until there is an error. |
| 887 | If triggered via a mouse EVENT, moves point to the position clicked | ||
| 888 | with the mouse before calling the macro. | ||
| 887 | 889 | ||
| 888 | To give a macro a name, so you can call it even after defining other | 890 | To give a macro a name, so you can call it even after defining other |
| 889 | macros, use \\[kmacro-name-last-macro]." | 891 | macros, use \\[kmacro-name-last-macro]." |
| 890 | (interactive "p") | 892 | (interactive (list current-prefix-arg nil |
| 893 | (if (consp last-input-event) last-input-event))) | ||
| 891 | (if defining-kbd-macro | 894 | (if defining-kbd-macro |
| 892 | (kmacro-end-macro nil)) | 895 | (kmacro-end-macro nil)) |
| 896 | (if event (mouse-set-point event)) | ||
| 893 | (kmacro-call-macro arg no-repeat)) | 897 | (kmacro-call-macro arg no-repeat)) |
| 894 | 898 | ||
| 895 | |||
| 896 | ;;;###autoload | 899 | ;;;###autoload |
| 897 | (defun kmacro-end-call-mouse (event) | 900 | (define-obsolete-function-alias 'kmacro-end-call-mouse |
| 898 | "Move point to the position clicked with the mouse and call last kbd macro. | 901 | #'kmacro-end-and-call-macro "31.1") |
| 899 | If kbd macro currently being defined end it before activating it." | ||
| 900 | (interactive "e") | ||
| 901 | (when defining-kbd-macro | ||
| 902 | (end-kbd-macro) | ||
| 903 | (when (and last-kbd-macro (= (length last-kbd-macro) 0)) | ||
| 904 | (setq last-kbd-macro nil) | ||
| 905 | (message "Ignore empty macro") | ||
| 906 | ;; Don't call `kmacro-ring-empty-p' to avoid its messages. | ||
| 907 | (while (and (null last-kbd-macro) kmacro-ring) | ||
| 908 | (kmacro-pop-ring1)))) | ||
| 909 | (mouse-set-point event) | ||
| 910 | (kmacro-call-macro nil t)) | ||
| 911 | |||
| 912 | 902 | ||
| 913 | ;;; Misc. commands | 903 | ;;; Misc. commands |
| 914 | 904 | ||
diff --git a/lisp/language/korea-util.el b/lisp/language/korea-util.el index da91e692719..cca702f71b0 100644 --- a/lisp/language/korea-util.el +++ b/lisp/language/korea-util.el | |||
| @@ -27,13 +27,22 @@ | |||
| 27 | 27 | ||
| 28 | ;;; Code: | 28 | ;;; Code: |
| 29 | 29 | ||
| 30 | (defgroup korean nil | ||
| 31 | "Options for writing Korean." | ||
| 32 | :version "31.1" | ||
| 33 | :group 'languages) | ||
| 34 | |||
| 30 | ;;;###autoload | 35 | ;;;###autoload |
| 31 | (defvar default-korean-keyboard | 36 | (defcustom default-korean-keyboard |
| 32 | (if (string-search "3" (or (getenv "HANGUL_KEYBOARD_TYPE") "")) | 37 | (if (string-search "3" (or (getenv "HANGUL_KEYBOARD_TYPE") "")) |
| 33 | "3" | 38 | "3" |
| 34 | "") | 39 | "") |
| 35 | "The kind of Korean keyboard for Korean (Hangul) input method. | 40 | "The kind of Korean keyboard for Korean (Hangul) input method. |
| 36 | \"\" for 2, \"3\" for 3, and \"3f\" for 3f.") | 41 | \"\" for 2, \"3\" for 3, and \"3f\" for 3f." |
| 42 | :initialize #'custom-initialize-delay | ||
| 43 | :group 'korean | ||
| 44 | :version "31.1" | ||
| 45 | :type 'string) | ||
| 37 | 46 | ||
| 38 | ;; functions useful for Korean text input | 47 | ;; functions useful for Korean text input |
| 39 | 48 | ||
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 44e8665eebd..f96cd43eca6 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el | |||
| @@ -231,8 +231,8 @@ in the tool bar will close the current window where possible." | |||
| 231 | '(menu-item "Open Project Directory" project-dired | 231 | '(menu-item "Open Project Directory" project-dired |
| 232 | :enable (menu-bar-non-minibuffer-window-p) | 232 | :enable (menu-bar-non-minibuffer-window-p) |
| 233 | :help "Read the root directory of the current project, to operate on its files")) | 233 | :help "Read the root directory of the current project, to operate on its files")) |
| 234 | (define-key menu [dired] | 234 | (define-key menu [open-directory] |
| 235 | '(menu-item "Open Directory..." dired | 235 | '(menu-item "Open Directory..." dired-from-menubar |
| 236 | :enable (menu-bar-non-minibuffer-window-p) | 236 | :enable (menu-bar-non-minibuffer-window-p) |
| 237 | :help "Read a directory, to operate on its files")) | 237 | :help "Read a directory, to operate on its files")) |
| 238 | (define-key menu [project-open-file] | 238 | (define-key menu [project-open-file] |
| @@ -2287,7 +2287,7 @@ this frame." | |||
| 2287 | (and menu-bar-close-window | 2287 | (and menu-bar-close-window |
| 2288 | (window-parent (selected-window))))) | 2288 | (window-parent (selected-window))))) |
| 2289 | 2289 | ||
| 2290 | (put 'dired 'menu-enable '(menu-bar-non-minibuffer-window-p)) | 2290 | (put 'dired-from-menubar 'menu-enable '(menu-bar-non-minibuffer-window-p)) |
| 2291 | 2291 | ||
| 2292 | ;; Permit deleting frame if it would leave a visible or iconified frame. | 2292 | ;; Permit deleting frame if it would leave a visible or iconified frame. |
| 2293 | (defun delete-frame-enabled-p () | 2293 | (defun delete-frame-enabled-p () |
| @@ -2496,8 +2496,7 @@ It must accept a buffer as its only required argument.") | |||
| 2496 | ;; Ignore the initial frame if present. It can happen if | 2496 | ;; Ignore the initial frame if present. It can happen if |
| 2497 | ;; Emacs was started as a daemon. (bug#53740) | 2497 | ;; Emacs was started as a daemon. (bug#53740) |
| 2498 | (dolist (frame (frame-list)) | 2498 | (dolist (frame (frame-list)) |
| 2499 | (unless (equal (terminal-name (frame-terminal frame)) | 2499 | (unless (frame-initial-p frame) |
| 2500 | "initial_terminal") | ||
| 2501 | (push frame frames))) | 2500 | (push frame frames))) |
| 2502 | ;; Make the menu of buffers proper. | 2501 | ;; Make the menu of buffers proper. |
| 2503 | (setq buffers-menu | 2502 | (setq buffers-menu |
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 13d0e712821..94fc63440b4 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -2807,7 +2807,7 @@ has been requested by the completion table." | |||
| 2807 | "Update displayed *Completions* buffer after change in buffer contents." | 2807 | "Update displayed *Completions* buffer after change in buffer contents." |
| 2808 | (if (not (or (minibufferp nil t) completion-in-region-mode)) | 2808 | (if (not (or (minibufferp nil t) completion-in-region-mode)) |
| 2809 | (remove-hook 'after-change-functions #'completions--after-change t) | 2809 | (remove-hook 'after-change-functions #'completions--after-change t) |
| 2810 | (when-let* ((window (get-buffer-window "*Completions*" 0))) | 2810 | (when-let* ((window (get-buffer-window "*Completions*" 'visible))) |
| 2811 | (when completion-auto-deselect | 2811 | (when completion-auto-deselect |
| 2812 | (with-selected-window window | 2812 | (with-selected-window window |
| 2813 | (completions--deselect)))) | 2813 | (completions--deselect)))) |
| @@ -3480,7 +3480,7 @@ in the minibuffer window." | |||
| 3480 | 3480 | ||
| 3481 | (defun minibuffer--completions-visible () | 3481 | (defun minibuffer--completions-visible () |
| 3482 | "Return the window where the current *Completions* buffer is visible, if any." | 3482 | "Return the window where the current *Completions* buffer is visible, if any." |
| 3483 | (when-let* ((window (get-buffer-window "*Completions*" 0))) | 3483 | (when-let* ((window (get-buffer-window "*Completions*" 'visible))) |
| 3484 | (let ((reference-buffer | 3484 | (let ((reference-buffer |
| 3485 | (buffer-local-value 'completion-reference-buffer | 3485 | (buffer-local-value 'completion-reference-buffer |
| 3486 | (window-buffer window)))) | 3486 | (window-buffer window)))) |
diff --git a/lisp/net/imap.el b/lisp/net/imap.el index bb298d11d3c..a09cd730c0f 100644 --- a/lisp/net/imap.el +++ b/lisp/net/imap.el | |||
| @@ -870,7 +870,8 @@ t if it successfully authenticates, nil otherwise." | |||
| 870 | (base64-encode-string | 870 | (base64-encode-string |
| 871 | (format "\000%s\000%s" | 871 | (format "\000%s\000%s" |
| 872 | (imap-quote-specials user) | 872 | (imap-quote-specials user) |
| 873 | (imap-quote-specials passwd))))))))) | 873 | (imap-quote-specials passwd)) |
| 874 | t))))))) | ||
| 874 | 875 | ||
| 875 | (defun imap-anonymous-p (_buffer) | 876 | (defun imap-anonymous-p (_buffer) |
| 876 | t) | 877 | t) |
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index c20b5df9b59..f6bfd9ebbea 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el | |||
| @@ -451,21 +451,13 @@ Emacs dired can't find files." | |||
| 451 | (defun tramp-adb-handle-file-name-all-completions (filename directory) | 451 | (defun tramp-adb-handle-file-name-all-completions (filename directory) |
| 452 | "Like `file-name-all-completions' for Tramp files." | 452 | "Like `file-name-all-completions' for Tramp files." |
| 453 | (tramp-skeleton-file-name-all-completions filename directory | 453 | (tramp-skeleton-file-name-all-completions filename directory |
| 454 | (all-completions | 454 | (with-parsed-tramp-file-name (expand-file-name directory) nil |
| 455 | filename | 455 | (when (tramp-adb-do-ls v "-a" localname) |
| 456 | (with-parsed-tramp-file-name (expand-file-name directory) nil | 456 | (with-current-buffer (tramp-get-buffer v) |
| 457 | (with-tramp-file-property v localname "file-name-all-completions" | 457 | (mapcar |
| 458 | (when (tramp-adb-do-ls v "-a" localname) | 458 | (lambda (l) |
| 459 | (mapcar | 459 | (and (not (string-match-p (rx bol (* blank) eol) l)) l)) |
| 460 | (lambda (f) | 460 | (split-string (buffer-string) "\n" 'omit))))))) |
| 461 | (if (file-directory-p (expand-file-name f directory)) | ||
| 462 | (file-name-as-directory f) | ||
| 463 | f)) | ||
| 464 | (with-current-buffer (tramp-get-buffer v) | ||
| 465 | (mapcar | ||
| 466 | (lambda (l) | ||
| 467 | (and (not (string-match-p (rx bol (* blank) eol) l)) l)) | ||
| 468 | (split-string (buffer-string) "\n" 'omit)))))))))) | ||
| 469 | 461 | ||
| 470 | (defun tramp-adb-handle-file-local-copy (filename) | 462 | (defun tramp-adb-handle-file-local-copy (filename) |
| 471 | "Like `file-local-copy' for Tramp files." | 463 | "Like `file-local-copy' for Tramp files." |
diff --git a/lisp/net/tramp-container.el b/lisp/net/tramp-container.el index 91d9b239a70..fec2e16a624 100644 --- a/lisp/net/tramp-container.el +++ b/lisp/net/tramp-container.el | |||
| @@ -266,7 +266,7 @@ BODY is the backend specific code." | |||
| 266 | tramp--last-hop-directory) | 266 | tramp--last-hop-directory) |
| 267 | tramp-compat-temporary-file-directory)) | 267 | tramp-compat-temporary-file-directory)) |
| 268 | (program (let ((tramp-verbose 0)) | 268 | (program (let ((tramp-verbose 0)) |
| 269 | (tramp-get-method-parameter | 269 | (tramp-expand-args |
| 270 | (make-tramp-file-name :method ,method) | 270 | (make-tramp-file-name :method ,method) |
| 271 | 'tramp-login-program))) | 271 | 'tramp-login-program))) |
| 272 | (vec (when (tramp-tramp-file-p default-directory) | 272 | (vec (when (tramp-tramp-file-p default-directory) |
| @@ -656,10 +656,9 @@ see its function help for a description of the format." | |||
| 656 | '((tramp-config-check . tramp-kubernetes--current-context-data) | 656 | '((tramp-config-check . tramp-kubernetes--current-context-data) |
| 657 | ;; This variable will be eval'ed in `tramp-expand-args'. | 657 | ;; This variable will be eval'ed in `tramp-expand-args'. |
| 658 | (tramp-extra-expand-args | 658 | (tramp-extra-expand-args |
| 659 | . (?a (tramp-kubernetes--container (car tramp-current-connection)) | 659 | ?a (tramp-kubernetes--container (car tramp-current-connection)) |
| 660 | ?h (tramp-kubernetes--pod (car tramp-current-connection)) | 660 | ?h (tramp-kubernetes--pod (car tramp-current-connection)) |
| 661 | ?x (tramp-kubernetes--context-namespace | 661 | ?x (tramp-kubernetes--context-namespace (car tramp-current-connection)))) |
| 662 | (car tramp-current-connection))))) | ||
| 663 | "Default connection-local variables for remote kubernetes connections.") | 662 | "Default connection-local variables for remote kubernetes connections.") |
| 664 | 663 | ||
| 665 | (connection-local-set-profile-variables | 664 | (connection-local-set-profile-variables |
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el index 59e4cea2edb..4400f4fecd3 100644 --- a/lisp/net/tramp-crypt.el +++ b/lisp/net/tramp-crypt.el | |||
| @@ -741,18 +741,16 @@ absolute file names." | |||
| 741 | (defun tramp-crypt-handle-file-name-all-completions (filename directory) | 741 | (defun tramp-crypt-handle-file-name-all-completions (filename directory) |
| 742 | "Like `file-name-all-completions' for Tramp files." | 742 | "Like `file-name-all-completions' for Tramp files." |
| 743 | (tramp-skeleton-file-name-all-completions filename directory | 743 | (tramp-skeleton-file-name-all-completions filename directory |
| 744 | (all-completions | 744 | (let* (completion-regexp-list |
| 745 | filename | 745 | tramp-crypt-enabled |
| 746 | (let* (completion-regexp-list | 746 | (directory (file-name-as-directory directory)) |
| 747 | tramp-crypt-enabled | 747 | (enc-dir (tramp-crypt-encrypt-file-name directory))) |
| 748 | (directory (file-name-as-directory directory)) | 748 | (mapcar |
| 749 | (enc-dir (tramp-crypt-encrypt-file-name directory))) | 749 | (lambda (x) |
| 750 | (mapcar | 750 | (substring |
| 751 | (lambda (x) | 751 | (tramp-crypt-decrypt-file-name (concat enc-dir x)) |
| 752 | (substring | 752 | (length directory))) |
| 753 | (tramp-crypt-decrypt-file-name (concat enc-dir x)) | 753 | (file-name-all-completions "" enc-dir))))) |
| 754 | (length directory))) | ||
| 755 | (file-name-all-completions "" enc-dir)))))) | ||
| 756 | 754 | ||
| 757 | (defun tramp-crypt-handle-file-readable-p (filename) | 755 | (defun tramp-crypt-handle-file-readable-p (filename) |
| 758 | "Like `file-readable-p' for Tramp files." | 756 | "Like `file-readable-p' for Tramp files." |
diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el index 7e140a0e372..601690befd6 100644 --- a/lisp/net/tramp-ftp.el +++ b/lisp/net/tramp-ftp.el | |||
| @@ -49,7 +49,7 @@ present for backward compatibility." | |||
| 49 | (let ((a1 (rassq 'ange-ftp-hook-function file-name-handler-alist)) | 49 | (let ((a1 (rassq 'ange-ftp-hook-function file-name-handler-alist)) |
| 50 | (a2 (rassq 'ange-ftp-completion-hook-function file-name-handler-alist))) | 50 | (a2 (rassq 'ange-ftp-completion-hook-function file-name-handler-alist))) |
| 51 | (setq file-name-handler-alist | 51 | (setq file-name-handler-alist |
| 52 | (delete a1 (delete a2 file-name-handler-alist))))) | 52 | (seq-difference file-name-handler-alist (list a1 a2))))) |
| 53 | 53 | ||
| 54 | (with-eval-after-load 'ange-ftp | 54 | (with-eval-after-load 'ange-ftp |
| 55 | (tramp-disable-ange-ftp)) | 55 | (tramp-disable-ange-ftp)) |
diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el index b3e59063cd8..f7abddab1a1 100644 --- a/lisp/net/tramp-fuse.el +++ b/lisp/net/tramp-fuse.el | |||
| @@ -102,10 +102,7 @@ | |||
| 102 | "Like `file-name-all-completions' for Tramp files." | 102 | "Like `file-name-all-completions' for Tramp files." |
| 103 | (tramp-skeleton-file-name-all-completions filename directory | 103 | (tramp-skeleton-file-name-all-completions filename directory |
| 104 | (tramp-fuse-remove-hidden-files | 104 | (tramp-fuse-remove-hidden-files |
| 105 | (all-completions | 105 | (file-name-all-completions "" (tramp-fuse-local-file-name directory))))) |
| 106 | filename | ||
| 107 | (file-name-all-completions | ||
| 108 | filename (tramp-fuse-local-file-name directory)))))) | ||
| 109 | 106 | ||
| 110 | ;; This function isn't used. | 107 | ;; This function isn't used. |
| 111 | (defun tramp-fuse-handle-insert-directory | 108 | (defun tramp-fuse-handle-insert-directory |
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index 0f68e4d768a..a5919e071c3 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el | |||
| @@ -1479,19 +1479,7 @@ If FILE-SYSTEM is non-nil, return file system attributes." | |||
| 1479 | (defun tramp-gvfs-handle-file-name-all-completions (filename directory) | 1479 | (defun tramp-gvfs-handle-file-name-all-completions (filename directory) |
| 1480 | "Like `file-name-all-completions' for Tramp files." | 1480 | "Like `file-name-all-completions' for Tramp files." |
| 1481 | (tramp-skeleton-file-name-all-completions filename directory | 1481 | (tramp-skeleton-file-name-all-completions filename directory |
| 1482 | (unless (string-search "/" filename) | 1482 | (mapcar #'car (tramp-gvfs-get-directory-attributes directory)))) |
| 1483 | (all-completions | ||
| 1484 | filename | ||
| 1485 | (with-parsed-tramp-file-name (expand-file-name directory) nil | ||
| 1486 | (with-tramp-file-property v localname "file-name-all-completions" | ||
| 1487 | (let (result) | ||
| 1488 | ;; Get a list of directories and files. | ||
| 1489 | (dolist (item | ||
| 1490 | (tramp-gvfs-get-directory-attributes directory) | ||
| 1491 | result) | ||
| 1492 | (if (string-equal (cdr (assoc "type" item)) "directory") | ||
| 1493 | (push (file-name-as-directory (car item)) result) | ||
| 1494 | (push (car item) result)))))))))) | ||
| 1495 | 1483 | ||
| 1496 | (defun tramp-gvfs-handle-file-notify-add-watch (file-name flags _callback) | 1484 | (defun tramp-gvfs-handle-file-notify-add-watch (file-name flags _callback) |
| 1497 | "Like `file-notify-add-watch' for Tramp files." | 1485 | "Like `file-notify-add-watch' for Tramp files." |
| @@ -1545,11 +1533,13 @@ If FILE-SYSTEM is non-nil, return file system attributes." | |||
| 1545 | (when rest-string | 1533 | (when rest-string |
| 1546 | (tramp-message proc 10 "Previous string:\n%s" rest-string)) | 1534 | (tramp-message proc 10 "Previous string:\n%s" rest-string)) |
| 1547 | (tramp-message proc 6 "%S\n%s" proc string) | 1535 | (tramp-message proc 6 "%S\n%s" proc string) |
| 1548 | (setq string (concat rest-string string) | 1536 | (setq string |
| 1549 | ;; Fix action names. | 1537 | (thread-last |
| 1550 | string (string-replace "attributes changed" "attribute-changed" string) | 1538 | (concat rest-string string) |
| 1551 | string (string-replace "changes done" "changes-done-hint" string) | 1539 | ;; Fix action names. |
| 1552 | string (string-replace "renamed to" "moved" string)) | 1540 | (string-replace "attributes changed" "attribute-changed") |
| 1541 | (string-replace "changes done" "changes-done-hint") | ||
| 1542 | (string-replace "renamed to" "moved"))) | ||
| 1553 | ;; https://bugs.launchpad.net/bugs/1742946 | 1543 | ;; https://bugs.launchpad.net/bugs/1742946 |
| 1554 | (when | 1544 | (when |
| 1555 | (string-match-p | 1545 | (string-match-p |
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index c83a7a9978d..9aec9e38f65 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el | |||
| @@ -1993,48 +1993,39 @@ ID-FORMAT valid values are `string' and `integer'." | |||
| 1993 | "Like `file-name-all-completions' for Tramp files." | 1993 | "Like `file-name-all-completions' for Tramp files." |
| 1994 | (tramp-skeleton-file-name-all-completions filename directory | 1994 | (tramp-skeleton-file-name-all-completions filename directory |
| 1995 | (with-parsed-tramp-file-name (expand-file-name directory) nil | 1995 | (with-parsed-tramp-file-name (expand-file-name directory) nil |
| 1996 | (when (and (not (string-search "/" filename)) | 1996 | (let (result) |
| 1997 | (tramp-connectable-p v)) | 1997 | ;; Get a list of directories and files, including reliably |
| 1998 | (unless (string-search "/" filename) | 1998 | ;; tagging the directories with a trailing "/". |
| 1999 | (all-completions | 1999 | ;; Because I rock. --daniel@danann.net |
| 2000 | filename | 2000 | (if (tramp-get-remote-perl v) |
| 2001 | (with-tramp-file-property v localname "file-name-all-completions" | 2001 | (tramp-maybe-send-script |
| 2002 | (let (result) | 2002 | v tramp-perl-file-name-all-completions |
| 2003 | ;; Get a list of directories and files, including | 2003 | "tramp_perl_file_name_all_completions") |
| 2004 | ;; reliably tagging the directories with a trailing "/". | 2004 | (tramp-maybe-send-script |
| 2005 | ;; Because I rock. --daniel@danann.net | 2005 | v tramp-shell-file-name-all-completions |
| 2006 | (if (tramp-get-remote-perl v) | 2006 | "tramp_shell_file_name_all_completions")) |
| 2007 | (tramp-maybe-send-script | 2007 | |
| 2008 | v tramp-perl-file-name-all-completions | 2008 | (dolist |
| 2009 | "tramp_perl_file_name_all_completions") | 2009 | (elt |
| 2010 | (tramp-maybe-send-script | 2010 | (tramp-send-command-and-read |
| 2011 | v tramp-shell-file-name-all-completions | 2011 | v (format |
| 2012 | "tramp_shell_file_name_all_completions")) | 2012 | "%s %s" |
| 2013 | 2013 | (if (tramp-get-remote-perl v) | |
| 2014 | (dolist | 2014 | "tramp_perl_file_name_all_completions" |
| 2015 | (elt | 2015 | "tramp_shell_file_name_all_completions") |
| 2016 | (tramp-send-command-and-read | 2016 | (tramp-shell-quote-argument localname)) |
| 2017 | v (format | 2017 | 'noerror) |
| 2018 | "%s %s" | 2018 | result) |
| 2019 | (if (tramp-get-remote-perl v) | 2019 | ;; Don't cache "." and "..". |
| 2020 | "tramp_perl_file_name_all_completions" | 2020 | (when (string-match-p |
| 2021 | "tramp_shell_file_name_all_completions") | 2021 | directory-files-no-dot-files-regexp |
| 2022 | (tramp-shell-quote-argument localname)) | 2022 | (file-name-nondirectory (car elt))) |
| 2023 | 'noerror) | 2023 | (tramp-set-file-property v (car elt) "file-exists-p" (nth 1 elt)) |
| 2024 | result) | 2024 | (tramp-set-file-property v (car elt) "file-readable-p" (nth 2 elt)) |
| 2025 | ;; Don't cache "." and "..". | 2025 | (tramp-set-file-property v (car elt) "file-directory-p" (nth 3 elt)) |
| 2026 | (when (string-match-p | 2026 | (tramp-set-file-property v (car elt) "file-executable-p" (nth 4 elt))) |
| 2027 | directory-files-no-dot-files-regexp | 2027 | |
| 2028 | (file-name-nondirectory (car elt))) | 2028 | (push (file-name-nondirectory (car elt)) result)))))) |
| 2029 | (tramp-set-file-property v (car elt) "file-exists-p" (nth 1 elt)) | ||
| 2030 | (tramp-set-file-property v (car elt) "file-readable-p" (nth 2 elt)) | ||
| 2031 | (tramp-set-file-property v (car elt) "file-directory-p" (nth 3 elt)) | ||
| 2032 | (tramp-set-file-property v (car elt) "file-executable-p" (nth 4 elt))) | ||
| 2033 | |||
| 2034 | (push | ||
| 2035 | (concat | ||
| 2036 | (file-name-nondirectory (car elt)) (and (nth 3 elt) "/")) | ||
| 2037 | result)))))))))) | ||
| 2038 | 2029 | ||
| 2039 | ;; cp, mv and ln | 2030 | ;; cp, mv and ln |
| 2040 | 2031 | ||
| @@ -2803,7 +2794,7 @@ The method used must be an out-of-band method." | |||
| 2803 | (append switches (split-string (tramp-sh--quoting-style-options v)) | 2794 | (append switches (split-string (tramp-sh--quoting-style-options v)) |
| 2804 | (when dired `(,dired)))) | 2795 | (when dired `(,dired)))) |
| 2805 | (unless dired | 2796 | (unless dired |
| 2806 | (setq switches (delete "-N" (delete "--dired" switches))))) | 2797 | (setq switches (seq-difference switches '("-N" "--dired"))))) |
| 2807 | (when wildcard | 2798 | (when wildcard |
| 2808 | (setq wildcard (tramp-run-real-handler | 2799 | (setq wildcard (tramp-run-real-handler |
| 2809 | #'file-name-nondirectory (list localname))) | 2800 | #'file-name-nondirectory (list localname))) |
| @@ -3917,11 +3908,13 @@ Fall back to normal file name handler if no Tramp handler exists." | |||
| 3917 | (when rest-string | 3908 | (when rest-string |
| 3918 | (tramp-message proc 10 "Previous string:\n%s" rest-string)) | 3909 | (tramp-message proc 10 "Previous string:\n%s" rest-string)) |
| 3919 | (tramp-message proc 6 "%S\n%s" proc string) | 3910 | (tramp-message proc 6 "%S\n%s" proc string) |
| 3920 | (setq string (concat rest-string string) | 3911 | (setq string |
| 3921 | ;; Fix action names. | 3912 | (thread-last |
| 3922 | string (string-replace "attributes changed" "attribute-changed" string) | 3913 | (concat rest-string string) |
| 3923 | string (string-replace "changes done" "changes-done-hint" string) | 3914 | ;; Fix action names. |
| 3924 | string (string-replace "renamed to" "moved" string)) | 3915 | (string-replace "attributes changed" "attribute-changed") |
| 3916 | (string-replace "changes done" "changes-done-hint") | ||
| 3917 | (string-replace "renamed to" "moved"))) | ||
| 3925 | 3918 | ||
| 3926 | (catch 'doesnt-work | 3919 | (catch 'doesnt-work |
| 3927 | ;; https://bugs.launchpad.net/bugs/1742946 | 3920 | ;; https://bugs.launchpad.net/bugs/1742946 |
| @@ -5044,7 +5037,7 @@ Goes through the list `tramp-inline-compress-commands'." | |||
| 5044 | ;; Use plink options. | 5037 | ;; Use plink options. |
| 5045 | ((string-match-p | 5038 | ((string-match-p |
| 5046 | (rx "plink" (? ".exe") eol) | 5039 | (rx "plink" (? ".exe") eol) |
| 5047 | (tramp-get-method-parameter vec 'tramp-login-program)) | 5040 | (tramp-expand-args vec 'tramp-login-program)) |
| 5048 | (concat | 5041 | (concat |
| 5049 | (if (eq tramp-use-connection-share 'suppress) | 5042 | (if (eq tramp-use-connection-share 'suppress) |
| 5050 | "-noshare" "-share") | 5043 | "-noshare" "-share") |
| @@ -5405,7 +5398,7 @@ connection if a previous connection has died for some reason." | |||
| 5405 | hop 'tramp-connection-timeout | 5398 | hop 'tramp-connection-timeout |
| 5406 | tramp-connection-timeout)) | 5399 | tramp-connection-timeout)) |
| 5407 | (command | 5400 | (command |
| 5408 | (tramp-get-method-parameter | 5401 | (tramp-expand-args |
| 5409 | hop 'tramp-login-program)) | 5402 | hop 'tramp-login-program)) |
| 5410 | ;; We don't create the temporary file. In | 5403 | ;; We don't create the temporary file. In |
| 5411 | ;; fact, it is just a prefix for the | 5404 | ;; fact, it is just a prefix for the |
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 554aa354c00..8eec0e1bd08 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el | |||
| @@ -603,12 +603,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." | |||
| 603 | (copy-directory filename newname keep-date 'parents 'copy-contents) | 603 | (copy-directory filename newname keep-date 'parents 'copy-contents) |
| 604 | 604 | ||
| 605 | (tramp-barf-if-file-missing v filename | 605 | (tramp-barf-if-file-missing v filename |
| 606 | ;; `file-local-copy' returns a file name also for a local | 606 | ;; Suppress `jka-compr-handler'. |
| 607 | ;; file with `jka-compr-handler', so we cannot trust its | 607 | (if-let* ((jka-compr-inhibit t) |
| 608 | ;; result as indication for a remote file name. | 608 | (tmpfile (file-local-copy filename))) |
| 609 | (if-let* ((tmpfile | ||
| 610 | (and (tramp-tramp-file-p filename) | ||
| 611 | (file-local-copy filename)))) | ||
| 612 | ;; Remote filename. | 609 | ;; Remote filename. |
| 613 | (condition-case err | 610 | (condition-case err |
| 614 | (rename-file tmpfile newname ok-if-already-exists) | 611 | (rename-file tmpfile newname ok-if-already-exists) |
| @@ -1068,18 +1065,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." | |||
| 1068 | (defun tramp-smb-handle-file-name-all-completions (filename directory) | 1065 | (defun tramp-smb-handle-file-name-all-completions (filename directory) |
| 1069 | "Like `file-name-all-completions' for Tramp files." | 1066 | "Like `file-name-all-completions' for Tramp files." |
| 1070 | (tramp-skeleton-file-name-all-completions filename directory | 1067 | (tramp-skeleton-file-name-all-completions filename directory |
| 1071 | (all-completions | 1068 | (mapcar #'car (tramp-smb-get-file-entries directory)))) |
| 1072 | filename | ||
| 1073 | (when (file-directory-p directory) | ||
| 1074 | (with-parsed-tramp-file-name (expand-file-name directory) nil | ||
| 1075 | (with-tramp-file-property v localname "file-name-all-completions" | ||
| 1076 | (mapcar | ||
| 1077 | (lambda (x) | ||
| 1078 | (list | ||
| 1079 | (if (string-search "d" (nth 1 x)) | ||
| 1080 | (file-name-as-directory (nth 0 x)) | ||
| 1081 | (nth 0 x)))) | ||
| 1082 | (tramp-smb-get-file-entries directory)))))))) | ||
| 1083 | 1069 | ||
| 1084 | (defun tramp-smb-handle-file-system-info (filename) | 1070 | (defun tramp-smb-handle-file-system-info (filename) |
| 1085 | "Like `file-system-info' for Tramp files." | 1071 | "Like `file-system-info' for Tramp files." |
| @@ -1752,9 +1738,6 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)." | |||
| 1752 | (unless share | 1738 | (unless share |
| 1753 | (tramp-set-connection-property v "share-cache" res))) | 1739 | (tramp-set-connection-property v "share-cache" res))) |
| 1754 | 1740 | ||
| 1755 | ;; Add directory itself. | ||
| 1756 | (push '("" "drwxrwxrwx" 0 (0 0)) res) | ||
| 1757 | |||
| 1758 | ;; Return entries. | 1741 | ;; Return entries. |
| 1759 | (delq nil res))))) | 1742 | (delq nil res))))) |
| 1760 | 1743 | ||
| @@ -2295,9 +2278,6 @@ SHARE will be passed to the call of `tramp-smb-get-localname'." | |||
| 2295 | 2278 | ||
| 2296 | ;; * Return more comprehensive file permission string. | 2279 | ;; * Return more comprehensive file permission string. |
| 2297 | ;; | 2280 | ;; |
| 2298 | ;; * Try to remove the inclusion of dummy "" directory. Seems to be at | ||
| 2299 | ;; several places, especially in `tramp-smb-handle-insert-directory'. | ||
| 2300 | ;; | ||
| 2301 | ;; * Keep a separate connection process per share. | 2281 | ;; * Keep a separate connection process per share. |
| 2302 | ;; | 2282 | ;; |
| 2303 | ;; * Keep a permanent connection process for `process-file'. | 2283 | ;; * Keep a permanent connection process for `process-file'. |
diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el index 2cb5b5b1ed1..f4073158683 100644 --- a/lisp/net/tramp-sshfs.el +++ b/lisp/net/tramp-sshfs.el | |||
| @@ -269,7 +269,7 @@ arguments to pass to the OPERATION." | |||
| 269 | (setq ret | 269 | (setq ret |
| 270 | (apply | 270 | (apply |
| 271 | #'tramp-call-process | 271 | #'tramp-call-process |
| 272 | v (tramp-get-method-parameter v 'tramp-login-program) | 272 | v (tramp-expand-args v 'tramp-login-program) |
| 273 | nil outbuf display | 273 | nil outbuf display |
| 274 | (tramp-expand-args | 274 | (tramp-expand-args |
| 275 | v 'tramp-login-args nil | 275 | v 'tramp-login-args nil |
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el index 9511c899b2b..8bf6a9f50b0 100644 --- a/lisp/net/tramp-sudoedit.el +++ b/lisp/net/tramp-sudoedit.el | |||
| @@ -498,24 +498,16 @@ the result will be a local, non-Tramp, file name." | |||
| 498 | (defun tramp-sudoedit-handle-file-name-all-completions (filename directory) | 498 | (defun tramp-sudoedit-handle-file-name-all-completions (filename directory) |
| 499 | "Like `file-name-all-completions' for Tramp files." | 499 | "Like `file-name-all-completions' for Tramp files." |
| 500 | (tramp-skeleton-file-name-all-completions filename directory | 500 | (tramp-skeleton-file-name-all-completions filename directory |
| 501 | (all-completions | 501 | (with-parsed-tramp-file-name (expand-file-name directory) nil |
| 502 | filename | 502 | (tramp-sudoedit-send-command |
| 503 | (with-parsed-tramp-file-name (expand-file-name directory) nil | 503 | v "ls" "-a1" "--quoting-style=literal" "--show-control-chars" |
| 504 | (with-tramp-file-property v localname "file-name-all-completions" | 504 | (if (tramp-string-empty-or-nil-p localname) |
| 505 | (tramp-sudoedit-send-command | 505 | "" (file-name-unquote localname))) |
| 506 | v "ls" "-a1" "--quoting-style=literal" "--show-control-chars" | 506 | (mapcar |
| 507 | (if (tramp-string-empty-or-nil-p localname) | 507 | (lambda (l) (and (not (string-match-p (rx bol (* blank) eol) l)) l)) |
| 508 | "" (file-name-unquote localname))) | 508 | (split-string |
| 509 | (mapcar | 509 | (tramp-get-buffer-string (tramp-get-connection-buffer v)) |
| 510 | (lambda (f) | 510 | "\n" 'omit))))) |
| 511 | (if (ignore-errors (file-directory-p (expand-file-name f directory))) | ||
| 512 | (file-name-as-directory f) | ||
| 513 | f)) | ||
| 514 | (mapcar | ||
| 515 | (lambda (l) (and (not (string-match-p (rx bol (* blank) eol) l)) l)) | ||
| 516 | (split-string | ||
| 517 | (tramp-get-buffer-string (tramp-get-connection-buffer v)) | ||
| 518 | "\n" 'omit)))))))) | ||
| 519 | 511 | ||
| 520 | (defun tramp-sudoedit-handle-file-readable-p (filename) | 512 | (defun tramp-sudoedit-handle-file-readable-p (filename) |
| 521 | "Like `file-readable-p' for Tramp files." | 513 | "Like `file-readable-p' for Tramp files." |
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 5441a26d7a0..03089dffb55 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el | |||
| @@ -2002,12 +2002,11 @@ expected to be a string, which will be used." | |||
| 2002 | "Construct a Tramp hop name from VEC." | 2002 | "Construct a Tramp hop name from VEC." |
| 2003 | (concat | 2003 | (concat |
| 2004 | (tramp-file-name-hop vec) | 2004 | (tramp-file-name-hop vec) |
| 2005 | (replace-regexp-in-string | 2005 | (thread-last |
| 2006 | tramp-prefix-regexp "" | 2006 | (replace-regexp-in-string |
| 2007 | (replace-regexp-in-string | 2007 | (rx (regexp tramp-postfix-host-regexp) eos) tramp-postfix-hop-format |
| 2008 | (rx (regexp tramp-postfix-host-regexp) eos) | 2008 | (tramp-make-tramp-file-name (tramp-file-name-unify vec))) |
| 2009 | tramp-postfix-hop-format | 2009 | (replace-regexp-in-string tramp-prefix-regexp "")))) |
| 2010 | (tramp-make-tramp-file-name (tramp-file-name-unify vec)))))) | ||
| 2011 | 2010 | ||
| 2012 | (defun tramp-completion-make-tramp-file-name (method user host localname) | 2011 | (defun tramp-completion-make-tramp-file-name (method user host localname) |
| 2013 | "Construct a Tramp file name from METHOD, USER, HOST and LOCALNAME. | 2012 | "Construct a Tramp file name from METHOD, USER, HOST and LOCALNAME. |
| @@ -2957,7 +2956,7 @@ not in completion mode." | |||
| 2957 | (or (and (cond | 2956 | (or (and (cond |
| 2958 | ;; Completion styles like `flex' and `substring' check for | 2957 | ;; Completion styles like `flex' and `substring' check for |
| 2959 | ;; the file name "/". This does exist. | 2958 | ;; the file name "/". This does exist. |
| 2960 | ((string-equal filename "/")) | 2959 | ((string-equal filename tramp-prefix-format)) |
| 2961 | ;; Is it a valid method? | 2960 | ;; Is it a valid method? |
| 2962 | ((and (not (string-empty-p tramp-postfix-method-format)) | 2961 | ((and (not (string-empty-p tramp-postfix-method-format)) |
| 2963 | (string-match | 2962 | (string-match |
| @@ -3001,30 +3000,59 @@ not in completion mode." | |||
| 3001 | 3000 | ||
| 3002 | (tramp-run-real-handler #'file-exists-p (list filename)))) | 3001 | (tramp-run-real-handler #'file-exists-p (list filename)))) |
| 3003 | 3002 | ||
| 3003 | (defvar tramp-fnac-add-trailing-slash t | ||
| 3004 | "Whether `file-name-all-completions' shall add a trailing slash. | ||
| 3005 | This is not desired, if that function is used in `directory-files', or | ||
| 3006 | in `tramp-completion-handle-file-name-all-completions'.") | ||
| 3007 | |||
| 3004 | (defmacro tramp-skeleton-file-name-all-completions | 3008 | (defmacro tramp-skeleton-file-name-all-completions |
| 3005 | (filename directory &rest body) | 3009 | (filename directory &rest body) |
| 3006 | "Skeleton for `tramp-*-handle-filename-all-completions'. | 3010 | "Skeleton for `tramp-*-handle-filename-all-completions'. |
| 3007 | BODY is the backend specific code." | 3011 | BODY is the backend specific code." |
| 3008 | (declare (indent 2) (debug t)) | 3012 | (declare (indent 2) (debug t)) |
| 3009 | `(ignore-error file-missing | 3013 | `(ignore-error file-missing |
| 3010 | (seq-uniq (delq nil (delete "" | 3014 | (all-completions |
| 3011 | (let* ((case-fold-search read-file-name-completion-ignore-case) | 3015 | ,filename |
| 3012 | (result (progn ,@body))) | 3016 | (when (file-directory-p ,directory) |
| 3013 | ;; Some storage systems do not return "." and "..". | 3017 | (seq-uniq (delq nil |
| 3014 | (when (tramp-tramp-file-p ,directory) | 3018 | (let* ((case-fold-search read-file-name-completion-ignore-case) |
| 3015 | (dolist (elt '(".." ".")) | 3019 | (result |
| 3016 | (when (string-prefix-p ,filename elt) | 3020 | (if (tramp-tramp-file-p ,directory) |
| 3017 | (setq result (cons (concat elt "/") result))))) | 3021 | (with-parsed-tramp-file-name |
| 3018 | (if (consp completion-regexp-list) | 3022 | (expand-file-name ,directory) nil |
| 3019 | ;; Discriminate over `completion-regexp-list'. | 3023 | (when (and (not (string-search "/" ,filename)) |
| 3020 | (mapcar | 3024 | (tramp-connectable-p v)) |
| 3021 | (lambda (x) | 3025 | (with-tramp-file-property |
| 3022 | (when (stringp x) | 3026 | v localname |
| 3023 | (catch 'match | 3027 | (format |
| 3024 | (dolist (elt completion-regexp-list x) | 3028 | "file-name-all-completions-%s" |
| 3025 | (unless (string-match-p elt x) (throw 'match nil)))))) | 3029 | tramp-fnac-add-trailing-slash) |
| 3026 | result) | 3030 | ;; Mark symlinked directories. Other |
| 3027 | result))))))) | 3031 | ;; directories are already marked. |
| 3032 | (mapcar | ||
| 3033 | (lambda (x) | ||
| 3034 | (let ((f (file-name-concat ,directory x))) | ||
| 3035 | (if (and tramp-fnac-add-trailing-slash | ||
| 3036 | (not (string-suffix-p "/" x)) | ||
| 3037 | (file-directory-p | ||
| 3038 | (if (file-symlink-p f) | ||
| 3039 | (file-truename f) f))) | ||
| 3040 | (concat x "/") x))) | ||
| 3041 | ;; Some storage systems do not return "." and "..". | ||
| 3042 | (seq-union | ||
| 3043 | (seq-difference (progn ,@body) '("." "..")) | ||
| 3044 | '("./" "../")))))) | ||
| 3045 | ,@body))) | ||
| 3046 | ;; Discriminate over `completion-regexp-list'. | ||
| 3047 | (if (consp completion-regexp-list) | ||
| 3048 | (mapcar | ||
| 3049 | (lambda (x) | ||
| 3050 | (when (stringp x) | ||
| 3051 | (catch 'match | ||
| 3052 | (dolist (elt completion-regexp-list x) | ||
| 3053 | (unless (string-match-p elt x) (throw 'match nil)))))) | ||
| 3054 | result) | ||
| 3055 | result)))))))) | ||
| 3028 | 3056 | ||
| 3029 | (defvar tramp--last-hop-directory nil | 3057 | (defvar tramp--last-hop-directory nil |
| 3030 | "Tracks the directory from which to run login programs.") | 3058 | "Tracks the directory from which to run login programs.") |
| @@ -3035,72 +3063,74 @@ BODY is the backend specific code." | |||
| 3035 | ;; completions. | 3063 | ;; completions. |
| 3036 | (defun tramp-completion-handle-file-name-all-completions (filename directory) | 3064 | (defun tramp-completion-handle-file-name-all-completions (filename directory) |
| 3037 | "Like `file-name-all-completions' for partial Tramp files." | 3065 | "Like `file-name-all-completions' for partial Tramp files." |
| 3038 | (tramp-skeleton-file-name-all-completions filename directory | 3066 | (let (tramp-fnac-add-trailing-slash) |
| 3039 | (let ((fullname | 3067 | (tramp-skeleton-file-name-all-completions filename directory |
| 3040 | (tramp-drop-volume-letter (expand-file-name filename directory))) | 3068 | (let ((fullname |
| 3041 | (directory (tramp-drop-volume-letter directory)) | 3069 | (tramp-drop-volume-letter (expand-file-name filename directory))) |
| 3042 | tramp--last-hop-directory hop result result1) | 3070 | (directory (tramp-drop-volume-letter directory)) |
| 3071 | tramp--last-hop-directory hop result result1) | ||
| 3072 | |||
| 3073 | ;; Suppress hop from completion. | ||
| 3074 | (when (string-match | ||
| 3075 | (rx | ||
| 3076 | (regexp tramp-prefix-regexp) | ||
| 3077 | (group (+ (regexp tramp-remote-file-name-spec-regexp) | ||
| 3078 | (regexp tramp-postfix-hop-regexp)))) | ||
| 3079 | fullname) | ||
| 3080 | (setq hop (match-string 1 fullname) | ||
| 3081 | fullname (replace-match "" nil nil fullname 1) | ||
| 3082 | tramp--last-hop-directory | ||
| 3083 | (tramp-make-tramp-file-name (tramp-dissect-hop-name hop)))) | ||
| 3084 | |||
| 3085 | (let (tramp-default-user tramp-default-user-alist | ||
| 3086 | tramp-default-host tramp-default-host-alist) | ||
| 3087 | |||
| 3088 | ;; Possible completion structures. | ||
| 3089 | (dolist (elt (tramp-completion-dissect-file-name fullname)) | ||
| 3090 | (let* ((method (tramp-file-name-method elt)) | ||
| 3091 | (user (tramp-file-name-user elt)) | ||
| 3092 | (host (tramp-file-name-host elt)) | ||
| 3093 | (localname (tramp-file-name-localname elt)) | ||
| 3094 | (m (tramp-find-method method user host)) | ||
| 3095 | all-user-hosts) | ||
| 3096 | |||
| 3097 | (unless localname ;; Nothing to complete. | ||
| 3098 | (if (or user host) | ||
| 3099 | ;; Method dependent user / host combinations. | ||
| 3100 | (progn | ||
| 3101 | (mapc | ||
| 3102 | (lambda (x) | ||
| 3103 | (setq all-user-hosts | ||
| 3104 | (append all-user-hosts | ||
| 3105 | (funcall (nth 0 x) (nth 1 x))))) | ||
| 3106 | (tramp-get-completion-function m)) | ||
| 3043 | 3107 | ||
| 3044 | ;; Suppress hop from completion. | 3108 | (setq result |
| 3045 | (when (string-match | 3109 | (append result |
| 3046 | (rx | 3110 | (mapcar |
| 3047 | (regexp tramp-prefix-regexp) | 3111 | (lambda (x) |
| 3048 | (group (+ (regexp tramp-remote-file-name-spec-regexp) | 3112 | (tramp-get-completion-user-host |
| 3049 | (regexp tramp-postfix-hop-regexp)))) | 3113 | method user host (nth 0 x) (nth 1 x))) |
| 3050 | fullname) | 3114 | all-user-hosts)))) |
| 3051 | (setq hop (match-string 1 fullname) | 3115 | |
| 3052 | fullname (replace-match "" nil nil fullname 1) | 3116 | ;; Possible methods. |
| 3053 | tramp--last-hop-directory | 3117 | (setq result |
| 3054 | (tramp-make-tramp-file-name (tramp-dissect-hop-name hop)))) | 3118 | (append result (tramp-get-completion-methods m hop))))))) |
| 3055 | 3119 | ||
| 3056 | (let (tramp-default-user tramp-default-user-alist | 3120 | ;; Add hop. |
| 3057 | tramp-default-host tramp-default-host-alist) | 3121 | (dolist (elt result) |
| 3058 | 3122 | (when elt | |
| 3059 | ;; Possible completion structures. | 3123 | (setq elt (replace-regexp-in-string |
| 3060 | (dolist (elt (tramp-completion-dissect-file-name fullname)) | 3124 | tramp-prefix-regexp |
| 3061 | (let* ((method (tramp-file-name-method elt)) | 3125 | (concat tramp-prefix-format hop) elt)) |
| 3062 | (user (tramp-file-name-user elt)) | 3126 | (push (substring elt (length directory)) result1))) |
| 3063 | (host (tramp-file-name-host elt)) | 3127 | |
| 3064 | (localname (tramp-file-name-localname elt)) | 3128 | ;; Complete local parts. |
| 3065 | (m (tramp-find-method method user host)) | 3129 | (append |
| 3066 | all-user-hosts) | 3130 | result1 |
| 3067 | 3131 | (ignore-errors | |
| 3068 | (unless localname ;; Nothing to complete. | 3132 | (tramp-run-real-handler |
| 3069 | (if (or user host) | 3133 | #'file-name-all-completions (list filename directory))))))))) |
| 3070 | ;; Method dependent user / host combinations. | ||
| 3071 | (progn | ||
| 3072 | (mapc | ||
| 3073 | (lambda (x) | ||
| 3074 | (setq all-user-hosts | ||
| 3075 | (append all-user-hosts | ||
| 3076 | (funcall (nth 0 x) (nth 1 x))))) | ||
| 3077 | (tramp-get-completion-function m)) | ||
| 3078 | |||
| 3079 | (setq result | ||
| 3080 | (append result | ||
| 3081 | (mapcar | ||
| 3082 | (lambda (x) | ||
| 3083 | (tramp-get-completion-user-host | ||
| 3084 | method user host (nth 0 x) (nth 1 x))) | ||
| 3085 | all-user-hosts)))) | ||
| 3086 | |||
| 3087 | ;; Possible methods. | ||
| 3088 | (setq result | ||
| 3089 | (append result (tramp-get-completion-methods m hop))))))) | ||
| 3090 | |||
| 3091 | ;; Add hop. | ||
| 3092 | (dolist (elt result) | ||
| 3093 | (when elt | ||
| 3094 | (setq elt (replace-regexp-in-string | ||
| 3095 | tramp-prefix-regexp (concat tramp-prefix-format hop) elt)) | ||
| 3096 | (push (substring elt (length directory)) result1))) | ||
| 3097 | |||
| 3098 | ;; Complete local parts. | ||
| 3099 | (append | ||
| 3100 | result1 | ||
| 3101 | (ignore-errors | ||
| 3102 | (tramp-run-real-handler | ||
| 3103 | #'file-name-all-completions (list filename directory)))))))) | ||
| 3104 | 3134 | ||
| 3105 | ;; Method, host name and user name completion for a file. | 3135 | ;; Method, host name and user name completion for a file. |
| 3106 | (defun tramp-completion-handle-file-name-completion | 3136 | (defun tramp-completion-handle-file-name-completion |
| @@ -3659,9 +3689,10 @@ BODY is the backend specific code." | |||
| 3659 | (signal 'error nil) | 3689 | (signal 'error nil) |
| 3660 | (setf ,directory | 3690 | (setf ,directory |
| 3661 | (file-name-as-directory (expand-file-name ,directory))) | 3691 | (file-name-as-directory (expand-file-name ,directory))) |
| 3662 | (let ((temp | 3692 | (let* (tramp-fnac-add-trailing-slash |
| 3663 | (with-tramp-file-property v localname "directory-files" ,@body)) | 3693 | (temp |
| 3664 | result item) | 3694 | (with-tramp-file-property v localname "directory-files" ,@body)) |
| 3695 | result item) | ||
| 3665 | (while temp | 3696 | (while temp |
| 3666 | (setq item (directory-file-name (pop temp))) | 3697 | (setq item (directory-file-name (pop temp))) |
| 3667 | (when (or (null ,match) (string-match-p ,match item)) | 3698 | (when (or (null ,match) (string-match-p ,match item)) |
| @@ -4496,8 +4527,8 @@ Let-bind it when necessary.") | |||
| 4496 | ;; "." and ".." are never interesting as completions, and are | 4527 | ;; "." and ".." are never interesting as completions, and are |
| 4497 | ;; actually in the way in a directory with only one file. See | 4528 | ;; actually in the way in a directory with only one file. See |
| 4498 | ;; file_name_completion() in dired.c. | 4529 | ;; file_name_completion() in dired.c. |
| 4499 | (when (and (consp fnac) (length= (delete "./" (delete "../" fnac)) 1)) | 4530 | (when (and (consp fnac) (length= (seq-difference fnac '("./" "../")) 1)) |
| 4500 | (setq fnac (delete "./" (delete "../" fnac)))) | 4531 | (setq fnac (seq-difference fnac '("./" "../")))) |
| 4501 | (or | 4532 | (or |
| 4502 | (try-completion | 4533 | (try-completion |
| 4503 | filename fnac | 4534 | filename fnac |
| @@ -5294,7 +5325,7 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.") | |||
| 5294 | (defvar tramp-extra-expand-args nil | 5325 | (defvar tramp-extra-expand-args nil |
| 5295 | "Method specific arguments.") | 5326 | "Method specific arguments.") |
| 5296 | 5327 | ||
| 5297 | (defun tramp-expand-args (vec parameter default &rest spec-list) | 5328 | (defun tramp-expand-args (vec parameter &optional default &rest spec-list) |
| 5298 | "Expand login arguments as given by PARAMETER in `tramp-methods'. | 5329 | "Expand login arguments as given by PARAMETER in `tramp-methods'. |
| 5299 | PARAMETER is a symbol like `tramp-login-args', denoting a list of | 5330 | PARAMETER is a symbol like `tramp-login-args', denoting a list of |
| 5300 | list of strings from `tramp-methods', containing %-sequences for | 5331 | list of strings from `tramp-methods', containing %-sequences for |
| @@ -5317,12 +5348,15 @@ a connection-local variable." | |||
| 5317 | (setq spec-list (cddr spec-list))) | 5348 | (setq spec-list (cddr spec-list))) |
| 5318 | (setq spec (apply #'format-spec-make extra-spec-list)) | 5349 | (setq spec (apply #'format-spec-make extra-spec-list)) |
| 5319 | ;; Expand format spec. | 5350 | ;; Expand format spec. |
| 5320 | (flatten-tree | 5351 | (cond |
| 5321 | (mapcar | 5352 | ((consp args) |
| 5322 | (lambda (x) | 5353 | (flatten-tree |
| 5323 | (setq x (mapcar (lambda (y) (tramp-format-spec y spec)) x)) | 5354 | (mapcar |
| 5324 | (unless (member "" x) x)) | 5355 | (lambda (x) |
| 5325 | args)))) | 5356 | (setq x (mapcar (lambda (y) (tramp-format-spec y spec)) x)) |
| 5357 | (unless (member "" x) x)) | ||
| 5358 | args))) | ||
| 5359 | (args (tramp-format-spec args spec))))) | ||
| 5326 | 5360 | ||
| 5327 | (defun tramp-post-process-creation (proc vec) | 5361 | (defun tramp-post-process-creation (proc vec) |
| 5328 | "Apply actions after creation of process PROC." | 5362 | "Apply actions after creation of process PROC." |
| @@ -5444,8 +5478,7 @@ processes." | |||
| 5444 | (tramp-get-method-parameter v 'tramp-direct-async) | 5478 | (tramp-get-method-parameter v 'tramp-direct-async) |
| 5445 | `(,(string-join command " "))) | 5479 | `(,(string-join command " "))) |
| 5446 | command)) | 5480 | command)) |
| 5447 | (login-program | 5481 | (login-program (tramp-expand-args v 'tramp-login-program)) |
| 5448 | (tramp-get-method-parameter v 'tramp-login-program)) | ||
| 5449 | ;; We don't create the temporary file. In fact, it is just | 5482 | ;; We don't create the temporary file. In fact, it is just |
| 5450 | ;; a prefix for the ControlPath option of ssh; the real | 5483 | ;; a prefix for the ControlPath option of ssh; the real |
| 5451 | ;; temporary file has another name, and it is created and | 5484 | ;; temporary file has another name, and it is created and |
| @@ -5487,7 +5520,7 @@ processes." | |||
| 5487 | v 'tramp-login-args nil | 5520 | v 'tramp-login-args nil |
| 5488 | ?h (or host "") ?u (or user "") ?p (or port "") | 5521 | ?h (or host "") ?u (or user "") ?p (or port "") |
| 5489 | ?c (format-spec (or options "") (format-spec-make ?t tmpfile)) | 5522 | ?c (format-spec (or options "") (format-spec-make ?t tmpfile)) |
| 5490 | ?d (or device "") ?a (or pta "") ?l "")))) | 5523 | ?w "" ?d (or device "") ?a (or pta "") ?l "")))) |
| 5491 | ;; Suppress `internal-default-process-sentinel', which is set | 5524 | ;; Suppress `internal-default-process-sentinel', which is set |
| 5492 | ;; when :sentinel is nil. (Bug#71049) | 5525 | ;; when :sentinel is nil. (Bug#71049) |
| 5493 | p (make-process | 5526 | p (make-process |
diff --git a/lisp/obsolete/linum.el b/lisp/obsolete/linum.el index 5a0a67ebff0..9b0efaf223a 100644 --- a/lisp/obsolete/linum.el +++ b/lisp/obsolete/linum.el | |||
| @@ -129,6 +129,7 @@ Linum mode is a buffer-local minor mode." | |||
| 129 | ;; Note that nowadays, this actually doesn't show line | 129 | ;; Note that nowadays, this actually doesn't show line |
| 130 | ;; numbers in client frames at all, because we visit the | 130 | ;; numbers in client frames at all, because we visit the |
| 131 | ;; file before creating the client frame. See bug#35726. | 131 | ;; file before creating the client frame. See bug#35726. |
| 132 | ;; Use `frame-initial-p'? | ||
| 132 | (and (daemonp) (eq (selected-frame) terminal-frame))) | 133 | (and (daemonp) (eq (selected-frame) terminal-frame))) |
| 133 | (linum-mode 1))) | 134 | (linum-mode 1))) |
| 134 | 135 | ||
diff --git a/lisp/outline.el b/lisp/outline.el index 4fb953b0f7c..ea66ee5c8e9 100644 --- a/lisp/outline.el +++ b/lisp/outline.el | |||
| @@ -326,10 +326,10 @@ non-nil and point is located on the heading line.") | |||
| 326 | (defcustom outline-minor-mode-use-buttons nil | 326 | (defcustom outline-minor-mode-use-buttons nil |
| 327 | "Whether to display clickable buttons on the headings. | 327 | "Whether to display clickable buttons on the headings. |
| 328 | These buttons can be used to hide and show the body under the heading. | 328 | These buttons can be used to hide and show the body under the heading. |
| 329 | When the value is `insert', additional placeholders for buttons are | 329 | When the value is \\+`insert', additional placeholders for buttons are |
| 330 | inserted to the buffer, so buttons are not only clickable, | 330 | inserted to the buffer, so buttons are not only clickable, |
| 331 | but also typing `RET' on them can hide and show the body. | 331 | but also typing `RET' on them can hide and show the body. |
| 332 | Using the value `insert' is not recommended in editable | 332 | Using the value \\+`insert' is not recommended in editable |
| 333 | buffers because it modifies them. | 333 | buffers because it modifies them. |
| 334 | When the value is `in-margins', then clickable buttons are | 334 | When the value is `in-margins', then clickable buttons are |
| 335 | displayed in the margins before the headings. | 335 | displayed in the margins before the headings. |
| @@ -513,7 +513,7 @@ font-lock faces defined by the major mode. Thus, a non-nil value will | |||
| 513 | work well only when there's no such conflict. | 513 | work well only when there's no such conflict. |
| 514 | If the value is t, use outline faces only if there are no major mode's | 514 | If the value is t, use outline faces only if there are no major mode's |
| 515 | font-lock faces on headings. When `override', completely overwrite major | 515 | font-lock faces on headings. When `override', completely overwrite major |
| 516 | mode's font-lock faces with outline faces. When `append', try to append | 516 | mode's font-lock faces with outline faces. When \\+`append', try to append |
| 517 | outline font-lock faces to those of major mode." | 517 | outline font-lock faces to those of major mode." |
| 518 | :type '(choice (const :tag "Do not use outline font-lock highlighting" nil) | 518 | :type '(choice (const :tag "Do not use outline font-lock highlighting" nil) |
| 519 | (const :tag "Overwrite major mode font-lock faces" override) | 519 | (const :tag "Overwrite major mode font-lock faces" override) |
diff --git a/lisp/paren.el b/lisp/paren.el index 1ab3f9a32cf..10c72dadc79 100644 --- a/lisp/paren.el +++ b/lisp/paren.el | |||
| @@ -434,9 +434,10 @@ It is the default value of `show-paren-data-function'." | |||
| 434 | (overlay-put show-paren--context-overlay 'priority | 434 | (overlay-put show-paren--context-overlay 'priority |
| 435 | show-paren-priority) | 435 | show-paren-priority) |
| 436 | (overlay-put show-paren--context-overlay | 436 | (overlay-put show-paren--context-overlay |
| 437 | 'face `(:box | 437 | 'face `( :inherit default |
| 438 | ( :line-width (1 . -1) | 438 | :box |
| 439 | :color ,(face-attribute 'shadow :foreground)))) | 439 | ( :line-width (1 . -1) |
| 440 | :color ,(face-attribute 'shadow :foreground)))) | ||
| 440 | (add-hook 'post-command-hook #'show-paren--delete-context-overlay | 441 | (add-hook 'post-command-hook #'show-paren--delete-context-overlay |
| 441 | nil 'local)) | 442 | nil 'local)) |
| 442 | 443 | ||
diff --git a/lisp/printing.el b/lisp/printing.el index b6be982f5cb..3f31472d176 100644 --- a/lisp/printing.el +++ b/lisp/printing.el | |||
| @@ -1431,7 +1431,7 @@ COMMAND Name of the program for printing a text file. On MS-DOS and | |||
| 1431 | specially, using NAME as the destination for output; any other | 1431 | specially, using NAME as the destination for output; any other |
| 1432 | program is treated like `lpr' except that an explicit filename | 1432 | program is treated like `lpr' except that an explicit filename |
| 1433 | is given as the last argument. | 1433 | is given as the last argument. |
| 1434 | If COMMAND is nil, it's used the default printing program: | 1434 | If COMMAND is nil, it stands for the default printing program: |
| 1435 | `print' for Windows system, `lp' for lp system and `lpr' for | 1435 | `print' for Windows system, `lp' for lp system and `lpr' for |
| 1436 | all other systems. See also `pr-path-alist'. | 1436 | all other systems. See also `pr-path-alist'. |
| 1437 | Examples: | 1437 | Examples: |
| @@ -1506,7 +1506,10 @@ Useful links: | |||
| 1506 | :type '(repeat | 1506 | :type '(repeat |
| 1507 | (list :tag "Text Printer" | 1507 | (list :tag "Text Printer" |
| 1508 | (symbol :tag "Printer Symbol Name") | 1508 | (symbol :tag "Printer Symbol Name") |
| 1509 | (string :tag "Printer Command") | 1509 | (choice :menu-tag "Printer Command" |
| 1510 | :tag "Printer Command" | ||
| 1511 | (const :tag "Default print command" nil) | ||
| 1512 | (string :tag "Explicit print command")) | ||
| 1510 | (repeat :tag "Printer Switches" | 1513 | (repeat :tag "Printer Switches" |
| 1511 | (sexp :tag "Switch" :value "")) | 1514 | (sexp :tag "Switch" :value "")) |
| 1512 | (choice :menu-tag "Printer Name" | 1515 | (choice :menu-tag "Printer Name" |
| @@ -1577,7 +1580,7 @@ COMMAND Name of the program for printing a PostScript file. On MS-DOS | |||
| 1577 | specially, using NAME as the destination for output; any other | 1580 | specially, using NAME as the destination for output; any other |
| 1578 | program is treated like `lpr' except that an explicit filename | 1581 | program is treated like `lpr' except that an explicit filename |
| 1579 | is given as the last argument. | 1582 | is given as the last argument. |
| 1580 | If COMMAND is nil, it's used the default printing program: | 1583 | If COMMAND is nil, it stands for the default printing program: |
| 1581 | `print' for Windows system, `lp' for lp system and `lpr' for | 1584 | `print' for Windows system, `lp' for lp system and `lpr' for |
| 1582 | all other systems. See also `pr-path-alist'. | 1585 | all other systems. See also `pr-path-alist'. |
| 1583 | Examples: | 1586 | Examples: |
| @@ -1756,7 +1759,10 @@ Useful links: | |||
| 1756 | (list | 1759 | (list |
| 1757 | :tag "PostScript Printer" | 1760 | :tag "PostScript Printer" |
| 1758 | (symbol :tag "Printer Symbol Name") | 1761 | (symbol :tag "Printer Symbol Name") |
| 1759 | (string :tag "Printer Command") | 1762 | (choice :menu-tag "Printer Command" |
| 1763 | :tag "Printer Command" | ||
| 1764 | (const :tag "Default print command" nil) | ||
| 1765 | (string :tag "Explicit print command")) | ||
| 1760 | (repeat :tag "Printer Switches" | 1766 | (repeat :tag "Printer Switches" |
| 1761 | (sexp :tag "Switch" :value "")) | 1767 | (sexp :tag "Switch" :value "")) |
| 1762 | (choice :menu-tag "Printer Name Switch" | 1768 | (choice :menu-tag "Printer Name Switch" |
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 87273ec91c0..be67e8db78f 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el | |||
| @@ -1567,6 +1567,7 @@ recommended to enable `electric-pair-mode' with this mode." | |||
| 1567 | (funcall c-ts-mode-indent-style) | 1567 | (funcall c-ts-mode-indent-style) |
| 1568 | (c-ts-mode--simple-indent-rules | 1568 | (c-ts-mode--simple-indent-rules |
| 1569 | 'cpp c-ts-mode-indent-style))) | 1569 | 'cpp c-ts-mode-indent-style))) |
| 1570 | (setq-local editorconfig-indent-size-vars '(c-ts-indent-offset)) | ||
| 1570 | 1571 | ||
| 1571 | ;; Font-lock. | 1572 | ;; Font-lock. |
| 1572 | (setq-local treesit-font-lock-settings | 1573 | (setq-local treesit-font-lock-settings |
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index 27b2e59409d..07974906a90 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el | |||
| @@ -991,6 +991,8 @@ You might also use mode hooks to specify it in certain modes, like this: | |||
| 991 | (file-name-sans-extension buffer-file-name)))))))) | 991 | (file-name-sans-extension buffer-file-name)))))))) |
| 992 | 992 | ||
| 993 | It's often useful to leave a space at the end of the value." | 993 | It's often useful to leave a space at the end of the value." |
| 994 | :group 'compilation | ||
| 995 | :initialize #'custom-initialize-delay | ||
| 994 | :type 'string) | 996 | :type 'string) |
| 995 | ;;;###autoload(put 'compile-command 'safe-local-variable (lambda (a) (and (stringp a) (if (boundp 'compilation-read-command) compilation-read-command t)))) | 997 | ;;;###autoload(put 'compile-command 'safe-local-variable (lambda (a) (and (stringp a) (if (boundp 'compilation-read-command) compilation-read-command t)))) |
| 996 | 998 | ||
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index a4f076a6197..0e1ed519b43 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el | |||
| @@ -2,12 +2,12 @@ | |||
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2018-2026 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2018-2026 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Version: 1.21 | 5 | ;; Version: 1.23 |
| 6 | ;; Author: João Távora <joaotavora@gmail.com> | 6 | ;; Author: João Távora <joaotavora@gmail.com> |
| 7 | ;; Maintainer: João Távora <joaotavora@gmail.com> | 7 | ;; Maintainer: João Távora <joaotavora@gmail.com> |
| 8 | ;; URL: https://github.com/joaotavora/eglot | 8 | ;; URL: https://github.com/joaotavora/eglot |
| 9 | ;; Keywords: convenience, languages | 9 | ;; Keywords: convenience, languages |
| 10 | ;; Package-Requires: ((emacs "26.3") (eldoc "1.14.0") (external-completion "0.1") (flymake "1.4.2") (jsonrpc "1.0.26") (project "0.11.2") (seq "2.23") (xref "1.6.2")) | 10 | ;; Package-Requires: ((emacs "26.3") (eldoc "1.16.0") (external-completion "0.1") (flymake "1.4.5") (jsonrpc "1.0.28") (project "0.11.2") (seq "2.23") (xref "1.7.0")) |
| 11 | 11 | ||
| 12 | ;; This is a GNU ELPA :core package. Avoid adding functionality | 12 | ;; This is a GNU ELPA :core package. Avoid adding functionality |
| 13 | ;; that is not available in the version of Emacs recorded above or any | 13 | ;; that is not available in the version of Emacs recorded above or any |
| @@ -2710,10 +2710,11 @@ still unanswered LSP requests to the server\n")))) | |||
| 2710 | 2710 | ||
| 2711 | (defconst eglot-mode-line-progress | 2711 | (defconst eglot-mode-line-progress |
| 2712 | '(:eval | 2712 | '(:eval |
| 2713 | (when-let ((server (eglot-current-server))) | 2713 | (when-let ((s (eglot-current-server))) |
| 2714 | (cl-loop | 2714 | (cl-loop |
| 2715 | for pr hash-values of (eglot--progress-reporters server) | 2715 | for pr in (cl-delete 'eglot--mode-line-reporter |
| 2716 | when (eq (car pr) 'eglot--mode-line-reporter) | 2716 | (hash-table-values (eglot--progress-reporters s)) |
| 2717 | :key #'car :test-not #'eq) | ||
| 2717 | for v = (nth 4 pr) | 2718 | for v = (nth 4 pr) |
| 2718 | when v sum 1 into n and sum v into acc | 2719 | when v sum 1 into n and sum v into acc |
| 2719 | collect (format "(%s) %s %s" (nth 1 pr) (nth 2 pr) (nth 3 pr)) | 2720 | collect (format "(%s) %s %s" (nth 1 pr) (nth 2 pr) (nth 3 pr)) |
| @@ -4092,7 +4093,7 @@ for which LSP on-type-formatting should be requested." | |||
| 4092 | parameter | 4093 | parameter |
| 4093 | ;; ...perhaps highlight it in the formals list | 4094 | ;; ...perhaps highlight it in the formals list |
| 4094 | (when (eq i active-param) | 4095 | (when (eq i active-param) |
| 4095 | (save-excursion ;; FIXME: Sink into the `if' or hoist out of loop? | 4096 | (save-excursion |
| 4096 | (goto-char (point-min)) | 4097 | (goto-char (point-min)) |
| 4097 | (pcase-let | 4098 | (pcase-let |
| 4098 | ((`(,beg ,end) | 4099 | ((`(,beg ,end) |
| @@ -4100,8 +4101,7 @@ for which LSP on-type-formatting should be requested." | |||
| 4100 | (let ((case-fold-search nil)) | 4101 | (let ((case-fold-search nil)) |
| 4101 | (and (search-forward parlabel (line-end-position) t) | 4102 | (and (search-forward parlabel (line-end-position) t) |
| 4102 | (list (match-beginning 0) (match-end 0)))) | 4103 | (list (match-beginning 0) (match-end 0)))) |
| 4103 | (list (+ (point-min) (aref parlabel 0)) | 4104 | (list (1+ (aref parlabel 0)) (1+ (aref parlabel 1)))))) |
| 4104 | (+ (point-min) (aref parlabel 1)))))) | ||
| 4105 | (if (and beg end) | 4105 | (if (and beg end) |
| 4106 | (add-face-text-property | 4106 | (add-face-text-property |
| 4107 | beg end | 4107 | beg end |
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index 4e828eba8a0..f62f9f5ce3c 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el | |||
| @@ -1330,6 +1330,8 @@ Interactively, with a prefix arg, FORCE is t." | |||
| 1330 | (buffer (current-buffer))) | 1330 | (buffer (current-buffer))) |
| 1331 | (cl-labels | 1331 | (cl-labels |
| 1332 | ((visible-buffer-window () | 1332 | ((visible-buffer-window () |
| 1333 | ;; This can use `frame-initial-p' once | ||
| 1334 | ;; we can assume Emacs 31 or later. | ||
| 1333 | (and (or (not (daemonp)) | 1335 | (and (or (not (daemonp)) |
| 1334 | (not (eq (selected-frame) terminal-frame))) | 1336 | (not (eq (selected-frame) terminal-frame))) |
| 1335 | (get-buffer-window (current-buffer)))) | 1337 | (get-buffer-window (current-buffer)))) |
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index 128952a2dd4..72a05a082bb 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el | |||
| @@ -1089,11 +1089,15 @@ list is empty)." | |||
| 1089 | match) | 1089 | match) |
| 1090 | (while (setq match (text-property-search-forward 'compilation-annotation)) | 1090 | (while (setq match (text-property-search-forward 'compilation-annotation)) |
| 1091 | (add-text-properties (prop-match-beginning match) (prop-match-end match) | 1091 | (add-text-properties (prop-match-beginning match) (prop-match-end match) |
| 1092 | '(read-only t))) | 1092 | '(read-only t front-sticky t))) |
| 1093 | (goto-char (point-min)) | 1093 | (goto-char (point-min)) |
| 1094 | (while (setq match (text-property-search-forward 'compilation-message)) | 1094 | (while (setq match (text-property-search-forward 'compilation-message)) |
| 1095 | (add-text-properties (prop-match-beginning match) (prop-match-end match) | 1095 | (add-text-properties (prop-match-beginning match) (prop-match-end match) |
| 1096 | '(read-only t occur-prefix t)) | 1096 | '( read-only t occur-prefix t |
| 1097 | ;; Allow insertion of text right | ||
| 1098 | ;; after prefix, but not before. | ||
| 1099 | front-sticky t | ||
| 1100 | rear-nonsticky t)) | ||
| 1097 | (let ((loc (compilation--message->loc (prop-match-value match))) | 1101 | (let ((loc (compilation--message->loc (prop-match-value match))) |
| 1098 | m) | 1102 | m) |
| 1099 | ;; Update the markers if necessary. | 1103 | ;; Update the markers if necessary. |
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index ebf8df9f795..2c21d08d448 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el | |||
| @@ -73,6 +73,7 @@ | |||
| 73 | (require 'cl-lib) | 73 | (require 'cl-lib) |
| 74 | (require 'ring) | 74 | (require 'ring) |
| 75 | (require 'project) | 75 | (require 'project) |
| 76 | (require 'text-property-search) | ||
| 76 | 77 | ||
| 77 | (eval-and-compile | 78 | (eval-and-compile |
| 78 | (when (version< emacs-version "28.0.60") | 79 | (when (version< emacs-version "28.0.60") |
| @@ -628,7 +629,7 @@ If SELECT is non-nil, select the target window." | |||
| 628 | (run-hooks 'xref-after-jump-hook))) | 629 | (run-hooks 'xref-after-jump-hook))) |
| 629 | 630 | ||
| 630 | 631 | ||
| 631 | ;;; XREF buffer (part of the UI) | 632 | ;;; Xref buffer (part of the UI) |
| 632 | 633 | ||
| 633 | ;; The xref buffer is used to display a set of xrefs. | 634 | ;; The xref buffer is used to display a set of xrefs. |
| 634 | (defconst xref-buffer-name "*xref*" | 635 | (defconst xref-buffer-name "*xref*" |
| @@ -1004,12 +1005,13 @@ point." | |||
| 1004 | (define-key map (kbd ".") #'xref-next-line) | 1005 | (define-key map (kbd ".") #'xref-next-line) |
| 1005 | (define-key map (kbd ",") #'xref-prev-line) | 1006 | (define-key map (kbd ",") #'xref-prev-line) |
| 1006 | (define-key map (kbd "M-,") #'xref-quit-and-pop-marker-stack) | 1007 | (define-key map (kbd "M-,") #'xref-quit-and-pop-marker-stack) |
| 1008 | (define-key map (kbd "e") #'xref-change-to-xref-edit-mode) | ||
| 1007 | map)) | 1009 | map)) |
| 1008 | 1010 | ||
| 1009 | (declare-function outline-search-text-property "outline" | 1011 | (declare-function outline-search-text-property "outline" |
| 1010 | (property &optional value bound move backward looking-at)) | 1012 | (property &optional value bound move backward looking-at)) |
| 1011 | 1013 | ||
| 1012 | (define-derived-mode xref--xref-buffer-mode special-mode "XREF" | 1014 | (define-derived-mode xref--xref-buffer-mode special-mode "Xref" |
| 1013 | "Mode for displaying cross-references." | 1015 | "Mode for displaying cross-references." |
| 1014 | (setq buffer-read-only t) | 1016 | (setq buffer-read-only t) |
| 1015 | (setq next-error-function #'xref--next-error-function) | 1017 | (setq next-error-function #'xref--next-error-function) |
| @@ -1039,7 +1041,7 @@ point." | |||
| 1039 | 1041 | ||
| 1040 | (define-derived-mode xref--transient-buffer-mode | 1042 | (define-derived-mode xref--transient-buffer-mode |
| 1041 | xref--xref-buffer-mode | 1043 | xref--xref-buffer-mode |
| 1042 | "XREF Transient.") | 1044 | "Xref Transient") |
| 1043 | 1045 | ||
| 1044 | (defun xref--imenu-prev-index-position () | 1046 | (defun xref--imenu-prev-index-position () |
| 1045 | "Move point to previous line in `xref' buffer. | 1047 | "Move point to previous line in `xref' buffer. |
| @@ -1471,6 +1473,106 @@ between them by typing in the minibuffer with completion." | |||
| 1471 | 'xref--show-defs-minibuffer #'xref-show-definitions-completing-read "28.1") | 1473 | 'xref--show-defs-minibuffer #'xref-show-definitions-completing-read "28.1") |
| 1472 | 1474 | ||
| 1473 | 1475 | ||
| 1476 | (defun xref-edit--prepare-buffer () | ||
| 1477 | "Mark relevant regions read-only, and add relevant occur text-properties." | ||
| 1478 | (save-excursion | ||
| 1479 | (goto-char (point-min)) | ||
| 1480 | (let ((inhibit-read-only t) | ||
| 1481 | match) | ||
| 1482 | (while (setq match (text-property-search-forward 'xref-group)) | ||
| 1483 | (add-text-properties (prop-match-beginning match) (prop-match-end match) | ||
| 1484 | '( read-only t | ||
| 1485 | front-sticky t))) | ||
| 1486 | (goto-char (point-min)) | ||
| 1487 | (while (setq match (text-property-search-forward 'xref-item)) | ||
| 1488 | (let ((line-number-end (save-excursion | ||
| 1489 | (forward-line 0) | ||
| 1490 | (and (looking-at " *[0-9]+:") | ||
| 1491 | (match-end 0))))) | ||
| 1492 | (when line-number-end | ||
| 1493 | (add-text-properties (prop-match-beginning match) line-number-end | ||
| 1494 | '( read-only t | ||
| 1495 | occur-prefix t | ||
| 1496 | ;; Allow insertion of text right | ||
| 1497 | ;; after prefix, but not before. | ||
| 1498 | front-sticky t | ||
| 1499 | rear-nonsticky t)))))))) | ||
| 1500 | |||
| 1501 | (defvar xref-edit-mode-map | ||
| 1502 | (let ((map (make-sparse-keymap))) | ||
| 1503 | (define-key map (kbd "C-c C-c") #'xref-edit-save-changes) | ||
| 1504 | (define-key map (kbd "RET") #'xref-goto-xref) | ||
| 1505 | (define-key map (kbd "M-,") #'xref-quit-and-pop-marker-stack) | ||
| 1506 | (define-key map (kbd "C-o") #'xref-show-location-at-point) | ||
| 1507 | map) | ||
| 1508 | "Keymap for `xref-edit-mode'.") | ||
| 1509 | |||
| 1510 | (defvar xref-edit-mode-hook nil | ||
| 1511 | "Hooks run when changing to Xref-Edit mode.") | ||
| 1512 | |||
| 1513 | (defun xref-edit-mode () | ||
| 1514 | "Major mode for editing *xref* buffers. | ||
| 1515 | In this mode, changes to the *xref* buffer are applied to the | ||
| 1516 | originating files. | ||
| 1517 | \\<xref-edit-mode-map> | ||
| 1518 | Type \\[xref-edit-save-changes] to exit Xref-Edit mode, return to Xref | ||
| 1519 | mode. | ||
| 1520 | |||
| 1521 | The only editable texts in an Xref-Edit buffer are the match results." | ||
| 1522 | (interactive) | ||
| 1523 | (error "This mode can be enabled only by `xref-change-to-xref-edit-mode'")) | ||
| 1524 | (put 'xref-edit-mode 'mode-class 'special) | ||
| 1525 | |||
| 1526 | (defun xref-change-to-xref-edit-mode () | ||
| 1527 | "Switch to `xref-edit-mode' to edit *xref* buffer." | ||
| 1528 | (interactive) | ||
| 1529 | (unless (derived-mode-p 'xref--xref-buffer-mode) | ||
| 1530 | (error "Not an Xref buffer")) | ||
| 1531 | (use-local-map xref-edit-mode-map) | ||
| 1532 | (xref-edit--prepare-buffer) | ||
| 1533 | (setq buffer-read-only nil) | ||
| 1534 | (setq major-mode 'xref-edit-mode) | ||
| 1535 | (setq mode-name "Xref-Edit") | ||
| 1536 | (buffer-enable-undo) | ||
| 1537 | (set-buffer-modified-p nil) | ||
| 1538 | (setq buffer-undo-list nil) | ||
| 1539 | (add-hook 'before-change-functions #'xref-edit--before-change-function nil t) | ||
| 1540 | (add-hook 'after-change-functions #'occur-after-change-function nil t) | ||
| 1541 | (run-mode-hooks 'xref-edit-mode-hook) | ||
| 1542 | (message (substitute-command-keys | ||
| 1543 | "Editing: Type \\[xref-edit-save-changes] to return to Xref mode"))) | ||
| 1544 | |||
| 1545 | (defun xref-edit-save-changes () | ||
| 1546 | "Switch back to Xref mode." | ||
| 1547 | (interactive) | ||
| 1548 | (unless (derived-mode-p 'xref-edit-mode) | ||
| 1549 | (error "Not a Xref-Edit buffer")) | ||
| 1550 | (remove-hook 'before-change-functions #'xref-edit--before-change-function t) | ||
| 1551 | (remove-hook 'after-change-functions #'occur-after-change-function t) | ||
| 1552 | (use-local-map xref--xref-buffer-mode-map) | ||
| 1553 | (setq buffer-read-only t) | ||
| 1554 | (setq major-mode 'xref--xref-buffer-mode) | ||
| 1555 | (setq mode-name "Xref") | ||
| 1556 | (force-mode-line-update) | ||
| 1557 | (buffer-disable-undo) | ||
| 1558 | (setq buffer-undo-list t) | ||
| 1559 | (let ((inhibit-read-only t)) | ||
| 1560 | (remove-text-properties (point-min) (point-max) | ||
| 1561 | '(occur-target nil occur-prefix nil))) | ||
| 1562 | (message "Switching to Xref mode")) | ||
| 1563 | |||
| 1564 | (defun xref-edit--before-change-function (_beg _end) | ||
| 1565 | (when (and (not (get-text-property (pos-bol) 'occur-target)) | ||
| 1566 | (get-text-property (pos-bol) 'occur-prefix)) | ||
| 1567 | (let ((m (xref-location-marker (xref-item-location | ||
| 1568 | (get-text-property (pos-bol) 'xref-item)))) | ||
| 1569 | (inhibit-read-only t) | ||
| 1570 | (inhibit-modification-hooks t) | ||
| 1571 | (buffer-undo-list t)) | ||
| 1572 | (add-text-properties (pos-bol) (pos-eol) | ||
| 1573 | `(occur-target ((,m . ,m))))))) | ||
| 1574 | |||
| 1575 | |||
| 1474 | (defcustom xref-show-xrefs-function 'xref--show-xref-buffer | 1576 | (defcustom xref-show-xrefs-function 'xref--show-xref-buffer |
| 1475 | "Function to display a list of search results. | 1577 | "Function to display a list of search results. |
| 1476 | 1578 | ||
diff --git a/lisp/server.el b/lisp/server.el index fcfc6c01972..f5dea9c590f 100644 --- a/lisp/server.el +++ b/lisp/server.el | |||
| @@ -706,6 +706,7 @@ the `server-process' variable." | |||
| 706 | ;; when we can't get user input, which may happen when | 706 | ;; when we can't get user input, which may happen when |
| 707 | ;; doing emacsclient --eval "(kill-emacs)" in daemon mode. | 707 | ;; doing emacsclient --eval "(kill-emacs)" in daemon mode. |
| 708 | (cond | 708 | (cond |
| 709 | ;; Use `frame-initial-p'? | ||
| 709 | ((and (daemonp) | 710 | ((and (daemonp) |
| 710 | (null (cdr (frame-list))) | 711 | (null (cdr (frame-list))) |
| 711 | (eq (selected-frame) terminal-frame)) | 712 | (eq (selected-frame) terminal-frame)) |
| @@ -1429,6 +1430,7 @@ The following commands are accepted by the client: | |||
| 1429 | (or (eq use-current-frame 'always) | 1430 | (or (eq use-current-frame 'always) |
| 1430 | ;; We can't use the Emacs daemon's | 1431 | ;; We can't use the Emacs daemon's |
| 1431 | ;; terminal frame. | 1432 | ;; terminal frame. |
| 1433 | ;; Use `frame-initial-p'? | ||
| 1432 | (not (and (daemonp) | 1434 | (not (and (daemonp) |
| 1433 | (null (cdr (frame-list))) | 1435 | (null (cdr (frame-list))) |
| 1434 | (eq (selected-frame) | 1436 | (eq (selected-frame) |
| @@ -1453,6 +1455,7 @@ The following commands are accepted by the client: | |||
| 1453 | ;; If there won't be a current frame to use, fall | 1455 | ;; If there won't be a current frame to use, fall |
| 1454 | ;; back to trying to create a new one. | 1456 | ;; back to trying to create a new one. |
| 1455 | ((and use-current-frame | 1457 | ((and use-current-frame |
| 1458 | ;; Use `frame-initial-p'? | ||
| 1456 | (daemonp) | 1459 | (daemonp) |
| 1457 | (null (cdr (frame-list))) | 1460 | (null (cdr (frame-list))) |
| 1458 | (eq (selected-frame) terminal-frame) | 1461 | (eq (selected-frame) terminal-frame) |
diff --git a/lisp/subr.el b/lisp/subr.el index a1d718ca5b7..b0e04bc5f99 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -160,6 +160,10 @@ of previous VARs. | |||
| 160 | (push `(set-default ',(pop args) ,(pop args)) exps)) | 160 | (push `(set-default ',(pop args) ,(pop args)) exps)) |
| 161 | `(progn . ,(nreverse exps)))) | 161 | `(progn . ,(nreverse exps)))) |
| 162 | 162 | ||
| 163 | (defun set-local (variable value) | ||
| 164 | "Make VARIABLE buffer local and set it to VALUE." | ||
| 165 | (set (make-local-variable variable) value)) | ||
| 166 | |||
| 163 | (defmacro setq-local (&rest pairs) | 167 | (defmacro setq-local (&rest pairs) |
| 164 | "Make each VARIABLE local to current buffer and set it to corresponding VALUE. | 168 | "Make each VARIABLE local to current buffer and set it to corresponding VALUE. |
| 165 | 169 | ||
| @@ -181,7 +185,7 @@ In some corner cases you may need to resort to | |||
| 181 | \(fn [VARIABLE VALUE]...)" | 185 | \(fn [VARIABLE VALUE]...)" |
| 182 | (declare (debug setq)) | 186 | (declare (debug setq)) |
| 183 | (unless (evenp (length pairs)) | 187 | (unless (evenp (length pairs)) |
| 184 | (error "PAIRS must have an even number of variable/value members")) | 188 | (signal 'wrong-number-of-arguments (list 'setq-local (length pairs)))) |
| 185 | (let ((expr nil)) | 189 | (let ((expr nil)) |
| 186 | (while pairs | 190 | (while pairs |
| 187 | (unless (symbolp (car pairs)) | 191 | (unless (symbolp (car pairs)) |
| @@ -229,7 +233,7 @@ in order to restore the state of the local variables set via this macro. | |||
| 229 | \(fn [VARIABLE VALUE]...)" | 233 | \(fn [VARIABLE VALUE]...)" |
| 230 | (declare (debug setq)) | 234 | (declare (debug setq)) |
| 231 | (unless (evenp (length pairs)) | 235 | (unless (evenp (length pairs)) |
| 232 | (error "PAIRS must have an even number of variable/value members")) | 236 | (signal 'wrong-number-of-arguments (list 'buffer-local-set-state (length pairs)))) |
| 233 | (let ((vars nil) | 237 | (let ((vars nil) |
| 234 | (tmp pairs)) | 238 | (tmp pairs)) |
| 235 | (while tmp (push (car tmp) vars) (setq tmp (cddr tmp))) | 239 | (while tmp (push (car tmp) vars) (setq tmp (cddr tmp))) |
| @@ -1226,8 +1230,13 @@ with | |||
| 1226 | (member-if (lambda (x) (foo (bar x))) items)" | 1230 | (member-if (lambda (x) (foo (bar x))) items)" |
| 1227 | (declare (compiler-macro | 1231 | (declare (compiler-macro |
| 1228 | (lambda (_) | 1232 | (lambda (_) |
| 1229 | (let ((x (make-symbol "x"))) | 1233 | (let* ((x (make-symbol "x")) |
| 1230 | `(drop-while (lambda (,x) (not (funcall ,pred ,x))) ,list))))) | 1234 | (f (and (not (internal--effect-free-fun-arg-p pred)) |
| 1235 | (make-symbol "f"))) | ||
| 1236 | (form `(drop-while (lambda (,x) | ||
| 1237 | (not (funcall ,(or f pred) ,x))) | ||
| 1238 | ,list))) | ||
| 1239 | (if f `(let ((,f ,pred)) ,form) form))))) | ||
| 1231 | (drop-while (lambda (x) (not (funcall pred x))) list)) | 1240 | (drop-while (lambda (x) (not (funcall pred x))) list)) |
| 1232 | 1241 | ||
| 1233 | ;; This is good to have for improved readability in certain uses, but | 1242 | ;; This is good to have for improved readability in certain uses, but |
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index ad749557987..3399e5ef93e 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el | |||
| @@ -292,6 +292,7 @@ a list of frames to update." | |||
| 292 | (and (eq auto-resize-tab-bars 'grow-only) | 292 | (and (eq auto-resize-tab-bars 'grow-only) |
| 293 | (> (frame-parameter frame 'tab-bar-lines) 1)) | 293 | (> (frame-parameter frame 'tab-bar-lines) 1)) |
| 294 | ;; Don't enable tab-bar in daemon's initial frame. | 294 | ;; Don't enable tab-bar in daemon's initial frame. |
| 295 | ;; Use `frame-initial-p'? | ||
| 295 | (and (daemonp) (eq frame terminal-frame))) | 296 | (and (daemonp) (eq frame terminal-frame))) |
| 296 | (set-frame-parameter frame 'tab-bar-lines | 297 | (set-frame-parameter frame 'tab-bar-lines |
| 297 | (tab-bar--tab-bar-lines-for-frame frame))))) | 298 | (tab-bar--tab-bar-lines-for-frame frame))))) |
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index a56fc018e18..355555df090 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | ;; Copyright (C) 2006-2026 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2006-2026 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> | 5 | ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> |
| 6 | ;; Maintainer: Simen Heggestøyl <simenheg@gmail.com> | 6 | ;; Maintainer: Simen Heggestøyl <simenheg@runbox.com> |
| 7 | ;; Keywords: hypermedia | 7 | ;; Keywords: hypermedia |
| 8 | 8 | ||
| 9 | ;; This file is part of GNU Emacs. | 9 | ;; This file is part of GNU Emacs. |
| @@ -66,7 +66,7 @@ | |||
| 66 | 66 | ||
| 67 | (defconst css-pseudo-class-ids | 67 | (defconst css-pseudo-class-ids |
| 68 | '("active" "checked" "default" "disabled" "empty" "enabled" "first" | 68 | '("active" "checked" "default" "disabled" "empty" "enabled" "first" |
| 69 | "first-child" "first-of-type" "focus" "focus-within" "hover" | 69 | "first-child" "first-of-type" "focus" "focus-within" "has" "hover" |
| 70 | "in-range" "indeterminate" "invalid" "lang" "last-child" | 70 | "in-range" "indeterminate" "invalid" "lang" "last-child" |
| 71 | "last-of-type" "left" "link" "not" "nth-child" "nth-last-child" | 71 | "last-of-type" "left" "link" "not" "nth-child" "nth-last-child" |
| 72 | "nth-last-of-type" "nth-of-type" "only-child" "only-of-type" | 72 | "nth-last-of-type" "nth-of-type" "only-child" "only-of-type" |
diff --git a/lisp/textmodes/enriched.el b/lisp/textmodes/enriched.el index a269cae0c9b..c5ae2a15557 100644 --- a/lisp/textmodes/enriched.el +++ b/lisp/textmodes/enriched.el | |||
| @@ -390,6 +390,16 @@ which can be the value of the `face' text property." | |||
| 390 | (list (list "x-color" (cadr face)))) | 390 | (list (list "x-color" (cadr face)))) |
| 391 | ((and (listp face) (eq (car face) :background)) | 391 | ((and (listp face) (eq (car face) :background)) |
| 392 | (list (list "x-bg-color" (cadr face)))) | 392 | (list (list "x-bg-color" (cadr face)))) |
| 393 | ((and (listp face) (eq (car face) :underline)) | ||
| 394 | (list (list "underline"))) | ||
| 395 | ((and (listp face) | ||
| 396 | (eq (car face) :weight) | ||
| 397 | (eq (cadr face) 'bold)) | ||
| 398 | (list (list "bold"))) | ||
| 399 | ((and (listp face) | ||
| 400 | (eq (car face) :slant) | ||
| 401 | (memq (cadr face) '(italic oblique))) | ||
| 402 | (list (list "italic"))) | ||
| 393 | ((listp face) | 403 | ((listp face) |
| 394 | (apply #'append (mapcar #'enriched-face-ans face))) | 404 | (apply #'append (mapcar #'enriched-face-ans face))) |
| 395 | ((let* ((fg (face-attribute face :foreground)) | 405 | ((let* ((fg (face-attribute face :foreground)) |
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el index 9445b4a6b9a..c1ccdf2ec5f 100644 --- a/lisp/textmodes/fill.el +++ b/lisp/textmodes/fill.el | |||
| @@ -1700,7 +1700,7 @@ and URL `https://rhodesmill.org/brandon/2012/one-sentence-per-line/'." | |||
| 1700 | (to (copy-marker (max from to) t)) | 1700 | (to (copy-marker (max from to) t)) |
| 1701 | pfx) | 1701 | pfx) |
| 1702 | (goto-char from) | 1702 | (goto-char from) |
| 1703 | (let ((fill-column (* 2 (point-max)))) ; Wide characters span up to two columns. | 1703 | (let ((fill-column most-positive-fixnum)) |
| 1704 | (setq pfx (or (save-excursion | 1704 | (setq pfx (or (save-excursion |
| 1705 | (fill-region-as-paragraph-default (point) | 1705 | (fill-region-as-paragraph-default (point) |
| 1706 | to | 1706 | to |
diff --git a/lisp/textmodes/markdown-ts-mode.el b/lisp/textmodes/markdown-ts-mode.el index cc3eaf03e15..657d6bc466d 100644 --- a/lisp/textmodes/markdown-ts-mode.el +++ b/lisp/textmodes/markdown-ts-mode.el | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | (require 'treesit) | 40 | (require 'treesit) |
| 41 | (require 'subr-x) | 41 | (require 'subr-x) |
| 42 | (require 'outline) | 42 | (require 'outline) |
| 43 | (require 'seq) | ||
| 43 | 44 | ||
| 44 | (treesit-declare-unavailable-functions) | 45 | (treesit-declare-unavailable-functions) |
| 45 | 46 | ||
| @@ -296,7 +297,12 @@ the same features enabled in MODE." | |||
| 296 | (plist-get configs :simple-indent))) | 297 | (plist-get configs :simple-indent))) |
| 297 | (setq treesit-range-settings | 298 | (setq treesit-range-settings |
| 298 | (append treesit-range-settings | 299 | (append treesit-range-settings |
| 299 | (plist-get configs :range))) | 300 | ;; Filter out function queries, because they are |
| 301 | ;; usually some hack and might escape the code block. | ||
| 302 | ;; Case in point: c-ts-mode's range setting. | ||
| 303 | (seq-filter (lambda (setting) | ||
| 304 | (not (functionp (car setting)))) | ||
| 305 | (plist-get configs :range)))) | ||
| 300 | (setq-local indent-line-function #'treesit-indent) | 306 | (setq-local indent-line-function #'treesit-indent) |
| 301 | (setq-local indent-region-function #'treesit-indent-region))) | 307 | (setq-local indent-region-function #'treesit-indent-region))) |
| 302 | 308 | ||
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el index b7f72f2619c..671cf5a1547 100644 --- a/lisp/time-stamp.el +++ b/lisp/time-stamp.el | |||
| @@ -53,7 +53,7 @@ with %, which are converted as follows: | |||
| 53 | %H 24-hour clock hour %I 12-hour clock hour | 53 | %H 24-hour clock hour %I 12-hour clock hour |
| 54 | %m month number | 54 | %m month number |
| 55 | %M minute | 55 | %M minute |
| 56 | %p meridian indicator: `AM', `PM' | 56 | %p meridiem indicator: `AM', `PM' |
| 57 | %S seconds | 57 | %S seconds |
| 58 | %w day number of week, Sunday is 0 | 58 | %w day number of week, Sunday is 0 |
| 59 | %Y 4-digit year %y 2-digit year | 59 | %Y 4-digit year %y 2-digit year |
| @@ -1039,39 +1039,45 @@ This is an internal function called by `time-stamp'." | |||
| 1039 | offset-secs) | 1039 | offset-secs) |
| 1040 | "Format a time offset according to a %z variation. | 1040 | "Format a time offset according to a %z variation. |
| 1041 | 1041 | ||
| 1042 | With no flags, the output includes hours and minutes: +-HHMM | 1042 | Format parts FLAG-MINIMIZE, FLAG-PAD-SPACES-ONLY, |
| 1043 | unless there is a non-zero seconds part, in which case the seconds | 1043 | FLAG-PAD-ZEROS-FIRST, COLON-COUNT, and FIELD-WIDTH |
| 1044 | are included: +-HHMMSS | 1044 | are used to format time zone offset OFFSET-SECS. |
| 1045 | |||
| 1046 | FLAG-MINIMIZE is whether \"-\" was specified. If non-nil, the | ||
| 1047 | output may be limited to hours if minutes and seconds are zero. | ||
| 1048 | |||
| 1049 | FLAG-PAD-SPACES-ONLY is whether \"_\" was specified. If non-nil, | ||
| 1050 | seconds must be output, so that any padding can be spaces only. | ||
| 1051 | |||
| 1052 | FLAG-PAD-ZEROS-FIRST is whether \"0\" was specified. If non-nil, | ||
| 1053 | padding to the requested FIELD-WIDTH (if any) is done by adding | ||
| 1054 | 00 seconds before padding with spaces. | ||
| 1055 | |||
| 1056 | COLON-COUNT is the number of colons preceding the \"z\" (0-3). One or | ||
| 1057 | two colons put that many colons in the output (+-HH:MM or +-HH:MM:SS). | ||
| 1058 | Three colons outputs only hours if minutes and seconds are zero and | ||
| 1059 | includes colon separators if minutes and seconds are output. | ||
| 1060 | |||
| 1061 | FIELD-WIDTH is a whole number giving the minimum number of characters | ||
| 1062 | in the output; 0 specifies no minimum. Additional characters will be | ||
| 1063 | added on the right if necessary. The added characters will be spaces | ||
| 1064 | unless FLAG-PAD-ZEROS-FIRST is non-nil. | ||
| 1065 | |||
| 1066 | OFFSET-SECS is the time zone offset (in seconds east of UTC) to be | ||
| 1067 | formatted according to the preceding parameters. | ||
| 1068 | 1045 | ||
| 1069 | This is an internal function used by `time-stamp'." | 1046 | This is an internal function used by `time-stamp'." |
| 1047 | |||
| 1070 | ;; Callers of this function need to have already parsed the %z | 1048 | ;; Callers of this function need to have already parsed the %z |
| 1071 | ;; format string; this function accepts just the parts of the format. | 1049 | ;; format string; this function accepts just the parts of the format. |
| 1072 | ;; `time-stamp-string-preprocess' is the full-fledged parser normally | 1050 | ;; `time-stamp-string-preprocess' is the full-fledged parser normally |
| 1073 | ;; used. The unit test (in time-stamp-tests.el) defines the simpler | 1051 | ;; used. The unit test (in time-stamp-tests.el) defines the simpler |
| 1074 | ;; parser `format-time-offset'. | 1052 | ;; parser `format-time-offset'. |
| 1053 | |||
| 1054 | ;; OFFSET-SECS is the time zone offset (in seconds east of UTC) to be | ||
| 1055 | ;; formatted according to the following parameters. | ||
| 1056 | |||
| 1057 | ;; FLAG-MINIMIZE is whether \"-\" was specified. If non-nil, the | ||
| 1058 | ;; output may be limited to hours if minutes and seconds are zero. | ||
| 1059 | |||
| 1060 | ;; FLAG-PAD-SPACES-ONLY is whether \"_\" was specified. If non-nil, | ||
| 1061 | ;; seconds must be output, so that any padding can be spaces only. | ||
| 1062 | |||
| 1063 | ;; FLAG-PAD-ZEROS-FIRST is whether \"0\" was specified. If non-nil, | ||
| 1064 | ;; padding to the requested FIELD-WIDTH (if any) is done by adding | ||
| 1065 | ;; 00 seconds before padding with spaces. | ||
| 1066 | |||
| 1067 | ;; COLON-COUNT is the number of colons preceding the \"z\" (0-3). One or | ||
| 1068 | ;; two colons put that many colons in the output (+-HH:MM or +-HH:MM:SS). | ||
| 1069 | ;; Three colons outputs only hours if minutes and seconds are zero and | ||
| 1070 | ;; includes colon separators if minutes and seconds are output. | ||
| 1071 | |||
| 1072 | ;; FIELD-WIDTH is a whole number giving the minimum number of characters | ||
| 1073 | ;; in the output; 0 specifies no minimum. Additional characters will be | ||
| 1074 | ;; added on the right if necessary. The added characters will be spaces | ||
| 1075 | ;; unless FLAG-PAD-ZEROS-FIRST is non-nil. | ||
| 1076 | |||
| 1077 | ;; With no flags set, the output includes hours and minutes: +-HHMM | ||
| 1078 | ;; unless there is a non-zero seconds part, in which case the seconds | ||
| 1079 | ;; are included: +-HHMMSS | ||
| 1080 | |||
| 1075 | (let ((hrs (/ (abs offset-secs) 3600)) | 1081 | (let ((hrs (/ (abs offset-secs) 3600)) |
| 1076 | (mins (/ (% (abs offset-secs) 3600) 60)) | 1082 | (mins (/ (% (abs offset-secs) 3600) 60)) |
| 1077 | (secs (% (abs offset-secs) 60)) | 1083 | (secs (% (abs offset-secs) 60)) |
diff --git a/lisp/tool-bar.el b/lisp/tool-bar.el index 73df2e0bca8..d9b1f50b40c 100644 --- a/lisp/tool-bar.el +++ b/lisp/tool-bar.el | |||
| @@ -330,7 +330,7 @@ holds a keymap." | |||
| 330 | :vert-only t) | 330 | :vert-only t) |
| 331 | (tool-bar-add-item-from-menu 'menu-find-file-existing "open" nil | 331 | (tool-bar-add-item-from-menu 'menu-find-file-existing "open" nil |
| 332 | :label "Open" :vert-only t) | 332 | :label "Open" :vert-only t) |
| 333 | (tool-bar-add-item-from-menu 'dired "diropen" nil :vert-only t) | 333 | (tool-bar-add-item-from-menu 'dired-from-menubar "diropen" nil :vert-only t) |
| 334 | (tool-bar-add-item-from-menu 'kill-this-buffer "close" nil :vert-only t) | 334 | (tool-bar-add-item-from-menu 'kill-this-buffer "close" nil :vert-only t) |
| 335 | (tool-bar-add-item-from-menu 'save-buffer "save" nil | 335 | (tool-bar-add-item-from-menu 'save-buffer "save" nil |
| 336 | :label "Save") | 336 | :label "Save") |
diff --git a/lisp/treesit.el b/lisp/treesit.el index 7d6113e3249..14c05b0dd16 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el | |||
| @@ -753,10 +753,10 @@ that encompasses the region between START and END." | |||
| 753 | (numberp (cdr range-offset))) | 753 | (numberp (cdr range-offset))) |
| 754 | (signal 'treesit-error (list "Value of :offset option should be a pair of numbers" range-offset))) | 754 | (signal 'treesit-error (list "Value of :offset option should be a pair of numbers" range-offset))) |
| 755 | (setq offset range-offset))) | 755 | (setq offset range-offset))) |
| 756 | (:range-fn (let ((range-fn (pop query-specs))) | 756 | (:range-fn (let ((fn (pop query-specs))) |
| 757 | (unless (functionp range-fn) | 757 | (unless (functionp fn) |
| 758 | (signal 'treesit-error (list "Value of :range-fn option should be a function" range-fn))) | 758 | (signal 'treesit-error (list "Value of :range-fn option should be a function" fn))) |
| 759 | (setq range-fn range-fn))) | 759 | (setq range-fn fn))) |
| 760 | (query (if (functionp query) | 760 | (query (if (functionp query) |
| 761 | (push (list query nil nil) result) | 761 | (push (list query nil nil) result) |
| 762 | (when (null embed) | 762 | (when (null embed) |
| @@ -1423,22 +1423,31 @@ LANGUAGE is the language of QUERY.") | |||
| 1423 | (setf (nth 1 new-setting) t) | 1423 | (setf (nth 1 new-setting) t) |
| 1424 | new-setting)) | 1424 | new-setting)) |
| 1425 | 1425 | ||
| 1426 | (defun treesit--font-lock-level-setter (sym val) | 1426 | (defun treesit--font-lock-level-setter (sym val &optional buffer-local) |
| 1427 | "Custom setter for `treesit-font-lock-level'. | 1427 | "Custom setter for `treesit-font-lock-level'. |
| 1428 | Set the default value of SYM to VAL, recompute fontification | 1428 | Set the default value of SYM to VAL, recompute fontification |
| 1429 | features and refontify for every buffer where tree-sitter-based | 1429 | features and refontify for every buffer where tree-sitter-based |
| 1430 | fontification is enabled." | 1430 | fontification is enabled. |
| 1431 | (set-default sym val) | 1431 | |
| 1432 | (when (treesit-available-p) | 1432 | If optional BUFFER-LOCAL is non-nil, only affect the current buffer. |
| 1433 | (dolist (buffer (buffer-list)) | 1433 | Set SYM buffer locally and refontify." |
| 1434 | (with-current-buffer buffer | 1434 | ;; FIXME: This doesn't re-run major mode hooks, meaning any |
| 1435 | ;; FIXME: This doesn't re-run major mode hooks, meaning any | 1435 | ;; customization done in major mode hooks (e.g., with |
| 1436 | ;; customization done in major mode hooks (e.g., with | 1436 | ;; `treesit-font-lock-recompute-features') may be overridden. |
| 1437 | ;; `treesit-font-lock-recompute-features') is lost. | 1437 | (cond (buffer-local |
| 1438 | (when treesit-font-lock-settings | 1438 | (set-local sym val) |
| 1439 | (treesit-font-lock-recompute-features) | 1439 | (when (and (treesit-available-p) |
| 1440 | (treesit-font-lock-fontify-region | 1440 | treesit-font-lock-settings) |
| 1441 | (point-min) (point-max))))))) | 1441 | (treesit-font-lock-recompute-features) |
| 1442 | (font-lock-flush))) | ||
| 1443 | (t | ||
| 1444 | (set-default sym val) | ||
| 1445 | (when (treesit-available-p) | ||
| 1446 | (dolist (buffer (buffer-list)) | ||
| 1447 | (with-current-buffer buffer | ||
| 1448 | (when treesit-font-lock-settings | ||
| 1449 | (treesit-font-lock-recompute-features) | ||
| 1450 | (font-lock-flush)))))))) | ||
| 1442 | 1451 | ||
| 1443 | (defcustom treesit-font-lock-level 3 | 1452 | (defcustom treesit-font-lock-level 3 |
| 1444 | "Decoration level to be used by tree-sitter fontifications. | 1453 | "Decoration level to be used by tree-sitter fontifications. |
| @@ -2050,9 +2059,8 @@ If LOUDLY is non-nil, display some debugging information." | |||
| 2050 | (pcase-let ((`(,max-depth ,max-width) | 2059 | (pcase-let ((`(,max-depth ,max-width) |
| 2051 | (treesit-subtree-stat | 2060 | (treesit-subtree-stat |
| 2052 | (treesit-buffer-root-node language)))) | 2061 | (treesit-buffer-root-node language)))) |
| 2053 | (if (or (> max-depth 100) (> max-width 4000)) | 2062 | (setq treesit--font-lock-fast-mode |
| 2054 | (setq treesit--font-lock-fast-mode t) | 2063 | (or (> max-depth 100) (> max-width 4000))))) |
| 2055 | (setq treesit--font-lock-fast-mode nil)))) | ||
| 2056 | 2064 | ||
| 2057 | ;; Only activate if ENABLE flag is t. | 2065 | ;; Only activate if ENABLE flag is t. |
| 2058 | (when-let* | 2066 | (when-let* |
| @@ -5849,7 +5857,7 @@ language." | |||
| 5849 | "Pattern matching" | 5857 | "Pattern matching" |
| 5850 | (treesit-query-capture | 5858 | (treesit-query-capture |
| 5851 | :no-eval (treesit-query-capture node '((identifier) @id "return" @ret)) | 5859 | :no-eval (treesit-query-capture node '((identifier) @id "return" @ret)) |
| 5852 | :eg-result-string "((id . #<treesit-node (identifier) in 195-196>) (ret . #<treesit-node "return" in 338-344>))") | 5860 | :eg-result-string "((id . #<treesit-node (identifier) in 195-196>) (ret . #<treesit-node \"return\" in 338-344>))") |
| 5853 | (treesit-query-compile | 5861 | (treesit-query-compile |
| 5854 | :no-eval (treesit-query-compile 'c '((identifier) @id "return" @ret)) | 5862 | :no-eval (treesit-query-compile 'c '((identifier) @id "return" @ret)) |
| 5855 | :eg-result-string "#<treesit-compiled-query>") | 5863 | :eg-result-string "#<treesit-compiled-query>") |
diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index 042733f4c61..2dcae7362b7 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el | |||
| @@ -977,6 +977,7 @@ In the latter case, VC mode is deactivated for this buffer." | |||
| 977 | noninteractive | 977 | noninteractive |
| 978 | ;; Copied from server-start. Seems like there should | 978 | ;; Copied from server-start. Seems like there should |
| 979 | ;; be a better way to ask "can we get user input?"... | 979 | ;; be a better way to ask "can we get user input?"... |
| 980 | ;; Use `frame-initial-p'? | ||
| 980 | (and (daemonp) | 981 | (and (daemonp) |
| 981 | (null (cdr (frame-list))) | 982 | (null (cdr (frame-list))) |
| 982 | (eq (selected-frame) terminal-frame)) | 983 | (eq (selected-frame) terminal-frame)) |
diff --git a/lisp/whitespace.el b/lisp/whitespace.el index 9eb88eb35d0..50a687fe16b 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el | |||
| @@ -907,9 +907,9 @@ means that `whitespace-mode' is turned on for buffers in C and | |||
| 907 | C++ modes only. | 907 | C++ modes only. |
| 908 | 908 | ||
| 909 | Global `whitespace-mode' will not automatically turn on in internal | 909 | Global `whitespace-mode' will not automatically turn on in internal |
| 910 | buffers (with name starting from space) and special buffers (with name | 910 | buffers (whose names start with a space) and special buffers (whose |
| 911 | starting from \"*\"), except \"*scratch*\" buffer. Use | 911 | names start with \"*\"), with the exception of the \"*scratch*\" buffer. |
| 912 | `whitespace-global-mode-buffers' to customize this behavior." | 912 | Use `whitespace-global-mode-buffers' to customize this behavior." |
| 913 | :type '(choice :tag "Global Modes" | 913 | :type '(choice :tag "Global Modes" |
| 914 | (const :tag "None" nil) | 914 | (const :tag "None" nil) |
| 915 | (const :tag "All" t) | 915 | (const :tag "All" t) |
| @@ -919,11 +919,11 @@ starting from \"*\"), except \"*scratch*\" buffer. Use | |||
| 919 | (repeat :inline t | 919 | (repeat :inline t |
| 920 | (symbol :tag "Mode"))))) | 920 | (symbol :tag "Mode"))))) |
| 921 | 921 | ||
| 922 | (defcustom whitespace-global-mode-buffers (list (regexp-quote "*scratch*")) | 922 | (defcustom whitespace-global-mode-buffers (list (rx bos "*scratch*" eos)) |
| 923 | "Buffer name regexps where global `whitespace-mode' can be auto-enabled. | 923 | "Buffer name regexps where global `whitespace-mode' can be auto-enabled. |
| 924 | The value is a list of regexps. Set this custom option when you need | 924 | The value is a list of regexps. Set this custom option when you need |
| 925 | `whitespace-mode' in special buffers like *Org Src*." | 925 | `whitespace-mode' in special buffers like \"*Org Src*\"." |
| 926 | :type '(list (regexp :tag "Regexp matching buffer name")) | 926 | :type '(repeat (regexp :tag "Regexp matching buffer name")) |
| 927 | :version "31.1") | 927 | :version "31.1") |
| 928 | 928 | ||
| 929 | (defcustom whitespace-action nil | 929 | (defcustom whitespace-action nil |
| @@ -1049,14 +1049,13 @@ See also `whitespace-newline' and `whitespace-display-mappings'." | |||
| 1049 | ;; ...we have a display (not running a batch job) | 1049 | ;; ...we have a display (not running a batch job) |
| 1050 | (not noninteractive) | 1050 | (not noninteractive) |
| 1051 | ;; ...the buffer is not internal (name starts with a space) | 1051 | ;; ...the buffer is not internal (name starts with a space) |
| 1052 | (not (eq (aref (buffer-name) 0) ?\ )) | 1052 | (not (eq (aref (buffer-name) 0) ?\s)) |
| 1053 | ;; ...the buffer is not special (name starts with *) | 1053 | ;; ...the buffer is not special (name starts with *) |
| 1054 | (or (not (eq (aref (buffer-name) 0) ?*)) | 1054 | (or (not (eq (aref (buffer-name) 0) ?*)) |
| 1055 | ;; except the scratch buffer. | 1055 | ;; except, e.g., the scratch buffer. |
| 1056 | (seq-find | 1056 | (any (lambda (re) |
| 1057 | (lambda (re) | 1057 | (string-match-p re (buffer-name))) |
| 1058 | (string-match-p re (buffer-name))) | 1058 | whitespace-global-mode-buffers)))) |
| 1059 | whitespace-global-mode-buffers)))) | ||
| 1060 | "Predicate to decide which buffers obey `global-whitespace-mode'. | 1059 | "Predicate to decide which buffers obey `global-whitespace-mode'. |
| 1061 | This function is called with no argument and should return non-nil | 1060 | This function is called with no argument and should return non-nil |
| 1062 | if the current buffer should obey `global-whitespace-mode'. | 1061 | if the current buffer should obey `global-whitespace-mode'. |
diff --git a/lisp/window.el b/lisp/window.el index 1f7ae726f49..bd0653fe0d4 100644 --- a/lisp/window.el +++ b/lisp/window.el | |||
| @@ -1010,6 +1010,14 @@ and may be called only if no window on SIDE exists yet." | |||
| 1010 | (cons `(dedicated . ,(or display-buffer-mark-dedicated 'side)) | 1010 | (cons `(dedicated . ,(or display-buffer-mark-dedicated 'side)) |
| 1011 | alist)))) | 1011 | alist)))) |
| 1012 | (when window | 1012 | (when window |
| 1013 | ;; Protect the sibling (the main-window group) from recombination. | ||
| 1014 | ;; Without this, deleting a side window can flatten the group into | ||
| 1015 | ;; the root, causing subsequent side windows on other sides to be | ||
| 1016 | ;; placed incorrectly (Bug#80665). | ||
| 1017 | (when-let* ((sibling (or (window-prev-sibling window) | ||
| 1018 | (window-next-sibling window))) | ||
| 1019 | ((window-child sibling))) | ||
| 1020 | (set-window-combination-limit sibling t)) | ||
| 1013 | ;; Initialize `window-side' parameter of new window to SIDE and | 1021 | ;; Initialize `window-side' parameter of new window to SIDE and |
| 1014 | ;; make that parameter persistent. | 1022 | ;; make that parameter persistent. |
| 1015 | (set-window-parameter window 'window-side side) | 1023 | (set-window-parameter window 'window-side side) |
diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el index 67c475d563a..b93d914380f 100644 --- a/lisp/xt-mouse.el +++ b/lisp/xt-mouse.el | |||
| @@ -509,16 +509,14 @@ enable, ?l to disable)." | |||
| 509 | "Enable xterm mouse tracking on TERMINAL." | 509 | "Enable xterm mouse tracking on TERMINAL." |
| 510 | (when (and xterm-mouse-mode (eq t (terminal-live-p terminal)) | 510 | (when (and xterm-mouse-mode (eq t (terminal-live-p terminal)) |
| 511 | ;; Avoid the initial terminal which is not a termcap device. | 511 | ;; Avoid the initial terminal which is not a termcap device. |
| 512 | ;; FIXME: is there more elegant way to detect the initial | 512 | (not (frame-initial-p terminal))) |
| 513 | ;; terminal? | ||
| 514 | (not (string= (terminal-name terminal) "initial_terminal"))) | ||
| 515 | (unless (terminal-parameter terminal 'xterm-mouse-mode) | 513 | (unless (terminal-parameter terminal 'xterm-mouse-mode) |
| 516 | ;; Simulate selecting a terminal by selecting one of its frames | 514 | ;; Simulate selecting a terminal by selecting one of its frames |
| 517 | ;; so that we can set the terminal-local `input-decode-map'. | 515 | ;; so that we can set the terminal-local `input-decode-map'. |
| 518 | ;; Use the tty-top-frame to avoid accidentally making an invisible | 516 | ;; Use the tty-top-frame to avoid accidentally making an invisible |
| 519 | ;; child frame visible by selecting it (bug#79960). | 517 | ;; child frame visible by selecting it (bug#79960). |
| 520 | ;; The test for match mode is here because xt-mouse-tests run in | 518 | ;; The test for batch mode is here because xt-mouse-tests run in |
| 521 | ;; match mode, and there is no top-frame in that case. | 519 | ;; batch mode, and there is no top-frame in that case. |
| 522 | (with-selected-frame (if noninteractive | 520 | (with-selected-frame (if noninteractive |
| 523 | (car (frame-list)) | 521 | (car (frame-list)) |
| 524 | (tty-top-frame terminal)) | 522 | (tty-top-frame terminal)) |