[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/inf-clojure 723064d 151/313: [Fix #83] Harden parsing of r
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/inf-clojure 723064d 151/313: [Fix #83] Harden parsing of repl responses (#85) |
Date: |
Wed, 11 Aug 2021 10:00:05 -0400 (EDT) |
branch: elpa/inf-clojure
commit 723064d2a934549b29d20fd2db054a31862c4f9b
Author: Andrea Richiardi <a.richiardi.work@gmail.com>
Commit: Bozhidar Batsov <bozhidar.batsov@gmail.com>
[Fix #83] Harden parsing of repl responses (#85)
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.
---
CHANGELOG.md | 1 +
inf-clojure.el | 122 +++++++++++++++++++++++++++++++++++++--------------------
2 files changed, 80 insertions(+), 43 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1871a9a..3afd462 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
### Bugs Fixed
* [#77](https://github.com/clojure-emacs/inf-clojure/pull/77): Fix request
"Eval expression:" if arglists return is `nil`.
+* [#83](https://github.com/clojure-emacs/inf-clojure/pull/85): No such
namespace: complete.core in lumo REPL.
## 2.0.0 (2017-05-01)
diff --git a/inf-clojure.el b/inf-clojure.el
index 6145974..082d22e 100644
--- a/inf-clojure.el
+++ b/inf-clojure.el
@@ -940,17 +940,22 @@ prefix argument PROMPT-FOR-SYMBOL, it prompts for a
symbol name."
(inf-clojure-symbol-at-point))))
(comint-proc-query (inf-clojure-proc) (format
(inf-clojure-var-source-form) var))))
+;;;; Response parsing
+;;;; ================
+
+(defvar inf-clojure--redirect-buffer-name " *Inf-Clojure Redirect Buffer*")
+
;; Originally from:
;; https://github.com/glycerine/lush2/blob/master/lush2/etc/lush.el#L287
-(defun inf-clojure-results-from-process (process command &optional beg-string
end-string)
- "Send COMMAND to PROCESS.
+(defun inf-clojure--process-response (command process &optional beg-string
end-string)
+ "Send COMMAND to PROCESS and return the response.
Return the result of COMMAND starting with BEG-STRING and ending
with END-STRING if non-nil. If BEG-STRING is nil, the result
string will start from (point) in the results buffer. If
END-STRING is nil, the result string will end at (point-max) in
-the results buffer. It cuts out the output from
-`inf-clojure-prompt` onwards unconditionally."
- (let ((work-buffer " *Inf-Clojure Redirect Work Buffer*"))
+the results buffer. It cuts out the output from and including
+the `inf-clojure-prompt`."
+ (let ((work-buffer inf-clojure--redirect-buffer-name))
(save-excursion
(set-buffer (get-buffer-create work-buffer))
(erase-buffer)
@@ -963,29 +968,68 @@ the results buffer. It cuts out the output from
;; Collect the output
(set-buffer work-buffer)
(goto-char (point-min))
- ;; Skip past the command, if it was echoed
- (and (looking-at command)
- (forward-line))
- (let* ((beg (if beg-string
- (progn (search-forward beg-string nil t)
(match-beginning 0))
- (point)))
- (end (if end-string
- (search-forward end-string nil t)
- (point-max)))
- (buffer-string (buffer-substring-no-properties beg end)))
- (when (and buffer-string (string-match inf-clojure-prompt
buffer-string))
- (substring buffer-string 0 (match-beginning 0)))))))
+ (let* ((beg (or (when (and beg-string (search-forward beg-string nil t))
+ (match-beginning 0))
+ (point-min)))
+ (end (or (when end-string
+ (search-forward end-string nil t))
+ (point-max)))
+ (prompt (when (search-forward inf-clojure-prompt nil t)
+ (match-beginning 0))))
+ (buffer-substring-no-properties beg (or prompt end))))))
+
+(defun inf-clojure--nil-string-match-p (string)
+ "Return true iff STRING is not nil.
+This function also takes into consideration weird escape
+character and matches if nil is anywhere within the input
+string."
+ (string-match-p "\\Ca*nil\\Ca*" string))
+
+(defun inf-clojure--some (data)
+ "Return DATA unless nil or includes \"nil\" as string."
+ (cond
+ ((null data) nil)
+ ((and (stringp data)
+ (inf-clojure--nil-string-match-p data)) nil)
+ (t data)))
+
+(defun inf-clojure--read-or-nil (response)
+ "Read RESPONSE and return it as data.
+
+If response is nil or includes the \"nil\" string return nil
+instead.
+
+Note that the read operation will always return the first
+readable sexp only."
+ ;; The following reads the first LISP expression
+ (inf-clojure--some
+ (when response
+ (ignore-errors (read response)))))
+
+(defun inf-clojure--process-response-match-p (match-p proc form)
+ "Eval MATCH-P on the response of sending to PROC the input FORM.
+Note that this function will add a \n to the end (or )f the string
+for evaluation, therefore FORM should not include it."
+ (when-let ((response (inf-clojure--process-response form proc)))
+ (funcall match-p response)))
+
+(defun inf-clojure--some-response-p (proc form)
+ "Return true iff PROC's response after evaluating FORM is not nil."
+ (inf-clojure--process-response-match-p
+ (lambda (string)
+ (not (inf-clojure--nil-string-match-p string)))
+ proc form))
+
+;;;; Commands
+;;;; ========
(defun inf-clojure-arglists (fn)
"Send a query to the inferior Clojure for the arglists for function FN.
See variable `inf-clojure-arglists-form'."
- (let* ((arglists-snippet (format (inf-clojure-arglists-form) fn))
- (arglists-result (inf-clojure-results-from-process (inf-clojure-proc)
arglists-snippet))
- (arglists-data (when arglists-result (read arglists-result))))
- (cond
- ((null arglists-data) nil)
- ((stringp arglists-data) arglists-data)
- ((listp arglists-data) arglists-result))))
+ (thread-first
+ (format (inf-clojure-arglists-form) fn)
+ (inf-clojure--process-response (inf-clojure-proc) "(" ")")
+ (inf-clojure--some)))
(defun inf-clojure-show-arglists (prompt-for-symbol)
"Show the arglists for function FN in the mini-buffer.
@@ -1051,26 +1095,18 @@ See variable `inf-clojure-buffer'."
(or proc
(error "No Clojure subprocess; see variable `inf-clojure-buffer'"))))
+(defun inf-clojure--list-or-nil (data)
+ "Return DATA if and only if it is a list."
+ (when (listp data) data))
+
(defun inf-clojure-completions (expr)
"Return a list of completions for the Clojure expression starting with EXPR."
- (let* ((proc (inf-clojure-proc))
- (comint-filt (process-filter proc))
- (kept "")
- completions)
- (set-process-filter proc (lambda (_proc string) (setq kept (concat kept
string))))
- (unwind-protect
- (let ((completion-snippet
- (format
- (inf-clojure-completion-form) (substring-no-properties expr))))
- (process-send-string proc completion-snippet)
- (while (and (not (string-match inf-clojure-prompt kept))
- (accept-process-output proc 2)))
- (setq completions (read kept))
- ;; Subprocess echoes output on Windows and OS X.
- (when (and completions (string= (concat (car completions) "\n")
completion-snippet))
- (setq completions (cdr completions))))
- (set-process-filter proc comint-filt))
- completions))
+ (when (not (string-blank-p expr))
+ (thread-first
+ (format (inf-clojure-completion-form) (substring-no-properties expr))
+ (inf-clojure--process-response (inf-clojure-proc) "(" ")")
+ (inf-clojure--read-or-nil)
+ (inf-clojure--list-or-nil))))
(defconst inf-clojure-clojure-expr-break-chars " \t\n\"\'`><,;|&{(")
@@ -1232,7 +1268,7 @@ to suppress the usage of the target buffer discovery
logic."
"Return MATCH-P on the result of sending FORM to PROC.
Note that this function will add a \n to the end of the string
for evaluation, therefore FORM should not include it."
- (funcall match-p (inf-clojure-results-from-process proc form nil)))
+ (funcall match-p (inf-clojure--process-response form proc nil)))
;;;; Lumo
;;;; ====
- [nongnu] elpa/inf-clojure 5ef6bdf 123/313: Revert "Remove unwanted ansi chars from the REPL output", (continued)
- [nongnu] elpa/inf-clojure 5ef6bdf 123/313: Revert "Remove unwanted ansi chars from the REPL output", ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 7441d3b 120/313: Fix REPL type detection, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 2669544 129/313: [Fix #63] Avoid spurious output by using buffer redirection, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 0fbcfcb 140/313: Improve the README a bit, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure db7bfaf 155/313: Fix the changelog, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 42f860f 169/313: Add Multiple Process Support section to README, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 3a93815 170/313: [Fix #105] Add planck-specific function for show-arglist (#106), ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 204e5b7 114/313: Do some cleanup in preparation for a major release, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure d81e266 116/313: [Fix #48] Stop prompting for the symbol at point by default (#51), ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 431c068 127/313: Fix three "variable is void" bugs, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 723064d 151/313: [Fix #83] Harden parsing of repl responses (#85),
ELPA Syncer <=
- [nongnu] elpa/inf-clojure a705085 152/313: Add nil parameter to lumo completions' atom, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure f7ec13a 160/313: Improve performance of inf-clojure--process-response and close #89, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 12583f4 175/313: Add :safe clause for inf-clojure-repl-use-same-window, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 247ca70 182/313: Release 2.1.0, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 62bb0fc 186/313: Update CHANGELOG.md, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure dcb523b 191/313: Avoid computing completion bounds when no valid chars are at point, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 1507faa 119/313: Add dir support in Lumo, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure ff72d66 236/313: [Fix #171] Release 2.2.0, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure ac40726 241/313: Move all repl stuff into single nested alist, ELPA Syncer, 2021/08/11
- [nongnu] elpa/inf-clojure 24121e5 246/313: Add babashka repl and readme cleanups, ELPA Syncer, 2021/08/11