conjure
conjure copied to clipboard
Displaying multiline results inline
Currently, conjure only displays the last line of the results inline. This is rarely useful though, for instance, when working with arrays. Example in Hy:
(import numpy :as np)
(np.array [[1, 2, 3] [7, 8, 9]]) ; => [7, 8, 9]])
I'm not sure how the inline display works currently. I searched around the code a bit and it doesn't seem to be using extmarks
. Yet with extmarks
it would be possible to loop over each line of the result and display all of them together at the end, like so:
(np.array [[1, 2, 3] [7, 8, 9]]) ; => array([[1, 2, 3],
; [7, 8, 9]])
Hmm I'm not sure about multi line results, that brings in a LOT of questions about how to make it fit in different buffers. I only really ever want to deal with single line virtual text which is done here https://github.com/Olical/conjure/blob/2717348d1a0687327f59880914fa260e4ad9c685/fnl/conjure/inline.fnl
I think this might be a client specific issue really, in the Clojure client we join all lines before they're displayed as virtual text, that should be happening in every client. So I'd argue, at least for now, we should just fix the Hy client or the bug that's preventing the lines from joining.
I didn't ever intend the virtual text to display all of the information for multi line results such as large data structures so I don't want to introduce the required complexity to support it. It's intended for small glances, I will still always defer to the log buffer for anything more substantial.
Yeah this just looks like how the Hy client is implemented. This fn needs to call on-result
with the whole string, not just the last value, but that might break anything. This probably all stems from the fact that we're using a stdio REPL and we're trying to infer very rich detailed meaning from when we see a new line or some prompt character. I need to overhaul the stdio wrapper code, if I can make that smarter the clients can get dumber (in the best way).
(defn eval-str [opts]
(var last-value nil)
(with-repl-or-warn
(fn [repl]
(repl.send
(prep-code opts.code)
(fn [msg]
(log.dbg "msg" msg)
; (let [msgs (a.filter #(not (= "" $1)) (str.split (or msg.err msg.out) "\n"))])
(let [msgs (->> (str.split (or msg.err msg.out) "\n")
(a.filter #(not (= "" $1))))]
; prefix (.. comment-prefix (if msg.err "(err)" "(out)") " ")]
(set last-value (or (a.last msgs) last-value))
; (log.append (a.map #(.. prefix $1) msgs))
(display-result msg)
(when msg.done?
; (log.append [(.. comment-prefix "Finished")])
(log.append [""])
(when opts.on-result
(opts.on-result last-value)))))))))
The code I mean, it seems to pick the last value. I might do some refactoring here at some point soon.
The Python client does the same thing. It returns the last line of the response as the return value while the other lines are treated as output. The buffer shows:
np.array([[1, 2, 3], [7, 8, 9]]) # [7, 8, 9]])
The log shows:
# (out) array([[1, 2, 3],
[7, 8, 9]])
The responses from the REPL appear to provide enough information to change how the client handles the results. With :let g:conjure#debug=v:true
, the log shows:
# debug: receive
"out" nil "array([[1, 2, 3],
[7, 8, 9]])
"
# debug: receive
"err" nil ">>> "
It may help to define the desired behavior for the various use-cases of "evaluating" code.
So could we just join the results with a space and use that whole string as the result instead of using the last line in these cases 🤔 not ideal, but better until the stdio layer has a deeper understanding of the text.