-
Notifications
You must be signed in to change notification settings - Fork 180
/
mini-pick.txt
1446 lines (1117 loc) · 55.8 KB
/
mini-pick.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
*mini.pick* Pick anything
*MiniPick*
MIT License Copyright (c) 2023 Evgeni Chasnovski
==============================================================================
Features:
- Single window general purpose interface for picking element from any array.
- On demand toggleable preview and info views.
- Interactive query matching (filter+sort) with fast non-blocking default
which does fuzzy matching and allows other modes (|MiniPick.default_match()|).
- Built-in pickers (see |MiniPick.builtin|):
- Files.
- Pattern match (for fixed pattern and with live feedback).
- Buffers.
- Help tags.
- CLI output.
- Resume latest picker.
- |:Pick| command to work with extensible |MiniPick.registry|.
- |vim.ui.select()| wrapper (see |MiniPick.ui_select()|).
- Rich and customizable built-in |MiniPick-actions| when picker is active:
- Manually change currently focused item.
- Scroll vertically and horizontally.
- Toggle preview or info view.
- Mark/unmark items to choose later.
- Refine current matches (make them part of a new picker).
- And many more.
- Minimal yet flexible |MiniPick-source| specification with:
- Items (array, callable, or manually set later).
- Source name.
- Working directory.
- Matching algorithm.
- Way matches are shown in main window.
- Item preview.
- "On choice" action for current and marked items.
- Custom actions/keys can be configured globally, per buffer, or per picker.
- Out of the box support for 'ignorecase' and 'smartcase'.
- Match caching to increase responsiveness on repeated prompts.
Notes:
- Works on all supported versions but using Neovim>=0.9 is recommended.
Neovim>=0.10 will give more visual feedback in floating window footer.
- For more pickers see |MiniExtra.pickers|.
Sources with more details:
- |MiniPick-overview|
- |MiniPick-source|
- |MiniPick-actions|
- |MiniPick-examples|
- |MiniPick.builtin|
# Dependencies ~
Suggested dependencies (provide extra functionality, will work without them):
- Enabled |MiniIcons| module for icons near the items representing actual paths.
Falls back to 'nvim-tree/nvim-web-devicons' plugin or no icons will be used.
*MiniPick-cli-tools*
- CLI tool(s) to power |MiniPick.builtin.files()|, |MiniPick.builtin.grep()|, and
|MiniPick.builtin.grep_live()| built-in pickers:
- `rg` (github.com/BurntSushi/ripgrep; enough for all three; recommended).
- `fd` (github.com/sharkdp/fd; for `files` only).
- `git` (github.com/git/git; enough for all three).
Note: CLI tools are called only with basic arguments needed to get items.
To customize the output, use their respective configuration approaches.
Here are some examples of where to start:
- github.com/BurntSushi/ripgrep/blob/master/GUIDE.md#configuration-file
- github.com/sharkdp/fd#excluding-specific-files-or-directories
- git-scm.com/docs/gitignore
# Setup ~
This module needs a setup with `require('mini.pick').setup({})` (replace
`{}` with your `config` table). It will create global Lua table `MiniPick`
which you can use for scripting or manually (with `:lua MiniPick.*`).
See |MiniPick.config| for available config settings.
You can override runtime config settings locally to buffer inside
`vim.b.minipick_config` which should have same structure as `MiniPick.config`.
See |mini.nvim-buffer-local-config| for more details.
# Comparisons ~
- 'nvim-telescope/telescope.nvim':
- The main inspiration for this module, so there is significant overlap.
- Has three (or two) window UI (prompt, matches, preview), while this
module combines everything in one window. It allows more straightforward
customization for unusual scenarios.
- Default match algorithm is somewhat slow, while this module should
match relatively lag-free for at least 100K+ items.
- Has many built-in pickers, while this module has handful at its core
relying on other 'mini.nvim' modules to provide more (see |MiniExtra|).
- 'ibhagwan/fzf-lua':
- Mostly same comparison as with 'nvim-telescope/telescope.nvim'.
- Requires 'junegunn/fzf' installed to power fuzzy matching, while this
module provides built-in Lua matching.
# Highlight groups ~
* `MiniPickBorder` - window border.
* `MiniPickBorderBusy` - window border while picker is busy processing.
* `MiniPickBorderText` - non-prompt on border.
* `MiniPickCursor` - cursor during active picker (hidden by default).
* `MiniPickIconDirectory` - default icon for directory.
* `MiniPickIconFile` - default icon for file.
* `MiniPickHeader` - headers in info buffer and previews.
* `MiniPickMatchCurrent` - current matched item.
* `MiniPickMatchMarked` - marked matched items.
* `MiniPickMatchRanges` - ranges matching query elements.
* `MiniPickNormal` - basic foreground/background highlighting.
* `MiniPickPreviewLine` - target line in preview.
* `MiniPickPreviewRegion` - target region in preview.
* `MiniPickPrompt` - prompt.
To change any highlight group, modify it directly with |:highlight|.
------------------------------------------------------------------------------
*MiniPick-events*
Events ~
To allow user customization and integration of external tools, certain |User|
autocommand events are triggered under common circumstances:
- `MiniPickStart` - just after picker has started.
- `MiniPickStop` - just before picker is stopped.
------------------------------------------------------------------------------
*MiniPick-overview*
# Overview ~
General idea is to take array of objects, display them with interactive
filter/sort/navigate/preview, and allow to choose one or more items.
## How to start a picker ~
- Use |MiniPick.start()| with `opts.source` defining |MiniPick-source|.
Example: `MiniPick.start({ source = { items = vim.fn.readdir('.') } })`
- Use any of |MiniPick.builtin| pickers directly.
Example: `MiniPick.builtin.files({ tool = 'git' })`
- Use |:Pick| command which uses customizable pickers from |MiniPick.registry|.
Example: `:Pick files tool='git'`
## User interface ~
UI consists from a single window capable of displaying three different views:
- "Main" - where current query matches are shown.
- "Preview" - preview of current item (toggle with `<Tab>`).
- "Info" - general info about picker and its state (toggle with `<S-Tab>`).
Current prompt is displayed (in Neovim>=0.9) at the top left of the window
border with vertical line indicating caret (current input position).
Bottom part of window border displays (in Neovim>=0.10) extra visual feedback:
- Left part is a picker name.
- Right part contains information in the format >
<current index in matches> | <match count> | <marked count> / <total count>
<
When picker is busy (like if there are no items yet set or matching is active)
window border changes color to be `MiniPickBorderBusy` after `config.delay.busy`
milliseconds of idle time.
## Life cycle ~
- Type characters to filter and sort matches. It uses |MiniPick.default_match()|
with `query` being an array of pressed characters.
Overview of how it matches:
- If query starts with `'`, the match is exact.
- If query starts with `^`, the match is exact at start.
- If query ends with `$`, the match is exact at end.
- If query starts with `*`, the match is forced to be fuzzy.
- Otherwise match is fuzzy.
- Sorting is done to first minimize match width and then match start.
Nothing more: no favoring certain places in string, etc.
- Type special keys to perform |MiniPick-actions|. Here are some basic ones:
- `<C-n>` / `<Down>` moves down; `<C-p>` / `<Up>` moves up.
- `<Left>` / `<Right>` moves prompt caret left / right.
- `<S-Tab>` toggles information window with all available mappings.
- `<Tab>` toggles preview.
- `<C-x>` / `<C-a>` toggles current / all item(s) as (un)marked.
- `<C-Space>` / `<M-Space>` makes all matches or marked items as new picker.
- `<CR>` / `<M-CR>` chooses current/marked item(s).
- `<Esc>` / `<C-c>` stops picker.
## Implementation details ~
- Any picker is non-blocking but waits to return the chosen item. Example:
`file = MiniPick.builtin.files()` allows other actions to be executed when
picker is shown while still assigning `file` with value of the chosen item.
------------------------------------------------------------------------------
*MiniPick-source*
Source is defined as a `source` field inside one of (in increasing priority):
- |MiniPick.config| - has global effect.
- |vim.b.minipick_config| - has buffer-local effect.
- `opts.source` in picker call - has effect for that particular call.
Example of source to choose from |arglist|: >lua
{ items = vim.fn.argv, name = 'Arglist' }
<
Note: this is mostly useful for writing pickers. Can safely skip if you
want to just use provided pickers.
*MiniPick-source.items*
# Items ~
`source.items` defines items to choose from. It should be one of the following:
- Array of objects which can have different types. Any type is allowed.
- `nil`. Picker waits for explicit |MiniPick.set_picker_items()| call.
- Callable returning any of the previous types. Will be called once on start.
*MiniPick-source.items-stritems*
Matching is done for items array based on the string representation of its
elements (here called "stritems"). For single item it is computed as follows:
- Callable is called once with output used in next steps.
- String item is used as is.
- String <text> field of table item is used (if present).
- Use output of |vim.inspect()|.
Example: >lua
items = { 'aaa.txt', { text = 'bbb' }, function() return 'ccc' end }
-- corresponding stritems are { 'aaa.txt', 'bbb', 'ccc' }
<
Default value is `nil`, assuming it always be supplied by the caller.
*MiniPick-source.items-common*
There are some recommendations for common item types in order for them to work
out of the box with |MiniPick.default_show()|, |MiniPick.default_preview()|,
|MiniPick.default_choose()|, |MiniPick.default_choose_marked()|:
- Path (file or directory). Use string or `path` field of a table. Path can
be either absolute, relative to the `source.cwd`, or have a general URI format
(only if supplied as table field).
Examples: `'aaa.txt'`, `{ path = 'aaa.txt' }`
- Buffer. Use buffer id as number, string, or `bufnr` / `buf_id` / `buf`
field of a table (any name is allowed).
Examples: `1`, `'1'`, `{ bufnr = 1 }`, `{ buf_id = 1 }`, `{ buf = 1 }`
- Line in file or buffer. Use table representation with `lnum` field with line
number (starting from 1) or string in "<path>\0<line>" format (`\0` is
an actual null character; don't escape the slash; may need to be `\000`).
Examples: >lua
{ path = 'aaa.txt', lnum = 2 }, 'aaa.txt\0002', { bufnr = 1, lnum = 3 }
<
- Position in file or buffer. Use table representation with `lnum` and `col`
fields with line and column numbers (starting from 1) or string in
"<path>\0<line>\0<col>" format (`\0` is an actual null character, don't
escape the slash; may need to be `\000`).
Examples: >lua
{ path = 'aaa.txt', lnum = 2, col = 3 }, 'aaa.txt\0' .. '2\0003',
{ bufnr = 1, lnum = 3, col = 4 }
<
- Region in file or buffer. Use table representation with `lnum`, `col`,
`end_lnum`, `end_col` fields for start and end line/column. All numbers
start from 1, end line is inclusive, end column is exclusive.
This naming is similar to |getqflist()| and |diagnostic-structure|.
Examples: >lua
{ path = 'aaa.txt', lnum = 2, col = 3, end_lnum = 4, end_col = 5 },
{ bufnr = 1, lnum = 3, col = 4, end_lnum = 5, end_col = 6 }
<
Note: all table items will benefit from having `text` field for better matching.
*MiniPick-source.name*
# Name ~
`source.name` defines the name of the picker to be used for visual feedback.
Default value is "<No name>".
*MiniPick-source.cwd*
# Current working directory ~
`source.cwd` is a string defining the current working directory in which
picker operates. It should point to a valid actually present directory path.
This is a part of source to allow persistent way to use relative paths,
i.e. not depend on current directory being constant after picker start.
It also makes the |MiniPick.builtin.resume()| picker more robust.
Default value is |current-directory|.
*MiniPick-source.match*
# Match ~
`source.match` is a callable defining how stritems
(see |MiniPick-source.items-stritems|) are matched (filtered and sorted) based
on the query.
It will be called with the following arguments:
- `stritems` - all available stritems for current picker.
- `inds` - array of `stritems` indexes usually pointing at current matches.
It does point to current matches in the case of interactively appending
character at the end of the query. It assumes that matches for such bigger
query is a subset of previous matches (implementation can ignore it).
This can be utilized to increase performance by checking fewer stritems.
- `query` - array of strings. Usually (like is common case of user interactively
typing query) each string represents one character. However, any strings are
allowed, as query can be set with |MiniPick.set_picker_query()|.
It should either return array of match indexes for stritems elements matching
the query (synchronous) or explicitly use |MiniPick.set_picker_match_inds()|
to set them (may be asynchronous).
Notes:
- The result can be any array of `stritems` indexes, i.e. not necessarily
a subset of input `inds`.
- Both `stritems` and `query` depend on values of 'ignorecase' and 'smartcase'.
If query shows "ignore case" properties (only 'ignorecase' is set or both
'ignorecase' / 'smartcase' are set and query has only lowercase characters),
then `stritems` and `query` will have only lowercase characters.
This allows automatic support for case insensitive matching while being
faster and having simpler match function implementation.
- Writing custom `source.match` usually means also changing |MiniPick-source.show|
because it is used to highlight stritems parts actually matching the query.
Example of simple "exact" `match()` preserving initial order: >lua
local match_exact = function(stritems, inds, query)
local prompt_pattern = vim.pesc(table.concat(query))
local f = function(i) return stritems[i]:find(prompt_pattern) ~= nil end
return vim.tbl_filter(f, inds)
end
-- For non-blocking version see `:h MiniPick.poke_is_picker_active()`
<
Default value is |MiniPick.default_match()|.
*MiniPick-source.show*
# Show ~
`source.show` is a callable defining how matched items are shown in the window.
It will be called with the following arguments:
- `buf_id` - identifier of the target buffer.
- `items_to_show` - array of actual items to be shown in `buf_id`. This is
a subset of currently matched items computed to fit in current window view.
- `query` - array of strings. Same as in `source.match`.
It should update buffer `buf_id` to visually represent `items_to_show`
__one item per line starting from line one__ (it shouldn't depend on
`options.content_from_bottom`). This also includes possible visualization
of which parts of stritem actually matched query.
Example (assuming string items; without highlighting): >lua
local show_prepend = function(buf_id, items_arr, query)
local lines = vim.tbl_map(function(x) return 'Item: ' .. x end, items_arr)
vim.api.nvim_buf_set_lines(buf_id, 0, -1, false, lines)
end
<
Default value is |MiniPick.default_show()|.
*MiniPick-source.preview*
# Preview ~
`source.preview` is a callable defining how item preview is done.
It will be called with the following arguments:
- `buf_id` - identifier of the target buffer. Note: for every separate instance
of item previewing new scratch buffer is be created.
- `item` - item to preview.
It should update buffer `buf_id` to visually represent `item`.
Example: >lua
local preview_inspect = function(buf_id, item)
local lines = vim.split(vim.inspect(item), '\n')
vim.api.nvim_buf_set_lines(buf_id, 0, -1, false, lines)
end
<
Default value is |MiniPick.default_preview()|.
*MiniPick-source.choose*
# Choose an item ~
`source.choose` is a callable defining what to do when an item is chosen.
It will be called with the following arguments:
- `item` - chosen item. Always non-`nil`.
It should perform any intended "choose" action for an item and return
a value indicating whether picker should continue (i.e. not stop):
`nil` and `false` will stop picker, other values will continue.
Notes:
- It is called when picker window is still current. Use `windows.target` value
from |MiniPick.get_picker_state()| output to do something with target window.
Example: >lua
local choose_file_continue = function(item)
if vim.fn.filereadable(item) == 0 then return end
vim.api.nvim_win_call(
MiniPick.get_picker_state().windows.main,
function() vim.cmd('edit ' .. item) end
)
return true
end
<
Default value is |MiniPick.default_choose()|.
*MiniPick-source.choose_marked*
# Choose marked items ~
`source.choose_marked` is a callable defining what to do when marked items
(see |MiniPick-actions-mark|) are chosen. Serves as a companion to
`source.choose` which can choose several items.
It will be called with the following arguments:
- `items_marked` - array of marked items. Can be empty.
It should perform any intended "choose" action for several items and return
a value indicating whether picker should continue (i.e. not stop):
`nil` and `false` will stop picker, other values will continue.
Notes:
- It is called when picker window is still current. Use `windows.target` value
from |MiniPick.get_picker_state()| output to do something with target window.
Example: >lua
local choose_marked_print = function(items) print(vim.inspect(items)) end
<
Default value is |MiniPick.default_choose_marked()|.
------------------------------------------------------------------------------
*MiniPick-actions*
When picker is active, `mappings` table defines a set of special keys which when
pressed will execute certain actions. Those can be of two types:
- Built-in: actions present in default `config.mappings`. Can be only overridden
with a different key.
- Custom: user defined actions. Should be a table with `char` and `func` fields.
# Built-in ~
*MiniPick-actions-caret*
## Caret ~
User can add character not only at query end, but more generally at caret.
- `mappings.caret_left` - move caret to left.
- `mappings.caret_right` - move caret to right.
*MiniPick-actions-choose*
## Choose ~
Choose is a fundamental action that actually implements the intent of
calling a picker, i.e. pick an item.
- `mappings.choose` - choose as is, i.e. apply `source.choose` for current item.
- `mappings.choose_in_split` - make horizontal split at target window, update
target window to the new split, and choose.
- `mappings.choose_in_tabpage` - same as `choose_in_split`, but create tabpage.
- `mappings.choose_in_vsplit` - same as `choose_in_split`, but split vertically.
- `mappings.choose_marked` - choose marked items as is, i.e.
apply `source.choose_marked` at current marked items.
*MiniPick-actions-delete*
## Delete ~
Delete actions are for deleting elements from query.
- `mappings.delete_char` - delete one character to the left.
- `mappings.delete_char_right` - delete one character to the right.
- `mappings.delete_left` - delete everything to the left (like |i_CTRL-U|).
- `mappings.delete_word` - delete word to the left (like |i_CTRL-W|).
*MiniPick-actions-mark*
## Mark ~
Marking is an action of adding certain items to a separate list which then can
be chosen with `mappings.choose_marked` (for example, sent to quickfix list).
This is a companion to a regular choosing which can pick only one item.
- `mappings.mark` - toggle marked/unmarked state of current item.
- `mappings.mark_all` - toggle marked/unmarked state (mark all if not all
marked; unmark all otherwise) of all currently matched items.
Notes:
- Marks persist across queries and matches. For example, user can make a query
with marking all matches several times and marked items from all queries
will be preserved.
*MiniPick-actions-move*
## Move ~
Move is a fundamental action of changing which item is current.
- `mappings.move_down` - change focus to the item below.
- `mappings.move_start` change focus to the first currently matched item
- `mappings.move_up` - change focus to the item above.
Notes:
- Up and down wrap around edges: `move_down` on last item moves to first,
`move_up` on first moves to last.
- Moving when preview or info view is shown updates the view with new item.
- These also work with non-overridable alternatives:
- `<Down>` moves down.
- `<Home>` moves to first matched.
- `<Up>` moves up.
*MiniPick-actions-paste*
## Paste ~
Paste is an action to paste content of |registers| at caret.
- `mappings.paste` - paste from register defined by the next key press.
Notes:
- Does not support expression register `=`.
*MiniPick-actions-refine*
## Refine ~
Refine is an action that primarily executes the following:
- Takes certain items and makes them be all items (in order they are present).
- Resets query.
- Updates `source.match` to be the one from config.
- `mappings.refine` - refine currently matched items.
- `mappings.refin_marked` - refine currently marked items.
This action is useful in at least two cases:
- Perform consecutive "narrowing" queries. Example: to get items that contain
both "hello" and "world" exact matches (in no particular order) with default
matching, type "'hello" (notice "'" at the start) followed by `<C-Space>` and
another "'world".
- Reset `match` to default. Particularly useful in |MiniPick.builtin.grep_live()|.
*MiniPick-actions-scroll*
## Scroll ~
Scroll is an action to either move current item focus further than to the
neighbor item or adjust window view to see more information.
- `mappings.scroll_down` - when matches are shown, go down by the amount of
visible matches. In preview and info view - scroll down as with |CTRL-F|.
- `mappings.scroll_left` - scroll left as with |zH|.
- `mappings.scroll_right` - scroll right as with |zL|.
- `mappings.scroll_up` - when matches are shown, go up by the amount of
visible matches. In preview and info view - scroll up as with |CTRL-B|.
*MiniPick-actions-stop*
## Stop ~
`mappings.stop` stops the picker. <C-c> also always stops the picker.
*MiniPick-actions-toggle*
## Toggle ~
Toggle action is a way to change view: show if target is not shown, reset to
main view otherwise.
- `mappings.toggle_info` - toggle info view.
- `mappings.toggle_preview` - toggle preview.
Note:
- Updating query in any way resets window view to show matches.
- Moving current item focus keeps preview or info view with updated item.
*MiniPick-actions-custom*
# Custom ~
Along with built-in actions, users can define custom actions. This can be
done by supplying custom elements to `mappings` table. The field defines action
name (used to infer an action description in info view). The value is a table
with the following fields:
- <char> `(string)` - single character acting as action trigger.
- <func> `(function)` - callable to be executed without arguments after
user presses <char>. Its return value is treated as "should stop picker
after execution", i.e. returning nothing, `nil`, or `false` continues
picker while everything else (prefer `true`) stops it.
Example of `execute` custom mapping: >lua
execute = {
char = '<C-e>',
func = function() vim.cmd(vim.fn.input('Execute: ')) end,
}
<
------------------------------------------------------------------------------
*MiniPick-examples*
Common configuration examples ~
- Disable icons in |MiniPick.builtin| pickers related to paths: >lua
local pick = require('mini.pick')
pick.setup({ source = { show = pick.default_show } })
<
- Mappings to switch `toggle_{preview,info}` and `move_{up,down}`: >lua
require('mini.pick').setup({
mappings = {
toggle_info = '<C-k>',
toggle_preview = '<C-p>',
move_down = '<Tab>',
move_up = '<S-Tab>',
}
})
<
- Different window styles: >lua
-- Different border
{ window = { config = { border = 'double' } } }
-- "Cursor tooltip"
{
window = {
config = {
relative = 'cursor', anchor = 'NW',
row = 0, col = 0, width = 40, height = 20,
},
},
}
-- Centered on screen
local win_config = function()
height = math.floor(0.618 * vim.o.lines)
width = math.floor(0.618 * vim.o.columns)
return {
anchor = 'NW', height = height, width = width,
row = math.floor(0.5 * (vim.o.lines - height)),
col = math.floor(0.5 * (vim.o.columns - width)),
}
end
{ window = { config = win_config } }
<
------------------------------------------------------------------------------
*MiniPick.setup()*
`MiniPick.setup`({config})
Module setup
*:Pick*
Calling this function creates a `:Pick` user command. It takes picker name
from |MiniPick.registry| as mandatory first argument and executes it with
following (expanded, |expandcmd()|) |<f-args>| combined in a single table.
To add custom pickers, update |MiniPick.registry|.
Example: >vim
:Pick files tool='git'
:Pick grep pattern='<cword>'
<
Parameters ~
{config} `(table|nil)` Module config table. See |MiniPick.config|.
Usage ~
>lua
require('mini.pick').setup() -- use default config
-- OR
require('mini.pick').setup({}) -- replace {} with your config table
<
------------------------------------------------------------------------------
*MiniPick.config*
`MiniPick.config`
Module config
Default values:
>lua
MiniPick.config = {
-- Delays (in ms; should be at least 1)
delay = {
-- Delay between forcing asynchronous behavior
async = 10,
-- Delay between computation start and visual feedback about it
busy = 50,
},
-- Keys for performing actions. See `:h MiniPick-actions`.
mappings = {
caret_left = '<Left>',
caret_right = '<Right>',
choose = '<CR>',
choose_in_split = '<C-s>',
choose_in_tabpage = '<C-t>',
choose_in_vsplit = '<C-v>',
choose_marked = '<M-CR>',
delete_char = '<BS>',
delete_char_right = '<Del>',
delete_left = '<C-u>',
delete_word = '<C-w>',
mark = '<C-x>',
mark_all = '<C-a>',
move_down = '<C-n>',
move_start = '<C-g>',
move_up = '<C-p>',
paste = '<C-r>',
refine = '<C-Space>',
refine_marked = '<M-Space>',
scroll_down = '<C-f>',
scroll_left = '<C-h>',
scroll_right = '<C-l>',
scroll_up = '<C-b>',
stop = '<Esc>',
toggle_info = '<S-Tab>',
toggle_preview = '<Tab>',
},
-- General options
options = {
-- Whether to show content from bottom to top
content_from_bottom = false,
-- Whether to cache matches (more speed and memory on repeated prompts)
use_cache = false,
},
-- Source definition. See `:h MiniPick-source`.
source = {
items = nil,
name = nil,
cwd = nil,
match = nil,
show = nil,
preview = nil,
choose = nil,
choose_marked = nil,
},
-- Window related options
window = {
-- Float window config (table or callable returning it)
config = nil,
-- String to use as cursor in prompt
prompt_cursor = '▏',
-- String to use as prefix in prompt
prompt_prefix = '> ',
},
}
<
# Delays ~
`config.delay` defines plugin delays (in ms). All should be strictly positive.
`delay.async` is a delay between forcing asynchronous behavior. This usually
means making screen redraws and utilizing |MiniPick.poke_is_picker_active()|
(for example, to stop current matching if query has updated).
Smaller values give smoother user experience at the cost of more computations.
`delay.busy` is a delay between when some computation starts and showing
visual feedback about it by making window border to have `MiniPickBorderBusy`
highlight group.
Smaller values will give feedback faster at the cost of feeling like flicker.
# Mappings ~
`config.mappings` defines keys for special actions to be triggered after certain
keys. See |MiniPick-actions| for more information.
# Options ~
`config.options` contains some general purpose options.
`options.content_from_bottom` is a boolean indicating whether content should be
shown from bottom to top. That means that best matches will be shown at
the bottom. Note: for better experience use Neovim>=0.10, which has floating
window footer capability. Default: `false`.
`options.use_cache` is a boolean indicating whether match results should be
cached per prompt (i.e. concatenated query). This results into faster response
on repeated prompts (like when deleting query entries) at the cost of using
more memory. Default: `false`.
# Source ~
`config.source` defines fallbacks for source specification. For example, this
can be used to change default `match` to use different implementation or `show`
to not show icons for some |MiniPick.builtin| pickers (see |MiniPick-examples|).
See |MiniPick-source| for more information.
# Window ~
`config.window` contains window specific configurations.
`window.config` defines a (parts of) default floating window config for the main
picker window. This can be either a table overriding some parts or a callable
returning such table. See |MiniPick-examples| for some examples.
`window.prompt_cursor` defines how cursor is displayed in window's prompt.
Default: '▏'.
`window.prompt_prefix` defines what prefix is used in window's prompt.
Default: '> '.
------------------------------------------------------------------------------
*MiniPick.start()*
`MiniPick.start`({opts})
Start picker
Notes:
- If there is currently an active picker, it is properly stopped and new one
is started "soon" in the main event-loop (see |vim.schedule()|).
- Current window at the moment of this function call is treated as "target".
See |MiniPick.get_picker_state()| and |MiniPick.set_picker_target_window()|.
Parameters ~
{opts} `(table|nil)` Options. Should have same structure as |MiniPick.config|.
Default values are inferred from there.
Usually should have proper |MiniPick-source.items| defined.
Return ~
`(any)` Item which was current when picker is stopped; `nil` if aborted.
------------------------------------------------------------------------------
*MiniPick.stop()*
`MiniPick.stop`()
Stop active picker
------------------------------------------------------------------------------
*MiniPick.refresh()*
`MiniPick.refresh`()
Refresh active picker
------------------------------------------------------------------------------
*MiniPick.default_match()*
`MiniPick.default_match`({stritems}, {inds}, {query}, {opts})
Default match
Filter target stritems to contain query and sort from best to worst matches.
Implements default value for |MiniPick-source.match|.
By default (if no special modes apply) it does the following fuzzy matching:
- Stritem contains query if it contains all its elements verbatim in the same
order (possibly with gaps, i.e. not strictly one after another).
Note: empty query and empty string element is contained in any string.
- Sorting is done with the following ordering (same as in |mini.fuzzy|):
- The smaller the match width (end column minus start column) the better.
- Among same match width, the smaller start column the better.
- Among same match width and start column, preserve original order.
Notes:
- Most common interactive usage results into `query` containing one typed
character per element.
# Special modes ~
- Forced modes:
- Query starts with "*": match the rest fuzzy (without other modes).
- Query starts with "'": match the rest exactly (without gaps).
- Place modes:
- Query starts with '^': match the rest exactly at start.
- Query ends with '$': match the rest exactly at end.
- Both modes can be used simultaneously.
- Grouped: query contains at least one whitespace element. Output is computed
as if query is split at whitespace indexes with concatenation between them.
Precedence of modes:
"forced exact" = "forced fuzzy" > "place start/end" > "grouped" > "default"
# Examples ~
Assuming `stritems` are `{ '_abc', 'a_bc', 'ab_c', 'abc_' }`, here are some
example matches based on prompt (concatenated query): >
| Prompt | Matches |
|--------|------------------------|
| abc | All |
| *abc | All |
| | |
| 'abc | abc_, _abc |
| *'abc | None (no "'" in items) |
| | |
| ^abc | abc_ |
| *^abc | None (no "^" in items) |
| | |
| abc$ | _abc |
| *abc$ | None (no "$" in items) |
| | |
| ab c | abc_, _abc, ab_c |
| *ab c | None (no " " in items) |
Having query `{ 'ab', 'c' }` is the same as "ab c" prompt.
You can have a feel of how this works with this command: >lua
MiniPick.start({ source = { items = { '_abc', 'a_bc', 'ab_c', 'abc_' } } })
<
Parameters ~
{stritems} `(table)` Array of all stritems.
{inds} `(table)` Array of `stritems` indexes to match. All of them should point
at string elements of `stritems`. No check is done for performance reasons.
{query} `(table)` Array of strings.
{opts} `(table|nil)` Options. Possible fields:
- <sync> `(boolean)` - Whether to match synchronously. Default: `false`.
- <preserve_order> `(boolean)` - Whether to skip sort step. Default: `false`.
Return ~
`(table|nil)` Depending on whether computation is synchronous (either `opts.sync`
is `true` or there is an active picker):
- If yes, array of `stritems` indexes matching the `query` (from best to worst).
- If no, `nil` is returned with |MiniPick.set_picker_match_inds()| used later.
------------------------------------------------------------------------------
*MiniPick.default_show()*
`MiniPick.default_show`({buf_id}, {items}, {query}, {opts})
Default show
Show items in a buffer and highlight parts that actually match query (assuming
match is done with |MiniPick.default_match()|). Lines are computed based on
the |MiniPick-source.items-stritems|.
Implements default value for |MiniPick-source.show|.
Uses the following highlight groups (see |MiniPick| for their description):
* `MiniPickIconDirectory`
* `MiniPickIconFile`
* `MiniPickMatchCurrent`
* `MiniPickMatchMarked`
* `MiniPickMatchRanges`
Parameters ~
{buf_id} `(number)` Identifier of target buffer.
{items} `(table)` Array of items to show.
{query} `(table)` Array of strings representing query.
{opts} `(table|nil)` Options. Possible fields:
- <show_icons> `(boolean)` - whether to show icons for entries recognized as
valid actually present paths on disk (see |MiniPick-source.items-common|),
empty space otherwise. Tries to use `text` field as fallback for path.
Default: `false`. Note: |MiniPick.builtin| pickers showing file/directory
paths use `true` by default.
- <icons> `(table)` - table with fallback icons used if icon provider
does not itself supply default icons for category. Can have fields:
- <directory> `(string)` - icon for directory. Default: " ".
- <file> `(string)` - icon for file. Default: " ".
- <none> `(string)` - icon for non-valid path. Default: " ".
------------------------------------------------------------------------------
*MiniPick.default_preview()*
`MiniPick.default_preview`({buf_id}, {item}, {opts})
Default preview
Preview item. Logic follows the rules in |MiniPick-source.items-common|:
- File and buffer are shown at the start.
- Directory has its content listed.
- Line/position/region in file or buffer is shown at start.
- Others are shown directly with |vim.inspect()|.
Implements default value for |MiniPick-source.preview|.
Uses the following highlight groups (see |MiniPick| for their description):
* `MiniPickPreviewLine`
* `MiniPickPreviewRegion`
Parameters ~
{buf_id} `(number)` Identifier of target buffer.
{item} `(any)` Item to preview.
{opts} `(table|nil)` Options. Possible values:
- <n_context_lines> `(number)` - number of lines to load past target position
when reading from disk. Useful to explore context. Default: 'lines' twice.
- <line_position> `(string)` - where in the window to show item position.
One of "top", "center", "bottom". Default: "top".