diff options
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | lisp/ansi-osc.el (renamed from lisp/osc.el) | 105 | ||||
| -rw-r--r-- | lisp/comint.el | 14 | ||||
| -rw-r--r-- | test/lisp/ansi-osc-tests.el (renamed from test/lisp/osc-tests.el) | 12 |
4 files changed, 68 insertions, 67 deletions
| @@ -2577,12 +2577,12 @@ Enabling this minor mode turns on hiding header material, like | |||
| 2577 | 'elide-head' does; disabling it shows the header. The commands | 2577 | 'elide-head' does; disabling it shows the header. The commands |
| 2578 | 'elide-head' and 'elide-head-show' are now obsolete. | 2578 | 'elide-head' and 'elide-head-show' are now obsolete. |
| 2579 | 2579 | ||
| 2580 | *** New package osc.el. | 2580 | *** New package ansi-osc.el. |
| 2581 | Support for OSC ("Operating System Command") escape sequences has been | 2581 | Support for OSC ("Operating System Command") escape sequences has been |
| 2582 | extracted from comint.el in order to provide interpretation of OSC | 2582 | extracted from comint.el in order to provide interpretation of OSC |
| 2583 | sequences in compilation buffers. | 2583 | sequences in compilation buffers. |
| 2584 | 2584 | ||
| 2585 | Adding the new function 'osc-compilation-filter' to | 2585 | Adding the new function 'ansi-osc-compilation-filter' to |
| 2586 | 'compilation-filter-hook' enables interpretation of OSC escape | 2586 | 'compilation-filter-hook' enables interpretation of OSC escape |
| 2587 | sequences in compilation buffers. By default, all sequences are | 2587 | sequences in compilation buffers. By default, all sequences are |
| 2588 | filtered out. | 2588 | filtered out. |
diff --git a/lisp/osc.el b/lisp/ansi-osc.el index 14f7fe6a4f3..67a85516281 100644 --- a/lisp/osc.el +++ b/lisp/ansi-osc.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; osc.el --- Support for OSC escape sequences -*- lexical-binding: t; -*- | 1 | ;;; ansi-osc.el --- Support for OSC escape sequences -*- lexical-binding: t; -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2022 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2022 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -26,37 +26,37 @@ | |||
| 26 | ;; Handlers for OSC 2, 7 and 8 (for window title, current directory | 26 | ;; Handlers for OSC 2, 7 and 8 (for window title, current directory |
| 27 | ;; and hyperlinks respectively) are provided. | 27 | ;; and hyperlinks respectively) are provided. |
| 28 | 28 | ||
| 29 | ;; The function `osc-compilation-filter' can be added to | 29 | ;; The function `ansi-osc-compilation-filter' can be added to |
| 30 | ;; `compilation-filter-hook' to collect OSC sequences in compilation | 30 | ;; `compilation-filter-hook' to collect OSC sequences in compilation |
| 31 | ;; buffers. The variable `osc-for-compilation-buffer' tells what to | 31 | ;; buffers. The variable `ansi-osc-for-compilation-buffer' tells what |
| 32 | ;; do with collected sequences. | 32 | ;; to do with collected sequences. |
| 33 | 33 | ||
| 34 | ;;; Code: | 34 | ;;; Code: |
| 35 | 35 | ||
| 36 | (defconst osc-control-seq-regexp | 36 | (defconst ansi-osc-control-seq-regexp |
| 37 | ;; See ECMA 48, section 8.3.89 "OSC - OPERATING SYSTEM COMMAND". | 37 | ;; See ECMA 48, section 8.3.89 "OSC - OPERATING SYSTEM COMMAND". |
| 38 | "\e\\][\x08-\x0D]*[\x20-\x7E]*\\(\a\\|\e\\\\\\)" | 38 | "\e\\][\x08-\x0D]*[\x20-\x7E]*\\(\a\\|\e\\\\\\)" |
| 39 | "Regexp matching an OSC control sequence.") | 39 | "Regexp matching an OSC control sequence.") |
| 40 | 40 | ||
| 41 | (defun osc-filter-region (begin end) | 41 | (defun ansi-osc-filter-region (begin end) |
| 42 | "Filter out all OSC control sequences from region between BEGIN and END." | 42 | "Filter out all OSC control sequences from region between BEGIN and END." |
| 43 | (save-excursion | 43 | (save-excursion |
| 44 | (goto-char begin) | 44 | (goto-char begin) |
| 45 | ;; Delete escape sequences. | 45 | ;; Delete escape sequences. |
| 46 | (while (re-search-forward osc-control-seq-regexp end t) | 46 | (while (re-search-forward ansi-osc-control-seq-regexp end t) |
| 47 | (delete-region (match-beginning 0) (match-end 0))))) | 47 | (delete-region (match-beginning 0) (match-end 0))))) |
| 48 | 48 | ||
| 49 | (defvar-local osc-handlers '(("2" . osc-window-title-handler) | 49 | (defvar-local ansi-osc-handlers '(("2" . ansi-osc-window-title-handler) |
| 50 | ("7" . osc-directory-tracker) | 50 | ("7" . ansi-osc-directory-tracker) |
| 51 | ("8" . osc-hyperlink-handler)) | 51 | ("8" . ansi-osc-hyperlink-handler)) |
| 52 | "Alist of handlers for OSC escape sequences. | 52 | "Alist of handlers for OSC escape sequences. |
| 53 | See `osc-apply-on-region' for details.") | 53 | See `ansi-osc-apply-on-region' for details.") |
| 54 | 54 | ||
| 55 | (defvar-local osc--marker nil) | 55 | (defvar-local ansi-osc--marker nil) |
| 56 | ;; The function `osc-apply-on-region' can set `osc--marker' to the start | 56 | ;; The function `ansi-osc-apply-on-region' can set `ansi-osc--marker' |
| 57 | ;; position of an escape sequence without termination. | 57 | ;; to the start position of an escape sequence without termination. |
| 58 | 58 | ||
| 59 | (defun osc-apply-on-region (begin end) | 59 | (defun ansi-osc-apply-on-region (begin end) |
| 60 | "Interpret OSC escape sequences in region between BEGIN and END. | 60 | "Interpret OSC escape sequences in region between BEGIN and END. |
| 61 | This function searches for escape sequences of the forms | 61 | This function searches for escape sequences of the forms |
| 62 | 62 | ||
| @@ -64,12 +64,13 @@ This function searches for escape sequences of the forms | |||
| 64 | ESC ] command ; text ESC \\ | 64 | ESC ] command ; text ESC \\ |
| 65 | 65 | ||
| 66 | Every occurrence of such escape sequences is removed from the | 66 | Every occurrence of such escape sequences is removed from the |
| 67 | buffer. Then, if `command' is a key in the alist that is the value | 67 | buffer. Then, if `command' is a key in the alist that is the |
| 68 | of the local variable `osc-handlers', that key's value, which should | 68 | value of the local variable `ansi-osc-handlers', that key's |
| 69 | be a function, is called with `command' and `text' as arguments, with | 69 | value, which should be a function, is called with `command' and |
| 70 | point where the escape sequence was located." | 70 | `text' as arguments, with point where the escape sequence was |
| 71 | located." | ||
| 71 | (save-excursion | 72 | (save-excursion |
| 72 | (goto-char (or osc--marker begin)) | 73 | (goto-char (or ansi-osc--marker begin)) |
| 73 | (when (eq (char-before) ?\e) (backward-char)) | 74 | (when (eq (char-before) ?\e) (backward-char)) |
| 74 | (while (re-search-forward "\e]" end t) | 75 | (while (re-search-forward "\e]" end t) |
| 75 | (let ((pos0 (match-beginning 0)) | 76 | (let ((pos0 (match-beginning 0)) |
| @@ -79,35 +80,35 @@ point where the escape sequence was located." | |||
| 79 | (if (re-search-forward "\a\\|\e\\\\" end t) | 80 | (if (re-search-forward "\a\\|\e\\\\" end t) |
| 80 | (let ((text (buffer-substring-no-properties | 81 | (let ((text (buffer-substring-no-properties |
| 81 | pos1 (match-beginning 0)))) | 82 | pos1 (match-beginning 0)))) |
| 82 | (setq osc--marker nil) | 83 | (setq ansi-osc--marker nil) |
| 83 | (delete-region pos0 (point)) | 84 | (delete-region pos0 (point)) |
| 84 | (when-let ((fun (cdr (assoc-string code osc-handlers)))) | 85 | (when-let ((fun (cdr (assoc-string code ansi-osc-handlers)))) |
| 85 | (funcall fun code text))) | 86 | (funcall fun code text))) |
| 86 | (put-text-property pos0 end 'invisible t) | 87 | (put-text-property pos0 end 'invisible t) |
| 87 | (setq osc--marker (copy-marker pos0))))))) | 88 | (setq ansi-osc--marker (copy-marker pos0))))))) |
| 88 | 89 | ||
| 89 | ;; Window title handling (OSC 2) | 90 | ;; Window title handling (OSC 2) |
| 90 | 91 | ||
| 91 | (defvar-local osc-window-title nil) | 92 | (defvar-local ansi-osc-window-title nil) |
| 92 | (defun osc-window-title-handler (_ text) | 93 | (defun ansi-osc-window-title-handler (_ text) |
| 93 | "Set value of `osc-window-title' from an OSC 2 escape sequence. | 94 | "Set value of `ansi-osc-window-title' from an OSC 2 escape sequence. |
| 94 | The variable `osc-window-title' can then be referenced in | 95 | The variable `ansi-osc-window-title' can then be referenced in |
| 95 | `frame-title-format' to dynamically set the frame title. | 96 | `frame-title-format' to dynamically set the frame title. |
| 96 | 97 | ||
| 97 | This function is intended to be included as an element of the | 98 | This function is intended to be included as an element of the |
| 98 | list that is the value of `osc-handlers'." | 99 | list that is the value of `ansi-osc-handlers'." |
| 99 | (setq osc-window-title text)) | 100 | (setq ansi-osc-window-title text)) |
| 100 | 101 | ||
| 101 | ;; Current directory tracking (OSC 7) | 102 | ;; Current directory tracking (OSC 7) |
| 102 | 103 | ||
| 103 | (declare-function url-host "url/url-parse.el") | 104 | (declare-function url-host "url/url-parse.el") |
| 104 | (declare-function url-type "url/url-parse.el") | 105 | (declare-function url-type "url/url-parse.el") |
| 105 | (declare-function url-filename "url/url-parse.el") | 106 | (declare-function url-filename "url/url-parse.el") |
| 106 | (defun osc-directory-tracker (_ text) | 107 | (defun ansi-osc-directory-tracker (_ text) |
| 107 | "Update `default-directory' from OSC 7 escape sequences. | 108 | "Update `default-directory' from OSC 7 escape sequences. |
| 108 | 109 | ||
| 109 | This function is intended to be included as an element of the | 110 | This function is intended to be included as an element of the |
| 110 | the list that is the value of `osc-handlers'. You should arrange | 111 | the list that is the value of `ansi-osc-handlers'. You should arrange |
| 111 | for your shell to print the appropriate escape sequence at each prompt, | 112 | for your shell to print the appropriate escape sequence at each prompt, |
| 112 | such as with the following command: | 113 | such as with the following command: |
| 113 | 114 | ||
| @@ -124,7 +125,7 @@ and `shell-dirtrack-mode'." | |||
| 124 | 125 | ||
| 125 | ;; Hyperlink handling (OSC 8) | 126 | ;; Hyperlink handling (OSC 8) |
| 126 | 127 | ||
| 127 | (defvar osc-hyperlink-map | 128 | (defvar ansi-osc-hyperlink-map |
| 128 | (let ((map (make-sparse-keymap))) | 129 | (let ((map (make-sparse-keymap))) |
| 129 | (define-key map "\C-c\r" 'browse-url-button-open) | 130 | (define-key map "\C-c\r" 'browse-url-button-open) |
| 130 | (define-key map [mouse-2] 'browse-url-button-open) | 131 | (define-key map [mouse-2] 'browse-url-button-open) |
| @@ -132,29 +133,29 @@ and `shell-dirtrack-mode'." | |||
| 132 | map) | 133 | map) |
| 133 | "Keymap used by OSC 8 hyperlink buttons.") | 134 | "Keymap used by OSC 8 hyperlink buttons.") |
| 134 | 135 | ||
| 135 | (define-button-type 'osc-hyperlink | 136 | (define-button-type 'ansi-osc-hyperlink |
| 136 | 'keymap osc-hyperlink-map | 137 | 'keymap ansi-osc-hyperlink-map |
| 137 | 'help-echo (lambda (_ buffer pos) | 138 | 'help-echo (lambda (_ buffer pos) |
| 138 | (when-let ((url (get-text-property pos 'browse-url-data buffer))) | 139 | (when-let ((url (get-text-property pos 'browse-url-data buffer))) |
| 139 | (format "mouse-2, C-c RET: Open %s" url)))) | 140 | (format "mouse-2, C-c RET: Open %s" url)))) |
| 140 | 141 | ||
| 141 | (defvar-local osc-hyperlink--state nil) | 142 | (defvar-local ansi-osc-hyperlink--state nil) |
| 142 | 143 | ||
| 143 | (defun osc-hyperlink-handler (_ text) | 144 | (defun ansi-osc-hyperlink-handler (_ text) |
| 144 | "Create a hyperlink from an OSC 8 escape sequence. | 145 | "Create a hyperlink from an OSC 8 escape sequence. |
| 145 | This function is intended to be included as an elemnt of the list | 146 | This function is intended to be included as an elemnt of the list |
| 146 | that is the value of `osc-handlers'." | 147 | that is the value of `ansi-osc-handlers'." |
| 147 | (when osc-hyperlink--state | 148 | (when ansi-osc-hyperlink--state |
| 148 | (let ((start (car osc-hyperlink--state)) | 149 | (let ((start (car ansi-osc-hyperlink--state)) |
| 149 | (url (cdr osc-hyperlink--state))) | 150 | (url (cdr ansi-osc-hyperlink--state))) |
| 150 | (make-text-button start (point) | 151 | (make-text-button start (point) |
| 151 | 'type 'osc-hyperlink | 152 | 'type 'ansi-osc-hyperlink |
| 152 | 'browse-url-data url))) | 153 | 'browse-url-data url))) |
| 153 | (setq osc-hyperlink--state | 154 | (setq ansi-osc-hyperlink--state |
| 154 | (and (string-match ";\\(.+\\)" text) | 155 | (and (string-match ";\\(.+\\)" text) |
| 155 | (cons (point-marker) (match-string-no-properties 1 text))))) | 156 | (cons (point-marker) (match-string-no-properties 1 text))))) |
| 156 | 157 | ||
| 157 | (defcustom osc-for-compilation-buffer 'filter | 158 | (defcustom ansi-osc-for-compilation-buffer 'filter |
| 158 | "What to do with OSC escape sequences in compilation output. | 159 | "What to do with OSC escape sequences in compilation output. |
| 159 | 160 | ||
| 160 | If nil, do nothing. | 161 | If nil, do nothing. |
| @@ -162,9 +163,9 @@ If nil, do nothing. | |||
| 162 | If the symbol `filter', then filter out all OSC control sequences. | 163 | If the symbol `filter', then filter out all OSC control sequences. |
| 163 | 164 | ||
| 164 | If any other non-nil value, then collect OSC control sequences | 165 | If any other non-nil value, then collect OSC control sequences |
| 165 | and call the appropriate handlers as described in `osc-handlers'. | 166 | and call the appropriate handlers as described in `ansi-osc-handlers'. |
| 166 | 167 | ||
| 167 | In order for this to have any effect, `osc-compilation-filter' | 168 | In order for this to have any effect, `ansi-osc-compilation-filter' |
| 168 | must be in `compilation-filter-hook'." | 169 | must be in `compilation-filter-hook'." |
| 169 | :type '(choice (const :tag "Do nothing" nil) | 170 | :type '(choice (const :tag "Do nothing" nil) |
| 170 | (const :tag "Filter out OSC" filter) | 171 | (const :tag "Filter out OSC" filter) |
| @@ -175,17 +176,17 @@ must be in `compilation-filter-hook'." | |||
| 175 | (defvar compilation-filter-start) | 176 | (defvar compilation-filter-start) |
| 176 | 177 | ||
| 177 | ;;;###autoload | 178 | ;;;###autoload |
| 178 | (defun osc-compilation-filter () | 179 | (defun ansi-osc-compilation-filter () |
| 179 | "Maybe collect OSC control sequences. | 180 | "Maybe collect OSC control sequences. |
| 180 | This function depends on the variable `osc-for-compilation-buffer', | 181 | This function depends on the variable `ansi-osc-for-compilation-buffer', |
| 181 | and is meant to be used in `compilation-filter-hook'." | 182 | and is meant to be used in `compilation-filter-hook'." |
| 182 | (let ((inhibit-read-only t)) | 183 | (let ((inhibit-read-only t)) |
| 183 | (pcase osc-for-compilation-buffer | 184 | (pcase ansi-osc-for-compilation-buffer |
| 184 | ('nil nil) | 185 | ('nil nil) |
| 185 | ('filter | 186 | ('filter |
| 186 | (osc-filter-region compilation-filter-start (point))) | 187 | (ansi-osc-filter-region compilation-filter-start (point))) |
| 187 | (_ | 188 | (_ |
| 188 | (osc-apply-on-region compilation-filter-start (point)))))) | 189 | (ansi-osc-apply-on-region compilation-filter-start (point)))))) |
| 189 | 190 | ||
| 190 | (provide 'osc) | 191 | (provide 'ansi-osc) |
| 191 | ;;; osc.el ends here | 192 | ;;; ansi-osc.el ends here |
diff --git a/lisp/comint.el b/lisp/comint.el index a70a75c6487..b1f3ad8259d 100644 --- a/lisp/comint.el +++ b/lisp/comint.el | |||
| @@ -103,7 +103,7 @@ | |||
| 103 | 103 | ||
| 104 | (require 'ring) | 104 | (require 'ring) |
| 105 | (require 'ansi-color) | 105 | (require 'ansi-color) |
| 106 | (require 'osc) | 106 | (require 'ansi-osc) |
| 107 | (require 'regexp-opt) ;For regexp-opt-charset. | 107 | (require 'regexp-opt) ;For regexp-opt-charset. |
| 108 | (eval-when-compile (require 'subr-x)) | 108 | (eval-when-compile (require 'subr-x)) |
| 109 | 109 | ||
| @@ -3918,11 +3918,11 @@ REGEXP-GROUP is the regular expression group in REGEXP to use." | |||
| 3918 | ;; sequences. | 3918 | ;; sequences. |
| 3919 | 3919 | ||
| 3920 | ;; Aliases defined for reverse compatibility | 3920 | ;; Aliases defined for reverse compatibility |
| 3921 | (defvaralias 'comint-osc-handlers 'osc-handlers) | 3921 | (defvaralias 'comint-osc-handlers 'ansi-osc-handlers) |
| 3922 | (defalias 'comint-osc-directory-tracker 'osc-directory-tracker) | 3922 | (defalias 'comint-osc-directory-tracker 'ansi-osc-directory-tracker) |
| 3923 | (defalias 'comint-osc-hyperlink-handler 'osc-hyperlink-handler) | 3923 | (defalias 'comint-osc-hyperlink-handler 'ansi-osc-hyperlink-handler) |
| 3924 | (defalias 'comint-osc-hyperlink 'osc-hyperlink) | 3924 | (defalias 'comint-osc-hyperlink 'ansi-osc-hyperlink) |
| 3925 | (defvaralias 'comint-osc-hyperlink-map 'osc-hyperlink-map) | 3925 | (defvaralias 'comint-osc-hyperlink-map 'ansi-osc-hyperlink-map) |
| 3926 | 3926 | ||
| 3927 | (defun comint-osc-process-output (_) | 3927 | (defun comint-osc-process-output (_) |
| 3928 | "Interpret OSC escape sequences in comint output. | 3928 | "Interpret OSC escape sequences in comint output. |
| @@ -3941,7 +3941,7 @@ arguments, with point where the escape sequence was located." | |||
| 3941 | (let ((start (1- comint-last-output-start)) | 3941 | (let ((start (1- comint-last-output-start)) |
| 3942 | ;; Start one char before last output to catch a possibly stray ESC | 3942 | ;; Start one char before last output to catch a possibly stray ESC |
| 3943 | (bound (process-mark (get-buffer-process (current-buffer))))) | 3943 | (bound (process-mark (get-buffer-process (current-buffer))))) |
| 3944 | (osc-apply-on-region start bound))) | 3944 | (ansi-osc-apply-on-region start bound))) |
| 3945 | 3945 | ||
| 3946 | 3946 | ||
| 3947 | ;;; Input fontification and indentation through an indirect buffer | 3947 | ;;; Input fontification and indentation through an indirect buffer |
diff --git a/test/lisp/osc-tests.el b/test/lisp/ansi-osc-tests.el index d53bab08d3d..b3d66fb036c 100644 --- a/test/lisp/osc-tests.el +++ b/test/lisp/ansi-osc-tests.el | |||
| @@ -26,10 +26,10 @@ | |||
| 26 | 26 | ||
| 27 | ;;; Code: | 27 | ;;; Code: |
| 28 | 28 | ||
| 29 | (require 'osc) | 29 | (require 'ansi-osc) |
| 30 | (require 'ert) | 30 | (require 'ert) |
| 31 | 31 | ||
| 32 | (defvar osc-tests--strings | 32 | (defvar ansi-osc-tests--strings |
| 33 | `( | 33 | `( |
| 34 | ("Hello World" "Hello World") | 34 | ("Hello World" "Hello World") |
| 35 | 35 | ||
| @@ -48,10 +48,10 @@ | |||
| 48 | ;; Don't output those strings to stdout since they may have | 48 | ;; Don't output those strings to stdout since they may have |
| 49 | ;; side-effects on the environment | 49 | ;; side-effects on the environment |
| 50 | 50 | ||
| 51 | (ert-deftest osc-tests-apply-region-no-handlers () | 51 | (ert-deftest ansi-osc-tests-apply-region-no-handlers () |
| 52 | (let ((osc-handlers nil)) | 52 | (let ((ansi-osc-handlers nil)) |
| 53 | (pcase-dolist (`(,input ,text) osc-tests--strings) | 53 | (pcase-dolist (`(,input ,text) ansi-osc-tests--strings) |
| 54 | (with-temp-buffer | 54 | (with-temp-buffer |
| 55 | (insert input) | 55 | (insert input) |
| 56 | (osc-apply-on-region (point-min) (point-max)) | 56 | (ansi-osc-apply-on-region (point-min) (point-max)) |
| 57 | (should (equal (buffer-string) text)))))) | 57 | (should (equal (buffer-string) text)))))) |