Compare commits
6 Commits
2ceb5ad757
...
4b78434ea4
Author | SHA1 | Date | |
---|---|---|---|
4b78434ea4 | |||
fe25203bad | |||
3a577b71d8 | |||
bf8fa80dac | |||
d62b9dea3e | |||
d962dd7c41 |
39
command.fnl
39
command.fnl
@ -47,14 +47,16 @@
|
|||||||
#$1.buffer.name]
|
#$1.buffer.name]
|
||||||
[:url
|
[:url
|
||||||
(fn [term]
|
(fn [term]
|
||||||
(if (> (# term) 2)
|
(let [from-history
|
||||||
(icollect [v (_G.history:find-distinct term)]
|
(if (> (# term) 2)
|
||||||
(let [label (.. v.url " " (or v.title ""))]
|
(icollect [v (_G.history:find-distinct term)]
|
||||||
(completion { :text v.url
|
(let [label (.. v.url " " (or v.title ""))]
|
||||||
:widget (Gtk.Button { : label })
|
(completion { :text v.url
|
||||||
:value v.url
|
:widget (Gtk.Button { : label })
|
||||||
})))
|
:value v.url
|
||||||
[]))
|
})))
|
||||||
|
[])]
|
||||||
|
(lume.unique (lume.concat from-history [(completion {:text term})]))))
|
||||||
#($1.buffer:location)]
|
#($1.buffer:location)]
|
||||||
]
|
]
|
||||||
(fn [{:url url :buffer buffer}]
|
(fn [{:url url :buffer buffer}]
|
||||||
@ -67,6 +69,7 @@
|
|||||||
#$1.buffer.name]]
|
#$1.buffer.name]]
|
||||||
(fn [{: buffer}] (buffer:back)))
|
(fn [{: buffer}] (buffer:back)))
|
||||||
|
|
||||||
|
|
||||||
(fn find-command [name]
|
(fn find-command [name]
|
||||||
(. commands name))
|
(. commands name))
|
||||||
|
|
||||||
@ -168,8 +171,8 @@
|
|||||||
|
|
||||||
{:command nil}
|
{:command nil}
|
||||||
(set-completions
|
(set-completions
|
||||||
(collect [k _ (pairs commands)]
|
(icollect [k _ (pairs commands)]
|
||||||
(if (= (k:find str 1 true) 1) (values k k)))))))
|
(if (= (k:find str 1 true) 1) (completion { :text k})))))))
|
||||||
|
|
||||||
(fn activate [{: state : entry : prompt &as self}]
|
(fn activate [{: state : entry : prompt &as self}]
|
||||||
(tset state :active true)
|
(tset state :active true)
|
||||||
@ -205,12 +208,8 @@
|
|||||||
(fn new-commander [frame]
|
(fn new-commander [frame]
|
||||||
(let [entry (Gtk.Entry {:sensitive false })
|
(let [entry (Gtk.Entry {:sensitive false })
|
||||||
prompt (Gtk.Label { :label ""})
|
prompt (Gtk.Label { :label ""})
|
||||||
box (Gtk.Box {
|
box (Gtk.Box { :orientation Gtk.Orientation.VERTICAL })
|
||||||
:orientation Gtk.Orientation.VERTICAL
|
hbox (Gtk.Box { :orientation Gtk.Orientation.HORIZONTAL })
|
||||||
})
|
|
||||||
hbox (Gtk.Box {
|
|
||||||
:orientation Gtk.Orientation.HORIZONTAL
|
|
||||||
})
|
|
||||||
completions (Gtk.FlowBox)
|
completions (Gtk.FlowBox)
|
||||||
self {
|
self {
|
||||||
:state default-state
|
:state default-state
|
||||||
@ -230,13 +229,9 @@
|
|||||||
(hbox:pack_start entry true true 5)
|
(hbox:pack_start entry true true 5)
|
||||||
(box:pack_start hbox true false 0)
|
(box:pack_start hbox true false 0)
|
||||||
(box:pack_start completions true true 0)
|
(box:pack_start completions true true 0)
|
||||||
(tset entry :on_changed
|
(tset entry :on_changed #(self:on-input $1.text))
|
||||||
(fn [event]
|
|
||||||
(self:on-input event.text)))
|
|
||||||
(tset entry :on_activate
|
(tset entry :on_activate
|
||||||
(fn [event]
|
#(update-widget-state self (self:on-input-finished $1.text)))
|
||||||
(let [result (self:on-input-finished event.text)]
|
|
||||||
(update-widget-state self result))))
|
|
||||||
self))
|
self))
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
(local Frame (require :frame))
|
(local Frame (require :frame))
|
||||||
(local Buffer (require :buffer))
|
(local Buffer (require :buffer))
|
||||||
|
|
||||||
|
(local search (require :search))
|
||||||
|
|
||||||
;;; when we decide how to do an init file/rc file, this will go in it
|
;;; when we decide how to do an init file/rc file, this will go in it
|
||||||
|
|
||||||
(local my-keymap {
|
(local my-keymap {
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
(s:nrows)))
|
(s:nrows)))
|
||||||
|
|
||||||
(fn find-distinct [self term]
|
(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")]
|
(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)))
|
(assert (= 0 (s:bind_values term)))
|
||||||
(s:nrows)))
|
(s:nrows)))
|
||||||
|
41
musing.md
41
musing.md
@ -40,29 +40,10 @@ a consideration we haven't touched on yet: in emacs, not all buffers
|
|||||||
are files - e.g. the buffer list, or the process list, or the magit
|
are files - e.g. the buffer list, or the process list, or the magit
|
||||||
status buffer - there is a well-used affordance for elisp to put
|
status buffer - there is a well-used affordance for elisp to put
|
||||||
semi-persistent interactable content onscreen - do we need such a
|
semi-persistent interactable content onscreen - do we need such a
|
||||||
thing here or is it ok to say "just call gtk" to command authors
|
thing here or is it ok to say "just call gtk" to command authors?
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
when input widget is active for a parameter, show the completions
|
|
||||||
flowbox
|
|
||||||
|
|
||||||
while typing, use the typed input to get a completions list. each
|
|
||||||
completion is an acceptable value: convert to a gtk widget by calling
|
|
||||||
(to-label value) and add to flowbox.
|
|
||||||
|
|
||||||
|
|
||||||
if the value is a table
|
|
||||||
if :to-label key present, use it as-is
|
|
||||||
else Gtk.Label { :label value.value }
|
|
||||||
else (assume it's a string)
|
|
||||||
Gtk.Label { :label value }
|
|
||||||
|
|
||||||
on RET, check there is a completion value whose stringification
|
|
||||||
matches the input string. Hide the flowbox
|
|
||||||
|
|
||||||
to activate a rendered completion, the callback needs to perform the
|
|
||||||
same action as RET would on the chosen value
|
|
||||||
|
|
||||||
is there a role for TAB?
|
is there a role for TAB?
|
||||||
|
|
||||||
@ -81,26 +62,22 @@ focus from entry to step through the completions then RET activates
|
|||||||
* [done] visit-location url defaults to current
|
* [done] visit-location url defaults to current
|
||||||
* [done] ESC to cancel interactive command
|
* [done] ESC to cancel interactive command
|
||||||
* [done] C-g to cancel key sequence
|
* [done] C-g to cancel key sequence
|
||||||
|
* [done] display unbound key error
|
||||||
|
* [done] back binding
|
||||||
|
* [done] save url history, use it in completions
|
||||||
|
* [done] autocomplete command name
|
||||||
|
|
||||||
* custom rendering for completions (e.g. buffer thumbnails)
|
* custom rendering for completions (e.g. buffer thumbnails)
|
||||||
* less ugly default completions rendering
|
* less ugly default completions rendering
|
||||||
* buffer name is often going to be useless. find buffers by url/title
|
* buffer name is often going to be useless. find buffers by url/title
|
||||||
still need some 1:1 mapping between the buffer object and
|
still need some 1:1 mapping between the buffer object and
|
||||||
a text-representable form of same
|
a text-representable form of same
|
||||||
* click in commander widget activates visit-location
|
* bind event to echo-area click, ideally dependent on what's being shown
|
||||||
|
in there
|
||||||
* in general, can we bind commands to widget events?
|
* in general, can we bind commands to widget events?
|
||||||
* display unbound key error
|
|
||||||
* autocomplete command name
|
|
||||||
* command to create new buffer
|
* command to create new buffer
|
||||||
* keyboard navigation of completions
|
* keyboard navigation of completions
|
||||||
|
|
||||||
|
* suppress "Return is undefined" message after a command executes
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
I think we're misusing the commander to show url and error messages
|
|
||||||
and key prompts. It's OK to have that part of the screen be multipurpose
|
|
||||||
but philosophically those things are not related to the command system.
|
|
||||||
|
|
||||||
- hide commander when inactive and replace it with echo area
|
|
||||||
- move it to bottom?
|
|
||||||
|
|
||||||
commander can't hide itself, it needs to ask its parent to hide it
|
|
||||||
|
52
search.fnl
Normal file
52
search.fnl
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
(local { : Gtk } (require :lgi))
|
||||||
|
(local { : view } (require :fennel))
|
||||||
|
(local lume (require :lume))
|
||||||
|
|
||||||
|
(local {: define-command : completion } (require :command))
|
||||||
|
(local Buffer (require :buffer))
|
||||||
|
|
||||||
|
(fn url-escape [s]
|
||||||
|
(string.gsub s
|
||||||
|
"([^A-Za-z0-9_])"
|
||||||
|
#(string.format "%%%02x" (string.byte $1))))
|
||||||
|
|
||||||
|
(local searchers
|
||||||
|
{:ddg
|
||||||
|
{:name "Duck Duck Go"
|
||||||
|
:function (fn [term]
|
||||||
|
(.. "https://duckduckgo.com/?q=" (url-escape term)))
|
||||||
|
}
|
||||||
|
:google
|
||||||
|
{:name "Google"
|
||||||
|
:function (fn [term]
|
||||||
|
(.. "https://www.google.com/search?q=" (url-escape term)))
|
||||||
|
}
|
||||||
|
:luai
|
||||||
|
{:name "Lua interactive reference manual"
|
||||||
|
:function (fn [term]
|
||||||
|
(.. "https://pgl.yoyo.org/luai/i/" (url-escape term)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
(fn completions [term]
|
||||||
|
(icollect [keyword {: name : function} (pairs searchers)]
|
||||||
|
(if (string.match keyword term)
|
||||||
|
(completion {
|
||||||
|
:text keyword
|
||||||
|
:value keyword
|
||||||
|
:widget (Gtk.Button { :label name })
|
||||||
|
}))))
|
||||||
|
|
||||||
|
|
||||||
|
(define-command
|
||||||
|
"search"
|
||||||
|
[[:term
|
||||||
|
#[(completion {:text $1})]
|
||||||
|
#""]
|
||||||
|
[:buffer
|
||||||
|
#(lume.map (Buffer.match $1) #(completion { :text $1.name :value $1 }))
|
||||||
|
#$1.buffer.name]
|
||||||
|
[:engine completions #:ddg]]
|
||||||
|
(fn [{: term : engine : buffer}]
|
||||||
|
(buffer:visit ((. (. searchers engine) :function) term))))
|
8
test/buffer.fnl
Normal file
8
test/buffer.fnl
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
(local Buffer (require :buffer))
|
||||||
|
|
||||||
|
(let [_ (Buffer.new "first")
|
||||||
|
_ (Buffer.new "second")
|
||||||
|
_ (Buffer.new "third")
|
||||||
|
_ (Buffer.new "through")
|
||||||
|
_ (Buffer.new "throughput")]
|
||||||
|
(assert (= (# (Buffer.match "")) 5)))
|
Loading…
Reference in New Issue
Block a user