diff options
| author | Juri Linkov | 2018-04-19 23:30:46 +0300 |
|---|---|---|
| committer | Juri Linkov | 2018-04-19 23:30:46 +0300 |
| commit | 99de04e6a84dbc93aab479666af126c8fb109b95 (patch) | |
| tree | 20ceee48fe073cdc4713017b64025975df5bf879 | |
| parent | 54f60fcad198be5f39fead6f4d453cea0942322a (diff) | |
| download | emacs-99de04e6a84dbc93aab479666af126c8fb109b95.tar.gz emacs-99de04e6a84dbc93aab479666af126c8fb109b95.zip | |
Use text properties to save search parameters. (Bug#22479)
* lisp/isearch.el (isearch-update-ring): Call isearch-string-propertize.
Delete duplicates with possibly different text properties.
(isearch-string-propertize)
(isearch-update-from-string-properties): New functions.
(with-isearch-suspended, isearch-ring-adjust1):
Call isearch-update-from-string-properties.
(isearch-edit-string): Let-bind minibuffer-allow-text-properties to t.
(isearch-query-replace): Use propertized isearch-string.
(isearch--lax-regexp-function-p): Simplify.
* lisp/replace.el (query-replace-descr): Rewrite to keep text properties
non-destructively in the replacement string.
(query-replace--split-string): Don't remove text properties
by substring-no-properties.
(query-replace-read-args): Try to get isearch-regexp-function
from text-properties.
(perform-replace): Display parameters in the replacement message.
* lisp/desktop.el (desktop--v2s): Check if text properties are unreadable.
(Bug#30786)
| -rw-r--r-- | lisp/desktop.el | 10 | ||||
| -rw-r--r-- | lisp/isearch.el | 53 | ||||
| -rw-r--r-- | lisp/replace.el | 36 |
3 files changed, 73 insertions, 26 deletions
diff --git a/lisp/desktop.el b/lisp/desktop.el index 55ec71c1b94..3e1ba200b50 100644 --- a/lisp/desktop.el +++ b/lisp/desktop.el | |||
| @@ -841,10 +841,12 @@ QUOTE may be `may' (value may be quoted), | |||
| 841 | ((or (numberp value) (null value) (eq t value) (keywordp value)) | 841 | ((or (numberp value) (null value) (eq t value) (keywordp value)) |
| 842 | (cons 'may value)) | 842 | (cons 'may value)) |
| 843 | ((stringp value) | 843 | ((stringp value) |
| 844 | (let ((copy (copy-sequence value))) | 844 | ;; Get rid of unreadable text properties. |
| 845 | (set-text-properties 0 (length copy) nil copy) | 845 | (if (condition-case nil (read (format "%S" value)) (error nil)) |
| 846 | ;; Get rid of text properties because we cannot read them. | 846 | (cons 'may value) |
| 847 | (cons 'may copy))) | 847 | (let ((copy (copy-sequence value))) |
| 848 | (set-text-properties 0 (length copy) nil copy) | ||
| 849 | (cons 'may copy)))) | ||
| 848 | ((symbolp value) | 850 | ((symbolp value) |
| 849 | (cons 'must value)) | 851 | (cons 'must value)) |
| 850 | ((vectorp value) | 852 | ((vectorp value) |
diff --git a/lisp/isearch.el b/lisp/isearch.el index e0066942f99..85193738c6f 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el | |||
| @@ -1126,10 +1126,29 @@ NOPUSH is t and EDIT is t." | |||
| 1126 | (defun isearch-update-ring (string &optional regexp) | 1126 | (defun isearch-update-ring (string &optional regexp) |
| 1127 | "Add STRING to the beginning of the search ring. | 1127 | "Add STRING to the beginning of the search ring. |
| 1128 | REGEXP if non-nil says use the regexp search ring." | 1128 | REGEXP if non-nil says use the regexp search ring." |
| 1129 | (add-to-history | 1129 | (let ((history-delete-duplicates t)) |
| 1130 | (if regexp 'regexp-search-ring 'search-ring) | 1130 | (add-to-history |
| 1131 | string | 1131 | (if regexp 'regexp-search-ring 'search-ring) |
| 1132 | (if regexp regexp-search-ring-max search-ring-max))) | 1132 | (isearch-string-propertize string) |
| 1133 | (if regexp regexp-search-ring-max search-ring-max) | ||
| 1134 | t))) | ||
| 1135 | |||
| 1136 | (defun isearch-string-propertize (string &optional properties) | ||
| 1137 | "Add isearch properties to the isearch string." | ||
| 1138 | (unless properties | ||
| 1139 | (setq properties `(isearch-case-fold-search ,isearch-case-fold-search)) | ||
| 1140 | (unless isearch-regexp | ||
| 1141 | (setq properties (append properties `(isearch-regexp-function ,isearch-regexp-function))))) | ||
| 1142 | (apply 'propertize string properties)) | ||
| 1143 | |||
| 1144 | (defun isearch-update-from-string-properties (string) | ||
| 1145 | "Update isearch properties from the isearch string" | ||
| 1146 | (when (memq 'isearch-case-fold-search (text-properties-at 0 string)) | ||
| 1147 | (setq isearch-case-fold-search | ||
| 1148 | (get-text-property 0 'isearch-case-fold-search string))) | ||
| 1149 | (when (memq 'isearch-regexp-function (text-properties-at 0 string)) | ||
| 1150 | (setq isearch-regexp-function | ||
| 1151 | (get-text-property 0 'isearch-regexp-function string)))) | ||
| 1133 | 1152 | ||
| 1134 | 1153 | ||
| 1135 | ;; The search status structure and stack. | 1154 | ;; The search status structure and stack. |
| @@ -1335,6 +1354,8 @@ You can update the global isearch variables by setting new values to | |||
| 1335 | multi-isearch-file-list multi-isearch-file-list-new | 1354 | multi-isearch-file-list multi-isearch-file-list-new |
| 1336 | multi-isearch-buffer-list multi-isearch-buffer-list-new) | 1355 | multi-isearch-buffer-list multi-isearch-buffer-list-new) |
| 1337 | 1356 | ||
| 1357 | (isearch-update-from-string-properties isearch-string) | ||
| 1358 | |||
| 1338 | ;; Restore the minibuffer message before moving point. | 1359 | ;; Restore the minibuffer message before moving point. |
| 1339 | (funcall (or isearch-message-function #'isearch-message) nil t) | 1360 | (funcall (or isearch-message-function #'isearch-message) nil t) |
| 1340 | 1361 | ||
| @@ -1401,7 +1422,9 @@ The following additional command keys are active while editing. | |||
| 1401 | (history-add-new-input nil) | 1422 | (history-add-new-input nil) |
| 1402 | ;; Binding minibuffer-history-symbol to nil is a work-around | 1423 | ;; Binding minibuffer-history-symbol to nil is a work-around |
| 1403 | ;; for some incompatibility with gmhist. | 1424 | ;; for some incompatibility with gmhist. |
| 1404 | (minibuffer-history-symbol)) | 1425 | (minibuffer-history-symbol) |
| 1426 | ;; Search string might have meta information on text properties. | ||
| 1427 | (minibuffer-allow-text-properties t)) | ||
| 1405 | (setq isearch-new-string | 1428 | (setq isearch-new-string |
| 1406 | (read-from-minibuffer | 1429 | (read-from-minibuffer |
| 1407 | (isearch-message-prefix nil isearch-nonincremental) | 1430 | (isearch-message-prefix nil isearch-nonincremental) |
| @@ -1826,7 +1849,9 @@ replacements from Isearch is `M-s w ... M-%'." | |||
| 1826 | ;; `exit-recursive-edit' in `isearch-done' that terminates | 1849 | ;; `exit-recursive-edit' in `isearch-done' that terminates |
| 1827 | ;; the execution of this command when it is non-nil. | 1850 | ;; the execution of this command when it is non-nil. |
| 1828 | ;; We call `exit-recursive-edit' explicitly at the end below. | 1851 | ;; We call `exit-recursive-edit' explicitly at the end below. |
| 1829 | (isearch-recursive-edit nil)) | 1852 | (isearch-recursive-edit nil) |
| 1853 | (isearch-string-propertized | ||
| 1854 | (isearch-string-propertize isearch-string))) | ||
| 1830 | (isearch-done nil t) | 1855 | (isearch-done nil t) |
| 1831 | (isearch-clean-overlays) | 1856 | (isearch-clean-overlays) |
| 1832 | (if (and isearch-other-end | 1857 | (if (and isearch-other-end |
| @@ -1839,12 +1864,12 @@ replacements from Isearch is `M-s w ... M-%'." | |||
| 1839 | (< (mark) (point)))))) | 1864 | (< (mark) (point)))))) |
| 1840 | (goto-char isearch-other-end)) | 1865 | (goto-char isearch-other-end)) |
| 1841 | (set query-replace-from-history-variable | 1866 | (set query-replace-from-history-variable |
| 1842 | (cons isearch-string | 1867 | (cons isearch-string-propertized |
| 1843 | (symbol-value query-replace-from-history-variable))) | 1868 | (symbol-value query-replace-from-history-variable))) |
| 1844 | (perform-replace | 1869 | (perform-replace |
| 1845 | isearch-string | 1870 | isearch-string-propertized |
| 1846 | (query-replace-read-to | 1871 | (query-replace-read-to |
| 1847 | isearch-string | 1872 | isearch-string-propertized |
| 1848 | (concat "Query replace" | 1873 | (concat "Query replace" |
| 1849 | (isearch--describe-regexp-mode (or delimited isearch-regexp-function) t) | 1874 | (isearch--describe-regexp-mode (or delimited isearch-regexp-function) t) |
| 1850 | (if backward " backward" "") | 1875 | (if backward " backward" "") |
| @@ -2552,7 +2577,8 @@ Search is updated accordingly." | |||
| 2552 | length))) | 2577 | length))) |
| 2553 | (setq isearch-string (nth yank-pointer ring) | 2578 | (setq isearch-string (nth yank-pointer ring) |
| 2554 | isearch-message (mapconcat 'isearch-text-char-description | 2579 | isearch-message (mapconcat 'isearch-text-char-description |
| 2555 | isearch-string ""))))) | 2580 | isearch-string "")) |
| 2581 | (isearch-update-from-string-properties isearch-string)))) | ||
| 2556 | 2582 | ||
| 2557 | (defun isearch-ring-adjust (advance) | 2583 | (defun isearch-ring-adjust (advance) |
| 2558 | ;; Helper for isearch-ring-advance and isearch-ring-retreat | 2584 | ;; Helper for isearch-ring-advance and isearch-ring-retreat |
| @@ -2768,11 +2794,8 @@ Can be changed via `isearch-search-fun-function' for special needs." | |||
| 2768 | 2794 | ||
| 2769 | (defun isearch--lax-regexp-function-p () | 2795 | (defun isearch--lax-regexp-function-p () |
| 2770 | "Non-nil if next regexp-function call should be lax." | 2796 | "Non-nil if next regexp-function call should be lax." |
| 2771 | (not (or isearch-nonincremental | 2797 | (or (memq this-command '(isearch-printing-char isearch-del-char)) |
| 2772 | (null (car isearch-cmds)) | 2798 | isearch-yank-flag)) |
| 2773 | (eq (length isearch-string) | ||
| 2774 | (length (isearch--state-string | ||
| 2775 | (car isearch-cmds))))))) | ||
| 2776 | 2799 | ||
| 2777 | (defun isearch-search-fun-default () | 2800 | (defun isearch-search-fun-default () |
| 2778 | "Return default functions to use for the search." | 2801 | "Return default functions to use for the search." |
diff --git a/lisp/replace.el b/lisp/replace.el index 7f3541d7735..0e723390347 100644 --- a/lisp/replace.el +++ b/lisp/replace.el | |||
| @@ -147,15 +147,26 @@ is highlighted lazily using isearch lazy highlighting (see | |||
| 147 | See `replace-regexp' and `query-replace-regexp-eval'.") | 147 | See `replace-regexp' and `query-replace-regexp-eval'.") |
| 148 | 148 | ||
| 149 | (defun query-replace-descr (string) | 149 | (defun query-replace-descr (string) |
| 150 | (mapconcat 'isearch-text-char-description string "")) | 150 | (setq string (copy-sequence string)) |
| 151 | (dotimes (i (length string) string) | ||
| 152 | (let ((c (aref string i))) | ||
| 153 | (cond | ||
| 154 | ((< c ?\s) (add-text-properties | ||
| 155 | i (1+ i) | ||
| 156 | `(display ,(propertize (format "^%c" (+ c 64)) 'face 'escape-glyph)) | ||
| 157 | string)) | ||
| 158 | ((= c ?\^?) (add-text-properties | ||
| 159 | i (1+ i) | ||
| 160 | `(display ,(propertize "^?" 'face 'escape-glyph)) | ||
| 161 | string)))))) | ||
| 151 | 162 | ||
| 152 | (defun query-replace--split-string (string) | 163 | (defun query-replace--split-string (string) |
| 153 | "Split string STRING at a substring with property `separator'." | 164 | "Split string STRING at a substring with property `separator'." |
| 154 | (let* ((length (length string)) | 165 | (let* ((length (length string)) |
| 155 | (split-pos (text-property-any 0 length 'separator t string))) | 166 | (split-pos (text-property-any 0 length 'separator t string))) |
| 156 | (if (not split-pos) | 167 | (if (not split-pos) |
| 157 | (substring-no-properties string) | 168 | string |
| 158 | (cons (substring-no-properties string 0 split-pos) | 169 | (cons (substring string 0 split-pos) |
| 159 | (substring-no-properties | 170 | (substring-no-properties |
| 160 | string (or (text-property-not-all | 171 | string (or (text-property-not-all |
| 161 | (1+ split-pos) length 'separator t string) | 172 | (1+ split-pos) length 'separator t string) |
| @@ -301,7 +312,9 @@ the original string if not." | |||
| 301 | (to (if (consp from) (prog1 (cdr from) (setq from (car from))) | 312 | (to (if (consp from) (prog1 (cdr from) (setq from (car from))) |
| 302 | (query-replace-read-to from prompt regexp-flag)))) | 313 | (query-replace-read-to from prompt regexp-flag)))) |
| 303 | (list from to | 314 | (list from to |
| 304 | (and current-prefix-arg (not (eq current-prefix-arg '-))) | 315 | (or (and current-prefix-arg (not (eq current-prefix-arg '-))) |
| 316 | (and (memq 'isearch-regexp-function (text-properties-at 0 from)) | ||
| 317 | (get-text-property 0 'isearch-regexp-function from))) | ||
| 305 | (and current-prefix-arg (eq current-prefix-arg '-))))) | 318 | (and current-prefix-arg (eq current-prefix-arg '-))))) |
| 306 | 319 | ||
| 307 | (defun query-replace (from-string to-string &optional delimited start end backward region-noncontiguous-p) | 320 | (defun query-replace (from-string to-string &optional delimited start end backward region-noncontiguous-p) |
| @@ -2379,8 +2392,17 @@ characters." | |||
| 2379 | (message | 2392 | (message |
| 2380 | (if query-flag | 2393 | (if query-flag |
| 2381 | (apply 'propertize | 2394 | (apply 'propertize |
| 2382 | (substitute-command-keys | 2395 | (concat "Query replacing " |
| 2383 | "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ") | 2396 | (if backward "backward " "") |
| 2397 | (if delimited-flag | ||
| 2398 | (or (and (symbolp delimited-flag) | ||
| 2399 | (get delimited-flag | ||
| 2400 | 'isearch-message-prefix)) | ||
| 2401 | "word ") "") | ||
| 2402 | (if regexp-flag "regexp " "") | ||
| 2403 | "%s with %s: " | ||
| 2404 | (substitute-command-keys | ||
| 2405 | "(\\<query-replace-map>\\[help] for help) ")) | ||
| 2384 | minibuffer-prompt-properties)))) | 2406 | minibuffer-prompt-properties)))) |
| 2385 | 2407 | ||
| 2386 | ;; Unless a single contiguous chunk is selected, operate on multiple chunks. | 2408 | ;; Unless a single contiguous chunk is selected, operate on multiple chunks. |
| @@ -2598,13 +2620,13 @@ characters." | |||
| 2598 | (with-output-to-temp-buffer "*Help*" | 2620 | (with-output-to-temp-buffer "*Help*" |
| 2599 | (princ | 2621 | (princ |
| 2600 | (concat "Query replacing " | 2622 | (concat "Query replacing " |
| 2623 | (if backward "backward " "") | ||
| 2601 | (if delimited-flag | 2624 | (if delimited-flag |
| 2602 | (or (and (symbolp delimited-flag) | 2625 | (or (and (symbolp delimited-flag) |
| 2603 | (get delimited-flag | 2626 | (get delimited-flag |
| 2604 | 'isearch-message-prefix)) | 2627 | 'isearch-message-prefix)) |
| 2605 | "word ") "") | 2628 | "word ") "") |
| 2606 | (if regexp-flag "regexp " "") | 2629 | (if regexp-flag "regexp " "") |
| 2607 | (if backward "backward " "") | ||
| 2608 | from-string " with " | 2630 | from-string " with " |
| 2609 | next-replacement ".\n\n" | 2631 | next-replacement ".\n\n" |
| 2610 | (substitute-command-keys | 2632 | (substitute-command-keys |