Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert SQL client #599

Merged
merged 3 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 70 additions & 65 deletions fnl/conjure/client/sql/stdio.fnl
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
(import-macros {: module : def : defn : defonce : def- : defn- : defonce- : wrap-last-expr : wrap-module-body : deftest} :nfnl.macros.aniseed)

(module conjure.client.sql.stdio
{autoload {a conjure.aniseed.core
str conjure.aniseed.string
nvim conjure.aniseed.nvim
stdio conjure.remote.stdio-rt
config conjure.config
text conjure.text
mapping conjure.mapping
client conjure.client
log conjure.log
ts conjure.tree-sitter}
require-macros [conjure.macros]})
(local {: autoload} (require :nfnl.module))
(local a (autoload :conjure.aniseed.core))
(local str (autoload :conjure.aniseed.string))
(local client (autoload :conjure.client))
(local log (autoload :conjure.log))
(local stdio (autoload :conjure.remote.stdio-rt))
(local config (autoload :conjure.config))
(local mapping (autoload :conjure.mapping))

(import-macros {: augroup : autocmd} :conjure.macros)

;;------------------------------------------------------------
;; Based on fnl/conjure/client/fennel/stdio.fnl.
Expand Down Expand Up @@ -43,45 +39,44 @@
:stop "cS"
:interrupt "ei"}}}}}))

(def- cfg (config.get-in-fn [:client :sql :stdio]))

