Skip to content

Commit

Permalink
feat: option to exit automatically after timeout
Browse files Browse the repository at this point in the history
The feature is available for f/t motions, and for s/x after auto-jump to
first match or cold-repeat.

API change: new `opts` field `exit_after_idle_msecs`.

Closes #64
  • Loading branch information
ggandor committed Nov 5, 2021
1 parent b7fe66e commit be9e1b4
Show file tree
Hide file tree
Showing 4 changed files with 653 additions and 630 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ are fine with the defaults.)
require'lightspeed'.setup {
jump_to_first_match = true,
jump_on_partial_input_safety_timeout = 400,
exit_after_idle_msecs = { labeled = 1500, unlabeled = 1000 },
highlight_unique_chars = true,
grey_out_search_area = true,
match_only_the_start_of_same_char_seqs = true,
Expand All @@ -314,14 +315,14 @@ require'lightspeed'.setup {
}
```

For a detailed description of the available options, see the docs: `:h
lightspeed-config`.

You can also set options individually from the command line:
```Lua
lua require'lightspeed'.opts.jump_to_first_match = false
```

For a detailed description of the available options, see the docs: `:h
lightspeed-config`.

### Keymaps

Lightspeed aims to be part of an "extended native" layer, similar to such
Expand Down
10 changes: 8 additions & 2 deletions doc/lightspeed.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*lightspeed.txt* For Neovim version 0.5 Last change: 2021 November 01
*lightspeed.txt* For Neovim version 0.5 Last change: 2021 November 05

.-.. .. --. .... - ... .--. . . -..
__ _ __ __ __
Expand Down Expand Up @@ -152,7 +152,13 @@ Available options~

Timeout value, in milliseconds, until the follow-up character is
"swallowed", when jumping to a unique character right after the first
input (see |lightspeed-jump-on-partial-input|).
input of s/x (see |lightspeed-jump-on-partial-input|).

`exit_after_idle_msecs = { labeled = 1500, unlabeled = 1000 }`

Timeout value, in milliseconds, after which the plugin should exit
unconditionally. (`unlabeled` refers to f/t-mode, and "cold-repeating" s/x
searches.) The feature can be disabled by setting the given value to `nil`.

`highlight_unique_chars = true`

Expand Down
48 changes: 27 additions & 21 deletions fnl/lightspeed.fnl
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,6 @@
(fn same-pos? [[l1 c1] [l2 c2]] (and (= l1 l2) (= c1 c2)))


(fn getchar-as-str []
(local (ok? ch) (pcall vim.fn.getchar)) ; handling <C-c>
(values ok? (if (= (type ch) :number) (vim.fn.nr2char ch) ch)))


(fn char-at-pos [[line byte-col] {: char-offset}] ; expects (1,1)-indexed input
"Get character at the given position in a multibyte-aware manner.
An optional offset argument can be given to get the nth-next screen
Expand Down Expand Up @@ -128,6 +123,8 @@ character instead."

(var opts {:jump_to_first_match true
:jump_on_partial_input_safety_timeout 400
:exit_after_idle_msecs {:labeled 1500
:unlabeled 1000}
:highlight_unique_chars true
:grey_out_search_area true
:match_only_the_start_of_same_char_seqs true
Expand Down Expand Up @@ -508,11 +505,16 @@ interrupted change-operation."
res#))


(fn get-input []
(let [(ok? res) (getchar-as-str)]
; <esc> should cleanly exit anytime.
(when (and ok? (not= res (replace-keycodes "<esc>")))
res)))
(fn get-input [?timeout]
(let [esc-keycode 27
(ok? ch) (if ?timeout
(when (vim.fn.wait ?timeout
#(not= (vim.fn.getchar 1) 0)
100)
(values true (vim.fn.getchar 0)))
(pcall vim.fn.getchar))] ; pcall for handling <C-c>
(when (and ok? (not= ch esc-keycode)) ; <esc> should cleanly exit anytime
(if (= (type ch) :number) (vim.fn.nr2char ch) ch))))


; repeat.vim support
Expand Down Expand Up @@ -659,7 +661,8 @@ interrupted change-operation."
(do
(highlight-cursor)
(vim.cmd :redraw)
(match (or (with-highlight-cleanup (get-input))
(match (or (with-highlight-cleanup
(get-input opts.exit_after_idle_msecs.unlabeled))
(exit (reset-instant-state)))
in2
(let [mode (if (= (vim.fn.mode) :n) :n :x) ; vim-cutlass compat (#28)
Expand Down Expand Up @@ -920,12 +923,10 @@ sub-table containing label-target k-v pairs for these targets."


(fn ignore-char-until-timeout [char-to-ignore]
(let [start (os.clock)
timeout-secs (/ opts.jump_on_partial_input_safety_timeout 1000)
(ok? input) (getchar-as-str)]
(when-not (and (= input char-to-ignore)
(< (os.clock) (+ start timeout-secs)))
(when ok? (vim.fn.feedkeys input :i)))))
(match (get-input opts.jump_on_partial_input_safety_timeout)
input (when (not= input char-to-ignore)
(vim.fn.feedkeys input :i))))


; //> Helpers

Expand Down Expand Up @@ -1108,15 +1109,20 @@ sub-table containing label-target k-v pairs for these targets."
(with-highlight-chores
(each [_ {:pos [line col]} (ipairs target-list)]
(hl:add-hl hl.group.one-char-match (dec line) (dec col) (inc col))))
(vim.fn.feedkeys (or (with-highlight-cleanup (get-input)) "") :i)))
(-> (or (with-highlight-cleanup
(get-input opts.exit_after_idle_msecs.unlabeled))
"")
(vim.fn.feedkeys :i))))

(fn select-match-group [target-list]
(let [num-of-groups (ceil (/ (length target-list) (length labels)))
max-offset (dec num-of-groups)]
((fn recur [group-offset]
((fn recur [group-offset initial-invoc?]
(set-beacons target-list {:repeat? enter-repeat?})
(with-highlight-chores (light-up-beacons target-list))
(match (with-highlight-cleanup (get-input))
(match (with-highlight-cleanup
(get-input (when initial-invoc?
opts.exit_after_idle_msecs.labeled)))
input
(if (one-of? input cycle-fwd-key cycle-bwd-key)
(let [group-offset* (-> group-offset
Expand All @@ -1127,7 +1133,7 @@ sub-table containing label-target k-v pairs for these targets."
:group-offset group-offset*})
(recur group-offset*))
[input group-offset])))
0)))
0 true)))

; //> Helpers

Expand Down
Loading

0 comments on commit be9e1b4

Please sign in to comment.