fennel-xl/editor.fnl
Jeremy Penner 1bcea81f43 lite-xl 2.1 support, sort of (currently requires hack for luasocket)
some nrepl fixes, "project file" support for customizing lite-xl on a
per-project basis by loading a fennel file
2022-12-27 21:20:44 -05:00

131 lines
5.2 KiB
Fennel

(local lume (require :plugins.fennel-xl.lume))
(local util (require :plugins.fennel-xl.util))
(local core (require :core))
(local command (require :core.command))
(local keymap (require :core.keymap))
(local common (require :core.common))
(fn place-to-line [selection]
(let [selection (lume.clone selection)]
(when (selection:place?)
(set selection.acol 1)
(set selection.bcol math.huge))
selection))
(fn get-selection []
(let [ldoc core.active_view.doc
(aline acol bline bcol) (ldoc:get_selection)]
{: ldoc : aline : acol : bline : bcol
:place? (fn [self] (and (= self.aline self.bline) (= self.acol self.bcol)))
:rtl? (fn [self] (or (and (= self.aline self.bline) (< self.bcol self.acol)) (< self.bline self.aline)))
:get-text (fn [self] (self.ldoc:get_text self.aline self.acol self.bline self.bcol))
:replace-text (fn [self text]
(self.ldoc:set_selection self.aline self.acol self.bline self.bcol)
(self.ldoc:text_input text))}))
(fn to-place [selection ?beginning]
(let [selection (lume.clone selection)]
(if (or (and ?beginning (not (selection:rtl?))) (and (not ?beginning) (selection:rtl?)))
(set (selection.bline selection.bcol) (values selection.aline selection.acol))
(set (selection.aline selection.acol) (values selection.bline selection.bcol)))
selection))
(fn selected-form [] (: (place-to-line (get-selection)) :get-text))
(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 (and start (<= start i-target)) (values start (+ end 1))
(values i-target i-target)))
(local symbol-pattern "[a-zA-Z%!%@%#%$%%%^%&%*%<%>%?%/%~%-%_%=%+][a-zA-Z%!%@%#%$%%%^%&%*%<%>%?%/%~%-%_%=%+0-9%.%:]*")
(fn place-to-symbol [selection]
(let [selection (lume.clone selection)]
(when (selection:place?)
(let [line (: (place-to-line selection) :get-text)]
(set (selection.acol selection.bcol) (find-closest line symbol-pattern selection.acol))))
selection))
(fn selected-symbol [] (: (place-to-symbol (get-selection)) :get-text))
(fn inline-eval [eval] (: (to-place (get-selection)) :replace-text (eval (selected-form))))
(local {: show : submit} (util.require :plugins.fennel-xl.debug))
(local replsession (require :plugins.fennel-xl.replsession))
(local mm (util.require :plugins.fennel-xl.multimethod))
(local nrepl (require :plugins.fennel-xl.nrepl))
(command.add :plugins.fennel-xl.replview {
"repl:submit" #(core.active_view:submit)
"repl:restart" #(replsession.restart core.active_view.conn.session)
})
(command.add nil {
"repl:create" #(show)
"repl:switch-connection"
#(core.command_view:enter "Connection Type"
{:submit #(when $2.text (set replsession.default-repl $2.text))
:suggest #(mm.keys replsession.submit)})
})
(command.add #(nrepl:connected?) {
"nrepl:disconnect" #(nrepl:disconnect)
})
(command.add #(not (nrepl:connected?)) {
"nrepl:connect" #(nrepl:connect)
})
(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))
ldoc (when (> (length filename) 0) (core.open_doc filename))]
(when ldoc
(core.root_view:open_doc ldoc)
(ldoc:set_selection line 1 line 1)
true))))
(core.log (.. "Unable to find symbol " symbol))))
(: (replsession.session) :submit (.. ",find " symbol) jump-to-find-result) true)
(fn replace-selected-symbol [text] (: (place-to-symbol (get-selection)) :replace-text text))
(fn autocomplete-results [text]
(var symbols [])
(: (replsession.session) :submit (.. ",complete " text) #(set symbols (or $1.vals [])) true)
(icollect [_ symbol (ipairs symbols)]
(let [item {:text symbol}]
(: (replsession.session) :submit (.. ",doc " symbol) #(when $1.vals (set item.info (. $1.vals 1))))
item)))
(fn autocomplete-symbol [callback ?starting-text]
(fn fixup-result [text item] (callback (or (and item item.text) text)))
(core.command_view:enter "Symbol" {:submit fixup-result :suggest autocomplete-results})
(print "start-text" ?starting-text)
(when ?starting-text
(core.command_view:set_text ?starting-text)
(core.command_view:update_suggestions)))
(command.add :core.docview {
"fennel:eval" #(submit (selected-form))
"fennel:go-to-definition-under-cursor" #(go-to-definition (selected-symbol))
"fennel:go-to-definition" #(autocomplete-symbol #(go-to-definition $1) (selected-symbol))
"fennel:autocomplete" #(autocomplete-symbol #(replace-selected-symbol $1) (selected-symbol))
})
(keymap.add {
:return "repl:submit"
"alt+e" "fennel:eval"
"alt+d" "fennel:go-to-definition-under-cursor"
"ctrl+space" "fennel:autocomplete"
})
{: inline-eval : symbol-pattern}