-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathopts.lua
663 lines (568 loc) · 21.6 KB
/
opts.lua
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
local M = {}
---@type GrugFarOptions
M.defaultOptions = {
-- debounce milliseconds for issuing search while user is typing
-- prevents excessive searching
debounceMs = 500,
-- minimum number of chars which will cause a search to happen
-- prevents performance issues in larger dirs
minSearchChars = 2,
-- stops search after this number of matches as getting millions of matches is most likely pointless
-- and can even freeze the search buffer sometimes
-- can help prevent performance issues when searching for very common strings or when slowly starting
-- to type your search string
-- note that it can overshoot a little bit, but should not really matter in practice
-- set to nil to disable
maxSearchMatches = 2000,
-- disable automatic debounced search and trigger search when leaving insert mode or making normal mode changes instead
-- Note that normal mode changes such as `diw`, `rF`, etc will still trigger a search
normalModeSearch = false,
-- deprecated, was renamed to normalModeSearch
searchOnInsertLeave = false,
-- max number of parallel replacements tasks
maxWorkers = 4,
-- ripgrep executable to use, can be a different path if you need to configure
-- deprecated, please use engines.ripgrep.path
rgPath = 'rg',
-- extra args that you always want to pass to rg
-- like for example if you always want context lines around matches
-- deprecated, please use engines.ripgrep.extraArgs
extraRgArgs = '',
-- search and replace engines configuration
engines = {
-- see https://github.com/BurntSushi/ripgrep
ripgrep = {
-- ripgrep executable to use, can be a different path if you need to configure
path = 'rg',
-- extra args that you always want to pass
-- like for example if you always want context lines around matches
extraArgs = '',
-- whether to show diff of the match being replaced as opposed to just the
-- replaced result. It usually makes it easier to understand the change being made
showReplaceDiff = true,
-- placeholders to show in input areas when they are empty
-- set individual ones to '' to disable, or set enabled = false for complete disable
placeholders = {
-- whether to show placeholders
enabled = true,
search = 'ex: foo foo([a-z0-9]*) fun\\(',
replacement = 'ex: bar ${1}_foo $$MY_ENV_VAR ',
replacement_lua = 'ex: if vim.startsWith(match, "use") \\n then return "employ" .. match \\n else return match end',
filesFilter = 'ex: *.lua *.{css,js} **/docs/*.md (specify one per line)',
flags = 'ex: --help --ignore-case (-i) --replace= (empty replace) --multiline (-U)',
paths = 'ex: /foo/bar ../ ./hello\\ world/ ./src/foo.lua',
},
},
-- see https://ast-grep.github.io
astgrep = {
-- ast-grep executable to use, can be a different path if you need to configure
path = 'sg',
-- extra args that you always want to pass
-- like for example if you always want context lines around matches
extraArgs = '',
-- placeholders to show in input areas when they are empty
-- set individual ones to '' to disable, or set enabled = false for complete disable
placeholders = {
-- whether to show placeholders
enabled = true,
search = 'ex: $A && $A() foo.bar($$$ARGS) $_FUNC($_FUNC)',
replacement = 'ex: $A?.() blah($$$ARGS)',
replacement_lua = 'ex: return vars.A == "blah" and "foo(" .. vim.fn.join(vars.ARGS, ", ") .. ")" or match',
filesFilter = 'ex: *.lua *.{css,js} **/docs/*.md (specify one per line, filters via ripgrep)',
flags = 'ex: --help (-h) --debug-query=ast --rewrite= (empty replace) --strictness=<STRICTNESS>',
paths = 'ex: /foo/bar ../ ./hello\\ world/ ./src/foo.lua',
},
},
},
-- search and replace engine to use.
-- Must be one of 'ripgrep' | 'astgrep' | nil
-- if nil, defaults to 'ripgrep'
engine = 'ripgrep',
-- replacement interpreters that are enabled for usage (in addition to the default).
-- Those allow you to evaluate the replacement input as a an interpreted string for each search match.
-- The result of that evaluation is used as the replacement in each case.
-- Supported:
-- * 'default': treat replacement as a string to pass to the current engine
-- * 'lua': treat replacement as lua function body where search match is identified by `match` and
-- meta variables (with astgrep for example) are avaible in `vars` table (ex: `vars.A` captures `$A`)
enabledReplacementInterpreters = { 'default', 'lua', 'vimscript' },
-- which replacement interprer to use
-- Must be one of enabledReplacementInterpreters defined above.
-- TODO (sbadragan): add vimscript
replacementInterpreter = 'default',
-- specifies the command to run (with `vim.cmd(...)`) in order to create
-- the window in which the grug-far buffer will appear
-- ex (horizontal bottom right split): 'botright split'
-- ex (open new tab): 'tabnew %'
windowCreationCommand = 'vsplit',
-- buffer line numbers + match line numbers can get a bit visually overwhelming
-- turn this off if you still like to see the line numbers
disableBufferLineNumbers = true,
-- maximum number of search chars to show in buffer and quickfix list titles
-- zero disables showing it
maxSearchCharsInTitles = 30,
-- static title to use for grug-far buffer, as opposed to the dynamically generated title.
-- Note that nvim does not allow multiple buffers with the same name, so this option is meant more
-- as something to be speficied for a particular instance as opposed to something set in the setup function
-- nil or '' disables it
staticTitle = nil,
-- whether to start in insert mode,
-- set to false for normal mode
startInInsertMode = true,
-- row in the window to position the cursor at at start
startCursorRow = 3,
-- whether to wrap text in the grug-far buffer
wrap = true,
-- whether or not to make a transient buffer which is both unlisted and fully deletes itself when not in use
transient = false,
-- by default, in visual mode, the visual selection is used to prefill the search
-- setting this option to true disables that behaviour
ignoreVisualSelection = false,
-- shortcuts for the actions you see at the top of the buffer
-- set to '' or false to unset. Mappings with no normal mode value will be removed from the help header
-- you can specify either a string which is then used as the mapping for both normal and insert mode
-- or you can specify a table of the form { [mode] = <lhs> } (ex: { i = '<C-enter>', n = '<localleader>gr'})
-- it is recommended to use <localleader> though as that is more vim-ish
-- see https://learnvimscriptthehardway.stevelosh.com/chapters/11.html#local-leader
keymaps = {
replace = { n = '<localleader>r' },
qflist = { n = '<localleader>q' },
syncLocations = { n = '<localleader>s' },
syncLine = { n = '<localleader>l' },
close = { n = '<localleader>c' },
historyOpen = { n = '<localleader>t' },
historyAdd = { n = '<localleader>a' },
refresh = { n = '<localleader>f' },
openLocation = { n = '<localleader>o' },
openNextLocation = { n = '<down>' },
openPrevLocation = { n = '<up>' },
gotoLocation = { n = '<enter>' },
pickHistoryEntry = { n = '<enter>' },
abort = { n = '<localleader>b' },
help = { n = 'g?' },
toggleShowCommand = { n = '<localleader>p' },
swapEngine = { n = '<localleader>e' },
previewLocation = { n = '<localleader>i' },
swapReplacementInterpreter = { n = '<localleader>x' },
},
-- separator between inputs and results, default depends on nerdfont
resultsSeparatorLineChar = '',
-- highlight the results with TreeSitter, if available
resultsHighlight = true,
-- highlight the inputs with TreeSitter, if available
inputsHighlight = true,
-- spinner states, default depends on nerdfont, set to false to disable
spinnerStates = {
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
},
-- whether to report duration of replace/sync operations
reportDuration = true,
-- icons for UI, default ones depend on nerdfont
-- set individual ones to '' to disable, or set enabled = false for complete disable
icons = {
-- whether to show icons
enabled = true,
-- provider to use for file icons
-- acceptable values: 'first_available', 'nvim-web-devicons', 'mini.icons', false (to disable)
fileIconsProvider = 'first_available',
actionEntryBullet = ' ',
searchInput = ' ',
replaceInput = ' ',
filesFilterInput = ' ',
flagsInput = ' ',
pathsInput = ' ',
resultsStatusReady = ' ',
resultsStatusError = ' ',
resultsStatusSuccess = ' ',
resultsActionMessage = ' ',
resultsEngineLeft = '⟪',
resultsEngineRight = '⟫',
resultsChangeIndicator = '┃',
resultsAddedIndicator = '▒',
resultsRemovedIndicator = '▒',
resultsDiffSeparatorIndicator = '┊',
historyTitle = ' ',
helpTitle = ' ',
newline = ' ',
},
-- strings to auto-fill in each input area at start
-- those are not necessarily useful as global defaults but quite useful as overrides
-- when launching through the lua API. For example, this is how you would launch grug-far.nvim
-- with the current word under the cursor as the search string
--
-- require('grug-far').open({ prefills = { search = vim.fn.expand("<cword>") } })
--
prefills = {
search = '',
replacement = '',
filesFilter = '',
flags = '',
paths = '',
},
-- search history settings
history = {
-- maximum number of lines in history file, end of file will be smartly truncated
-- to remove oldest entries
maxHistoryLines = 10000,
-- directory where to store history file
historyDir = vim.fn.stdpath('state') .. '/grug-far',
-- configuration for when to auto-save history entries
autoSave = {
-- whether to auto-save at all, trumps all other settings below
enabled = true,
-- auto-save after a replace
onReplace = true,
-- auto-save after sync all
onSyncAll = true,
-- auto-save after buffer is deleted
onBufDelete = true,
},
},
-- unique instance name. This is used as a handle to refer to a particular instance of grug-far when
-- toggling visibility, etc.
-- As this needs to be unique per instance, this option is meant to be speficied for a particular instance
-- as opposed to something set in the setup function
instanceName = nil,
-- folding related options
folding = {
-- whether to enable folding
enabled = true,
-- sets foldlevel, folds with higher level will be closed.
-- result matche lines for each file have fold level 1
-- set it to 0 if you would like to have the results initially collapsed
-- See :h foldlevel
foldlevel = 1,
-- visual indicator of folds, see :h foldcolumn
-- set to '0' to disable
foldcolumn = '1',
},
-- options related to locations in results list
resultLocation = {
-- whether to show the result location number label
-- this can be useful for example if you would like to use that number
-- as a count to goto directly to a result
-- (for instance `3<enter>` would goto the third result's location)
showNumberLabel = true,
-- position of the number when visible, acceptable values are:
-- 'right_align', 'eol' and 'inline'
numberLabelPosition = 'right_align',
-- format for the number label, by default it displays as for example: [42]
numberLabelFormat = ' [%d]',
},
}
---@class KeymapTable
---@field n? string
---@field i? string
---@alias KeymapDef KeymapTable | string | boolean
---@class Keymaps
---@field replace KeymapDef
---@field qflist KeymapDef
---@field syncLocations KeymapDef
---@field historyAdd KeymapDef
---@field historyOpen KeymapDef
---@field refresh KeymapDef
---@field syncLine KeymapDef
---@field close KeymapDef
---@field gotoLocation KeymapDef
---@field openLocation KeymapDef
---@field openNextLocation KeymapDef
---@field openPrevLocation KeymapDef
---@field pickHistoryEntry KeymapDef
---@field toggleShowCommand KeymapDef
---@field abort KeymapDef
---@field help KeymapDef
---@field swapEngine KeymapDef
---@field previewLocation KeymapDef
---@field swapReplacementInterpreter KeymapDef
---@class KeymapsOverride
---@field replace? KeymapDef
---@field qflist? KeymapDef
---@field syncLocations? KeymapDef
---@field historyAdd? KeymapDef
---@field historyOpen? KeymapDef
---@field refresh? KeymapDef
---@field syncLine? KeymapDef
---@field close? KeymapDef
---@field open? KeymapDef
---@field gotoLocation? KeymapDef
---@field openLocation? KeymapDef
---@field openNextLocation? KeymapDef
---@field openPrevLocation? KeymapDef
---@field pickHistoryEntry? KeymapDef
---@field toggleShowCommand? KeymapDef
---@field abort? KeymapDef
---@field help? KeymapDef
---@field swapEngine? KeymapDef
---@field previewLocation? KeymapDef
---@field swapReplacementInterpreter? KeymapDef
---@class AutoSaveTable
---@field enabled boolean
---@field onReplace boolean
---@field onSyncAll boolean
---@field onBufDelete boolean
---@class AutoSaveTableOverride
---@field enabled? boolean
---@field onReplace? boolean
---@field onSyncAll? boolean
---@field onBufDelete? boolean
---@class HistoryTable
---@field maxHistoryLines integer
---@field historyDir string
---@field autoSave AutoSaveTable
---@class HistoryTableOverride
---@field maxHistoryLines? integer
---@field historyDir? string
---@field autoSave? AutoSaveTable
---@alias FileIconsProviderType "first_available" | "mini.icons" | "nvim-web-devicons" | false
---@class IconsTable
---@field enabled boolean
---@field fileIconsProvider FileIconsProviderType
---@field searchInput string
---@field actionEntryBullet string
---@field replaceInput string
---@field filesFilterInput string
---@field flagsInput string
---@field resultsStatusReady string
---@field resultsStatusError string
---@field resultsStatusSuccess string
---@field resultsActionMessage string
---@field resultsChangeIndicator string
---@field resultsAddedIndicator string
---@field resultsRemovedIndicator string
---@field resultsDiffSeparatorIndicator string
---@field historyTitle string
---@field helpTitle string
---@field newline string
---@class IconsTableOverride
---@field enabled? boolean
---@field fileIconsProvider? FileIconsProviderType
---@field searchInput? string
---@field actionEntryBullet? string
---@field replaceInput? string
---@field filesFilterInput? string
---@field flagsInput? string
---@field resultsStatusReady? string
---@field resultsStatusError? string
---@field resultsStatusSuccess? string
---@field resultsActionMessage? string
---@field resultsChangeIndicator? string
---@field resultsAddedIndicator? string
---@field resultsRemovedIndicator? string
---@field resultsDiffSeparatorIndicator? string
---@field historyTitle? string
---@field helpTitle? string
---@field newline? string
---@class PlaceholdersTable
---@field enabled boolean
---@field search string
---@field replacement string
---@field replacement_lua string
---@field filesFilter string
---@field flags string
---@field paths string
---@class PlaceholdersTableOverride
---@field enabled? boolean
---@field search? string
---@field replacement? string
---@field replacement_lua? string
---@field filesFilter? string
---@field flags? string
---@field paths? string
---@class GrugFarPrefills
---@field search string
---@field replacement string
---@field filesFilter string
---@field flags string
---@field paths string
---@class GrugFarPrefillsOverride
---@field search? string
---@field replacement? string
---@field filesFilter? string
---@field flags? string
---@field paths? string
---@class FoldingTable
---@field enabled boolean
---@field foldlevel integer
---@field foldcolumn string
---@class FoldingTableOverride
---@field enabled? boolean
---@field foldlevel? integer
---@field foldcolumn? string | integer
---@class RipgrepEngineTable
---@field path string
---@field extraArgs string
---@field showReplaceDiff boolean
---@field placeholders PlaceholdersTable
---@class RipgrepEngineTableOverride
---@field path? string
---@field extraArgs? string
---@field showReplaceDiff? boolean
---@field placeholders? PlaceholdersTableOverride
---@class AstgrepEngineTable
---@field path string
---@field extraArgs string
---@field placeholders PlaceholdersTable
---@class AstgrepEngineTableOverride
---@field path? string
---@field extraArgs? string
---@field placeholders? PlaceholdersTableOverride
---@class EnginesTable
---@field ripgrep RipgrepEngineTable
---@field astgrep AstgrepEngineTable
---@class EnginesTableOverride
---@field ripgrep? RipgrepEngineTableOverride
---@field astgrep? AstgrepEngineTableOverride
---@alias GrugFarEngineType "ripgrep" | "astgrep"
---@alias GrugFarReplacementInterpreterType "lua" | "vimscript" | "default"
---@alias NumberLabelPosition "right_align" | "eol" | "inline"
---@class ResultLocationTable
---@field showNumberLabel boolean
---@field numberLabelPosition NumberLabelPosition
---@field numberLabelFormat string
---@class ResultLocationTableOverride
---@field showNumberLabel? boolean
---@field numberLabelPosition? NumberLabelPosition
---@field numberLabelFormat? string
---@class GrugFarOptions
---@field debounceMs integer
---@field minSearchChars integer
---@field maxSearchMatches integer?
---@field searchOnInsertLeave boolean
---@field normalModeSearch boolean
---@field maxWorkers integer
---@field rgPath string
---@field extraRgArgs string
---@field windowCreationCommand string
---@field disableBufferLineNumbers boolean
---@field maxSearchCharsInTitles integer
---@field staticTitle? string
---@field startInInsertMode boolean
---@field startCursorRow integer
---@field wrap boolean
---@field transient boolean
---@field ignoreVisualSelection boolean
---@field keymaps Keymaps
---@field resultsSeparatorLineChar string
---@field resultsHighlight boolean
---@field inputsHighlight boolean
---@field spinnerStates string[] | false
---@field reportDuration boolean
---@field icons IconsTable
---@field prefills GrugFarPrefills
---@field history HistoryTable
---@field instanceName? string
---@field folding FoldingTable
---@field engines EnginesTable
---@field engine GrugFarEngineType
---@field replacementInterpreter GrugFarReplacementInterpreterType
---@field enabledReplacementInterpreters GrugFarReplacementInterpreterType[]
---@field resultLocation ResultLocationTable
---@class GrugFarOptionsOverride
---@field debounceMs? integer
---@field minSearchChars? integer
---@field maxSearchMatches? integer
---@field searchOnInsertLeave? boolean
---@field normalModeSearch? boolean
---@field maxWorkers? integer
---@field rgPath? string
---@field extraRgArgs? string
---@field windowCreationCommand? string
---@field disableBufferLineNumbers? boolean
---@field maxSearchCharsInTitles? integer
---@field staticTitle? string
---@field startInInsertMode? boolean
---@field startCursorRow? integer
---@field wrap? boolean
---@field transient? boolean
---@field ignoreVisualSelection? boolean
---@field keymaps? KeymapsOverride
---@field resultsSeparatorLineChar? string
---@field resultsHighlight? boolean
---@field inputsHighlight? boolean
---@field spinnerStates? string[] | false
---@field reportDuration? boolean
---@field icons? IconsTableOverride
---@field prefills? GrugFarPrefillsOverride
---@field history? HistoryTableOverride
---@field instanceName? string
---@field folding? FoldingTableOverride
---@field engines? EnginesTableOverride
---@field engine? GrugFarEngineType
---@field replacementInterpreter? GrugFarReplacementInterpreterType
---@field enabledReplacementInterpreters? GrugFarReplacementInterpreterType[]
---@field resultLocation? ResultLocationTableOverride
--- generates merged options
---@param options GrugFarOptionsOverride | GrugFarOptions
---@param defaults GrugFarOptions
---@return GrugFarOptions
function M.with_defaults(options, defaults)
local newOptions = vim.tbl_deep_extend('force', vim.deepcopy(defaults), options)
-- normalize keymaps opts
for key, value in pairs(newOptions.keymaps) do
if not value or value == '' then
newOptions.keymaps[key] = {}
end
if type(value) == 'string' then
newOptions.keymaps[key] = { i = value, n = value }
end
end
if options.rgPath then
vim.deprecate('options.rgPath', 'options.engines.ripgrep.path', 'soon', 'grug-far.nvim')
newOptions.engines.ripgrep.path = options.rgPath
end
if not options.normalModeSearch and options.searchOnInsertLeave then
vim.deprecate(
'options.searchOnInsertLeave',
'options.normalModeSearch',
'soon',
'grug-far.nvim'
)
newOptions.normalModeSearch = options.searchOnInsertLeave
end
if options['placeholders'] then
error(
'options.placeholders has been removed in favor of options.engines[engine].placeholders! Please use that one instead!'
)
end
if
not vim.tbl_contains(
newOptions.enabledReplacementInterpreters,
newOptions.replacementInterpreter
)
then
error('options.enabledReplacementInterpreters must contain options.replacementInterpreter')
end
if options.extraRgArgs then
vim.deprecate(
'options.extraRgArgs',
'options.engines.ripgrep.extraArgs',
'soon',
'grug-far.nvim'
)
newOptions.engines.ripgrep.extraArgs = options.extraRgArgs
end
return newOptions
end
--- gets icon with given name if icons enabled
---@param iconName string
---@param context GrugFarContext
---@return string|nil
function M.getIcon(iconName, context)
local icons = context.options.icons
if not icons.enabled then
return nil
end
return icons[iconName]
end
return M