Last active
October 15, 2023 00:56
-
-
Save Risto-Stevcev/51b29b79b661caeee38341fa12365aa7 to your computer and use it in GitHub Desktop.
Conjure nodejs client attempt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(local a (require :conjure.aniseed.core)) | |
;;(import-macros {: def} :aniseed) | |
(local extract (require :conjure.extract)) | |
(local str (require :conjure.aniseed.string)) | |
(local nvim (require :conjure.aniseed.nvim)) | |
(local stdio (require :conjure.remote.stdio)) | |
(local config (require :conjure.config)) | |
(local text (require :conjure.text)) | |
(local mapping (require :conjure.mapping)) | |
(local client (require :conjure.client)) | |
(local log (require :conjure.log)) | |
(local ts (require :conjure.tree-sitter)) | |
(local b64 (require :conjure.remote.transport.base64)) | |
(config.merge {:client {:nodejs {:stdio {:mapping {:start :cs | |
:stop :cS | |
:interrupt :ei} | |
:command "tee /home/risto/foo" | |
:prompt-pattern "> " | |
:delay-stderr-ms 10}}}}) | |
(local cfg (config.get-in-fn [:client :nodejs :stdio])) | |
(local state (client.new-state #(do | |
{:repl nil}))) | |
(local buf-suffix :.js) | |
(local comment-prefix "// ") | |
(fn form-node? [node] | |
(or (= :variable_declaration (node:type)) | |
(= :lexical_declaration (node:type)) (= :function_declaration (node:type)) | |
(= :class_declaration (node:type)) (= :generator_function (node:type)) | |
(= :arrow_function (node:type)) (= :function (node:type)) | |
(= :new_expression (node:type)) (= :parenthesized_expression (node:type)) | |
(= :statement_block (node:type)) (= :template_string (node:type)) | |
(= :string (node:type)) (= :object (node:type)) (= :array (node:type)) | |
(= :number (node:type)) (= :true (node:type)) (= :false (node:type)))) | |
(fn with-repl-or-warn [f opts] | |
(log.dbg (str.join ["With repl or warn" "!"])) | |
(let [repl (state :repl)] | |
(if repl | |
(f repl) | |
;(do | |
;(log.append [(str.join comment-prefix "has repl")]) | |
;(repl.send "TextEncoder;\n" (fn [msgs] (log.dbg "done")) {:batch? true}) | |
;(log.append [(str.join comment-prefix "send repl")]) | |
; (f repl)) | |
(log.append [(str.join comment-prefix "No REPL running") | |
(str.join comment-prefix "Start REPL with " | |
(config.get-in [:mapping :prefix]) | |
(cfg [:mapping :start]))])))) | |
(fn is-dots? [s] | |
(= (string.sub s 1 3) :str.join.)) | |
(fn format-msg [msg] | |
(->> (text.split-lines msg) | |
(a.filter #(not= "" $1)) | |
(a.filter #(not (is-dots? $1))))) | |
(fn get-console-output-msgs [msgs] | |
(->> (a.butlast msgs) | |
(a.map #(str.join comment-prefix "(out) " $1)))) | |
(fn get-expression-result [msgs] | |
(let [result (a.last msgs)] | |
(if (or (a.nil? result) (is-dots? result)) | |
nil | |
result))) | |
(fn unbatch [msgs] | |
(log.dbg "unbatch") | |
(->> msgs | |
(a.map #(or (a.get $1 :out) (a.get $1 :err))) | |
(str.join ""))) | |
;(fn prep-code [s] | |
; (log.append s) | |
; (str.join s "\nif(isnothing(ans)) display(nothing) end\n")) | |
(fn log-repl-output [msgs] | |
(log.dbg "log-repl-output") | |
(let [msgs (-> msgs unbatch format-msg) | |
console-output-msgs (get-console-output-msgs msgs) | |
cmd-result (get-expression-result msgs)] | |
(when (not (a.empty? console-output-msgs)) | |
(log.append console-output-msgs)) | |
(when cmd-result | |
(log.append [cmd-result])))) | |
(fn eval-str [opts] | |
(log.dbg :eval-str) | |
;(log.dbg opts.code) | |
(with-repl-or-warn (fn [repl] | |
(repl.send (str.join opts.code "\n") | |
(fn [msgs] | |
(log.dbg "received msg") | |
(log-repl-output msgs) | |
(when opts.on-result | |
(let [msgs (-> msgs unbatch format-msg) | |
cmd-result (get-expression-result msgs)] | |
(opts.on-result cmd-result)))) | |
{:batch? true})))) | |
(fn eval-file [opts] | |
(eval-str (a.assoc opts :code (a.slurp opts.file-path)))) | |
(fn display-repl-status [status] | |
(let [repl (state :repl)] | |
(when repl | |
(log.append [(str.join comment-prefix | |
(a.pr-str (a.get-in repl [:opts :cmd])) " (" status | |
")")] {:break? true})))) | |
(fn stop [] | |
(let [repl (state :repl)] | |
(when repl | |
(repl.destroy) | |
(display-repl-status :stopped) | |
(a.assoc (state) :repl nil)))) | |
(fn start [] | |
(if (state :repl) | |
(log.append [(str.join comment-prefix | |
"Can't start, REPL is already running.") | |
(str.join comment-prefix "Stop the REPL with " | |
(config.get-in [:mapping :prefix]) | |
(cfg [:mapping :stop]))] | |
{:break? true}) | |
(if (not (pcall #(if vim.treesitter.language.require_language | |
(vim.treesitter.language.require_language :javascript) | |
(vim.treesitter.require_language :javascript)))) | |
(log.append [(str.join comment-prefix | |
"(error) The nodejs client requires a javascript treesitter parser in order to function.") | |
(str.join comment-prefix | |
"(error) See https://github.com/nvim-treesitter/nvim-treesitter") | |
(str.join comment-prefix | |
"(error) for installation instructions.")]) | |
(a.assoc (state) :repl | |
(stdio.start {:prompt-pattern (cfg [:prompt-pattern]) | |
:cmd (cfg [:command]) | |
:delay-stderr-ms (cfg [:delay-stderr-ms]) | |
:on-success (fn [] | |
(log.dbg "on-success") | |
(display-repl-status :started) | |
(with-repl-or-warn (fn [repl] | |
(repl.send "(1 + 2);\n" | |
(fn [msgs] | |
(log.dbg "received msg2") | |
;;(log.dbg (str.join msgs)) | |
;(log.append (-> msgs | |
; unbatch | |
; format-msg)) | |
) | |
{:batch? true})))) | |
:on-error (fn [err] | |
(display-repl-status err)) | |
:on-exit (fn [code signal] | |
(when (and (= :number (type code)) | |
(> code 0)) | |
(log.append [(str.join comment-prefix | |
"process exited with code " | |
code)])) | |
(when (and (= :number (type signal)) | |
(> signal 0)) | |
(log.append [(str.join comment-prefix | |
"process exited with signal " | |
signal)])) | |
(stop)) | |
:on-stray-output (fn [msg] | |
(log.db "stray-output") | |
(log.dbg (-> [msg] unbatch | |
format-msg) | |
{:join-first? true}))}))))) | |
(fn on-load [] | |
(if (config.get-in [:client_on_load]) | |
(do | |
(start)) | |
(log.append ["Not starting repl"]))) | |
(fn on-exit [] | |
(stop)) | |
(fn interrupt [] | |
(with-repl-or-warn (fn [repl] | |
(log.append [(str.join comment-prefix | |
" Sending interrupt signal.")] | |
{:break? true}) | |
(repl.send-signal vim.loop.constants.SIGINT)))) | |
(fn on-filetype [] | |
(mapping.buf :NodeJsStart (cfg [:mapping :start]) start | |
{:desc "Start the NodeJs REPL"}) | |
(mapping.buf :NodeJsStop (cfg [:mapping :stop]) stop | |
{:desc "Stop the NodeJs REPL"}) | |
(mapping.buf :NodeJsInterrupt (cfg [:mapping :interrupt]) interrupt | |
{:desc "Interrupt the current evaluation"})) | |
{: format-msg | |
:connect start | |
: with-repl-or-warn | |
: form-node? | |
: buf-suffix | |
: comment-prefix | |
: eval-str | |
: eval-file | |
: on-load | |
: on-exit | |
: on-filetype} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment