Skip to content

Commit

Permalink
Convert SQL client
Browse files Browse the repository at this point in the history
  • Loading branch information
russtoku committed Aug 27, 2024
1 parent d342536 commit b7c182f
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 193 deletions.
140 changes: 75 additions & 65 deletions fnl/conjure/client/sql/stdio.fnl
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
(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 nvim (autoload :conjure.aniseed.nvim))
(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 text (autoload :conjure.text))
(local mapping (autoload :conjure.mapping))
(local ts (autoload :conjure.tree-sitter))

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

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

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

(defonce- 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 +88,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 +172,18 @@
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

0 comments on commit b7c182f

Please sign in to comment.