-
-
Notifications
You must be signed in to change notification settings - Fork 116
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
sogaiu
committed
Oct 27, 2023
1 parent
cb86d46
commit 5036ec7
Showing
5 changed files
with
371 additions
and
2 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
*conjure-client-janet-stdio* | ||
|
||
============================================================================== | ||
CONTENTS *conjure-client-janet-stdio-contents* | ||
|
||
1. Introduction ........ |conjure-client-janet-stdio-introduction| | ||
2. Mappings ................ |conjure-client-janet-stdio-mappings| | ||
3. Configuration ...... |conjure-client-janet-stdio-configuration| | ||
|
||
============================================================================== | ||
INTRODUCTION *conjure-client-janet-stdio-introduction* | ||
> | ||
Janet is a functional and imperative programming language. It runs on | ||
Windows, Linux, macOS, BSDs, and should run on other systems with some | ||
porting. The entire language (core library, interpreter, compiler, | ||
assembler, PEG) is less than 1MB. You can also add Janet scripting to an | ||
application by embedding a single C file and two headers. | ||
Conjure starts a Janet REPL within Neovim when you first open a Janet file. | ||
|
||
The default Janet filetype client is `conjure.client.janet.netrepl`, to use | ||
this client instead you must override the configuration. | ||
> | ||
let g:conjure#filetype#janet = "conjure.client.janet.stdio" | ||
You should be able to evaluate files and forms as you would with other Conjure | ||
supported languages right away. | ||
|
||
Check out `:ConjureSchool` if you're unsure about what evaluation operations | ||
you can perform. | ||
|
||
* https://janet-lang.org/ | ||
|
||
============================================================================== | ||
MAPPINGS *conjure-client-janet-stdio-mappings* | ||
|
||
These mappings are the defaults, you can change them as described in | ||
|conjure-mappings| and |conjure-configuration|. | ||
|
||
See |conjure-client-janet-stdio-configuration| for specific configuration | ||
options relevant to these mappings. | ||
|
||
<localleader>cs Start the Janet REPL if it's not running already. | ||
|
||
<localleader>cS Stop any existing Janet REPL. | ||
|
||
============================================================================== | ||
CONFIGURATION *conjure-client-janet-stdio-configuration* | ||
|
||
All configuration can be set as described in |conjure-configuration|. | ||
|
||
|
||
*g:conjure#client#janet#stdio#mapping#start* | ||
`g:conjure#client#janet#stdio#mapping#start` | ||
Start the Janet REPL if it's not running already. | ||
Default: `"cs"` | ||
|
||
*g:conjure#client#janet#stdio#mapping#stop* | ||
`g:conjure#client#janet#stdio#mapping#stop` | ||
Stop any existing Janet REPL. | ||
Default: `"cS"` | ||
|
||
*g:conjure#client#janet#stdio#command* | ||
`g:conjure#client#janet#stdio#command` | ||
Command used to start the Janet REPL, you can modify this to add | ||
arguments or change the command entirely. | ||
Default: `"janet -n -s"` | ||
|
||
*g:conjure#client#janet#stdio#prompt_pattern* | ||
`g:conjure#client#janet#stdio#prompt_pattern` | ||
Lua pattern to identify a new REPL prompt. This match signals to | ||
Conjure that the previous evaluation is complete and we're ready | ||
to submit more code as well as collect all output prior to the | ||
marker as the result. | ||
Default: `"repl:[0-9]+:[^>]*> "` | ||
|
||
vim:tw=78:sw=2:ts=2:ft=help:norl:et:listchars= |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
(module conjure.client.scheme.stdio | ||
{autoload {a conjure.aniseed.core | ||
str conjure.aniseed.string | ||
nvim conjure.aniseed.nvim | ||
stdio conjure.remote.stdio | ||
config conjure.config | ||
mapping conjure.mapping | ||
client conjure.client | ||
log conjure.log | ||
ts conjure.tree-sitter} | ||
require-macros [conjure.macros]}) | ||
|
||
(config.merge | ||
{:client | ||
{:janet | ||
{:stdio | ||
{:mapping {:start "cs" | ||
:stop "cS"} | ||
;; -n -> disables ansi color | ||
;; -s -> raw stdin (no getline functionality) | ||
:command "janet -n -s" | ||
;; Example prompts: | ||
;; | ||
;; "repl:23:>" | ||
;; "repl:8:(>" | ||
;; | ||
:prompt_pattern "repl:[0-9]+:[^>]*> " | ||
;; XXX: Possibly at a future date (janet -d + (debug)): | ||
;; | ||
;; "debug[7]:2>" | ||
;; "debug[7]:2:{>" | ||
;; | ||
;;:prompt_pattern "(repl|debug\\[[0-9]+\\]):[0-9]+:[^>]*> " | ||
}}}}) | ||
|
||
(def- cfg (config.get-in-fn [:client :janet :stdio])) | ||
|
||
(defonce- state (client.new-state #(do {:repl nil}))) | ||
|
||
(def buf-suffix ".janet") | ||
(def comment-prefix "# ") | ||
(def form-node? ts.node-surrounded-by-form-pair-chars?) | ||
|
||
(defn- with-repl-or-warn [f opts] | ||
(let [repl (state :repl)] | ||
(if repl | ||
(f repl) | ||
(log.append [(.. comment-prefix "No REPL running")])))) | ||
|
||
(defn unbatch [msgs] | ||
{:out (->> msgs | ||
(a.map #(or (a.get $1 :out) (a.get $1 :err))) | ||
(str.join ""))}) | ||
|
||
(defn- format-message [msg] | ||
(->> (str.split msg.out "\n") | ||
(a.filter #(~= "" $1)))) | ||
|
||
(defn- prep-code [s] | ||
(.. s "\n")) | ||
|
||
(defn eval-str [opts] | ||
(with-repl-or-warn | ||
(fn [repl] | ||
(repl.send | ||
(prep-code opts.code) | ||
(fn [msgs] | ||
(let [lines (-> msgs unbatch format-message)] | ||
(when opts.on-result | ||
(opts.on-result (a.last lines))) | ||
(log.append lines))) | ||
{:batch? true})))) | ||
|
||
(defn eval-file [opts] | ||
(eval-str (a.assoc opts :code (a.slurp opts.file-path)))) | ||
|
||
(defn- 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 [] | ||
(let [repl (state :repl)] | ||
(when repl | ||
(repl.destroy) | ||
(display-repl-status :stopped) | ||
(a.assoc (state) :repl nil)))) | ||
|
||
(defn start [] | ||
(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}) | ||
(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] | ||
(log.append (format-message msg)))})))) | ||
|
||
(defn on-load [] | ||
(start)) | ||
|
||
(defn on-filetype [] | ||
(mapping.buf | ||
:JanetStart (cfg [:mapping :start]) | ||
start | ||
{:desc "Start the REPL"}) | ||
|
||
(mapping.buf | ||
:JanetStop (cfg [:mapping :stop]) | ||
stop | ||
{:desc "Stop the REPL"})) | ||
|
||
(defn on-exit [] | ||
(stop)) | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
local _2afile_2a = "fnl/conjure/client/janet/stdio.fnl" | ||
local _2amodule_name_2a = "conjure.client.scheme.stdio" | ||
local _2amodule_2a | ||
do | ||
package.loaded[_2amodule_name_2a] = {} | ||
_2amodule_2a = package.loaded[_2amodule_name_2a] | ||
end | ||
local _2amodule_locals_2a | ||
do | ||
_2amodule_2a["aniseed/locals"] = {} | ||
_2amodule_locals_2a = (_2amodule_2a)["aniseed/locals"] | ||
end | ||
local autoload = (require("conjure.aniseed.autoload")).autoload | ||
local a, client, config, log, mapping, nvim, stdio, str, ts, _ = autoload("conjure.aniseed.core"), autoload("conjure.client"), autoload("conjure.config"), autoload("conjure.log"), autoload("conjure.mapping"), autoload("conjure.aniseed.nvim"), autoload("conjure.remote.stdio"), autoload("conjure.aniseed.string"), autoload("conjure.tree-sitter"), nil | ||
_2amodule_locals_2a["a"] = a | ||
_2amodule_locals_2a["client"] = client | ||
_2amodule_locals_2a["config"] = config | ||
_2amodule_locals_2a["log"] = log | ||
_2amodule_locals_2a["mapping"] = mapping | ||
_2amodule_locals_2a["nvim"] = nvim | ||
_2amodule_locals_2a["stdio"] = stdio | ||
_2amodule_locals_2a["str"] = str | ||
_2amodule_locals_2a["ts"] = ts | ||
_2amodule_locals_2a["_"] = _ | ||
config.merge({client = {janet = {stdio = {mapping = {start = "cs", stop = "cS"}, command = "janet -n -s", prompt_pattern = "repl:[0-9]+:[^>]*> "}}}}) | ||
local cfg = config["get-in-fn"]({"client", "janet", "stdio"}) | ||
do end (_2amodule_locals_2a)["cfg"] = cfg | ||
local state | ||
local function _1_() | ||
return {repl = nil} | ||
end | ||
state = ((_2amodule_2a).state or client["new-state"](_1_)) | ||
do end (_2amodule_locals_2a)["state"] = state | ||
local buf_suffix = ".janet" | ||
_2amodule_2a["buf-suffix"] = buf_suffix | ||
local comment_prefix = "# " | ||
_2amodule_2a["comment-prefix"] = comment_prefix | ||
local form_node_3f = ts["node-surrounded-by-form-pair-chars?"] | ||
_2amodule_2a["form-node?"] = form_node_3f | ||
local function with_repl_or_warn(f, opts) | ||
local repl = state("repl") | ||
if repl then | ||
return f(repl) | ||
else | ||
return log.append({(comment_prefix .. "No REPL running")}) | ||
end | ||
end | ||
_2amodule_locals_2a["with-repl-or-warn"] = with_repl_or_warn | ||
local function unbatch(msgs) | ||
local function _3_(_241) | ||
return (a.get(_241, "out") or a.get(_241, "err")) | ||
end | ||
return {out = str.join("", a.map(_3_, msgs))} | ||
end | ||
_2amodule_2a["unbatch"] = unbatch | ||
local function format_message(msg) | ||
local function _4_(_241) | ||
return ("" ~= _241) | ||
end | ||
return a.filter(_4_, str.split(msg.out, "\n")) | ||
end | ||
_2amodule_locals_2a["format-message"] = format_message | ||
local function prep_code(s) | ||
return (s .. "\n") | ||
end | ||
_2amodule_locals_2a["prep-code"] = prep_code | ||
local function eval_str(opts) | ||
local function _5_(repl) | ||
local function _6_(msgs) | ||
local lines = format_message(unbatch(msgs)) | ||
if opts["on-result"] then | ||
opts["on-result"](a.last(lines)) | ||
else | ||
end | ||
return log.append(lines) | ||
end | ||
return repl.send(prep_code(opts.code), _6_, {["batch?"] = true}) | ||
end | ||
return with_repl_or_warn(_5_) | ||
end | ||
_2amodule_2a["eval-str"] = eval_str | ||
local function eval_file(opts) | ||
return eval_str(a.assoc(opts, "code", a.slurp(opts["file-path"]))) | ||
end | ||
_2amodule_2a["eval-file"] = eval_file | ||
local function display_repl_status(status) | ||
local repl = state("repl") | ||
if repl then | ||
return log.append({(comment_prefix .. a["pr-str"](a["get-in"](repl, {"opts", "cmd"})) .. " (" .. status .. ")")}, {["break?"] = true}) | ||
else | ||
return nil | ||
end | ||
end | ||
_2amodule_locals_2a["display-repl-status"] = display_repl_status | ||
local function stop() | ||
local repl = state("repl") | ||
if repl then | ||
repl.destroy() | ||
display_repl_status("stopped") | ||
return a.assoc(state(), "repl", nil) | ||
else | ||
return nil | ||
end | ||
end | ||
_2amodule_2a["stop"] = stop | ||
local function start() | ||
if state("repl") then | ||
return 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}) | ||
else | ||
local function _10_() | ||
return display_repl_status("started") | ||
end | ||
local function _11_(err) | ||
return display_repl_status(err) | ||
end | ||
local function _12_(code, signal) | ||
if (("number" == type(code)) and (code > 0)) then | ||
log.append({(comment_prefix .. "process exited with code " .. code)}) | ||
else | ||
end | ||
if (("number" == type(signal)) and (signal > 0)) then | ||
log.append({(comment_prefix .. "process exited with signal " .. signal)}) | ||
else | ||
end | ||
return stop() | ||
end | ||
local function _15_(msg) | ||
return log.append(format_message(msg)) | ||
end | ||
return a.assoc(state(), "repl", stdio.start({["prompt-pattern"] = cfg({"prompt_pattern"}), cmd = cfg({"command"}), ["on-success"] = _10_, ["on-error"] = _11_, ["on-exit"] = _12_, ["on-stray-output"] = _15_})) | ||
end | ||
end | ||
_2amodule_2a["start"] = start | ||
local function on_load() | ||
return start() | ||
end | ||
_2amodule_2a["on-load"] = on_load | ||
local function on_filetype() | ||
mapping.buf("JanetStart", cfg({"mapping", "start"}), start, {desc = "Start the REPL"}) | ||
return mapping.buf("JanetStop", cfg({"mapping", "stop"}), stop, {desc = "Stop the REPL"}) | ||
end | ||
_2amodule_2a["on-filetype"] = on_filetype | ||
local function on_exit() | ||
return stop() | ||
end | ||
_2amodule_2a["on-exit"] = on_exit | ||
return _2amodule_2a |