revisit completer/completion api

A completion is now a table with attributes :text, :widget, :value
A completer returns an array of completions

This means we can now render URL completions with the page title
as well as the URL
main
Daniel Barlow 2023-01-15 13:04:35 +00:00
parent 4d3a2bf237
commit 34fb1b2ff4
4 changed files with 51 additions and 16 deletions

View File

@ -44,9 +44,9 @@
:find (fn [term] (. buffers term)) :find (fn [term] (. buffers term))
;; will rename this to "find" once we've got rid of the ;; will rename this to "find" once we've got rid of the
;; only remaining call to the existing Buffer.find ;; only remaining call to the existing Buffer.find
:match (fn [s] (collect [name buffer (pairs buffers)] :match (fn [s] (icollect [name buffer (pairs buffers)]
(if (string.find name s) (if (string.find name s)
(values name buffer)))) (values buffer))))
:next (fn [buffer] :next (fn [buffer]
(let [n (or (next buffers buffer.name) (next buffers))] (let [n (or (next buffers buffer.name) (next buffers))]
(. buffers n))) (. buffers n)))

View File

@ -17,15 +17,24 @@
: params}] : params}]
(tset commands name v))) (tset commands name v)))
(fn completion [{: widget : text : value }]
(let [value (or value (assert text "must have text"))]
{
:widget (or widget (Gtk.Button { :label text }))
: text
: value
}))
(define-command (define-command
"quit-browser" "quit-browser"
[] []
#(Gtk.main_quit)) #(Gtk.main_quit))
(define-command (define-command
"switch-to-buffer" "switch-to-buffer"
[[:buffer [[:buffer
Buffer.match #(lume.map (Buffer.match $1) #(completion { :text $1.name :value $1 }))
#(. (Buffer.next $1.buffer) :name)] #(. (Buffer.next $1.buffer) :name)]
] ]
(fn [{:frame frame :buffer buffer}] (fn [{:frame frame :buffer buffer}]
@ -34,10 +43,18 @@
(define-command (define-command
"visit-location" "visit-location"
[[:buffer [[:buffer
Buffer.match #(lume.map (Buffer.match $1) #(completion { :text $1.name :value $1 }))
#$1.buffer.name] #$1.buffer.name]
[:url [:url
(fn [term] (collect [v (_G.history:find term)] (values v.url v.url))) (fn [term]
(if (> (# term) 2)
(icollect [v (_G.history:find-distinct term)]
(let [label (.. v.url " " (or v.title ""))]
(completion { :text v.url
:widget (Gtk.Button { : label })
:value v.url
})))
[]))
#($1.buffer:location)] #($1.buffer:location)]
] ]
(fn [{:url url :buffer buffer}] (fn [{:url url :buffer buffer}]
@ -45,7 +62,9 @@
(define-command (define-command
"back" "back"
[[:buffer Buffer.match #$1.buffer.name]] [[:buffer
#(lume.map (Buffer.match $1) #(completion { :text $1.name :value $1 }))
#$1.buffer.name]]
(fn [{: buffer}] (buffer:back))) (fn [{: buffer}] (buffer:back)))
(fn find-command [name] (fn find-command [name]
@ -96,8 +115,9 @@
{:command c :this-param k :collected-params p} {:command c :this-param k :collected-params p}
(let [{ : completer} (. c.params k) (let [{ : completer} (. c.params k)
vals (completer input-string) vals (completer input-string)
value (. vals input-string)] chosen (lume.match vals #(= $1.text input-string))]
(tset p k value) (assert chosen (view { : vals : input-string }))
(tset p k chosen.value)
(state-for-next-param c p)) (state-for-next-param c p))
{:command c :this-param nil :collected-params p} {:command c :this-param nil :collected-params p}
@ -133,13 +153,13 @@
set-completions set-completions
(fn [completions] (fn [completions]
(parent:foreach #(parent:remove $1)) (parent:foreach #(parent:remove $1))
(each [text _w (pairs completions)] (each [_ c (pairs completions)]
(parent:add (parent:add
(Gtk.Button { (doto c.widget
:label text (tset :on_clicked
:on_clicked #(update-widget-state
#(update-widget-state self (self:on-input-finished text)) self
}))) (self:on-input-finished c.text))))))
(parent:show_all))] (parent:show_all))]
(match self.state (match self.state
{:command c :this-param param-name} {:command c :this-param param-name}
@ -223,4 +243,5 @@
{ {
:commander new-commander :commander new-commander
: define-command : define-command
: completion
} }

View File

@ -41,6 +41,12 @@
(assert (= 0 (s:bind_values term))) (assert (= 0 (s:bind_values term)))
(s:nrows))) (s:nrows)))
(fn find-distinct [self term]
(print :self self :term term)
(let [s (self.db:prepare "select distinct v.url,pt.title from visits v left join page_titles pt on v.url = pt.url where instr(v.url, ?) >0")]
(assert (= 0 (s:bind_values term)))
(s:nrows)))
(fn open [pathname] (fn open [pathname]
(let [db (if pathname (sqlite.open pathname) (sqlite.open_memory))] (let [db (if pathname (sqlite.open pathname) (sqlite.open_memory))]
(migrate-all db) (migrate-all db)
@ -49,6 +55,7 @@
: visit : visit
: title : title
: find : find
: find-distinct
})) }))
{ {

View File

@ -5,6 +5,13 @@
(var happened false) (var happened false)
(fn before [] (set happened false)) (fn before [] (set happened false))
(assert
(match (Command.completion { :text "foo" })
(where { : widget : text : value }
(= text "foo")
(= value "foo"))
true))
(Command.define-command (Command.define-command
"no-args-command" "no-args-command"
[] []
@ -12,8 +19,8 @@
(Command.define-command (Command.define-command
"multiply" "multiply"
[[:a #{$1 $1} #"3"] [[:a #[(Command.completion {:text $1})] #"3"]
[:b #{$1 $1} #"2"]] [:b #[(Command.completion {:text $1})] #"2"]]
(fn [{: a : b }] (set happened (* (tonumber a) (tonumber b))))) (fn [{: a : b }] (set happened (* (tonumber a) (tonumber b)))))
(before) (before)