;; -*- lexical-binding: t -*- (defvar-local comint-osc-handlers '(("8" . comint-osc-8-handler)) "Alist of handlers for OSC escape sequences. See `comint-osc-process-output' for details.") (defvar-local comint-osc--marker nil) (defun comint-osc-process-output (_) "Interpret OSC control sequences in comint output. This function is intended to be added to `comint-output-filter-functions' and interprets control sequences of the forms `\\e];\\a' `\\e];\\e\\' Specifically, every occurrence of such control sequences is removed from the buffer. Then, if the alist `comint-osc-handlers' contains an entry , the corresponding value, which should be a function, is called with and as arguments, with point where the escape sequence was located." (let ((bound (process-mark (get-buffer-process (current-buffer))))) (save-excursion (goto-char (or comint-osc--marker (and (markerp comint-last-output-start) (eq (marker-buffer comint-last-output-start) (current-buffer)) comint-last-output-start) (point-min))) (when (eq (char-before) ?\e) (backward-char)) (while (re-search-forward "\e]" bound t) (let ((pos0 (match-beginning 0)) (code (and (re-search-forward "\\=\\([0-9A-Za-z]*\\);" bound t) (match-string 1))) (pos1 (point))) (if (re-search-forward "\a\\|\e\\\\" bound t) (let ((text (buffer-substring-no-properties pos1 (match-beginning 0)))) (setq comint-osc--marker nil) (delete-region pos0 (point)) (when-let ((fun (cdr (assoc-string code comint-osc-handlers)))) (funcall fun code text))) (put-text-property pos0 bound 'invisible t) (setq comint-osc--marker (copy-marker pos0)))))))) ;;; Hyperlink handling (defvar-local comint-osc-8--state nil) (defun comint-osc-8-handler (_ text) (when comint-osc-8--state (let ((start (car comint-osc-8--state)) (uri (cdr comint-osc-8--state))) (require 'shr) (shr-urlify start uri))) (setq comint-osc-8--state (and (string-match ";\\(.+\\)" text) (cons (point-marker) (match-string-no-properties 1 text)))))