From c0ae50fba0f4bf2f618e028933b7e066b2695932 Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sun, 10 Apr 2022 12:03:16 -0400 Subject: [PATCH] Implement go to definition, REPL restart on crash --- editor/init.fnl | 42 +++++++++++++++++++++++++++++++++++++++++- editor/replsession.fnl | 29 ++++++++++++++++++----------- main.lua | 12 +++++++----- sqlog/macros.fnl | 6 +++--- 4 files changed, 69 insertions(+), 20 deletions(-) diff --git a/editor/init.fnl b/editor/init.fnl index baaaf16..be4f4f8 100644 --- a/editor/init.fnl +++ b/editor/init.fnl @@ -11,6 +11,24 @@ (ldoc:get_text aline 1 aline 10000000) (ldoc:get_text aline acol bline bcol)))) +(fn find-closest [s pattern i-target] + (var (start end) nil) + (set (start end) (s:find pattern)) + (while (and start (< end (- i-target 1))) + (set (start end) (s:find pattern (+ end 1)))) + (if (<= start i-target) (values start end) + (values 1 0))) + +(local symbol-pattern "[a-zA-Z%!%@%#%$%%%^%&%*%<%>%?%/%~%-%_%=%+][a-zA-Z%!%@%#%$%%%^%&%*%<%>%?%/%~%-%_%=%+0-9%.%:]*") +(fn selected-symbol [] + (let [ldoc core.active_view.doc + (aline acol bline bcol) (ldoc:get_selection)] + (if (and (= aline bline) (= acol bcol)) + (let [line (ldoc:get_text aline 1 aline 10000000) + (start end) (find-closest line symbol-pattern acol)] + (ldoc:get_text aline start aline (+ end 1))) + (ldoc:get_text aline acol bline bcol)))) + (fn inline-eval [eval] (let [ldoc core.active_view.doc (aline acol bline bcol) (ldoc:get_selection)] @@ -23,15 +41,37 @@ }) (local {: show : submit} (util.require :inspector.debug)) +(local replsession (require :editor.replsession)) (command.add nil { "repl:create" #(show) }) + +(fn go-to-definition [symbol] + (fn jump-to-find-result [result] + (when (not (match result + {:vals [loc]} + (let [(filename line) (when loc (loc:match "(.*):([0-9]+)")) + filename (or filename "") + filename (if (filename:find "^%.%.%.") "" (or (filename:match "^%./(.*)") filename)) + line (tonumber (or line 0)) + doc (when (> (length filename) 0) (core.open_doc filename))] + (when doc + (core.root_view:open_doc doc) + (doc:set_selection line 1 line 1) + true)))) + (core.log (.. "Unable to find symbol " symbol)))) + (: (replsession.session) :submit (.. ",find " symbol) jump-to-find-result)) + (command.add :core.docview { "repl:eval" #(submit nil (selected-form)) + "repl:go-to-definition" #(go-to-definition (selected-symbol)) }) + (keymap.add { :return "repl:submit" "alt+e" "repl:eval" + "alt+d" "repl:go-to-definition" }) -{: inline-eval} +{: inline-eval : symbol-pattern} + diff --git a/editor/replsession.fnl b/editor/replsession.fnl index 36784bc..1cf725f 100644 --- a/editor/replsession.fnl +++ b/editor/replsession.fnl @@ -1,25 +1,32 @@ (local util (require :lib.util)) (local fennel (require :lib.fennel)) +(local core (require :core)) (local replsession (util.hot-table ...)) (set replsession.sessions {}) -(fn replsession.new-session [] - (let [run (fn [session] - (fennel.repl {:readChunk coroutine.yield - :onValues #(session.callback {:vals $1}) - :onError #(session.callback {:errType $1 :err $2 :luaSource $3 :traceback (fennel.traceback)}) - :pp #$1 - :env (lume.clone _G)})) - session {:coro (coroutine.create run) :submit replsession.submit}] - (coroutine.resume session.coro session) - session)) +(fn replsession.session-run [session] + (fennel.repl {:readChunk coroutine.yield + ; todo: log errors? + :onValues #(pcall session.callback {:vals $1}) + :onError #(pcall session.callback {:errType $1 :err $2 :luaSource $3 :traceback (fennel.traceback)}) + :pp #$1 + :env (lume.clone _G)})) + +(fn replsession.restart-session [session] + (set session.coro (coroutine.create replsession.session-run)) + (coroutine.resume session.coro session) + session) + +(fn replsession.new-session [] (replsession.restart-session {:submit replsession.submit})) (fn replsession.submit [session chunk callback] (assert (= session.callback nil)) (set session.callback callback) - (coroutine.resume session.coro (.. chunk "\n")) + (match (pcall coroutine.resume session.coro (.. chunk "\n")) + (false err) (do (core.log (.. "REPL crashed: " err)) + (replsession.restart-session session))) (assert (= session.callback callback)) (set session.callback nil)) diff --git a/main.lua b/main.lua index e6035df..8d806a9 100644 --- a/main.lua +++ b/main.lua @@ -7,12 +7,14 @@ pp = function(x) print(fv(x)) end lume = require("lib.lume") _coroutine_resume = coroutine.resume +function handle_error(ok, ...) + if not ok then + error(...) + end + return ok, ... +end function coroutine.resume(...) - local state,result = _coroutine_resume(...) - if not state then - error( tostring(result), 2 ) -- Output error message - end - return state,result + return handle_error(_coroutine_resume(...)) end require("vendor.lite.main") diff --git a/sqlog/macros.fnl b/sqlog/macros.fnl index 992b57d..6778a6a 100644 --- a/sqlog/macros.fnl +++ b/sqlog/macros.fnl @@ -1,6 +1,6 @@ -; [q X] -> q(X) -; [q :x] -> q(x) -; [q #(+ 1 2)] -> q(3) +; [q X] -> q(X) -> [:literal :q [:var :X]] +; [q :x] -> q(x) -> [:literal :q [:const :x]] +; [q #(+ 1 2)] -> q(3) -> [:literal q [:const (+ 1 2)]] (fn clause [c] (match c