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

283
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 ??)
(cl-incf index))
(?>
(setq format ?>)
(cl-incf index))
(?=
(setq format ?=)
(cl-incf index)))
(setf (eat--t-term-parser-state eat--t-term) (setf (eat--t-term-parser-state eat--t-term)
`(read-csi ,(concat buf (substring output `(read-csi-params ,format ,(list (list nil))))))
index)))) (`(read-csi-params ,format ,params)
(setq index (length output))) ;; Interpretion of the parameter depends on `format' and
(setf (eat--t-term-parser-state eat--t-term) nil) ;; other things (including things we haven't got yet)
(pcase ;; according to the standard. We don't recognize any other
(let ((str (concat buf (substring output index ;; format of parameters, so we can skip any checks.
match))) (let ((loop t))
(format nil) (while loop
(intermediate-bytes ""))
(save-match-data
(when (string-match
(rx (zero-or-more (any (?\s . ?/)))
string-end)
str)
(setq str (substring
str 0 (match-beginning 0))
intermediate-bytes
(match-string 0 str))))
(when (and (not (string-empty-p str))
(= (aref str 0) ??))
(setq format ?? str (substring str 1)))
(when (and (not (string-empty-p str))
(= (aref str 0) ?>))
(setq format ?> str (substring str 1)))
(when (and (not (string-empty-p str))
(= (aref str 0) ?=))
(setq format ?= str (substring str 1)))
(setq index (match-end 0))
(list
(concat intermediate-bytes
(match-string 0 output))
format
(cond (cond
((string-empty-p str) '((nil))) ((= index (length output))
((<= #x30 (aref str 0) #x3b) ;; Output exhausted. We need to wait for more.
(mapcar (lambda (p) (setf (eat--t-term-parser-state eat--t-term)
(mapcar (lambda (s) `(read-csi-params ,format ,params))
(unless (string-empty-p s) (setq loop nil))
(string-to-number s))) ((not (<= ?0 (aref output index) ?\;))
(split-string p ":"))) ;; End of parameters.
(split-string str ";"))) ;; NOTE: All parameter and their parts are in reverse
(t str)))) ;; order!
(setf (eat--t-term-parser-state eat--t-term)
`(read-csi-function ,format ,params nil))
(setq loop nil))
(t
(cond
((= (aref output index) ?:)
;; New parameter substring.
(push nil (car params)))
((= (aref output index) ?\;)
;; New parameter.
(push (list nil) params))
(t ; (<= ?0 (aref output index) ?9)
;; Number, save it.
(setf (caar params)
(+ (* (or (caar params) 0) 10)
(- (aref output index) #x30)))))
(cl-incf index))))))
(`(read-csi-function ,format ,params ,function)
(let ((loop t))
(while loop
(cond
((= index (length output))
(setf (eat--t-term-parser-state eat--t-term)
`(read-csi-function ,format ,params ,function))
(setq loop nil)))
(push (aref output index) function)
(cl-incf index)
(when (<= ?@ (car function) ?~)
;; Now we have enough information to execute it!
(setq loop nil)
(setf (eat--t-term-parser-state eat--t-term) nil)
;; NOTE: `function' and `params' are in reverse order!
(pcase (list function format params)
;; CSI <n> @. ;; CSI <n> @.
(`("@" nil ,(and (pred listp) params)) (`((?@) nil ((,n)))
(eat--t-insert-char (caar params))) (eat--t-insert-char n))
;; CSI <n> A. ;; CSI <n> A.
;; CSI <n> k. ;; CSI <n> k.
(`(,(or "A" "k") nil ,(and (pred listp) params)) (`((,(or ?A ?k)) nil ((,n)))
(eat--t-cur-up (caar params))) (eat--t-cur-up n))
;; CSI <n> B. ;; CSI <n> B.
;; CSI <n> e. ;; CSI <n> e.
(`(,(or "B" "e") nil ,(and (pred listp) params)) (`((,(or ?B ?e)) nil ((,n)))
(eat--t-cur-down (caar params))) (eat--t-cur-down n))
;; CSI <n> C. ;; CSI <n> C.
;; CSI <n> a. ;; CSI <n> a.
(`(,(or "C" "a") nil ,(and (pred listp) params)) (`((,(or ?C ?a)) nil ((,n)))
(eat--t-cur-right (caar params))) (eat--t-cur-right n))
;; CSI <n> D. ;; CSI <n> D.
;; CSI <n> j. ;; CSI <n> j.
(`(,(or "D" "j") nil ,(and (pred listp) params)) (`((,(or ?D ?j)) nil ((,n)))
(eat--t-cur-left (caar params))) (eat--t-cur-left n))
;; CSI <n> E. ;; CSI <n> E.
(`("E" nil ,(and (pred listp) params)) (`((?E) nil ((,n)))
(eat--t-beg-of-prev-line (caar params))) (eat--t-beg-of-prev-line n))
;; CSI <n> F. ;; CSI <n> F.
(`("F" nil ,(and (pred listp) params)) (`((?F) nil ((,n)))
(eat--t-beg-of-next-line (caar params))) (eat--t-beg-of-next-line n))
;; CSI <n> G. ;; CSI <n> G.
;; CSI <n> `. ;; CSI <n> `.
(`(,(or "G" "`") nil ,(and (pred listp) params)) (`((,(or ?G ?`)) nil ((,n)))
(eat--t-cur-horizontal-abs (caar params))) (eat--t-cur-horizontal-abs n))
;; CSI <n> ; <m> H ;; CSI <n> ; <m> H
;; CSI <n> ; <m> f ;; CSI <n> ; <m> f
(`(,(or "H" "f") nil ,(and (pred listp) params)) (`((,(or ?H ?f)) nil ,(and (pred listp) params))
(eat--t-goto (caar params) (caadr params))) (eat--t-goto (caadr params) (caar params)))
;; CSI <n> I. ;; CSI <n> I.
(`("I" nil ,(and (pred listp) params)) (`((?I) nil ((,n)))
(eat--t-horizontal-tab (caar params))) (eat--t-horizontal-tab n))
;; CSI <n> J. ;; CSI <n> J.
(`("J" nil ,(and (pred listp) params)) (`((?J) nil ((,n)))
(eat--t-erase-in-disp (caar params))) (eat--t-erase-in-disp n))
;; CSI <n> K. ;; CSI <n> K.
(`("K" nil ,(and (pred listp) params)) (`((?K) nil ((,n)))
(eat--t-erase-in-line (caar params))) (eat--t-erase-in-line n))
;; CSI <n> L. ;; CSI <n> L.
(`("L" nil ,(and (pred listp) params)) (`((?L) nil ((,n)))
(eat--t-insert-line (caar params))) (eat--t-insert-line n))
;; CSI <n> M. ;; CSI <n> M.
(`("M" nil ,(and (pred listp) params)) (`((?M) nil ((,n)))
(eat--t-delete-line (caar params))) (eat--t-delete-line n))
;; CSI <n> P. ;; CSI <n> P.
(`("P" nil ,(and (pred listp) params)) (`((?P) nil ((,n)))
(eat--t-delete-char (caar params))) (eat--t-delete-char n))
;; CSI <n> S. ;; CSI <n> S.
(`("S" nil ,(and (pred listp) params)) (`((?S) nil ((,n)))
(eat--t-scroll-up (caar params))) (eat--t-scroll-up n))
;; CSI <n> T. ;; CSI <n> T.
(`("T" nil ,(and (pred listp) params)) (`((?T) nil ((,n)))
(eat--t-scroll-down (caar params))) (eat--t-scroll-down n))
;; CSI <n> X. ;; CSI <n> X.
(`("X" nil ,(and (pred listp) params)) (`((?X) nil ((,n)))
(eat--t-erase-char (caar params))) (eat--t-erase-char n))
;; CSI <n> Z. ;; CSI <n> Z.
(`("Z" nil ,(and (pred listp) params)) (`((?Z) nil ((,n)))
(eat--t-horizontal-backtab (caar params))) (eat--t-horizontal-backtab n))
;; CSI <n> b. ;; CSI <n> b.
(`("b" nil ,(and (pred listp) params)) (`((?b) nil ((,n)))
(eat--t-repeat-last-char (caar params))) (eat--t-repeat-last-char n))
;; CSI <n> c. ;; CSI <n> c.
;; CSI > <n> c. ;; CSI > <n> c.
(`("c" ,format ,(and (pred listp) params)) (`((?c) ,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))))
;; TODO: This function kinda a HACK.
(eat--t-send-device-attrs params format)) (eat--t-send-device-attrs params format))
;; CSI <n> d. ;; CSI <n> d.
(`("d" nil ,(and (pred listp) params)) (`((?d) nil ((,n)))
(eat--t-cur-vertical-abs (caar params))) (eat--t-cur-vertical-abs n))
;; CSI ... h. ;; CSI ... h.
;; CSI ? ... h. ;; CSI ? ... h.
(`("h" ,format ,(and (pred listp) params)) (`((?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)) (eat--t-set-modes params format))
;; CSI ... l. ;; CSI ... l.
;; CSI ? ... l. ;; CSI ? ... l.
(`("l" ,format ,(and (pred listp) params)) (`((?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)) (eat--t-reset-modes params format))
;; CSI ... m. ;; CSI ... m.
(`("m" nil ,(and (pred listp) params)) (`((?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)) (eat--t-set-sgr-params params))
;; CSI 6 n. ;; CSI 6 n.
('("n" nil ((6))) ('((?n) nil ((6)))
(eat--t-device-status-report)) (eat--t-device-status-report))
;; CSI <n> ; <n> r. ;; CSI <n> ; <n> r.
(`("r" nil ,(and (pred listp) params)) (`((?r) nil ,(and (pred listp) params))
(eat--t-change-scroll-region (caar params) (eat--t-change-scroll-region (caadr params)
(caadr params))) (caar params)))
;; CSI s. ;; CSI s.
(`("s" nil nil) (`((?s) nil nil)
(eat--t-save-cur)) (eat--t-save-cur))
;; CSI u. ;; CSI u.
(`("u" nil nil) (`((?u) nil nil)
(eat--t-restore-cur)))))) (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)
(pcase charset ;; Nothing. This is here to just recognize the sequence.
;; 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."