Skip to content

Commit 608e4b8

Browse files
committed
Harden parsing of repl responses, fixes #83
This patch refactors the process response parsing code and adds more nil checks and ignore-errors around the reading of LISP expression for both completion and eldoc.
1 parent 9ba23b0 commit 608e4b8

File tree

1 file changed

+45
-40
lines changed

1 file changed

+45
-40
lines changed

inf-clojure.el

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -937,10 +937,15 @@ prefix argument PROMPT-FOR-SYMBOL, it prompts for a symbol name."
937937
(inf-clojure-symbol-at-point))))
938938
(comint-proc-query (inf-clojure-proc) (format (inf-clojure-var-source-form) var))))
939939

940+
;;;; Response parsing
941+
;;;; ================
942+
943+
(defvar inf-clojure--work-buffer-name "*Inf-Clojure Work Buffer*")
944+
940945
;; Originally from:
941946
;; https://github.com/glycerine/lush2/blob/master/lush2/etc/lush.el#L287
942-
(defun inf-clojure-results-from-process (process command &optional beg-string end-string)
943-
"Send COMMAND to PROCESS.
947+
(defun inf-clojure--process-response (process command &optional beg-string end-string)
948+
"Send to PROCESS the given COMMAND.
944949
Return the result of COMMAND starting with BEG-STRING and ending
945950
with END-STRING if non-nil. If BEG-STRING is nil, the result
946951
string will start from (point) in the results buffer. If
@@ -973,16 +978,45 @@ the results buffer. It cuts out the output from
973978
(when (and buffer-string (string-match inf-clojure-prompt buffer-string))
974979
(substring buffer-string 0 (match-beginning 0)))))))
975980

981+
(defun inf-clojure--nil-string-match-p (string)
982+
"Return true iff STRING is not nil.
983+
This function also takes into consideration weird escape
984+
character and matches if nil is anywhere within the input
985+
string."
986+
(string-match-p "\\Ca*nil\\Ca*" string))
987+
988+
(defun inf-clojure--read-response (response)
989+
"Common post-processing of a process RESPONSE."
990+
;; The following reads the first LISP expression from the (string )
991+
(let ((read-data (when response (ignore-errors (read response)))))
992+
(cond
993+
((null read-data) nil)
994+
((and (stringp read-data) (inf-clojure--nil-string-match-p read-data)) nil)
995+
((listp read-data) read-data))))
996+
997+
(defun inf-clojure--process-response-match-p (match-p proc form)
998+
"Eval MATCH-P on the response of sending to PROC the input FORM.
999+
Note that this function will add a \n to the end (or )f the string
1000+
for evaluation, therefore FORM should not include it."
1001+
(when-let ((response (inf-clojure--process-response proc form)))
1002+
(funcall match-p response)))
1003+
1004+
(defun inf-clojure--non-nil-response-p (proc form)
1005+
"Return true iff PROC's response after evaluating FORM is not nil."
1006+
(inf-clojure--process-response-match-p
1007+
(lambda (string)
1008+
(not (inf-clojure--nil-string-match-p string)))
1009+
proc form))
1010+
1011+
;;;; Commands
1012+
;;;; ========
1013+
9761014
(defun inf-clojure-arglists (fn)
9771015
"Send a query to the inferior Clojure for the arglists for function FN.
9781016
See variable `inf-clojure-arglists-form'."
9791017
(let* ((arglists-snippet (format (inf-clojure-arglists-form) fn))
980-
(arglists-result (inf-clojure-results-from-process (inf-clojure-proc) arglists-snippet))
981-
(arglists-data (when arglists-result (read arglists-result))))
982-
(cond
983-
((null arglists-data) nil)
984-
((stringp arglists-data) arglists-data)
985-
((listp arglists-data) arglists-result))))
1018+
(arglist-response (inf-clojure--process-response (inf-clojure-proc) arglists-snippet))
1019+
(inf-clojure--read-response arglist-response))))
9861020

9871021
(defun inf-clojure-show-arglists (prompt-for-symbol)
9881022
"Show the arglists for function FN in the mini-buffer.
@@ -1050,24 +1084,9 @@ See variable `inf-clojure-buffer'."
10501084

10511085
(defun inf-clojure-completions (expr)
10521086
"Return a list of completions for the Clojure expression starting with EXPR."
1053-
(let* ((proc (inf-clojure-proc))
1054-
(comint-filt (process-filter proc))
1055-
(kept "")
1056-
completions)
1057-
(set-process-filter proc (lambda (_proc string) (setq kept (concat kept string))))
1058-
(unwind-protect
1059-
(let ((completion-snippet
1060-
(format
1061-
(inf-clojure-completion-form) (substring-no-properties expr))))
1062-
(process-send-string proc completion-snippet)
1063-
(while (and (not (string-match inf-clojure-prompt kept))
1064-
(accept-process-output proc 2)))
1065-
(setq completions (read kept))
1066-
;; Subprocess echoes output on Windows and OS X.
1067-
(when (and completions (string= (concat (car completions) "\n") completion-snippet))
1068-
(setq completions (cdr completions))))
1069-
(set-process-filter proc comint-filt))
1070-
completions))
1087+
(let* ((compl-snippet (format (inf-clojure-completion-form) (substring-no-properties expr)))
1088+
(compl-response (inf-clojure--process-response (inf-clojure-proc) compl-snippet)))
1089+
(inf-clojure--read-response compl-response)))
10711090

10721091
(defconst inf-clojure-clojure-expr-break-chars " \t\n\"\'`><,;|&{(")
10731092

@@ -1225,12 +1244,6 @@ to suppress the usage of the target buffer discovery logic."
12251244
(inf-clojure (inf-clojure-cmd (inf-clojure-project-type)))
12261245
(rename-buffer target-buffer-name)))
12271246

1228-
(defun inf-clojure--response-match-p (form match-p proc)
1229-
"Return MATCH-P on the result of sending FORM to PROC.
1230-
Note that this function will add a \n to the end of the string
1231-
for evaluation, therefore FORM should not include it."
1232-
(funcall match-p (inf-clojure-results-from-process proc form nil)))
1233-
12341247
;;;; Lumo
12351248
;;;; ====
12361249

@@ -1240,14 +1253,6 @@ for evaluation, therefore FORM should not include it."
12401253
:type 'string
12411254
:package-version '(inf-clojure . "2.0.0"))
12421255

1243-
(defalias 'inf-clojure--lumo-p
1244-
(apply-partially 'inf-clojure--response-match-p
1245-
inf-clojure--lumo-repl-form
1246-
(lambda (string)
1247-
(string-match-p "\\Ca*true\\Ca*" string)))
1248-
"Ascertain that PROC is a Lumo REPL.")
1249-
1250-
12511256
;;;; Planck
12521257
;;;; ====
12531258

0 commit comments

Comments
 (0)