diff options
| author | Fabián Ezequiel Gallina | 2014-07-26 20:43:51 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2014-07-26 20:43:51 -0300 |
| commit | 60cc81af68080a8d1edb7584ce0966754595e187 (patch) | |
| tree | f1cc7f5b5194843d85d125b2ffd651679b05ca2e /lisp/progmodes/python.el | |
| parent | 9e9f8582a893f1e97b1f8955f69b96f969ee1f85 (diff) | |
| download | emacs-60cc81af68080a8d1edb7584ce0966754595e187.tar.gz emacs-60cc81af68080a8d1edb7584ce0966754595e187.zip | |
Robust shell syntax highlighting. (Bug#18084, Bug#16875)
* lisp/progmodes/python.el:
(python-shell-prompt-input-regexps): Add iPython block prompt.
(python-shell-output-syntax-table): Delete var.
(python-shell-font-lock-with-font-lock-buffer): New macro.
(python-shell-font-lock-get-or-create-buffer)
(python-shell-font-lock-kill-buffer)
(python-shell-font-lock-cleanup-buffer)
(python-shell-font-lock-post-command-hook)
(python-shell-font-lock-turn-off): New functions.
(python-shell-font-lock-turn-on): New function.
(inferior-python-mode): Use it.
(python-shell-font-lock-toggle): New command.
(python-shell-font-lock-enable): Rename from
python-shell-enable-font-lock.
(run-python-internal): Use it.
(python-shell-font-lock-comint-output-filter-function): New function.
(python-shell-comint-end-of-output-p): New function.
(python-shell-output-filter): Use it.
(python-util-comint-last-prompt): New function.
(python-util-text-properties-replace-name): New function.
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 250 |
1 files changed, 197 insertions, 53 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 89ef12d49eb..d8866a1c930 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -31,9 +31,9 @@ | |||
| 31 | ;; found in GNU/Emacs. | 31 | ;; found in GNU/Emacs. |
| 32 | 32 | ||
| 33 | ;; Implements Syntax highlighting, Indentation, Movement, Shell | 33 | ;; Implements Syntax highlighting, Indentation, Movement, Shell |
| 34 | ;; interaction, Shell completion, Shell virtualenv support, Pdb | 34 | ;; interaction, Shell completion, Shell virtualenv support, Shell |
| 35 | ;; tracking, Symbol completion, Skeletons, FFAP, Code Check, Eldoc, | 35 | ;; syntax highlighting, Pdb tracking, Symbol completion, Skeletons, |
| 36 | ;; Imenu. | 36 | ;; FFAP, Code Check, Eldoc, Imenu. |
| 37 | 37 | ||
| 38 | ;; Syntax highlighting: Fontification of code is provided and supports | 38 | ;; Syntax highlighting: Fontification of code is provided and supports |
| 39 | ;; python's triple quoted strings properly. | 39 | ;; python's triple quoted strings properly. |
| @@ -170,6 +170,12 @@ | |||
| 170 | ;; introduced as simple way of adding paths to the PYTHONPATH without | 170 | ;; introduced as simple way of adding paths to the PYTHONPATH without |
| 171 | ;; affecting existing values. | 171 | ;; affecting existing values. |
| 172 | 172 | ||
| 173 | ;; Shell syntax highlighting: when enabled current input in shell is | ||
| 174 | ;; highlighted. The variable `python-shell-font-lock-enable' controls | ||
| 175 | ;; activation of this feature globally when shells are started. | ||
| 176 | ;; Activation/deactivation can be also controlled on the fly via the | ||
| 177 | ;; `python-shell-font-lock-toggle' command. | ||
| 178 | |||
| 173 | ;; Pdb tracking: when you execute a block of code that contains some | 179 | ;; Pdb tracking: when you execute a block of code that contains some |
| 174 | ;; call to pdb (or ipdb) it will prompt the block of code and will | 180 | ;; call to pdb (or ipdb) it will prompt the block of code and will |
| 175 | ;; follow the execution of pdb marking the current line with an arrow. | 181 | ;; follow the execution of pdb marking the current line with an arrow. |
| @@ -1750,6 +1756,7 @@ position, else returns nil." | |||
| 1750 | (defcustom python-shell-prompt-input-regexps | 1756 | (defcustom python-shell-prompt-input-regexps |
| 1751 | '(">>> " "\\.\\.\\. " ; Python | 1757 | '(">>> " "\\.\\.\\. " ; Python |
| 1752 | "In \\[[0-9]+\\]: " ; IPython | 1758 | "In \\[[0-9]+\\]: " ; IPython |
| 1759 | " \\.\\.\\.: " ; IPython | ||
| 1753 | ;; Using ipdb outside IPython may fail to cleanup and leave static | 1760 | ;; Using ipdb outside IPython may fail to cleanup and leave static |
| 1754 | ;; IPython prompts activated, this adds some safeguard for that. | 1761 | ;; IPython prompts activated, this adds some safeguard for that. |
| 1755 | "In : " "\\.\\.\\.: ") | 1762 | "In : " "\\.\\.\\.: ") |
| @@ -1785,13 +1792,16 @@ It should not contain a caret (^) at the beginning." | |||
| 1785 | It should not contain a caret (^) at the beginning." | 1792 | It should not contain a caret (^) at the beginning." |
| 1786 | :type 'string) | 1793 | :type 'string) |
| 1787 | 1794 | ||
| 1788 | (defcustom python-shell-enable-font-lock t | 1795 | (defcustom python-shell-font-lock-enable t |
| 1789 | "Should syntax highlighting be enabled in the Python shell buffer? | 1796 | "Should syntax highlighting be enabled in the Python shell buffer? |
| 1790 | Restart the Python shell after changing this variable for it to take effect." | 1797 | Restart the Python shell after changing this variable for it to take effect." |
| 1791 | :type 'boolean | 1798 | :type 'boolean |
| 1792 | :group 'python | 1799 | :group 'python |
| 1793 | :safe 'booleanp) | 1800 | :safe 'booleanp) |
| 1794 | 1801 | ||
| 1802 | (define-obsolete-variable-alias | ||
| 1803 | 'python-shell-enable-font-lock python-shell-font-lock-enable "24.4") | ||
| 1804 | |||
| 1795 | (defcustom python-shell-process-environment nil | 1805 | (defcustom python-shell-process-environment nil |
| 1796 | "List of environment variables for Python shell. | 1806 | "List of environment variables for Python shell. |
| 1797 | This variable follows the same rules as `process-environment' | 1807 | This variable follows the same rules as `process-environment' |
| @@ -2090,6 +2100,20 @@ uniqueness for different types of configurations." | |||
| 2090 | (directory-file-name python-shell-virtualenv-path)) | 2100 | (directory-file-name python-shell-virtualenv-path)) |
| 2091 | path)))) | 2101 | path)))) |
| 2092 | 2102 | ||
| 2103 | (defun python-shell-comint-end-of-output-p (output) | ||
| 2104 | "Return non-nil if OUTPUT is ends with input prompt." | ||
| 2105 | (string-match | ||
| 2106 | ;; XXX: It seems on OSX an extra carriage return is attached | ||
| 2107 | ;; at the end of output, this handles that too. | ||
| 2108 | (concat | ||
| 2109 | "\r?\n?" | ||
| 2110 | ;; Remove initial caret from calculated regexp | ||
| 2111 | (replace-regexp-in-string | ||
| 2112 | (rx string-start ?^) "" | ||
| 2113 | python-shell--prompt-calculated-input-regexp) | ||
| 2114 | (rx eos)) | ||
| 2115 | output)) | ||
| 2116 | |||
| 2093 | (defun python-comint-output-filter-function (output) | 2117 | (defun python-comint-output-filter-function (output) |
| 2094 | "Hook run after content is put into comint buffer. | 2118 | "Hook run after content is put into comint buffer. |
| 2095 | OUTPUT is a string with the contents of the buffer." | 2119 | OUTPUT is a string with the contents of the buffer." |
| @@ -2097,19 +2121,140 @@ OUTPUT is a string with the contents of the buffer." | |||
| 2097 | 2121 | ||
| 2098 | (defvar python-shell--parent-buffer nil) | 2122 | (defvar python-shell--parent-buffer nil) |
| 2099 | 2123 | ||
| 2100 | (defvar python-shell-output-syntax-table | 2124 | (defvar python-shell--font-lock-buffer nil) |
| 2101 | (let ((table (make-syntax-table python-dotty-syntax-table))) | 2125 | |
| 2102 | (modify-syntax-entry ?\' "." table) | 2126 | (defun python-shell-font-lock-get-or-create-buffer () |
| 2103 | (modify-syntax-entry ?\" "." table) | 2127 | "Get or create a font-lock buffer for current inferior process." |
| 2104 | (modify-syntax-entry ?\( "." table) | 2128 | (if python-shell--font-lock-buffer |
| 2105 | (modify-syntax-entry ?\[ "." table) | 2129 | python-shell--font-lock-buffer |
| 2106 | (modify-syntax-entry ?\{ "." table) | 2130 | (let ((process-name |
| 2107 | (modify-syntax-entry ?\) "." table) | 2131 | (process-name (get-buffer-process (current-buffer))))) |
| 2108 | (modify-syntax-entry ?\] "." table) | 2132 | (generate-new-buffer |
| 2109 | (modify-syntax-entry ?\} "." table) | 2133 | (format "*%s-font-lock*" process-name))))) |
| 2110 | table) | 2134 | |
| 2111 | "Syntax table for shell output. | 2135 | (defun python-shell-font-lock-kill-buffer () |
| 2112 | It makes parens and quotes be treated as punctuation chars.") | 2136 | "Kill the font-lock buffer safely." |
| 2137 | (when (and python-shell--font-lock-buffer | ||
| 2138 | (buffer-live-p python-shell--font-lock-buffer)) | ||
| 2139 | (kill-buffer python-shell--font-lock-buffer) | ||
| 2140 | (when (eq major-mode 'inferior-python-mode) | ||
| 2141 | (setq python-shell--font-lock-buffer nil)))) | ||
| 2142 | |||
| 2143 | (defmacro python-shell-font-lock-with-font-lock-buffer (&rest body) | ||
| 2144 | "Execute the forms in BODY in the font-lock buffer. | ||
| 2145 | The value returned is the value of the last form in BODY. See | ||
| 2146 | also `with-current-buffer'." | ||
| 2147 | (declare (indent 0) (debug t)) | ||
| 2148 | `(save-current-buffer | ||
| 2149 | (when (not (eq major-mode 'inferior-python-mode)) | ||
| 2150 | (error "Current buffer is not in `inferior-python-mode'.")) | ||
| 2151 | (when (not (and python-shell--font-lock-buffer | ||
| 2152 | (get-buffer python-shell--font-lock-buffer))) | ||
| 2153 | (setq python-shell--font-lock-buffer | ||
| 2154 | (python-shell-font-lock-get-or-create-buffer))) | ||
| 2155 | (set-buffer python-shell--font-lock-buffer) | ||
| 2156 | (set (make-local-variable 'delay-mode-hooks) t) | ||
| 2157 | (let ((python-indent-guess-indent-offset nil)) | ||
| 2158 | (when (not (eq major-mode 'python-mode)) | ||
| 2159 | (python-mode)) | ||
| 2160 | ,@body))) | ||
| 2161 | |||
| 2162 | (defun python-shell-font-lock-cleanup-buffer () | ||
| 2163 | "Cleanup the font-lock buffer. | ||
| 2164 | Provided as a command because this might be handy if something | ||
| 2165 | goes wrong and syntax highlighting in the shell gets messed up." | ||
| 2166 | (interactive) | ||
| 2167 | (python-shell-font-lock-with-font-lock-buffer | ||
| 2168 | (delete-region (point-min) (point-max)))) | ||
| 2169 | |||
| 2170 | (defun python-shell-font-lock-comint-output-filter-function (output) | ||
| 2171 | "Clean up the font-lock buffer after any OUTPUT." | ||
| 2172 | (when (and (not (string= "" output)) | ||
| 2173 | ;; Is end of output and is not just a prompt. | ||
| 2174 | (not (member | ||
| 2175 | (python-shell-comint-end-of-output-p | ||
| 2176 | (ansi-color-filter-apply output)) | ||
| 2177 | '(nil 0)))) | ||
| 2178 | ;; If output is other than an input prompt then "real" output has | ||
| 2179 | ;; been received and the font-lock buffer must be cleaned up. | ||
| 2180 | (python-shell-font-lock-cleanup-buffer)) | ||
| 2181 | output) | ||
| 2182 | |||
| 2183 | (defun python-shell-font-lock-post-command-hook () | ||
| 2184 | "Fontifies current line in shell buffer." | ||
| 2185 | (if (eq this-command 'comint-send-input) | ||
| 2186 | ;; Add a newline when user sends input as this may be a block. | ||
| 2187 | (python-shell-font-lock-with-font-lock-buffer | ||
| 2188 | (goto-char (line-end-position)) | ||
| 2189 | (newline)) | ||
| 2190 | (when (and (python-util-comint-last-prompt) | ||
| 2191 | (> (point) (cdr (python-util-comint-last-prompt)))) | ||
| 2192 | (let ((input (buffer-substring-no-properties | ||
| 2193 | (cdr (python-util-comint-last-prompt)) (point-max)))) | ||
| 2194 | (delete-region (cdr (python-util-comint-last-prompt)) (point-max)) | ||
| 2195 | (insert | ||
| 2196 | (python-shell-font-lock-with-font-lock-buffer | ||
| 2197 | (delete-region (line-beginning-position) | ||
| 2198 | (line-end-position)) | ||
| 2199 | (insert input) | ||
| 2200 | ;; Ensure buffer is fontified, keeping it | ||
| 2201 | ;; compatible with Emacs < 24.4. | ||
| 2202 | (if (fboundp 'font-lock-ensure) | ||
| 2203 | (funcall 'font-lock-ensure) | ||
| 2204 | (font-lock-default-fontify-buffer)) | ||
| 2205 | ;; Replace FACE text properties with FONT-LOCK-FACE so they | ||
| 2206 | ;; are not overwritten by current buffer's font-lock | ||
| 2207 | (python-util-text-properties-replace-name | ||
| 2208 | 'face 'font-lock-face) | ||
| 2209 | (buffer-substring (line-beginning-position) | ||
| 2210 | (line-end-position)))))))) | ||
| 2211 | |||
| 2212 | (defun python-shell-font-lock-turn-on (&optional msg) | ||
| 2213 | "Turn on shell font-lock. | ||
| 2214 | With argument MSG show activation message." | ||
| 2215 | (python-shell-font-lock-kill-buffer) | ||
| 2216 | (set (make-local-variable 'python-shell--font-lock-buffer) nil) | ||
| 2217 | (add-hook 'post-command-hook | ||
| 2218 | #'python-shell-font-lock-post-command-hook nil 'local) | ||
| 2219 | (add-hook 'kill-buffer-hook | ||
| 2220 | #'python-shell-font-lock-kill-buffer nil 'local) | ||
| 2221 | (add-hook 'comint-output-filter-functions | ||
| 2222 | #'python-shell-font-lock-comint-output-filter-function | ||
| 2223 | 'append 'local) | ||
| 2224 | (when msg | ||
| 2225 | (message "Shell font-lock is enabled"))) | ||
| 2226 | |||
| 2227 | (defun python-shell-font-lock-turn-off (&optional msg) | ||
| 2228 | "Turn off shell font-lock. | ||
| 2229 | With argument MSG show deactivation message." | ||
| 2230 | (python-shell-font-lock-kill-buffer) | ||
| 2231 | (when (python-util-comint-last-prompt) | ||
| 2232 | ;; Cleanup current fontification | ||
| 2233 | (remove-text-properties | ||
| 2234 | (cdr (python-util-comint-last-prompt)) | ||
| 2235 | (line-end-position) | ||
| 2236 | '(face nil font-lock-face nil))) | ||
| 2237 | (set (make-local-variable 'python-shell--font-lock-buffer) nil) | ||
| 2238 | (remove-hook 'post-command-hook | ||
| 2239 | #'python-shell-font-lock-post-command-hook'local) | ||
| 2240 | (remove-hook 'kill-buffer-hook | ||
| 2241 | #'python-shell-font-lock-kill-buffer 'local) | ||
| 2242 | (remove-hook 'comint-output-filter-functions | ||
| 2243 | #'python-shell-font-lock-comint-output-filter-function | ||
| 2244 | 'local) | ||
| 2245 | (when msg | ||
| 2246 | (message "Shell font-lock is disabled"))) | ||
| 2247 | |||
| 2248 | (defun python-shell-font-lock-toggle (&optional msg) | ||
| 2249 | "Toggle font-lock for shell. | ||
| 2250 | With argument MSG show activation/deactivation message." | ||
| 2251 | (interactive "p") | ||
| 2252 | (set (make-local-variable 'python-shell-font-lock-enable) | ||
| 2253 | (not python-shell-font-lock-enable)) | ||
| 2254 | (if python-shell-font-lock-enable | ||
| 2255 | (python-shell-font-lock-turn-on msg) | ||
| 2256 | (python-shell-font-lock-turn-off msg)) | ||
| 2257 | python-shell-font-lock-enable) | ||
| 2113 | 2258 | ||
| 2114 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" | 2259 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" |
| 2115 | "Major mode for Python inferior process. | 2260 | "Major mode for Python inferior process. |
| @@ -2120,7 +2265,7 @@ interpreter is run. Variables | |||
| 2120 | `python-shell-prompt-regexp', | 2265 | `python-shell-prompt-regexp', |
| 2121 | `python-shell-prompt-output-regexp', | 2266 | `python-shell-prompt-output-regexp', |
| 2122 | `python-shell-prompt-block-regexp', | 2267 | `python-shell-prompt-block-regexp', |
| 2123 | `python-shell-enable-font-lock', | 2268 | `python-shell-font-lock-enable', |
| 2124 | `python-shell-completion-setup-code', | 2269 | `python-shell-completion-setup-code', |
| 2125 | `python-shell-completion-string-code', | 2270 | `python-shell-completion-string-code', |
| 2126 | `python-shell-completion-module-string-code', | 2271 | `python-shell-completion-module-string-code', |
| @@ -2165,29 +2310,8 @@ variable. | |||
| 2165 | (make-local-variable 'python-pdbtrack-buffers-to-kill) | 2310 | (make-local-variable 'python-pdbtrack-buffers-to-kill) |
| 2166 | (make-local-variable 'python-pdbtrack-tracked-buffer) | 2311 | (make-local-variable 'python-pdbtrack-tracked-buffer) |
| 2167 | (make-local-variable 'python-shell-internal-last-output) | 2312 | (make-local-variable 'python-shell-internal-last-output) |
| 2168 | (when python-shell-enable-font-lock | 2313 | (when python-shell-font-lock-enable |
| 2169 | (set-syntax-table python-mode-syntax-table) | 2314 | (python-shell-font-lock-turn-on)) |
| 2170 | (set (make-local-variable 'font-lock-defaults) | ||
| 2171 | '(python-font-lock-keywords nil nil nil nil)) | ||
| 2172 | (set (make-local-variable 'syntax-propertize-function) | ||
| 2173 | (eval | ||
| 2174 | ;; XXX: Unfortunately eval is needed here to make use of the | ||
| 2175 | ;; dynamic value of `comint-prompt-regexp'. | ||
| 2176 | `(syntax-propertize-rules | ||
| 2177 | (,comint-prompt-regexp | ||
| 2178 | (0 (ignore | ||
| 2179 | (put-text-property | ||
| 2180 | comint-last-input-start end 'syntax-table | ||
| 2181 | python-shell-output-syntax-table) | ||
| 2182 | ;; XXX: This might look weird, but it is the easiest | ||
| 2183 | ;; way to ensure font lock gets cleaned up before the | ||
| 2184 | ;; current prompt, which is needed for unclosed | ||
| 2185 | ;; strings to not mess up with current input. | ||
| 2186 | (font-lock-unfontify-region comint-last-input-start end)))) | ||
| 2187 | (,(python-rx string-delimiter) | ||
| 2188 | (0 (ignore | ||
| 2189 | (and (not (eq (get-text-property start 'field) 'output)) | ||
| 2190 | (python-syntax-stringify))))))))) | ||
| 2191 | (compilation-shell-minor-mode 1)) | 2315 | (compilation-shell-minor-mode 1)) |
| 2192 | 2316 | ||
| 2193 | (defun python-shell-make-comint (cmd proc-name &optional pop internal) | 2317 | (defun python-shell-make-comint (cmd proc-name &optional pop internal) |
| @@ -2267,10 +2391,10 @@ difference with global or dedicated shells is that these ones are | |||
| 2267 | attached to a configuration, not a buffer. This means that can | 2391 | attached to a configuration, not a buffer. This means that can |
| 2268 | be used for example to retrieve the sys.path and other stuff, | 2392 | be used for example to retrieve the sys.path and other stuff, |
| 2269 | without messing with user shells. Note that | 2393 | without messing with user shells. Note that |
| 2270 | `python-shell-enable-font-lock' and `inferior-python-mode-hook' | 2394 | `python-shell-font-lock-enable' and `inferior-python-mode-hook' |
| 2271 | are set to nil for these shells, so setup codes are not sent at | 2395 | are set to nil for these shells, so setup codes are not sent at |
| 2272 | startup." | 2396 | startup." |
| 2273 | (let ((python-shell-enable-font-lock nil) | 2397 | (let ((python-shell-font-lock-enable nil) |
| 2274 | (inferior-python-mode-hook nil)) | 2398 | (inferior-python-mode-hook nil)) |
| 2275 | (get-buffer-process | 2399 | (get-buffer-process |
| 2276 | (python-shell-make-comint | 2400 | (python-shell-make-comint |
| @@ -2390,16 +2514,7 @@ detecting a prompt at the end of the buffer." | |||
| 2390 | string (ansi-color-filter-apply string) | 2514 | string (ansi-color-filter-apply string) |
| 2391 | python-shell-output-filter-buffer | 2515 | python-shell-output-filter-buffer |
| 2392 | (concat python-shell-output-filter-buffer string)) | 2516 | (concat python-shell-output-filter-buffer string)) |
| 2393 | (when (string-match | 2517 | (when (python-shell-comint-end-of-output-p |
| 2394 | ;; XXX: It seems on OSX an extra carriage return is attached | ||
| 2395 | ;; at the end of output, this handles that too. | ||
| 2396 | (concat | ||
| 2397 | "\r?\n" | ||
| 2398 | ;; Remove initial caret from calculated regexp | ||
| 2399 | (replace-regexp-in-string | ||
| 2400 | (rx string-start ?^) "" | ||
| 2401 | python-shell--prompt-calculated-input-regexp) | ||
| 2402 | "$") | ||
| 2403 | python-shell-output-filter-buffer) | 2518 | python-shell-output-filter-buffer) |
| 2404 | ;; Output ends when `python-shell-output-filter-buffer' contains | 2519 | ;; Output ends when `python-shell-output-filter-buffer' contains |
| 2405 | ;; the prompt attached at the end of it. | 2520 | ;; the prompt attached at the end of it. |
| @@ -3912,6 +4027,18 @@ to \"^python-\"." | |||
| 3912 | (cdr pair)))) | 4027 | (cdr pair)))) |
| 3913 | (buffer-local-variables from-buffer))) | 4028 | (buffer-local-variables from-buffer))) |
| 3914 | 4029 | ||
| 4030 | (defvar comint-last-prompt-overlay) ; Shut up, bytecompiler | ||
| 4031 | |||
| 4032 | (defun python-util-comint-last-prompt () | ||
| 4033 | "Return comint last prompt overlay start and end. | ||
| 4034 | This is for compatibility with Emacs < 24.4." | ||
| 4035 | (cond ((bound-and-true-p comint-last-prompt-overlay) | ||
| 4036 | (cons (overlay-start comint-last-prompt-overlay) | ||
| 4037 | (overlay-end comint-last-prompt-overlay))) | ||
| 4038 | ((bound-and-true-p comint-last-prompt) | ||
| 4039 | comint-last-prompt) | ||
| 4040 | (t nil))) | ||
| 4041 | |||
| 3915 | (defun python-util-forward-comment (&optional direction) | 4042 | (defun python-util-forward-comment (&optional direction) |
| 3916 | "Python mode specific version of `forward-comment'. | 4043 | "Python mode specific version of `forward-comment'. |
| 3917 | Optional argument DIRECTION defines the direction to move to." | 4044 | Optional argument DIRECTION defines the direction to move to." |
| @@ -3939,6 +4066,23 @@ returned as is." | |||
| 3939 | n (1- n))) | 4066 | n (1- n))) |
| 3940 | (reverse acc)))) | 4067 | (reverse acc)))) |
| 3941 | 4068 | ||
| 4069 | (defun python-util-text-properties-replace-name | ||
| 4070 | (from to &optional start end) | ||
| 4071 | "Replace properties named FROM to TO, keeping its value. | ||
| 4072 | Arguments START and END narrow the buffer region to work on." | ||
| 4073 | (save-excursion | ||
| 4074 | (goto-char (or start (point-min))) | ||
| 4075 | (while (not (eobp)) | ||
| 4076 | (let ((plist (text-properties-at (point))) | ||
| 4077 | (next-change (or (next-property-change (point) (current-buffer)) | ||
| 4078 | (or end (point-max))))) | ||
| 4079 | (when (plist-get plist from) | ||
| 4080 | (let* ((face (plist-get plist from)) | ||
| 4081 | (plist (plist-put plist from nil)) | ||
| 4082 | (plist (plist-put plist to face))) | ||
| 4083 | (set-text-properties (point) next-change plist (current-buffer)))) | ||
| 4084 | (goto-char next-change))))) | ||
| 4085 | |||
| 3942 | (defun python-util-strip-string (string) | 4086 | (defun python-util-strip-string (string) |
| 3943 | "Strip STRING whitespace and newlines from end and beginning." | 4087 | "Strip STRING whitespace and newlines from end and beginning." |
| 3944 | (replace-regexp-in-string | 4088 | (replace-regexp-in-string |