Refactor selection expansion, implement autocomplete

This commit is contained in:
Jeremy Penner 2022-04-10 15:31:34 -04:00
parent 1673c7322e
commit 9f2da61b88
2 changed files with 49 additions and 26 deletions

View file

@ -1,38 +1,56 @@
(local util (require :lib.util)) (local util (require :lib.util))
(local lume (require :lib.lume))
(local core (require :core)) (local core (require :core))
(local command (require :core.command)) (local command (require :core.command))
(local keymap (require :core.keymap)) (local keymap (require :core.keymap))
(local common (require :core.common)) (local common (require :core.common))
(fn selected-form [] (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 (let [ldoc core.active_view.doc
(aline acol bline bcol) (ldoc:get_selection)] (aline acol bline bcol) (ldoc:get_selection)]
(if (and (= aline bline) (= acol bcol)) {: ldoc : aline : acol : bline : bcol
(ldoc:get_text aline 1 aline math.huge) :place? (fn [self] (and (= self.aline self.bline) (= self.acol self.bcol)))
(ldoc:get_text aline acol bline 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] (fn find-closest [s pattern i-target]
(var (start end) nil) (var (start end) nil)
(set (start end) (s:find pattern)) (set (start end) (s:find pattern))
(while (and start (< end (- i-target 1))) (while (and start (< end (- i-target 1)))
(set (start end) (s:find pattern (+ end 1)))) (set (start end) (s:find pattern (+ end 1))))
(if (and start (<= start i-target)) (values start end) (if (and start (<= start i-target)) (values start (+ end 1))
(values 1 0))) (values i-target i-target)))
(local symbol-pattern "[a-zA-Z%!%@%#%$%%%^%&%*%<%>%?%/%~%-%_%=%+][a-zA-Z%!%@%#%$%%%^%&%*%<%>%?%/%~%-%_%=%+0-9%.%:]*") (local symbol-pattern "[a-zA-Z%!%@%#%$%%%^%&%*%<%>%?%/%~%-%_%=%+][a-zA-Z%!%@%#%$%%%^%&%*%<%>%?%/%~%-%_%=%+0-9%.%:]*")
(fn selected-symbol [] (fn place-to-symbol [selection]
(let [ldoc core.active_view.doc (let [selection (lume.clone selection)]
(aline acol bline bcol) (ldoc:get_selection)] (when (selection:place?)
(if (and (= aline bline) (= acol bcol)) (let [line (: (place-to-line selection) :get-text)]
(let [line (ldoc:get_text aline 1 aline math.huge) (set (selection.acol selection.bcol) (find-closest line symbol-pattern selection.acol))))
(start end) (find-closest line symbol-pattern acol)] selection))
(ldoc:get_text aline start aline (+ end 1)))
(ldoc:get_text aline acol bline bcol))))
(fn inline-eval [eval] (fn selected-symbol [] (: (place-to-symbol (get-selection)) :get-text))
(let [ldoc core.active_view.doc
(aline acol bline bcol) (ldoc:get_selection)] (fn inline-eval [eval] (: (to-place (get-selection)) :replace-text (eval (selected-form))))
(ldoc:insert bline bcol (eval (selected-form)))))
(require :editor.editmode) (require :editor.editmode)
@ -60,30 +78,35 @@
(ldoc:set_selection line 1 line 1) (ldoc:set_selection line 1 line 1)
true)))) true))))
(core.log (.. "Unable to find symbol " symbol)))) (core.log (.. "Unable to find symbol " symbol))))
(: (replsession.session) :submit (.. ",find " symbol) jump-to-find-result)) (: (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] (fn autocomplete-results [text]
(var result []) (var result [])
(: (replsession.session) :submit (.. ",complete " text) #(set result (or $1.vals []))) (: (replsession.session) :submit (.. ",complete " text) #(set result (or $1.vals [])) true)
result) result)
(fn autocomplete-symbol [callback ?starting-text] (fn autocomplete-symbol [callback ?starting-text]
(fn fixup-result [text] (fn fixup-result [text item] (callback (or (and item item.text) text)))
(let [[completed-result] (autocomplete-results text)]
(callback (or completed-result text))))
(core.command_view:enter "Symbol" fixup-result autocomplete-results) (core.command_view:enter "Symbol" fixup-result autocomplete-results)
(when ?starting-text (core.command_view:set_text ?starting-text))) (print "start-text" ?starting-text)
(when ?starting-text
(core.command_view:set_text ?starting-text)
(core.command_view:update_suggestions)))
(command.add :core.docview { (command.add :core.docview {
"fennel:eval" #(submit nil (selected-form)) "fennel:eval" #(submit nil (selected-form))
"fennel:go-to-definition-under-cursor" #(go-to-definition (selected-symbol)) "fennel:go-to-definition-under-cursor" #(go-to-definition (selected-symbol))
"fennel:go-to-definition" #(autocomplete-symbol #(go-to-definition $1) (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 { (keymap.add {
:return "repl:submit" :return "repl:submit"
"alt+e" "fennel:eval" "alt+e" "fennel:eval"
"alt+d" "fennel:go-to-definition-under-cursor" "alt+d" "fennel:go-to-definition-under-cursor"
"ctrl+space" "fennel:autocomplete"
}) })
{: inline-eval : symbol-pattern} {: inline-eval : symbol-pattern}

View file

@ -21,11 +21,11 @@
(fn replsession.new-session [] (replsession.restart-session {:submit replsession.submit})) (fn replsession.new-session [] (replsession.restart-session {:submit replsession.submit}))
(fn replsession.submit [session chunk callback] (fn replsession.submit [session chunk callback ?suppress-crash]
(assert (= session.callback nil)) (assert (= session.callback nil))
(set session.callback callback) (set session.callback callback)
(match (pcall coroutine.resume session.coro (.. chunk "\n")) (match (pcall coroutine.resume session.coro (.. chunk "\n"))
(false err) (do (core.log (.. "REPL crashed: " err)) (false err) (do (when (not ?suppress-crash) (core.log (.. "REPL crashed: " err)))
(replsession.restart-session session))) (replsession.restart-session session)))
(assert (= session.callback callback)) (assert (= session.callback callback))
(set session.callback nil)) (set session.callback nil))