(defonce- state (client.new-state #(do {:repl nil})))
(local cfg (config.get-in-fn [:client :sql :stdio]))
(local state (client.new-state #(do {:repl nil})))

(def buf-suffix ".sql")
(def comment-prefix "-- ")
(local buf-suffix ".sql")
(local comment-prefix "-- ")

;; Rough equivalent of a Lisp form.
(defn form-node? [node]
(fn form-node? [node]
(or (= "statement" (node:type))))

;; Comment nodes are comment (--) and marginalia (/*...*/)
(defn comment-node? [node]
(fn comment-node? [node]
(or (= "comment" (node:type))
(= "marginalia" (node:type))))

(defn- with-repl-or-warn [f opts]
(fn with-repl-or-warn [f opts]
(let [repl (state :repl)]
(if repl
(f repl)
(log.append [(.. comment-prefix "No REPL running")]))))

;;;;-------- from client/fennel/stdio.fnl ----------------------
(defn- format-message [msg]
(fn format-message [msg]
(str.split (or msg.out msg.err) "\n"))

(defn- remove-blank-lines [msg]
(fn remove-blank-lines [msg]
(->> (format-message msg)
(a.filter #(not (= "" $1)))))

(defn- display-result [msg]
(fn display-result [msg]
(log.append (remove-blank-lines msg)))

(defn ->list [s]
(fn ->list [s]
(if (a.first s)
s
[s]))

(defn eval-str [opts]
(fn eval-str [opts]
(with-repl-or-warn
(fn [repl]
(repl.send
Expand All @@ -90,77 +85,75 @@
(let [msgs (->list msgs)]
(when opts.on-result
(opts.on-result (str.join "\n" (remove-blank-lines (a.last msgs)))))
(a.run! display-result msgs))
)
(a.run! display-result msgs)))
{:batch? false}))))
;;;;-------- End from client/fennel/stdio.fnl ------------------

(defn eval-file [opts]
(fn eval-file [opts]
(eval-str (a.assoc opts :code (a.slurp opts.file-path))))

(defn interrupt []
(fn interrupt []
(with-repl-or-warn
(fn [repl]
(log.append [(.. comment-prefix " Sending interrupt signal.")] {:break? true})
(repl.send-signal vim.loop.constants.SIGINT))))

(defn- display-repl-status [status]
(fn display-repl-status [status]
(let [repl (state :repl)]
(when repl
(log.append
[(.. comment-prefix (a.pr-str (a.get-in repl [:opts :cmd])) " (" status ")")]
{:break? true}))))

(defn stop []
(fn stop []
(let [repl (state :repl)]
(when repl
(repl.destroy)
(display-repl-status :stopped)
(a.assoc (state) :repl nil))))

(defn start []
(fn start []
(log.append [(.. comment-prefix "Starting SQL client...")])
(if (state :repl)
(log.append [(.. comment-prefix "Can't start, REPL is already running.")
(.. comment-prefix "Stop the REPL with "
(config.get-in [:mapping :prefix])
(cfg [:mapping :stop]))]
{:break? true})
(do
(a.assoc
(state) :repl
(stdio.start
{:prompt-pattern (cfg [:prompt_pattern])
:cmd (cfg [:command])

:on-success
(fn []
(display-repl-status :started))

:on-error
(fn [err]
(display-repl-status err))

:on-exit
(fn [code signal]
(when (and (= :number (type code)) (> code 0))
(log.append [(.. comment-prefix "process exited with code " code)]))
(when (and (= :number (type signal)) (> signal 0))
(log.append [(.. comment-prefix "process exited with signal " signal)]))
(stop))

:on-stray-output
(fn [msg]
(display-result msg))})))))

(defn on-load []
(a.assoc
(state) :repl
(stdio.start
{:prompt-pattern (cfg [:prompt_pattern])
:cmd (cfg [:command])

:on-success
(fn []
(display-repl-status :started))

:on-error
(fn [err]
(display-repl-status err))

:on-exit
(fn [code signal]
(when (and (= :number (type code)) (> code 0))
(log.append [(.. comment-prefix "process exited with code " code)]))
(when (and (= :number (type signal)) (> signal 0))
(log.append [(.. comment-prefix "process exited with signal " signal)]))
(stop))

:on-stray-output
(fn [msg]
(display-result msg))}))))

(fn on-load []
(when (config.get-in [:client_on_load])
(start)))

(defn on-exit []
(fn on-exit []
(stop))

(defn on-filetype []
(fn on-filetype []
(mapping.buf
:SqlStart (cfg [:mapping :start])
start
Expand All @@ -176,4 +169,16 @@
interrupt
{:desc "Interrupt the current REPL"}))

*module*
{: buf-suffix
: comment-prefix
: form-node?
: comment-node?
: ->list
: eval-str
: eval-file
: interrupt
: stop
: start
: on-load
: on-exit
: on-filetype}
29 changes: 15 additions & 14 deletions fnl/conjure/remote/stdio-rt.fnl
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
(import-macros {: module : def : defn : defonce : def- : defn- : defonce- : wrap-last-expr : wrap-module-body : deftest} :nfnl.macros.aniseed)
(local {: autoload} (require :nfnl.module))
(local a (autoload :conjure.aniseed.core))
(local nvim (autoload :conjure.aniseed.nvim))
(local str (autoload :conjure.aniseed.string))
(local client (autoload :conjure.client))
(local log (autoload :conjure.log))

(module conjure.remote.stdio-rt
{autoload {a conjure.aniseed.core
nvim conjure.aniseed.nvim
str conjure.aniseed.string
client conjure.client
log conjure.log}})
(local uv vim.loop)

(def- uv vim.loop)

(defn- parse-prompt [s pat]
(fn parse-prompt [s pat]
(if (s:find pat)
(values true (s:gsub pat ""))
(values false s)))

(defn parse-cmd [x]
(fn parse-cmd [x]
(if
(a.table? x)
{:cmd (a.first x)
Expand All @@ -23,7 +21,7 @@
(a.string? x)
(parse-cmd (str.split x "%s"))))

(defn- extend-env [vars]
(fn extend-env [vars]
(->> (a.merge
(nvim.fn.environ)
vars)
Expand All @@ -35,7 +33,7 @@
; This function sets up internal functions before spawning a child
; process to run the repl. It's called by a client to start a repl
; and returns a modified repl table.
(defn start [opts]
(fn start [opts]
"Starts an external REPL and gives you hooks to send code to it and read
responses back out. Tying an input to a result is near enough impossible
through this stdio medium, so it's a best effort.
Expand Down Expand Up @@ -154,4 +152,7 @@
(client.schedule #(opts.on-error pid-or-err))
(destroy))))))

*module*
{
: parse-cmd
: start
}
Loading