Decrease regexp usage while parsing output

* eat.el (eat--t-handle-output): Don't use regular expressions
while parsing plain text and CSI sequences.  Remove useless
code from VT300-specific charset set sequence parser.
This commit is contained in:
Akib Azmain Turja 2022-12-15 20:18:04 +06:00
parent f912425fb4
commit 61695d9671
No known key found for this signature in database
GPG key ID: 5535FCF54D88616B

379
eat.el
View file

@ -2609,27 +2609,20 @@ DATA is the selection data encoded in base64."
(defun eat--t-handle-output (output) (defun eat--t-handle-output (output)
"Parse and evaluate OUTPUT." "Parse and evaluate OUTPUT."
(let ((index 0)) (let ((index 0))
(while (< index (length output)) (while (/= index (length output))
(pcase-exhaustive (eat--t-term-parser-state eat--t-term) (pcase-exhaustive (eat--t-term-parser-state eat--t-term)
('nil ('nil
;; Regular expression to find the end of plain text. (let ((ins-beg index))
(let ((match (string-match (while (and (/= index (length output))
(1value (rx (or ?\0 ?\a ?\b ?\t ?\n ?\v (not (memq (aref output index)
?\f ?\r ?\C-n ?\C-o ?\e '( ?\0 ?\a ?\b ?\t ?\n ?\v ?\f ?\r
#x7f))) ;; TODO: Why #x7f?
output index))) ?\C-n ?\C-o ?\e #x7f))))
(if (not match) (cl-incf index))
;; The regex didn't match, so everything left to handle (when (/= ins-beg index)
;; is just plain text. ;; Insert.
(progn (eat--t-write output ins-beg index))
(eat--t-write output index) (when (/= index (length output))
(setq index (length output)))
(when (/= match index)
;; The regex matched, and the position is after the
;; current position. Process the plain text between
;; them and advance to the control sequence.
(eat--t-write output index match)
(setq index match))
;; Dispatch control sequence. ;; Dispatch control sequence.
(cl-incf index) (cl-incf index)
(pcase-exhaustive (aref output (1- index)) (pcase-exhaustive (aref output (1- index))
@ -2719,7 +2712,7 @@ DATA is the selection data encoded in base64."
;; ESC [, or CSI. ;; ESC [, or CSI.
(?\[ (?\[
(1value (setf (eat--t-term-parser-state eat--t-term) (1value (setf (eat--t-term-parser-state eat--t-term)
'(read-csi "")))) '(read-csi-format))))
;; ESC ], or OSC. ;; ESC ], or OSC.
(?\] (?\]
(1value (setf (eat--t-term-parser-state eat--t-term) (1value (setf (eat--t-term-parser-state eat--t-term)
@ -2741,151 +2734,196 @@ DATA is the selection data encoded in base64."
;; ESC o. ;; ESC o.
(?o (?o
(eat--t-change-charset 'g3))))) (eat--t-change-charset 'g3)))))
(`(read-csi ,buf) ('(read-csi-format)
(let ((match (string-match (rx (any (#x40 . #x7e))) (let ((format nil))
output index))) (pcase (aref output index)
(if (not match) (??
(progn (setq format ??)
(setf (eat--t-term-parser-state eat--t-term) (cl-incf index))
`(read-csi ,(concat buf (substring output (?>
index)))) (setq format ?>)
(setq index (length output))) (cl-incf index))
(setf (eat--t-term-parser-state eat--t-term) nil) (?=
(pcase (setq format ?=)
(let ((str (concat buf (substring output index (cl-incf index)))
match))) (setf (eat--t-term-parser-state eat--t-term)
(format nil) `(read-csi-params ,format ,(list (list nil))))))
(intermediate-bytes "")) (`(read-csi-params ,format ,params)
(save-match-data ;; Interpretion of the parameter depends on `format' and
(when (string-match ;; other things (including things we haven't got yet)
(rx (zero-or-more (any (?\s . ?/))) ;; according to the standard. We don't recognize any other
string-end) ;; format of parameters, so we can skip any checks.
str) (let ((loop t))
(setq str (substring (while loop
str 0 (match-beginning 0)) (cond
intermediate-bytes ((= index (length output))
(match-string 0 str)))) ;; Output exhausted. We need to wait for more.
(when (and (not (string-empty-p str)) (setf (eat--t-term-parser-state eat--t-term)
(= (aref str 0) ??)) `(read-csi-params ,format ,params))
(setq format ?? str (substring str 1))) (setq loop nil))
(when (and (not (string-empty-p str)) ((not (<= ?0 (aref output index) ?\;))
(= (aref str 0) ?>)) ;; End of parameters.
(setq format ?> str (substring str 1))) ;; NOTE: All parameter and their parts are in reverse
(when (and (not (string-empty-p str)) ;; order!
(= (aref str 0) ?=)) (setf (eat--t-term-parser-state eat--t-term)
(setq format ?= str (substring str 1))) `(read-csi-function ,format ,params nil))
(setq index (match-end 0)) (setq loop nil))
(list (t
(concat intermediate-bytes (cond
(match-string 0 output)) ((= (aref output index) ?:)
format ;; New parameter substring.
(cond (push nil (car params)))
((string-empty-p str) '((nil))) ((= (aref output index) ?\;)
((<= #x30 (aref str 0) #x3b) ;; New parameter.
(mapcar (lambda (p) (push (list nil) params))
(mapcar (lambda (s) (t ; (<= ?0 (aref output index) ?9)
(unless (string-empty-p s) ;; Number, save it.
(string-to-number s))) (setf (caar params)
(split-string p ":"))) (+ (* (or (caar params) 0) 10)
(split-string str ";"))) (- (aref output index) #x30)))))
(t str)))) (cl-incf index))))))
;; CSI <n> @. (`(read-csi-function ,format ,params ,function)
(`("@" nil ,(and (pred listp) params)) (let ((loop t))
(eat--t-insert-char (caar params))) (while loop
;; CSI <n> A. (cond
;; CSI <n> k. ((= index (length output))
(`(,(or "A" "k") nil ,(and (pred listp) params)) (setf (eat--t-term-parser-state eat--t-term)
(eat--t-cur-up (caar params))) `(read-csi-function ,format ,params ,function))
;; CSI <n> B. (setq loop nil)))
;; CSI <n> e. (push (aref output index) function)
(`(,(or "B" "e") nil ,(and (pred listp) params)) (cl-incf index)
(eat--t-cur-down (caar params))) (when (<= ?@ (car function) ?~)
;; CSI <n> C. ;; Now we have enough information to execute it!
;; CSI <n> a. (setq loop nil)
(`(,(or "C" "a") nil ,(and (pred listp) params)) (setf (eat--t-term-parser-state eat--t-term) nil)
(eat--t-cur-right (caar params))) ;; NOTE: `function' and `params' are in reverse order!
;; CSI <n> D. (pcase (list function format params)
;; CSI <n> j. ;; CSI <n> @.
(`(,(or "D" "j") nil ,(and (pred listp) params)) (`((?@) nil ((,n)))
(eat--t-cur-left (caar params))) (eat--t-insert-char n))
;; CSI <n> E. ;; CSI <n> A.
(`("E" nil ,(and (pred listp) params)) ;; CSI <n> k.
(eat--t-beg-of-prev-line (caar params))) (`((,(or ?A ?k)) nil ((,n)))
;; CSI <n> F. (eat--t-cur-up n))
(`("F" nil ,(and (pred listp) params)) ;; CSI <n> B.
(eat--t-beg-of-next-line (caar params))) ;; CSI <n> e.
;; CSI <n> G. (`((,(or ?B ?e)) nil ((,n)))
;; CSI <n> `. (eat--t-cur-down n))
(`(,(or "G" "`") nil ,(and (pred listp) params)) ;; CSI <n> C.
(eat--t-cur-horizontal-abs (caar params))) ;; CSI <n> a.
;; CSI <n> ; <m> H (`((,(or ?C ?a)) nil ((,n)))
;; CSI <n> ; <m> f (eat--t-cur-right n))
(`(,(or "H" "f") nil ,(and (pred listp) params)) ;; CSI <n> D.
(eat--t-goto (caar params) (caadr params))) ;; CSI <n> j.
;; CSI <n> I. (`((,(or ?D ?j)) nil ((,n)))
(`("I" nil ,(and (pred listp) params)) (eat--t-cur-left n))
(eat--t-horizontal-tab (caar params))) ;; CSI <n> E.
;; CSI <n> J. (`((?E) nil ((,n)))
(`("J" nil ,(and (pred listp) params)) (eat--t-beg-of-prev-line n))
(eat--t-erase-in-disp (caar params))) ;; CSI <n> F.
;; CSI <n> K. (`((?F) nil ((,n)))
(`("K" nil ,(and (pred listp) params)) (eat--t-beg-of-next-line n))
(eat--t-erase-in-line (caar params))) ;; CSI <n> G.
;; CSI <n> L. ;; CSI <n> `.
(`("L" nil ,(and (pred listp) params)) (`((,(or ?G ?`)) nil ((,n)))
(eat--t-insert-line (caar params))) (eat--t-cur-horizontal-abs n))
;; CSI <n> M. ;; CSI <n> ; <m> H
(`("M" nil ,(and (pred listp) params)) ;; CSI <n> ; <m> f
(eat--t-delete-line (caar params))) (`((,(or ?H ?f)) nil ,(and (pred listp) params))
;; CSI <n> P. (eat--t-goto (caadr params) (caar params)))
(`("P" nil ,(and (pred listp) params)) ;; CSI <n> I.
(eat--t-delete-char (caar params))) (`((?I) nil ((,n)))
;; CSI <n> S. (eat--t-horizontal-tab n))
(`("S" nil ,(and (pred listp) params)) ;; CSI <n> J.
(eat--t-scroll-up (caar params))) (`((?J) nil ((,n)))
;; CSI <n> T. (eat--t-erase-in-disp n))
(`("T" nil ,(and (pred listp) params)) ;; CSI <n> K.
(eat--t-scroll-down (caar params))) (`((?K) nil ((,n)))
;; CSI <n> X. (eat--t-erase-in-line n))
(`("X" nil ,(and (pred listp) params)) ;; CSI <n> L.
(eat--t-erase-char (caar params))) (`((?L) nil ((,n)))
;; CSI <n> Z. (eat--t-insert-line n))
(`("Z" nil ,(and (pred listp) params)) ;; CSI <n> M.
(eat--t-horizontal-backtab (caar params))) (`((?M) nil ((,n)))
;; CSI <n> b. (eat--t-delete-line n))
(`("b" nil ,(and (pred listp) params)) ;; CSI <n> P.
(eat--t-repeat-last-char (caar params))) (`((?P) nil ((,n)))
;; CSI <n> c. (eat--t-delete-char n))
;; CSI > <n> c. ;; CSI <n> S.
(`("c" ,format ,(and (pred listp) params)) (`((?S) nil ((,n)))
(eat--t-send-device-attrs params format)) (eat--t-scroll-up n))
;; CSI <n> d. ;; CSI <n> T.
(`("d" nil ,(and (pred listp) params)) (`((?T) nil ((,n)))
(eat--t-cur-vertical-abs (caar params))) (eat--t-scroll-down n))
;; CSI ... h. ;; CSI <n> X.
;; CSI ? ... h. (`((?X) nil ((,n)))
(`("h" ,format ,(and (pred listp) params)) (eat--t-erase-char n))
(eat--t-set-modes params format)) ;; CSI <n> Z.
;; CSI ... l. (`((?Z) nil ((,n)))
;; CSI ? ... l. (eat--t-horizontal-backtab n))
(`("l" ,format ,(and (pred listp) params)) ;; CSI <n> b.
(eat--t-reset-modes params format)) (`((?b) nil ((,n)))
;; CSI ... m. (eat--t-repeat-last-char n))
(`("m" nil ,(and (pred listp) params)) ;; CSI <n> c.
(eat--t-set-sgr-params params)) ;; CSI > <n> c.
;; CSI 6 n. (`((?c) ,format ,(and (pred listp) params))
('("n" nil ((6))) ;; Reverse `params' to get it into the correct
(eat--t-device-status-report)) ;; order.
;; CSI <n> ; <n> r. (setq params (nreverse params))
(`("r" nil ,(and (pred listp) params)) (let ((p params))
(eat--t-change-scroll-region (caar params) (while p
(caadr params))) (setf (car p) (nreverse (car p)))
;; CSI s. (setq p (cdr p))))
(`("s" nil nil) ;; TODO: This function kinda a HACK.
(eat--t-save-cur)) (eat--t-send-device-attrs params format))
;; CSI u. ;; CSI <n> d.
(`("u" nil nil) (`((?d) nil ((,n)))
(eat--t-restore-cur)))))) (eat--t-cur-vertical-abs n))
;; CSI ... h.
;; CSI ? ... h.
(`((?h) ,format ,(and (pred listp) params))
;; Reverse `params' to get it into the correct
;; order.
(setq params (nreverse params))
(let ((p params))
(while p
(setf (car p) (nreverse (car p)))
(setq p (cdr p))))
(eat--t-set-modes params format))
;; CSI ... l.
;; CSI ? ... l.
(`((?l) ,format ,(and (pred listp) params))
;; Reverse `params' to get it into the correct
;; order.
(setq params (nreverse params))
(let ((p params))
(while p
(setf (car p) (nreverse (car p)))
(setq p (cdr p))))
(eat--t-reset-modes params format))
;; CSI ... m.
(`((?m) nil ,(and (pred listp) params))
;; Reverse `params' to get it into the correct
;; order.
(setq params (nreverse params))
(let ((p params))
(while p
(setf (car p) (nreverse (car p)))
(setq p (cdr p))))
(eat--t-set-sgr-params params))
;; CSI 6 n.
('((?n) nil ((6)))
(eat--t-device-status-report))
;; CSI <n> ; <n> r.
(`((?r) nil ,(and (pred listp) params))
(eat--t-change-scroll-region (caadr params)
(caar params)))
;; CSI s.
(`((?s) nil nil)
(eat--t-save-cur))
;; CSI u.
(`((?u) nil nil)
(eat--t-restore-cur)))))))
(`(,(and (or 'read-dcs 'read-sos 'read-osc 'read-pm 'read-apc) (`(,(and (or 'read-dcs 'read-sos 'read-osc 'read-pm 'read-apc)
state) state)
,buf) ,buf)
@ -3023,13 +3061,10 @@ DATA is the selection data encoded in base64."
;; ESC + B. ;; ESC + B.
("B" 'us-ascii))))))) ("B" 'us-ascii)))))))
(`(read-charset-vt300 ,_slot) (`(read-charset-vt300 ,_slot)
(let ((_charset (aref output index))) (cl-incf index)
(cl-incf index) (setf (eat--t-term-parser-state eat--t-term) nil)
(setf (eat--t-term-parser-state eat--t-term) nil) ;; Nothing. This is here to just recognize the sequence.
(pcase charset )))))
;; TODO: Currently ignored. It is here just to recognize
;; the control sequence.
)))))))
(defun eat--t-resize (width height) (defun eat--t-resize (width height)
"Resize terminal to WIDTH x HEIGHT." "Resize terminal to WIDTH x HEIGHT."