, "Commands"
, "Mappings"
, "Options"
+ , "Functions"
, "Custom autocommands"
, "Overrides"
, "Troubleshooting"
, Whitespace
, Plaintext "using"
, Whitespace
+ , Plaintext "ripgrep"
+ , Whitespace
+ , Plaintext "(https://github.com/BurntSushi/ripgrep),"
+ , Whitespace
, Plaintext "The"
, Whitespace
, Plaintext "Silver"
, Whitespace
, Plaintext "On"
, Whitespace
+ , Plaintext "modern"
+ , Whitespace
+ , Plaintext "versions"
+ , Whitespace
+ , Plaintext "of"
+ , Whitespace
, Plaintext "Vim"
, Whitespace
- , Plaintext "version"
+ , Plaintext "(version"
, Whitespace
, Plaintext "8"
, Whitespace
, Whitespace
, Plaintext "higher,"
, Whitespace
+ , Plaintext "or"
+ , Whitespace
+ , Plaintext "Neovim),"
+ , Whitespace
, Plaintext "searches"
, Whitespace
, Plaintext "are"
, Whitespace
, Plaintext "only."
]
- , Paragraph
- [ Plaintext "Finally,"
- , Whitespace
- , Plaintext "Ferret"
- , Whitespace
- , Plaintext "offers"
- , Whitespace
- , Plaintext "integration"
- , Whitespace
- , Plaintext "with"
- , Whitespace
- , Plaintext "dispatch.vim"
- , Whitespace
- , Plaintext "(https://github.com/tpope/vim-dispatch),"
- , Whitespace
- , Plaintext "which"
- , Whitespace
- , Plaintext "enables"
- , Whitespace
- , Plaintext "asynchronous"
- , Whitespace
- , Plaintext "searching"
- , Whitespace
- , Plaintext "on"
- , Whitespace
- , Plaintext "older"
- , Whitespace
- , Plaintext "versions"
- , Whitespace
- , Plaintext "of"
- , Whitespace
- , Plaintext "Vim"
- , Whitespace
- , Plaintext "(prior"
- , Whitespace
- , Plaintext "to"
- , Whitespace
- , Plaintext "version"
- , Whitespace
- , Plaintext "8),"
- , Whitespace
- , Plaintext "despite"
- , Whitespace
- , Plaintext "the"
- , Whitespace
- , Plaintext "fact"
- , Whitespace
- , Plaintext "that"
- , Whitespace
- , Plaintext "Vim"
- , Whitespace
- , Plaintext "itself"
- , Whitespace
- , Plaintext "is"
- , Whitespace
- , Plaintext "single-threaded."
- ]
, SubheadingAnnotation "2. Streamlined multi-file replace"
, Paragraph
[ Plaintext "The"
, Whitespace
, Plaintext "covers"
, Whitespace
+ , Plaintext "on"
+ , Whitespace
+ , Plaintext "older"
+ , Whitespace
+ , Plaintext "versions"
+ , Whitespace
+ , Plaintext "of"
+ , Whitespace
+ , Plaintext "Vim"
+ , Whitespace
, Plaintext "by"
, Whitespace
, Link ":Acks"
, Whitespace
, Plaintext "its"
, Whitespace
- , Plaintext "work."
+ , Plaintext "work"
+ , Whitespace
+ , Plaintext "(on"
+ , Whitespace
+ , Plaintext "newer"
+ , Whitespace
+ , Plaintext "versions"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "built-in"
+ , Whitespace
+ , Link ":cfdo"
+ , Whitespace
+ , Plaintext "is"
+ , Whitespace
+ , Plaintext "used"
+ , Whitespace
+ , Plaintext "instead)."
]
, HeadingAnnotation "Installation"
, Paragraph
, Fenced [ ":call pathogen#helptags()" ]
, Project
[ Unit
+ [ FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#get_default_arguments"
+ , functionArguments = ArgumentList [ Argument "executable" ]
+ , functionAttributes = [ "abort" ]
+ , functionBody =
+ [ GenericStatement
+ "return get(ferret#private#executables(), a:executable, '')"
+ ]
+ }
+ ]
+ , Unit
[ FunctionDeclaration
{ functionBang = True
, functionName = "s:delete"
}
, FunctionDeclaration
{ functionBang = True
- , functionName = "ferret#private#dispatch"
+ , functionName = "ferret#private#nvim"
, functionArguments = ArgumentList []
- , functionAttributes = [ "abort" ]
+ , functionAttributes = []
, functionBody =
[ Empty
, LetStatement
- { letLexpr = "l:dispatch"
- , letValue = "get(g:, 'FerretDispatch', 1)"
- }
- , GenericStatement "return l:dispatch && exists(':Make') == 2"
+ { letLexpr = "l:nvim" , letValue = "get(g:, 'FerretNvim', 1)" }
+ , GenericStatement "return l:nvim && has('nvim')"
]
}
, FunctionDeclaration
, functionArguments = ArgumentList [ Argument "message" ]
, functionAttributes = [ "abort" ]
, functionBody =
- [ GenericStatement "call inputsave()"
+ [ GenericStatement "if has('lambda') && has('timers')"
+ , GenericStatement
+ "call timer_start(100, {-> s:print_error_with_echomsg(a:message)})"
+ , GenericStatement "else"
+ , GenericStatement "call inputsave()"
, GenericStatement "echohl ErrorMsg"
, GenericStatement
"unsilent call input(a:message . ': press ENTER to continue')"
, GenericStatement "call inputrestore()"
, GenericStatement "unsilent echo"
, GenericStatement "redraw!"
+ , GenericStatement "endif"
+ ]
+ }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "s:print_error_with_echomsg"
+ , functionArguments = ArgumentList [ Argument "message" ]
+ , functionAttributes = []
+ , functionBody =
+ [ GenericStatement "redraw!"
+ , GenericStatement "echohl ErrorMsg"
+ , GenericStatement "echomsg a:message"
+ , GenericStatement "echohl NONE"
]
}
, FunctionDeclaration
, UnletStatement
{ unletBang = False , unletBody = "g:ferret_lastsearch" }
, GenericStatement "endif"
+ , LetStatement
+ { letLexpr = "l:odd_number_of_backslashes"
+ , letValue = "'\\\\\\@<!\\\\\\(\\\\\\\\\\)*\\\\\\@!'"
+ }
+ , LetStatement
+ { letLexpr = "l:unescaped_space"
+ , letValue = "'\\('.l:odd_number_of_backslashes.'\\)\\@<! '"
+ }
+ , LetStatement
+ { letLexpr = "l:args"
+ , letValue = "split(a:args, l:unescaped_space)"
+ }
, LetStatement { letLexpr = "l:expanded_args" , letValue = "[]" }
- , GenericStatement "for l:arg in a:args"
+ , GenericStatement "for l:arg in l:args"
+ , LetStatement
+ { letLexpr = "l:arg"
+ , letValue = "substitute(l:arg, '\\\\ ', ' ', 'g')"
+ }
, GenericStatement "if ferret#private#option(l:arg)"
, GenericStatement "call add(l:expanded_args, l:arg)"
, GenericStatement "elseif exists('g:ferret_lastsearch')"
, GenericStatement "call add(l:expanded_args, l:arg)"
, GenericStatement "endif"
, GenericStatement "endfor"
- , GenericStatement "if ferret#private#async()"
+ , GenericStatement
+ "if ferret#private#nvim() || ferret#private#async()"
, GenericStatement "return l:expanded_args"
, GenericStatement "endif"
, LetStatement
, GenericStatement "endif"
]
}
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "s:qfsize"
+ , functionArguments = ArgumentList [ Argument "type" ]
+ , functionAttributes = [ "abort" ]
+ , functionBody =
+ [ GenericStatement "if has('patch-8.0.1112')"
+ , GenericStatement "if a:type ==# 'qf'"
+ , GenericStatement "return get(getqflist({'size' : 0}), 'size', 0)"
+ , GenericStatement "else"
+ , GenericStatement
+ "return get(getloclist(0, {'size' : 0}), 'size', 0)"
+ , GenericStatement "endif"
+ , GenericStatement "else"
+ , LetStatement
+ { letLexpr = "l:qflist"
+ , letValue = "a:type ==# 'qf' ? getqflist() : getloclist(0)"
+ }
+ , GenericStatement "return len(l:qflist)"
+ , GenericStatement "endif"
+ ]
+ }
, FunctionDeclaration
{ functionBang = True
, functionName = "ferret#private#post"
, functionBody =
[ GenericStatement "call ferret#private#clearautocmd()"
, LetStatement
- { letLexpr = "l:lastsearch "
+ { letLexpr = "l:lastsearch"
, letValue = "get(g:, 'ferret_lastsearch', '')"
}
, LetStatement
- { letLexpr = "l:qflist "
- , letValue = "a:type == 'qf' ? getqflist() : getloclist(0)"
- }
- , LetStatement
- { letLexpr = "l:tip "
+ { letLexpr = "l:tip"
, letValue = "' [see `:help ferret-quotes`]'"
}
- , GenericStatement "if len(l:qflist) == 0"
, LetStatement
- { letLexpr = "l:base "
+ { letLexpr = "l:len" , letValue = "s:qfsize(a:type)" }
+ , GenericStatement "if l:len == 0"
+ , LetStatement
+ { letLexpr = "l:base"
, letValue =
"'No results for search pattern `' . l:lastsearch . '`'"
}
, GenericStatement "endif"
, GenericStatement "else"
, LetStatement
- { letLexpr = "l:invalid "
+ { letLexpr = "l:qflist"
+ , letValue = "a:type ==# 'qf' ? getqflist() : getloclist(0)"
+ }
+ , LetStatement
+ { letLexpr = "l:invalid"
, letValue = "filter(copy(l:qflist), 'v:val.valid == 0')"
}
- , GenericStatement "if len(l:invalid) == len(l:qflist)"
+ , GenericStatement "if len(l:invalid) == l:len"
, GenericStatement "redraw!"
, GenericStatement "echohl ErrorMsg"
, GenericStatement "for l:item in l:invalid"
, GenericStatement "endfor"
, GenericStatement "echohl NONE"
, LetStatement
- { letLexpr = "l:base "
+ { letLexpr = "l:base"
, letValue = "'Search for `' . l:lastsearch . '` failed'"
}
- , LetStatement
- { letLexpr = "l:suffix "
- , letValue = "a:type == 'qf' && ferret#private#dispatch() ?"
- }
- , GenericStatement "\\ ' (run `:messages` to see details)' : ''"
, GenericStatement
"if l:lastsearch =~ '\\v^[' . \"'\" . '\"].+[^' . \"'\" . '\"]$'"
- , GenericStatement
- "call ferret#private#error(l:base . l:tip . l:suffix)"
+ , GenericStatement "call ferret#private#error(l:base . l:tip)"
, GenericStatement "else"
- , GenericStatement "call ferret#private#error(l:base . l:suffix)"
+ , GenericStatement "call ferret#private#error(l:base)"
, GenericStatement "endif"
, GenericStatement "endif"
, GenericStatement "endif"
+ , GenericStatement "return l:len"
]
}
, FunctionDeclaration
{ functionBang = True
, functionName = "ferret#private#ack"
, functionArguments =
- ArgumentList [ Argument "bang" , Argument "..." ]
+ ArgumentList [ Argument "bang" , Argument "args" ]
, functionAttributes = [ "abort" ]
, functionBody =
[ LetStatement
- { letLexpr = "l:command" , letValue = "s:parse(a:000)" }
+ { letLexpr = "l:command" , letValue = "s:parse(a:args)" }
, GenericStatement "call ferret#private#hlsearch()"
, LetStatement
{ letLexpr = "l:executable"
, GenericStatement "call ferret#private#installprompt()"
, GenericStatement "return"
, GenericStatement "endif"
- , GenericStatement "if ferret#private#async()"
+ , GenericStatement "if ferret#private#nvim()"
+ , GenericStatement
+ "call ferret#private#nvim#search(l:command, 1, a:bang)"
+ , GenericStatement "elseif ferret#private#async()"
, GenericStatement
"call ferret#private#async#search(l:command, 1, a:bang)"
- , GenericStatement "elseif ferret#private#dispatch()"
- , GenericStatement "call ferret#private#dispatch#search(l:command)"
, GenericStatement "else"
, GenericStatement
"call ferret#private#vanilla#search(l:command, 1)"
, letValue =
"filter(map(l:buflist, 'v:val.name'), 'v:val !=# \"\"')"
}
- , GenericStatement "return l:bufpaths"
+ , GenericStatement "return join(l:bufpaths, ' ')"
]
}
, FunctionDeclaration
{ functionBang = True
, functionName = "ferret#private#back"
, functionArguments =
- ArgumentList [ Argument "bang" , Argument "..." ]
+ ArgumentList [ Argument "bang" , Argument "args" ]
, functionAttributes = [ "abort" ]
, functionBody =
[ GenericStatement
- "call call('ferret#private#ack', a:bang, a:000 + ferret#private#buflist())"
+ "call call('ferret#private#ack', [a:bang, a:args . ' ' . ferret#private#buflist()])"
]
}
, FunctionDeclaration
{ functionBang = True
, functionName = "ferret#private#black"
, functionArguments =
- ArgumentList [ Argument "bang" , Argument "..." ]
+ ArgumentList [ Argument "bang" , Argument "args" ]
, functionAttributes = [ "abort" ]
, functionBody =
[ GenericStatement
- "call call('ferret#private#lack', a:bang, a:000 + ferret#private#buflist())"
+ "call call('ferret#private#lack', [a:bang, a:args . ' ' . ferret#private#buflist()])"
]
}
, FunctionDeclaration
{ functionBang = True
, functionName = "ferret#private#lack"
, functionArguments =
- ArgumentList [ Argument "bang" , Argument "..." ]
+ ArgumentList [ Argument "bang" , Argument "args" ]
, functionAttributes = [ "abort" ]
, functionBody =
[ LetStatement
- { letLexpr = "l:command" , letValue = "s:parse(a:000)" }
+ { letLexpr = "l:command" , letValue = "s:parse(a:args)" }
, GenericStatement "call ferret#private#hlsearch()"
, LetStatement
{ letLexpr = "l:executable"
, GenericStatement "call ferret#private#installprompt()"
, GenericStatement "return"
, GenericStatement "endif"
- , GenericStatement "if ferret#private#async()"
+ , GenericStatement "if ferret#private#nvim()"
+ , GenericStatement
+ "call ferret#private#nvim#search(l:command, 0, a:bang)"
+ , GenericStatement "elseif ferret#private#async()"
, GenericStatement
"call ferret#private#async#search(l:command, 0, a:bang)"
, GenericStatement "else"
, functionAttributes = [ "abort" ]
, functionBody =
[ LetStatement
- { letLexpr = "l:matches "
+ { letLexpr = "l:matches"
, letValue =
"matchlist(a:command, '\\v\\C^(([^|\"\\\\a-zA-Z0-9]).+\\2.*\\2)([cgeiI]*)$')"
}
, GenericStatement "return"
, GenericStatement "endif"
, LetStatement
- { letLexpr = "l:pattern " , letValue = "l:matches[1]" }
+ { letLexpr = "l:pattern" , letValue = "l:matches[1]" }
, LetStatement
- { letLexpr = "l:options " , letValue = "l:matches[3]" }
+ { letLexpr = "l:options" , letValue = "l:matches[3]" }
, GenericStatement "if l:options !~# 'e'"
, LetStatement { letLexpr = "l:options ." , letValue = "'e'" }
, GenericStatement "endif"
}
]
}
- , LetStatement { letLexpr = "s:options " , letValue = "{" }
+ , LetStatement { letLexpr = "s:options" , letValue = "{" }
, GenericStatement
"\\ 'ack': [ '--ignore-ack-defaults', '--ignore-case', '--ignore-dir', '--ignore-directory', '--invert-match', '--known-types', '--literal', '--no-recurse', '--recurse', '--sort-files', '--type', '--word-regexp', '-1', '-Q', '-R', '-i', '-k', '-r', '-v', '-w', ], 'ag': [ '--all-types', '--all-text', '--case-sensitive', '--depth', '--follow', '--ignore', '--ignore-case', '--ignore-dir', '--invert-match', '--literal', '--max-count', '--skip-vcs-ignores', '--unrestricted', '--word-regexp', '-Q', '-U', '-a', '-i', '-m', '-s', '-t', '-u', '-v', '-w' ], 'rg': [ '--case-sensitive', '--files-with-matches', '--follow', '--glob', '--hidden', '--ignore-case', '--invert-match', '--max-count', '--maxdepth', '--mmap', '--no-ignore', '--no-ignore-parent', '--no-ignore-vcs', '--no-mmap', '--regexp', '--smart-case', '--text', '--threads', '--type', '--type-not', '--unrestricted', '--word-regexp', '-F', '-L', '-R', '-T', '-a', '-e', '-g', '-i', '-j', '-m', '-s', '-t', '-u', '-v', '-w' ] }"
, LetStatement
}
, LetStatement { letLexpr = "s:executables" , letValue = "{" }
, GenericStatement
- "\\ 'rg': 'rg --vimgrep --no-heading', 'ag': 'ag', 'ack': 'ack --column --with-filename', 'ack-grep': 'ack-grep --column --with-filename' }"
+ "\\ 'rg': '--vimgrep --no-config --no-heading', 'ag': '', 'ack': '--column --with-filename', 'ack-grep': '--column --with-filename' }"
, LetStatement { letLexpr = "s:init_done" , letValue = "0" }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#executables"
+ , functionArguments = ArgumentList []
+ , functionAttributes = [ "abort" ]
+ , functionBody = [ GenericStatement "return copy(s:executables)" ]
+ }
, FunctionDeclaration
{ functionBang = True
, functionName = "ferret#private#init"
{ letLexpr = "l:ag_help" , letValue = "system('ag --help')" }
, GenericStatement "if match(l:ag_help, '--vimgrep') != -1"
, LetStatement
- { letLexpr = "s:executables['ag']." , letValue = "' --vimgrep'" }
+ { letLexpr = "s:executables['ag']." , letValue = "'--vimgrep'" }
, GenericStatement "else"
, LetStatement
- { letLexpr = "s:executables['ag']." , letValue = "' --column'" }
+ { letLexpr = "s:executables['ag']." , letValue = "'--column'" }
, GenericStatement "endif"
, GenericStatement "if match(l:ag_help, '--width') != -1"
, LetStatement
, GenericStatement "endif"
, GenericStatement "for l:executable in l:executables"
, GenericStatement "if executable(l:executable)"
- , GenericStatement "return s:executables[l:executable]"
+ , Empty
+ , LetStatement
+ { letLexpr = "l:overrides"
+ , letValue = "get(g:, 'FerretExecutableArguments', {})"
+ }
+ , LetStatement
+ { letLexpr = "l:type"
+ , letValue = "exists('v:t_dict') ? v:t_dict : 4"
+ }
+ , GenericStatement
+ "if type(l:overrides) == l:type && has_key(l:overrides, l:executable)"
+ , GenericStatement
+ "return l:executable . ' ' . l:overrides[l:executable]"
+ , GenericStatement "else"
+ , GenericStatement
+ "return l:executable . ' ' . s:executables[l:executable]"
+ , GenericStatement "endif"
, GenericStatement "endif"
, GenericStatement "endfor"
, GenericStatement "return ''"
]
}
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#limit"
+ , functionArguments = ArgumentList []
+ , functionAttributes = [ "abort" ]
+ , functionBody =
+ [ Empty
+ , GenericStatement
+ "return max([1, +get(g:, 'FerretMaxResults', 100000)]) - 1"
+ ]
+ }
, GenericStatement "call ferret#private#init()"
]
, Unit
]
}
, LetStatement
- { letLexpr = "s:limit"
- , letValue = "max([1, +get(g:, 'FerretMaxResults', 100000)]) - 1"
- }
+ { letLexpr = "s:limit" , letValue = "ferret#private#limit()" }
, FunctionDeclaration
{ functionBang = True
, functionName = "ferret#private#async#out_cb"
}
]
, Unit
- [ FunctionDeclaration
+ [ LetStatement { letLexpr = "s:jobs" , letValue = "{}" }
+ , FunctionDeclaration
{ functionBang = True
- , functionName = "ferret#private#shared#finalize_search"
- , functionArguments =
- ArgumentList [ Argument "output" , Argument "ack" ]
+ , functionName = "s:info_from_job"
+ , functionArguments = ArgumentList [ Argument "job" ]
, functionAttributes = []
, functionBody =
- [ LetStatement
- { letLexpr = "l:original_errorformat" , letValue = "&errorformat" }
- , GenericStatement "try"
- , LetStatement
- { letLexpr = "&errorformat" , letValue = "g:FerretFormat" }
- , GenericStatement "if a:ack"
- , GenericStatement "call s:swallow('cexpr a:1', a:output)"
- , GenericStatement
- "execute get(g:, 'FerretQFHandler', 'botright cwindow')"
- , GenericStatement "call ferret#private#post('qf')"
- , GenericStatement "else"
- , GenericStatement "call s:swallow('lexpr a:1', a:output)"
- , GenericStatement "execute get(g:, 'FerretLLHandler', 'lwindow')"
- , GenericStatement "call ferret#private#post('location')"
+ [ GenericStatement "if has_key(s:jobs, a:job)"
+ , GenericStatement "return s:jobs[a:job]"
, GenericStatement "endif"
- , GenericStatement "finally"
- , LetStatement
- { letLexpr = "&errorformat" , letValue = "l:original_errorformat" }
- , GenericStatement "endtry"
]
}
, FunctionDeclaration
{ functionBang = True
- , functionName = "s:swallow"
- , functionArguments =
- ArgumentList [ Argument "executable" , Argument "..." ]
- , functionAttributes = []
- , functionBody =
- [ GenericStatement "try"
- , GenericStatement "execute a:executable"
- , GenericStatement "catch"
- , GenericStatement "echomsg 'Caught: ' . v:exception"
- , GenericStatement "endtry"
- ]
- }
- ]
- , Unit
- [ FunctionDeclaration
- { functionBang = True
- , functionName = "ferret#private#vanilla#search"
+ , functionName = "ferret#private#nvim#search"
, functionArguments =
- ArgumentList [ Argument "command" , Argument "ack" ]
+ ArgumentList
+ [ Argument "command" , Argument "ack" , Argument "bang" ]
, functionAttributes = [ "abort" ]
, functionBody =
- [ LetStatement
- { letLexpr = "l:executable"
- , letValue = "ferret#private#executable()"
+ [ GenericStatement "call ferret#private#nvim#cancel()"
+ , GenericStatement
+ "call ferret#private#autocmd('FerretAsyncStart')"
+ , LetStatement
+ { letLexpr = "l:command_and_args"
+ , letValue =
+ "extend(split(ferret#private#executable()), a:command)"
}
, LetStatement
- { letLexpr = "l:output"
- , letValue = "system(l:executable . ' ' . a:command)"
+ { letLexpr = "l:job"
+ , letValue = "jobstart(l:command_and_args, {"
}
, GenericStatement
- "call ferret#private#shared#finalize_search(l:output, a:ack)"
+ "\\ 'on_stderr': 'ferret#private#nvim#err_cb', 'on_stdout': 'ferret#private#nvim#out_cb', 'on_exit': 'ferret#private#nvim#close_cb' })"
+ , LetStatement { letLexpr = "s:jobs[l:job]" , letValue = "{" }
+ , GenericStatement
+ "\\ 'job': l:job, 'errors': [], 'output': [], 'pending_error': '', 'pending_output': '', 'pending_error_length': 0, 'pending_output_length': 0, 'result_count': 0, 'ack': a:ack, 'bang': a:bang, 'window': win_getid() }"
]
}
- ]
- , Unit
- [ LetStatement
- { letLexpr = "s:options"
- , letValue = "get(g:, 'FerretQFOptions', 1)"
- }
- , GenericStatement "if s:options"
- , GenericStatement "setlocal nolist"
- , GenericStatement "if exists('+relativenumber')"
- , GenericStatement "setlocal norelativenumber"
- , GenericStatement "endif"
- , GenericStatement "setlocal nowrap"
- , GenericStatement "setlocal number"
- , LetStatement
- { letLexpr = "s:original_scrolloff" , letValue = "&scrolloff" }
- , GenericStatement "set scrolloff=0"
- , GenericStatement "if has('autocmd')"
- , GenericStatement "augroup FerretQF"
- , GenericStatement "autocmd!"
- , GenericStatement
- "autocmd BufLeave <buffer> execute 'set scrolloff=' . s:original_scrolloff"
- , GenericStatement
- "autocmd BufEnter <buffer> set scrolloff=0 | setlocal nocursorline"
- , GenericStatement "augroup END"
- , GenericStatement "endif"
- , GenericStatement "endif"
, LetStatement
- { letLexpr = "s:map" , letValue = "get(g:, 'FerretQFMap', 1)" }
- , GenericStatement "if s:map"
- , GenericStatement
- "nnoremap <buffer> <silent> d :set operatorfunc=ferret#private#qf_delete_motion<CR>g@"
- , GenericStatement
- "nnoremap <buffer> <silent> dd :call ferret#private#qf_delete()<CR>"
+ { letLexpr = "s:max_line_length" , letValue = "4096" }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#nvim#err_cb"
+ , functionArguments =
+ ArgumentList
+ [ Argument "job" , Argument "lines" , Argument "event" ]
+ , functionAttributes = [ "dict" ]
+ , functionBody =
+ [ LetStatement
+ { letLexpr = "l:info" , letValue = "s:info_from_job(a:job)" }
+ , GenericStatement "if type(l:info) == 4"
+ , LetStatement { letLexpr = "l:count" , letValue = "len(a:lines)" }
+ , GenericStatement "for l:i in range(l:count)"
+ , LetStatement { letLexpr = "l:line" , letValue = "a:lines[l:i]" }
+ , GenericStatement
+ "if l:i != l:count - 1 || l:line == '' && l:info.pending_error_length"
+ , GenericStatement
+ "if l:info.pending_error_length < s:max_line_length"
+ , LetStatement { letLexpr = "l:rest" , letValue = "strpart(" }
+ , GenericStatement
+ "\\ l:line, 0, s:max_line_length - l:info.pending_error_length )"
+ , GenericStatement
+ "call add(l:info.errors, l:info.pending_error . l:rest)"
+ , GenericStatement "else"
+ , GenericStatement "call add(l:info.errors, l:info.pending_error)"
+ , GenericStatement "endif"
+ , LetStatement
+ { letLexpr = "l:info.pending_error" , letValue = "''" }
+ , LetStatement
+ { letLexpr = "l:info.pending_error_length" , letValue = "0" }
+ , GenericStatement
+ "elseif l:info.pending_error_length < s:max_line_length"
+ , LetStatement
+ { letLexpr = "l:info.pending_error." , letValue = "l:line" }
+ , LetStatement
+ { letLexpr = "l:info.pending_error_length+"
+ , letValue = "strlen(l:line)"
+ }
+ , GenericStatement "endif"
+ , GenericStatement "endfor"
+ , GenericStatement "endif"
+ ]
+ }
+ , LetStatement
+ { letLexpr = "s:limit" , letValue = "ferret#private#limit()" }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#nvim#out_cb"
+ , functionArguments =
+ ArgumentList
+ [ Argument "job" , Argument "lines" , Argument "event" ]
+ , functionAttributes = [ "dict" ]
+ , functionBody =
+ [ LetStatement
+ { letLexpr = "l:info" , letValue = "s:info_from_job(a:job)" }
+ , GenericStatement "if type(l:info) == 4"
+ , GenericStatement
+ "if !l:info.bang && l:info.result_count > s:limit"
+ , GenericStatement "call s:MaxResultsExceeded(l:info)"
+ , GenericStatement "return"
+ , GenericStatement "endif"
+ , LetStatement { letLexpr = "l:count" , letValue = "len(a:lines)" }
+ , GenericStatement "for l:i in range(l:count)"
+ , LetStatement { letLexpr = "l:line" , letValue = "a:lines[l:i]" }
+ , GenericStatement
+ "if l:i != l:count - 1 || l:line == '' && l:info.pending_output_length"
+ , GenericStatement
+ "if l:info.pending_output_length < s:max_line_length"
+ , LetStatement { letLexpr = "l:rest" , letValue = "strpart(" }
+ , GenericStatement
+ "\\ l:line, 0, s:max_line_length - l:info.pending_output_length )"
+ , GenericStatement
+ "call add(l:info.output, l:info.pending_output . l:rest)"
+ , GenericStatement "else"
+ , GenericStatement "call add(l:info.output, l:info.pending_output)"
+ , GenericStatement "endif"
+ , LetStatement
+ { letLexpr = "l:info.pending_output" , letValue = "''" }
+ , LetStatement
+ { letLexpr = "l:info.pending_output_length" , letValue = "0" }
+ , GenericStatement "if !l:info.bang"
+ , LetStatement
+ { letLexpr = "l:info.result_count+" , letValue = "1" }
+ , GenericStatement "if l:info.result_count > s:limit"
+ , GenericStatement "call s:MaxResultsExceeded(l:info)"
+ , GenericStatement "break"
+ , GenericStatement "endif"
+ , GenericStatement "endif"
+ , GenericStatement
+ "elseif l:info.pending_output_length < s:max_line_length"
+ , LetStatement
+ { letLexpr = "l:info.pending_output." , letValue = "l:line" }
+ , LetStatement
+ { letLexpr = "l:info.pending_output_length+"
+ , letValue = "strlen(l:line)"
+ }
+ , GenericStatement "endif"
+ , GenericStatement "endfor"
+ , GenericStatement "endif"
+ ]
+ }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#nvim#close_cb"
+ , functionArguments =
+ ArgumentList
+ [ Argument "job" , Argument "data" , Argument "event" ]
+ , functionAttributes = [ "abort" , "dict" ]
+ , functionBody =
+ [ LetStatement
+ { letLexpr = "l:info" , letValue = "s:info_from_job(a:job)" }
+ , GenericStatement "if type(l:info) == 4"
+ , GenericStatement "call remove(s:jobs, a:job)"
+ , GenericStatement
+ "call ferret#private#autocmd('FerretAsyncFinish')"
+ , GenericStatement "if !l:info.ack"
+ , GenericStatement "call win_gotoid(l:info.window)"
+ , GenericStatement "endif"
+ , GenericStatement
+ "call ferret#private#shared#finalize_search(l:info.output, l:info.ack)"
+ , GenericStatement "for l:error in l:info.errors"
+ , GenericStatement "unsilent echomsg l:error"
+ , GenericStatement "endfor"
+ , GenericStatement "endif"
+ ]
+ }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#nvim#pull"
+ , functionArguments = ArgumentList []
+ , functionAttributes = [ "abort" ]
+ , functionBody =
+ [ GenericStatement "for l:job in keys(s:jobs)"
+ , LetStatement { letLexpr = "l:info" , letValue = "s:jobs[l:job]" }
+ , GenericStatement
+ "call ferret#private#shared#finalize_search(l:info.output, l:info.ack)"
+ , GenericStatement "endfor"
+ ]
+ }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#nvim#cancel"
+ , functionArguments = ArgumentList []
+ , functionAttributes = [ "abort" ]
+ , functionBody =
+ [ LetStatement { letLexpr = "l:canceled" , letValue = "0" }
+ , GenericStatement "for l:job in keys(s:jobs)"
+ , GenericStatement "call jobstop(l:job)"
+ , GenericStatement "call remove(s:jobs, l:job)"
+ , LetStatement { letLexpr = "l:canceled" , letValue = "1" }
+ , GenericStatement "endfor"
+ , GenericStatement "if l:canceled"
+ , GenericStatement
+ "call ferret#private#autocmd('FerretAsyncFinish')"
+ , GenericStatement "endif"
+ ]
+ }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "s:MaxResultsExceeded"
+ , functionArguments = ArgumentList [ Argument "info" ]
+ , functionAttributes = []
+ , functionBody =
+ [ GenericStatement
+ "call ferret#private#shared#finalize_search(a:info.output, a:info.ack)"
+ , GenericStatement "call jobstop(a:info.job)"
+ , GenericStatement "call remove(s:jobs, a:info.job)"
+ , GenericStatement
+ "call ferret#private#autocmd('FerretAsyncFinish')"
+ , GenericStatement
+ "call ferret#private#error( 'Maximum result count exceeded. ' . 'Either increase g:FerretMaxResults or ' . 're-run the search with :Ack!, :Lack! etc.' )"
+ ]
+ }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#nvim#debug"
+ , functionArguments = ArgumentList []
+ , functionAttributes = [ "abort" ]
+ , functionBody = [ GenericStatement "return s:jobs" ]
+ }
+ ]
+ , Unit
+ [ FunctionDeclaration
+ { functionBang = True
+ , functionName = "s:autojump"
+ , functionArguments = ArgumentList []
+ , functionAttributes = []
+ , functionBody =
+ [ LetStatement
+ { letLexpr = "l:autojump"
+ , letValue = "get(g:, 'FerretAutojump', 1)"
+ }
+ , GenericStatement
+ "if l:autojump != 0 && l:autojump != 1 && l:autojump != 2"
+ , LetStatement { letLexpr = "l:autojump" , letValue = "1" }
+ , GenericStatement "endif"
+ , GenericStatement "return l:autojump"
+ ]
+ }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "s:set_title"
+ , functionArguments =
+ ArgumentList [ Argument "type" , Argument "title" ]
+ , functionAttributes = []
+ , functionBody =
+ [ GenericStatement "if has('patch-7.4.2200')"
+ , GenericStatement "if a:type ==# 'qf'"
+ , GenericStatement "call setqflist([], 'a', {'title' : a:title})"
+ , GenericStatement "else"
+ , GenericStatement
+ "call setloclist(0, [], 'a', {'title' : a:title})"
+ , GenericStatement "endif"
+ , GenericStatement "elseif a:type ==# 'qf'"
+ , LetStatement
+ { letLexpr = "w:quickfix_title" , letValue = "a:title" }
+ , GenericStatement "endif"
+ ]
+ }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#shared#finalize_search"
+ , functionArguments =
+ ArgumentList [ Argument "output" , Argument "ack" ]
+ , functionAttributes = []
+ , functionBody =
+ [ LetStatement
+ { letLexpr = "l:lastsearch "
+ , letValue = "get(g:, 'ferret_lastsearch', '')"
+ }
+ , LetStatement
+ { letLexpr = "l:original_errorformat" , letValue = "&errorformat" }
+ , LetStatement
+ { letLexpr = "l:autojump" , letValue = "s:autojump()" }
+ , GenericStatement "if a:ack"
+ , LetStatement
+ { letLexpr = "l:prefix"
+ , letValue = "'c' \" Will use cexpr, cgetexpr."
+ }
+ , LetStatement
+ { letLexpr = "l:handler"
+ , letValue = "get(g:, 'FerretQFHandler', 'botright copen')"
+ }
+ , LetStatement { letLexpr = "l:post" , letValue = "'qf'" }
+ , GenericStatement "else"
+ , LetStatement
+ { letLexpr = "l:prefix"
+ , letValue = "'l' \" Will use lexpr, lgetexpr."
+ }
+ , LetStatement
+ { letLexpr = "l:handler"
+ , letValue = "get(g:, 'FerretLLHandler', 'lopen')"
+ }
+ , LetStatement { letLexpr = "l:post" , letValue = "'location'" }
+ , GenericStatement "endif"
+ , GenericStatement "try"
+ , LetStatement
+ { letLexpr = "&errorformat" , letValue = "g:FerretFormat" }
+ , GenericStatement
+ "if l:autojump == 2 \" Show listing and jump to first result."
+ , GenericStatement
+ "call s:swallow(l:prefix . 'expr a:1', a:output)"
+ , GenericStatement "else"
+ , GenericStatement
+ "call s:swallow(l:prefix . 'getexpr a:1', a:output)"
+ , GenericStatement "endif"
+ , GenericStatement
+ "call s:set_title(l:post, 'Search `' . l:lastsearch . '`')"
+ , LetStatement { letLexpr = "l:before" , letValue = "winnr()" }
+ , LetStatement
+ { letLexpr = "l:len" , letValue = "ferret#private#post(l:post)" }
+ , GenericStatement "if l:len"
+ , GenericStatement "execute l:handler"
+ , GenericStatement
+ "if l:autojump != 1 \" Show listing, but don't jump anywhere."
+ , LetStatement { letLexpr = "l:after" , letValue = "winnr()" }
+ , GenericStatement "if l:before != l:after"
+ , GenericStatement "execute l:before . 'wincmd w'"
+ , GenericStatement "end"
+ , GenericStatement "endif"
+ , GenericStatement "endif"
+ , GenericStatement "finally"
+ , LetStatement
+ { letLexpr = "&errorformat" , letValue = "l:original_errorformat" }
+ , GenericStatement "endtry"
+ ]
+ }
+ , FunctionDeclaration
+ { functionBang = True
+ , functionName = "s:swallow"
+ , functionArguments =
+ ArgumentList [ Argument "executable" , Argument "..." ]
+ , functionAttributes = []
+ , functionBody =
+ [ GenericStatement "try"
+ , GenericStatement "execute a:executable"
+ , GenericStatement "catch"
+ , GenericStatement "echomsg 'Caught: ' . v:exception"
+ , GenericStatement "endtry"
+ ]
+ }
+ ]
+ , Unit
+ [ FunctionDeclaration
+ { functionBang = True
+ , functionName = "ferret#private#vanilla#search"
+ , functionArguments =
+ ArgumentList [ Argument "command" , Argument "ack" ]
+ , functionAttributes = [ "abort" ]
+ , functionBody =
+ [ LetStatement
+ { letLexpr = "l:executable"
+ , letValue = "ferret#private#executable()"
+ }
+ , LetStatement
+ { letLexpr = "l:output"
+ , letValue = "system(l:executable . ' ' . a:command)"
+ }
+ , GenericStatement
+ "call ferret#private#shared#finalize_search(l:output, a:ack)"
+ ]
+ }
+ ]
+ , Unit
+ [ LetStatement
+ { letLexpr = "s:options"
+ , letValue = "get(g:, 'FerretQFOptions', 1)"
+ }
+ , GenericStatement "if s:options"
+ , GenericStatement "setlocal nolist"
+ , GenericStatement "if exists('+relativenumber')"
+ , GenericStatement "setlocal norelativenumber"
+ , GenericStatement "endif"
+ , GenericStatement "setlocal nowrap"
+ , GenericStatement "setlocal number"
+ , LetStatement
+ { letLexpr = "s:original_scrolloff" , letValue = "&scrolloff" }
+ , GenericStatement "set scrolloff=0"
+ , GenericStatement "if has('autocmd')"
+ , GenericStatement "augroup FerretQF"
+ , GenericStatement "autocmd!"
+ , GenericStatement
+ "autocmd BufLeave <buffer> execute 'set scrolloff=' . s:original_scrolloff"
+ , GenericStatement
+ "autocmd BufEnter <buffer> set scrolloff=0 | setlocal nocursorline"
+ , GenericStatement "augroup END"
+ , GenericStatement "endif"
+ , GenericStatement "endif"
+ , LetStatement
+ { letLexpr = "s:map" , letValue = "get(g:, 'FerretQFMap', 1)" }
+ , GenericStatement "if s:map"
+ , GenericStatement
+ "nnoremap <buffer> <silent> d :set operatorfunc=ferret#private#qf_delete_motion<CR>g@"
+ , GenericStatement
+ "nnoremap <buffer> <silent> dd :call ferret#private#qf_delete()<CR>"
, GenericStatement
"vnoremap <buffer> <silent> d :call ferret#private#qf_delete()<CR>"
, GenericStatement "endif"
, GenericStatement "call ferret#private#init()"
, GenericStatement "endif"
, GenericStatement
- "command! -bang -nargs=+ -complete=customlist,ferret#private#ackcomplete Ack call ferret#private#ack(<bang>0, <f-args>)"
+ "command! -bang -nargs=1 -complete=customlist,ferret#private#ackcomplete Ack call ferret#private#ack(<bang>0, <q-args>)"
, GenericStatement
- "command! -bang -nargs=+ -complete=customlist,ferret#private#lackcomplete Lack call ferret#private#lack(<bang>0, <f-args>)"
+ "command! -bang -nargs=1 -complete=customlist,ferret#private#lackcomplete Lack call ferret#private#lack(<bang>0, <q-args>)"
, GenericStatement
- "command! -bang -nargs=+ -complete=customlist,ferret#private#backcomplete Back call ferret#private#back(<bang>0, <f-args>)"
+ "command! -bang -nargs=1 -complete=customlist,ferret#private#backcomplete Back call ferret#private#back(<bang>0, <q-args>)"
, GenericStatement
- "command! -bang -nargs=+ -complete=customlist,ferret#private#blackcomplete Black call ferret#private#black(<bang>0, <f-args>)"
+ "command! -bang -nargs=1 -complete=customlist,ferret#private#blackcomplete Black call ferret#private#black(<bang>0, <q-args>)"
, GenericStatement
"command! -nargs=1 Acks call ferret#private#acks(<q-args>)"
, GenericStatement
, Whitespace
, Plaintext "UI."
]
- , Paragraph
- [ Plaintext "On"
- , Whitespace
- , Plaintext "older"
- , Whitespace
- , Plaintext "Vim"
- , Whitespace
- , Plaintext "versions"
- , Whitespace
- , Plaintext "(prior"
- , Whitespace
- , Plaintext "to"
- , Whitespace
- , Plaintext "version"
- , Whitespace
- , Plaintext "8),"
- , Whitespace
- , Plaintext "if"
- , Whitespace
- , Plaintext "dispatch.vim"
- , Whitespace
- , Plaintext "is"
- , Whitespace
- , Plaintext "installed"
- , Whitespace
- , Plaintext "the"
- , Whitespace
- , Plaintext "search"
- , Whitespace
- , Plaintext "process"
- , Whitespace
- , Plaintext "will"
- , Whitespace
- , Plaintext "run"
- , Whitespace
- , Plaintext "asynchronously"
- , Whitespace
- , Plaintext "via"
- , Whitespace
- , Plaintext "the"
- , Whitespace
- , Link ":Make"
- , Whitespace
- , Plaintext "command,"
- , Whitespace
- , Plaintext "otherwise"
- , Whitespace
- , Plaintext "it"
- , Whitespace
- , Plaintext "will"
- , Whitespace
- , Plaintext "be"
- , Whitespace
- , Plaintext "run"
- , Whitespace
- , Plaintext "synchronously"
- , Whitespace
- , Plaintext "via"
- , Whitespace
- , Link ":cexpr"
- , Plaintext "."
- , Whitespace
- , Plaintext "The"
- , Whitespace
- , Link "g:FerretDispatch"
- , Whitespace
- , Plaintext "option"
- , Whitespace
- , Plaintext "can"
- , Whitespace
- , Plaintext "be"
- , Whitespace
- , Plaintext "used"
- , Whitespace
- , Plaintext "to"
- , Whitespace
- , Plaintext "prevent"
- , Whitespace
- , Plaintext "the"
- , Whitespace
- , Plaintext "use"
- , Whitespace
- , Plaintext "of"
- , Whitespace
- , Plaintext "dispatch.vim."
- ]
, Paragraph
[ Plaintext "Asynchronous"
, Whitespace
, Plaintext "\"bar\""
, Whitespace
, Plaintext "subdirectories:"
- , Whitespace
- , Plaintext ">"
]
, Fenced [ ":Ack -w something foo bar" ]
, Paragraph
, Plaintext "via"
, Whitespace
, Link ":cexpr"
- , Plaintext ","
- , Whitespace
- , Plaintext "because"
- , Whitespace
- , Plaintext "dispatch.vim"
- , Whitespace
- , Plaintext "doesn't"
- , Whitespace
- , Plaintext "currently"
- , Whitespace
- , Plaintext "support"
- , Whitespace
- , Plaintext "the"
- , Whitespace
- , Link "location-list"
, Plaintext "."
]
, CommandAnnotation "Lack!" (Just "{pattern} {options}")
, Whitespace
, Plaintext "(mnemonic:"
, Whitespace
- , Plaintext "\"Ack"
+ , Plaintext "\"Ack"
+ , Whitespace
+ , Plaintext "substitute\")"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "perform"
+ , Whitespace
+ , Plaintext "replacements."
+ , Whitespace
+ , Plaintext "For"
+ , Whitespace
+ , Plaintext "example,"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "replace"
+ , Whitespace
+ , Plaintext "\"foo\""
+ , Whitespace
+ , Plaintext "with"
+ , Whitespace
+ , Plaintext "\"bar\""
+ , Whitespace
+ , Plaintext "across"
+ , Whitespace
+ , Plaintext "all"
+ , Whitespace
+ , Plaintext "files"
+ , Whitespace
+ , Plaintext "in"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "current"
+ , Whitespace
+ , Plaintext "directory:"
+ ]
+ , Fenced [ ":Ack foo" , ":Acks /foo/bar/" ]
+ , Paragraph
+ [ Plaintext "The"
+ , Whitespace
+ , Plaintext "pattern"
+ , Whitespace
+ , Plaintext "and"
+ , Whitespace
+ , Plaintext "replacement"
+ , Whitespace
+ , Plaintext "are"
+ , Whitespace
+ , Plaintext "passed"
+ , Whitespace
+ , Plaintext "through"
+ , Whitespace
+ , Plaintext "literally"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "Vim's"
+ , Whitespace
+ , Link ":substitute"
+ , Whitespace
+ , Plaintext "command,"
+ , Whitespace
+ , Plaintext "preserving"
+ , Whitespace
+ , Plaintext "all"
+ , Whitespace
+ , Plaintext "characters"
+ , Whitespace
+ , Plaintext "and"
+ , Whitespace
+ , Plaintext "escapes,"
+ , Whitespace
+ , Plaintext "including"
, Whitespace
- , Plaintext "substitute\")"
+ , Plaintext "references"
, Whitespace
, Plaintext "to"
, Whitespace
- , Plaintext "perform"
+ , Plaintext "matches"
, Whitespace
- , Plaintext "replacements."
+ , Plaintext "in"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "pattern."
, Whitespace
, Plaintext "For"
, Whitespace
, Plaintext "example,"
, Whitespace
- , Plaintext "to"
+ , Plaintext "the"
, Whitespace
- , Plaintext "replace"
+ , Plaintext "following"
, Whitespace
- , Plaintext "\"foo\""
+ , Plaintext "could"
, Whitespace
- , Plaintext "with"
+ , Plaintext "be"
, Whitespace
- , Plaintext "\"bar\""
+ , Plaintext "used"
, Whitespace
- , Plaintext "across"
+ , Plaintext "to"
, Whitespace
- , Plaintext "all"
+ , Plaintext "swap"
, Whitespace
- , Plaintext "files"
+ , Plaintext "the"
, Whitespace
- , Plaintext "in"
+ , Plaintext "order"
, Whitespace
- , Plaintext "the"
+ , Plaintext "of"
, Whitespace
- , Plaintext "current"
+ , Plaintext "\"foo123\""
, Whitespace
- , Plaintext "directory:"
+ , Plaintext "and"
+ , Whitespace
+ , Plaintext "\"bar\":"
]
- , Fenced [ ":Ack foo" , ":Acks /foo/bar/" ]
+ , Fenced [ ":Acks /\\v(foo\\d+)(bar)/\\2\\1/" ]
, CommandAnnotation "Qargs" Nothing
, Paragraph
[ Plaintext "This"
, Whitespace
, Plaintext "mapping"
, Whitespace
- , Plaintext "for"
+ , Plaintext "with"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "same"
+ , Whitespace
+ , Link "{lhs}"
, Whitespace
, Plaintext "already"
, Whitespace
, Whitespace
, Plaintext "to"
, Whitespace
- , Plaintext "1"
+ , Plaintext "0"
, Whitespace
, Plaintext "in"
, Whitespace
, "nmap <leader>u <Plug>(FerretAcks)"
]
, OptionsAnnotation
- , OptionAnnotation "g:FerretDispatch" "boolean" (Just "1")
+ , OptionAnnotation "g:FerretNvim" "boolean" (Just "1")
, Paragraph
[ Plaintext "Controls"
, Whitespace
, Whitespace
, Plaintext "use"
, Whitespace
- , Plaintext "vim-dispatch"
+ , Plaintext "Neovim's"
, Whitespace
- , Plaintext "(and"
+ , Link "job-control"
, Whitespace
- , Plaintext "specifically,"
+ , Plaintext "features,"
, Whitespace
- , Link ":Make"
- , Plaintext ")"
+ , Plaintext "when"
+ , Whitespace
+ , Plaintext "available,"
, Whitespace
, Plaintext "to"
, Whitespace
, Plaintext "run"
, Whitespace
- , Link ":Ack"
- , Whitespace
, Plaintext "searches"
, Whitespace
- , Plaintext "asynchronously,"
- , Whitespace
- , Plaintext "when"
- , Whitespace
- , Plaintext "available."
+ , Plaintext "asynchronously."
, Whitespace
, Plaintext "To"
, Whitespace
, Plaintext "prevent"
, Whitespace
- , Plaintext "vim-dispatch"
+ , Plaintext "this"
, Whitespace
, Plaintext "from"
, Whitespace
, Whitespace
, Plaintext "to"
, Whitespace
- , Plaintext "0:"
- ]
- , Fenced [ "let g:FerretDispatch=0" ]
- , Paragraph
- [ Plaintext "Note"
+ , Plaintext "0,"
, Whitespace
- , Plaintext "that"
+ , Plaintext "in"
, Whitespace
- , Plaintext "on"
+ , Plaintext "which"
, Whitespace
- , Plaintext "sufficiently"
+ , Plaintext "case"
, Whitespace
- , Plaintext "recent"
+ , Plaintext "Ferret"
, Whitespace
- , Plaintext "versions"
+ , Plaintext "will"
, Whitespace
- , Plaintext "of"
+ , Plaintext "fall"
, Whitespace
- , Plaintext "Vim"
+ , Plaintext "back"
, Whitespace
- , Plaintext "with"
+ , Plaintext "to"
, Whitespace
- , Link "+job"
+ , Plaintext "the"
, Whitespace
- , Plaintext "support,"
+ , Plaintext "next"
, Whitespace
- , Plaintext "Ferret"
+ , Plaintext "method"
, Whitespace
- , Plaintext "will"
+ , Plaintext "in"
, Whitespace
- , Plaintext "first"
+ , Plaintext "the"
, Whitespace
- , Plaintext "try"
+ , Plaintext "list"
, Whitespace
- , Plaintext "to"
+ , Plaintext "(Vim's"
, Whitespace
- , Plaintext "use"
+ , Plaintext "built-in"
, Whitespace
- , Link "+job"
- , Plaintext ","
+ , Plaintext "async"
, Whitespace
- , Plaintext "falling"
+ , Plaintext "primitives"
, Whitespace
- , Plaintext "back"
+ , Plaintext "--"
, Whitespace
- , Plaintext "to"
+ , Plaintext "see"
, Whitespace
- , Plaintext "vim-dispatch"
+ , Link "g:FerretJob"
, Whitespace
- , Plaintext "and"
+ , Plaintext "--"
, Whitespace
- , Plaintext "consulting"
+ , Plaintext "which"
, Whitespace
- , Link "g:FerretDispatch"
+ , Plaintext "are"
, Whitespace
- , Plaintext "only"
+ , Plaintext "typically"
, Whitespace
- , Plaintext "if"
+ , Plaintext "not"
, Whitespace
- , Link "g:FerretJob"
+ , Plaintext "available"
, Whitespace
- , Plaintext "is"
+ , Plaintext "in"
, Whitespace
- , Plaintext "set"
+ , Plaintext "Neovim,"
+ , Whitespace
+ , Plaintext "so"
+ , Whitespace
+ , Plaintext "will"
+ , Whitespace
+ , Plaintext "then"
+ , Whitespace
+ , Plaintext "fall"
+ , Whitespace
+ , Plaintext "back"
, Whitespace
, Plaintext "to"
, Whitespace
- , Plaintext "0."
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "next"
+ , Whitespace
+ , Plaintext "available"
+ , Whitespace
+ , Plaintext "method)."
]
+ , Fenced [ "let g:FerretNvim=0" ]
, OptionAnnotation "g:FerretJob" "boolean" (Just "1")
, Paragraph
[ Plaintext "Controls"
, Whitespace
, Plaintext "to"
, Whitespace
- , Plaintext "vim-dispatch"
+ , Plaintext "the"
, Whitespace
- , Plaintext "(see"
+ , Plaintext "next"
, Whitespace
- , Plaintext "also:"
+ , Plaintext "available"
, Whitespace
- , Link "g:FerretDispatch"
- , Plaintext "):"
+ , Plaintext "method."
]
, Fenced [ "let g:FerretJob=0" ]
, OptionAnnotation "g:FerretHlsearch" "boolean" Nothing
, Paragraph [ Plaintext "Example:" ]
, Fenced
[ "\" Prefer `ag` over `rg`." , "let g:FerretExecutable='ag,rg'" ]
+ , OptionAnnotation "g:FerretExecutableArguments" "dict" (Just "{}")
+ , Paragraph
+ [ Plaintext "Allows"
+ , Whitespace
+ , Plaintext "you"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "override"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "default"
+ , Whitespace
+ , Plaintext "arguments"
+ , Whitespace
+ , Plaintext "that"
+ , Whitespace
+ , Plaintext "get"
+ , Whitespace
+ , Plaintext "passed"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "underlying"
+ , Whitespace
+ , Plaintext "search"
+ , Whitespace
+ , Plaintext "executables."
+ , Whitespace
+ , Plaintext "For"
+ , Whitespace
+ , Plaintext "example,"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "add"
+ , Whitespace
+ , Code "-s"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "default"
+ , Whitespace
+ , Plaintext "arguments"
+ , Whitespace
+ , Plaintext "passed"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Code "ack"
+ , Whitespace
+ , Plaintext "("
+ , Code "--column --with-filename"
+ , Plaintext "):"
+ ]
+ , Fenced
+ [ "let g:FerretExecutableArguments = {"
+ , " \\ 'ack': '--column --with-filename -s'"
+ , " \\ }"
+ ]
+ , Paragraph
+ [ Plaintext "To"
+ , Whitespace
+ , Plaintext "find"
+ , Whitespace
+ , Plaintext "out"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "default"
+ , Whitespace
+ , Plaintext "arguments"
+ , Whitespace
+ , Plaintext "for"
+ , Whitespace
+ , Plaintext "a"
+ , Whitespace
+ , Plaintext "given"
+ , Whitespace
+ , Plaintext "executable,"
+ , Whitespace
+ , Plaintext "see"
+ , Whitespace
+ , Link "ferret#get_default_arguments()"
+ , Plaintext "."
+ ]
, OptionAnnotation "g:FerretMaxResults" "number" (Just "100000")
, Paragraph
[ Plaintext "Controls"
, Whitespace
, Plaintext "limit."
]
+ , OptionAnnotation "g:FerretAutojump" "number" (Just "1")
+ , Paragraph
+ [ Plaintext "Controls"
+ , Whitespace
+ , Plaintext "whether"
+ , Whitespace
+ , Plaintext "Ferret"
+ , Whitespace
+ , Plaintext "will"
+ , Whitespace
+ , Plaintext "automatically"
+ , Whitespace
+ , Plaintext "jump"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "first"
+ , Whitespace
+ , Plaintext "found"
+ , Whitespace
+ , Plaintext "match."
+ ]
+ , List
+ [ ListItem
+ [ Plaintext "Set"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "0,"
+ , Whitespace
+ , Plaintext "Ferret"
+ , Whitespace
+ , Plaintext "will"
+ , Whitespace
+ , Plaintext "show"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "search"
+ , Whitespace
+ , Plaintext "results"
+ , Whitespace
+ , Plaintext "but"
+ , Whitespace
+ , Plaintext "perform"
+ , Whitespace
+ , Plaintext "no"
+ , Whitespace
+ , Plaintext "jump."
+ ]
+ , ListItem
+ [ Plaintext "Set"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "1"
+ , Whitespace
+ , Plaintext "(the"
+ , Whitespace
+ , Plaintext "default),"
+ , Whitespace
+ , Plaintext "Ferret"
+ , Whitespace
+ , Plaintext "will"
+ , Whitespace
+ , Plaintext "show"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "search"
+ , Whitespace
+ , Plaintext "results"
+ , Whitespace
+ , Plaintext "and"
+ , Whitespace
+ , Plaintext "focus"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "result"
+ , Whitespace
+ , Plaintext "listing."
+ ]
+ , ListItem
+ [ Plaintext "Set"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "2,"
+ , Whitespace
+ , Plaintext "Ferret"
+ , Whitespace
+ , Plaintext "will"
+ , Whitespace
+ , Plaintext "show"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "search"
+ , Whitespace
+ , Plaintext "results"
+ , Whitespace
+ , Plaintext "and"
+ , Whitespace
+ , Plaintext "jump"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "first"
+ , Whitespace
+ , Plaintext "found"
+ , Whitespace
+ , Plaintext "match."
+ ]
+ ]
+ , Paragraph
+ [ Plaintext "Example" , Whitespace , Plaintext "override:" ]
+ , Fenced [ "let g:FerretAutojump=2" ]
, OptionAnnotation "g:FerretQFOptions" "boolean" (Just "1")
, Paragraph
[ Plaintext "Controls"
, Whitespace
, Plaintext "Ferret."
]
+ , FunctionsAnnotation
+ , FunctionAnnotation "ferret#get_default_arguments"
+ , Paragraph
+ [ Plaintext "Call"
+ , Whitespace
+ , Plaintext "this"
+ , Whitespace
+ , Plaintext "with"
+ , Whitespace
+ , Plaintext "an"
+ , Whitespace
+ , Plaintext "executable"
+ , Whitespace
+ , Plaintext "name"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "find"
+ , Whitespace
+ , Plaintext "out"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "default"
+ , Whitespace
+ , Plaintext "arguments"
+ , Whitespace
+ , Plaintext "that"
+ , Whitespace
+ , Plaintext "will"
+ , Whitespace
+ , Plaintext "be"
+ , Whitespace
+ , Plaintext "passed"
+ , Whitespace
+ , Plaintext "when"
+ , Whitespace
+ , Plaintext "invoking"
+ , Whitespace
+ , Plaintext "that"
+ , Whitespace
+ , Plaintext "executable."
+ , Whitespace
+ , Plaintext "For"
+ , Whitespace
+ , Plaintext "example:"
+ ]
+ , Fenced [ "echo ferret#get_default_arguments('rg')" ]
+ , Paragraph
+ [ Plaintext "This"
+ , Whitespace
+ , Plaintext "may"
+ , Whitespace
+ , Plaintext "be"
+ , Whitespace
+ , Plaintext "useful"
+ , Whitespace
+ , Plaintext "if"
+ , Whitespace
+ , Plaintext "you"
+ , Whitespace
+ , Plaintext "wish"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "extend"
+ , Whitespace
+ , Plaintext "or"
+ , Whitespace
+ , Plaintext "otherwise"
+ , Whitespace
+ , Plaintext "modify"
+ , Whitespace
+ , Plaintext "the"
+ , Whitespace
+ , Plaintext "arguments"
+ , Whitespace
+ , Plaintext "by"
+ , Whitespace
+ , Plaintext "setting"
+ , Whitespace
+ , Link "g:FerretExecutableArguments"
+ , Plaintext "."
+ ]
, FooterAnnotation
, HeadingAnnotation "Custom autocommands"
, LinkTargets [ "FerretWillWrite" , "FerretDidWrite" ]
]
, IndentAnnotation
, LinkTargets [ "ferret-nolist" ]
- , Paragraph [ Plaintext "'nolist'" ]
+ , SubheadingAnnotation "'nolist'"
, Paragraph
[ Plaintext "Turned"
, Whitespace
, Plaintext "results."
]
, LinkTargets [ "ferret-norelativenumber" ]
- , Paragraph [ Plaintext "'norelativenumber'" ]
+ , SubheadingAnnotation "'norelativenumber'"
, Paragraph
[ Plaintext "Turned"
, Whitespace
, Plaintext "respectively)."
]
, LinkTargets [ "ferret-nowrap" ]
- , Paragraph [ Plaintext "'nowrap'" ]
+ , SubheadingAnnotation "'nowrap'"
, Paragraph
[ Plaintext "Turned"
, Whitespace
, Plaintext "wrapping."
]
, LinkTargets [ "ferret-number" ]
- , Paragraph [ Plaintext "'number'" ]
+ , SubheadingAnnotation "'number'"
, Paragraph
[ Plaintext "Turned"
, Whitespace
, Plaintext "results."
]
, LinkTargets [ "ferret-scrolloff" ]
- , Paragraph [ Plaintext "'scrolloff'" ]
+ , SubheadingAnnotation "'scrolloff'"
, Paragraph
[ Plaintext "Set"
, Whitespace
, Plaintext "edge."
]
, LinkTargets [ "ferret-nocursorline" ]
- , Paragraph [ Plaintext "'nocursorline'" ]
+ , SubheadingAnnotation "'nocursorline'"
, Paragraph
[ Plaintext "Turned"
, Whitespace
, Whitespace
, Plaintext "2009"
, Whitespace
- , Plaintext "(https://wt.pe/h)."
+ , Plaintext "(https://rfr.to/h)."
]
, Paragraph
[ Plaintext "So,"
, Whitespace
, Plaintext "<greg@hurrell.net>."
]
- , Paragraph
- [ Plaintext "The"
- , Whitespace
- , Plaintext "idea"
- , Whitespace
- , Plaintext "for"
- , Whitespace
- , Plaintext "vim-dispatch"
- , Whitespace
- , Plaintext "integration"
- , Whitespace
- , Plaintext "was"
- , Whitespace
- , Plaintext "taken"
- , Whitespace
- , Plaintext "from"
- , Whitespace
- , Plaintext "Miles"
- , Whitespace
- , Plaintext "Sterrett's"
- , Whitespace
- , Plaintext "ack.vim"
- , Whitespace
- , Plaintext "plug-in"
- , Whitespace
- , Plaintext "(https://github.com/mileszs/ack.vim)."
- ]
, Paragraph
[ Plaintext "Other"
, Whitespace
, ListItem
[ Plaintext "Filip" , Whitespace , Plaintext "Szyma\324ski" ]
, ListItem [ Plaintext "Joe" , Whitespace , Plaintext "Lencioni" ]
+ , ListItem [ Plaintext "Jon" , Whitespace , Plaintext "Parise" ]
, ListItem
[ Plaintext "Nelo-Thara" , Whitespace , Plaintext "Wallus" ]
, ListItem [ Plaintext "Tom" , Whitespace , Plaintext "Dooner" ]
]
, HeadingAnnotation "History"
, SubheadingAnnotation "master (not yet released)"
+ , List
+ [ ListItem
+ [ Plaintext "Try"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "avoid"
+ , Whitespace
+ , Plaintext "\"press"
+ , Whitespace
+ , Plaintext "ENTER"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "continue\""
+ , Whitespace
+ , Plaintext "prompts."
+ ]
+ , ListItem
+ [ Plaintext "Put"
+ , Whitespace
+ , Plaintext "search"
+ , Whitespace
+ , Plaintext "term"
+ , Whitespace
+ , Plaintext "in"
+ , Whitespace
+ , Link "w:quickfix_title"
+ , Whitespace
+ , Plaintext "for"
+ , Whitespace
+ , Plaintext "use"
+ , Whitespace
+ , Plaintext "in"
+ , Whitespace
+ , Plaintext "statuslines"
+ , Whitespace
+ , Plaintext "(https://github.com/wincent/ferret/pull/57)."
+ ]
+ , ListItem
+ [ Plaintext "Add"
+ , Whitespace
+ , Link "g:FerretExecutableArguments"
+ , Whitespace
+ , Plaintext "and"
+ , Whitespace
+ , Link "ferret#get_default_arguments()"
+ , Whitespace
+ , Plaintext "(https://github.com/wincent/ferret/pull/46)."
+ ]
+ ]
+ , SubheadingAnnotation "3.0.3 (23 March 2018)"
+ , List
+ [ ListItem
+ [ Plaintext "Fix"
+ , Whitespace
+ , Plaintext "for"
+ , Whitespace
+ , Link ":Lack"
+ , Whitespace
+ , Plaintext "results"
+ , Whitespace
+ , Plaintext "opening"
+ , Whitespace
+ , Plaintext "in"
+ , Whitespace
+ , Plaintext "quickfix"
+ , Whitespace
+ , Plaintext "listing"
+ , Whitespace
+ , Plaintext "in"
+ , Whitespace
+ , Plaintext "Neovim"
+ , Whitespace
+ , Plaintext "(https://github.com/wincent/ferret/issues/47)."
+ ]
+ ]
+ , SubheadingAnnotation "3.0.2 (25 October 2017)"
+ , List
+ [ ListItem
+ [ Plaintext "Fix"
+ , Whitespace
+ , Plaintext "broken"
+ , Whitespace
+ , Link ":Back"
+ , Whitespace
+ , Plaintext "and"
+ , Whitespace
+ , Link ":Black"
+ , Whitespace
+ , Plaintext "commands"
+ , Whitespace
+ , Plaintext "(https://github.com/wincent/ferret/issues/48)."
+ ]
+ ]
+ , SubheadingAnnotation "3.0.1 (24 August 2017)"
+ , List
+ [ ListItem
+ [ Plaintext "Fix"
+ , Whitespace
+ , Plaintext "failure"
+ , Whitespace
+ , Plaintext "to"
+ , Whitespace
+ , Plaintext "handle"
+ , Whitespace
+ , Plaintext "search"
+ , Whitespace
+ , Plaintext "patterns"
+ , Whitespace
+ , Plaintext "containing"
+ , Whitespace
+ , Plaintext "multiple"
+ , Whitespace
+ , Plaintext "escaped"
+ , Whitespace
+ , Plaintext "spaces"
+ , Whitespace
+ , Plaintext "(https://github.com/wincent/ferret/issues/49)."
+ ]
+ ]
+ , SubheadingAnnotation "3.0 (13 June 2017)"
+ , List
+ [ ListItem
+ [ Plaintext "Improve"
+ , Whitespace
+ , Plaintext "handling"
+ , Whitespace
+ , Plaintext "of"
+ , Whitespace
+ , Plaintext "backslash"
+ , Whitespace
+ , Plaintext "escapes"
+ , Whitespace
+ , Plaintext "(https://github.com/wincent/ferret/issues/41)."
+ ]
+ , ListItem
+ [ Plaintext "Add"
+ , Whitespace
+ , Link "g:FerretAutojump"
+ , Plaintext "."
+ ]
+ , ListItem
+ [ Plaintext "Drop"
+ , Whitespace
+ , Plaintext "support"
+ , Whitespace
+ , Plaintext "for"
+ , Whitespace
+ , Plaintext "vim-dispatch."
+ ]
+ ]
+ , SubheadingAnnotation "2.0 (6 June 2017)"
+ , List
+ [ ListItem
+ [ Plaintext "Add"
+ , Whitespace
+ , Plaintext "support"
+ , Whitespace
+ , Plaintext "for"
+ , Whitespace
+ , Plaintext "Neovim,"
+ , Whitespace
+ , Plaintext "along"
+ , Whitespace
+ , Plaintext "with"
+ , Whitespace
+ , Link "g:FerretNvim"
+ , Whitespace
+ , Plaintext "setting."
+ ]
+ ]
+ , SubheadingAnnotation "1.5 \"Cinco de Cuatro\" (4 May 2017)"
, List
[ ListItem
[ Plaintext "Improvements"
### 1. Powerful multi-file search<a name="ferret-1-powerful-multi-file-search" href="#user-content-ferret-1-powerful-multi-file-search"></a>
-Ferret provides an <strong>[`:Ack`](#user-content-ack)</strong> command for searching across multiple files using The Silver Searcher (https://github.com/ggreer/the_silver_searcher), or Ack (http://beyondgrep.com/). Support for passing options through to the underlying search command exists, along with the ability to use full regular expression syntax without doing special escaping. On Vim version 8 or higher, searches are performed asynchronously (without blocking the UI).
+Ferret provides an <strong>[`:Ack`](#user-content-ack)</strong> command for searching across multiple files using ripgrep (https://github.com/BurntSushi/ripgrep), The Silver Searcher (https://github.com/ggreer/the_silver_searcher), or Ack (http://beyondgrep.com/). Support for passing options through to the underlying search command exists, along with the ability to use full regular expression syntax without doing special escaping. On modern versions of Vim (version 8 or higher, or Neovim), searches are performed asynchronously (without blocking the UI).
Shortcut mappings are provided to start an <strong>[`:Ack`](#user-content-ack)</strong> search (<leader>a) or to search for the word currently under the cursor (<leader>s).
<strong>[`:Back`](#user-content-back)</strong> and <strong>[`:Black`](#user-content-black)</strong> are analogous to <strong>[`:Ack`](#user-content-ack)</strong> and <strong>[`:Lack`](#user-content-lack)</strong>, but scoped to search within currently open buffers only.
-Finally, Ferret offers integration with dispatch.vim (https://github.com/tpope/vim-dispatch), which enables asynchronous searching on older versions of Vim (prior to version 8), despite the fact that Vim itself is single-threaded.
-
### 2. Streamlined multi-file replace<a name="ferret-2-streamlined-multi-file-replace" href="#user-content-ferret-2-streamlined-multi-file-replace"></a>
### 4. Easy operations on files in the quickfix listing<a name="ferret-4-easy-operations-on-files-in-the-quickfix-listing" href="#user-content-ferret-4-easy-operations-on-files-in-the-quickfix-listing"></a>
-Finally, Ferret provides a <strong>[`:Qargs`](#user-content-qargs)</strong> command that puts the files currently in the <strong>`quickfix`</strong> listing into the <strong>`:args`</strong> list, where they can be operated on in bulk via the <strong>`:argdo`</strong> command. This is what's used under the covers by <strong>[`:Acks`](#user-content-acks)</strong> to do its work.
+Finally, Ferret provides a <strong>[`:Qargs`](#user-content-qargs)</strong> command that puts the files currently in the <strong>`quickfix`</strong> listing into the <strong>`:args`</strong> list, where they can be operated on in bulk via the <strong>`:argdo`</strong> command. This is what's used under the covers on older versions of Vim by <strong>[`:Acks`](#user-content-acks)</strong> to do its work (on newer versions the built-in <strong>`:cfdo`</strong> is used instead).
## Installation<a name="ferret-installation" href="#user-content-ferret-installation"></a>
On newer versions of Vim (version 8 and above), the search process runs asynchronously in the background and does not block the UI.
-On older Vim versions (prior to version 8), if dispatch.vim is installed the search process will run asynchronously via the <strong>`:Make`</strong> command, otherwise it will be run synchronously via <strong>`:cexpr`</strong>. The <strong>[`g:FerretDispatch`](#user-content-gferretdispatch)</strong> option can be used to prevent the use of dispatch.vim.
-
Asynchronous searches are preferred because they do not block, despite the fact that Vim itself is single threaded.
The {pattern} is passed through as-is to the underlying search program, and no escaping is required other than preceding spaces by a single backslash. For example, to search for "\bfoo[0-9]{2} bar\b" (ie. using `ag`'s Perl-style regular expression syntax), you could do:
:Ack \bfoo[0-9]{2}\ bar\b
```
-Likewise, {options} are passed through. In this example, we pass the `-w` option (to search on word boundaries), and scope the search to the "foo" and "bar" subdirectories: >
+Likewise, {options} are passed through. In this example, we pass the `-w` option (to search on word boundaries), and scope the search to the "foo" and "bar" subdirectories:
```
:Ack -w something foo bar
Just like <strong>[`:Ack`](#user-content-ack)</strong>, but instead of using the <strong>`quickfix`</strong> listing, which is global across an entire Vim instance, it uses the <strong>`location-list`</strong>, which is a per-window construct.
-Note that <strong>[`:Lack`](#user-content-lack)</strong> always runs synchronously via <strong>`:cexpr`</strong>, because dispatch.vim doesn't currently support the <strong>`location-list`</strong>.
+Note that <strong>[`:Lack`](#user-content-lack)</strong> always runs synchronously via <strong>`:cexpr`</strong>.
<p align="right"><a name="lack" href="#user-content-lack"><code>:Lack!</code></a></p>
:Acks /foo/bar/
```
+The pattern and replacement are passed through literally to Vim's <strong>`:substitute`</strong> command, preserving all characters and escapes, including references to matches in the pattern. For example, the following could be used to swap the order of "foo123" and "bar":
+
+```
+:Acks /\v(foo\d+)(bar)/\2\1/
+```
+
<p align="right"><a name="qargs" href="#user-content-qargs"><code>:Qargs</code></a></p>
### `:Qargs`<a name="ferret-qargs" href="#user-content-ferret-qargs"></a>
Note that Ferret will not try to set up the <leader> mappings if any of the following are true:
-- A mapping for already exists.
+- A mapping with the same <strong>`{lhs}`</strong> already exists.
- An alternative mapping for the same functionality has already been set up from a <strong>`.vimrc`</strong>.
-- The mapping has been suppressed by setting <strong>[`g:FerretMap`](#user-content-gferretmap)</strong> to 1 in your <strong>`.vimrc`</strong>.
+- The mapping has been suppressed by setting <strong>[`g:FerretMap`](#user-content-gferretmap)</strong> to 0 in your <strong>`.vimrc`</strong>.
### Mappings specific to the quickfix window<a name="ferret-mappings-specific-to-the-quickfix-window" href="#user-content-ferret-mappings-specific-to-the-quickfix-window"></a>
## Options<a name="ferret-options" href="#user-content-ferret-options"></a>
-<p align="right"><a name="gferretdispatch" href="#user-content-gferretdispatch"><code>g:FerretDispatch</code></a></p>
+<p align="right"><a name="gferretnvim" href="#user-content-gferretnvim"><code>g:FerretNvim</code></a></p>
-### `g:FerretDispatch` (boolean, default: 1)<a name="ferret-gferretdispatch-boolean-default-1" href="#user-content-ferret-gferretdispatch-boolean-default-1"></a>
+### `g:FerretNvim` (boolean, default: 1)<a name="ferret-gferretnvim-boolean-default-1" href="#user-content-ferret-gferretnvim-boolean-default-1"></a>
-Controls whether to use vim-dispatch (and specifically, <strong>`:Make`</strong>) to run <strong>[`:Ack`](#user-content-ack)</strong> searches asynchronously, when available. To prevent vim-dispatch from being used, set to 0:
+Controls whether to use Neovim's <strong>`job-control`</strong> features, when available, to run searches asynchronously. To prevent this from being used, set to 0, in which case Ferret will fall back to the next method in the list (Vim's built-in async primitives -- see <strong>[`g:FerretJob`](#user-content-gferretjob)</strong> -- which are typically not available in Neovim, so will then fall back to the next available method).
```
-let g:FerretDispatch=0
+let g:FerretNvim=0
```
-Note that on sufficiently recent versions of Vim with <strong>`+job`</strong> support, Ferret will first try to use <strong>`+job`</strong>, falling back to vim-dispatch and consulting <strong>[`g:FerretDispatch`](#user-content-gferretdispatch)</strong> only if <strong>[`g:FerretJob`](#user-content-gferretjob)</strong> is set to 0.
-
<p align="right"><a name="gferretjob" href="#user-content-gferretjob"><code>g:FerretJob</code></a></p>
### `g:FerretJob` (boolean, default: 1)<a name="ferret-gferretjob-boolean-default-1" href="#user-content-ferret-gferretjob-boolean-default-1"></a>
-Controls whether to use Vim's <strong>`+job`</strong> feature, when available, to run searches asynchronously. To prevent <strong>`+job`</strong> from being used, set to 0, in which case Ferret will fall back to vim-dispatch (see also: <strong>[`g:FerretDispatch`](#user-content-gferretdispatch)</strong>):
+Controls whether to use Vim's <strong>`+job`</strong> feature, when available, to run searches asynchronously. To prevent <strong>`+job`</strong> from being used, set to 0, in which case Ferret will fall back to the next available method.
```
let g:FerretJob=0
let g:FerretExecutable='ag,rg'
```
+<p align="right"><a name="gferretexecutablearguments" href="#user-content-gferretexecutablearguments"><code>g:FerretExecutableArguments</code></a></p>
+
+### `g:FerretExecutableArguments` (dict, default: {})<a name="ferret-gferretexecutablearguments-dict-default-" href="#user-content-ferret-gferretexecutablearguments-dict-default-"></a>
+
+Allows you to override the default arguments that get passed to the underlying search executables. For example, to add `-s` to the default arguments passed to `ack` (`--column --with-filename`):
+
+```
+let g:FerretExecutableArguments = {
+ \ 'ack': '--column --with-filename -s'
+ \ }
+```
+
+To find out the default arguments for a given executable, see <strong>`ferret#get_default_arguments()`</strong>.
+
<p align="right"><a name="gferretmaxresults" href="#user-content-gferretmaxresults"><code>g:FerretMaxResults</code></a></p>
### `g:FerretMaxResults` (number, default: 100000)<a name="ferret-gferretmaxresults-number-default-100000" href="#user-content-ferret-gferretmaxresults-number-default-100000"></a>
In the event that Ferret aborts a search that has hit the <strong>[`g:FerretMaxResults`](#user-content-gferretmaxresults)</strong> limit, a message will be printed prompting users to run the search again with <strong>[`:Ack!`](#user-content-ack)</strong> or <strong>[`:Lack!`](#user-content-lack)</strong> if they want to bypass the limit.
+<p align="right"><a name="gferretautojump" href="#user-content-gferretautojump"><code>g:FerretAutojump</code></a></p>
+
+### `g:FerretAutojump` (number, default: 1)<a name="ferret-gferretautojump-number-default-1" href="#user-content-ferret-gferretautojump-number-default-1"></a>
+
+Controls whether Ferret will automatically jump to the first found match.
+
+- Set to 0, Ferret will show the search results but perform no jump.
+- Set to 1 (the default), Ferret will show the search results and focus the result listing.
+- Set to 2, Ferret will show the search results and jump to the first found match.
+
+Example override:
+
+```
+let g:FerretAutojump=2
+```
+
<p align="right"><a name="gferretqfoptions" href="#user-content-gferretqfoptions"><code>g:FerretQFOptions</code></a></p>
### `g:FerretQFOptions` (boolean, default: 1)<a name="ferret-gferretqfoptions-boolean-default-1" href="#user-content-ferret-gferretqfoptions-boolean-default-1"></a>
Sets the '<strong>`grepformat`</strong>' used by Ferret.
+## Functions<a name="ferret-functions" href="#user-content-ferret-functions"></a>
+
+<p align="right"><a name="ferretgetdefaultarguments" href="#user-content-ferretgetdefaultarguments"><code>ferret#get_default_arguments()</code></a></p>
+
+### `ferret#get_default_arguments()`<a name="ferret-ferretgetdefaultarguments" href="#user-content-ferret-ferretgetdefaultarguments"></a>
+
+Call this with an executable name to find out the default arguments that will be passed when invoking that executable. For example:
+
+```
+echo ferret#get_default_arguments('rg')
+```
+
+This may be useful if you wish to extend or otherwise modify the arguments by setting <strong>[`g:FerretExecutableArguments`](#user-content-gferretexecutablearguments)</strong>.
+
+
## Custom autocommands<a name="ferret-custom-autocommands" href="#user-content-ferret-custom-autocommands"></a>
<p align="right"><a name="ferretdidwrite" href="#user-content-ferretdidwrite"><code>FerretDidWrite</code></a> <a name="ferretwillwrite" href="#user-content-ferretwillwrite"><code>FerretWillWrite</code></a></p>
Additionally, Ferret includes an <strong>`ftplugin`</strong> for the <strong>`quickfix`</strong> listing that adjusts a number of settings to improve the usability of search results.
<p align="right"><a name="ferret-nolist" href="#user-content-ferret-nolist"><code>ferret-nolist</code></a></p>
-'nolist'
+
+### 'nolist'<a name="ferret-nolist" href="#user-content-ferret-nolist"></a>
Turned off to reduce visual clutter in the search results, and because 'list' is most useful in files that are being actively edited, which is not the case for <strong>`quickfix`</strong> results.
<p align="right"><a name="ferret-norelativenumber" href="#user-content-ferret-norelativenumber"><code>ferret-norelativenumber</code></a></p>
-'norelativenumber'
+
+### 'norelativenumber'<a name="ferret-norelativenumber" href="#user-content-ferret-norelativenumber"></a>
Turned off, because it is more useful to have a sense of absolute progress through the results list than to have the ability to jump to nearby results (especially seeing as the most common operations are moving to the next or previous file, which are both handled nicely by <strong>`:cnf`</strong> and <strong>`:cpf`</strong> respectively).
<p align="right"><a name="ferret-nowrap" href="#user-content-ferret-nowrap"><code>ferret-nowrap</code></a></p>
-'nowrap'
+
+### 'nowrap'<a name="ferret-nowrap" href="#user-content-ferret-nowrap"></a>
Turned off to avoid ugly wrapping that makes the results list hard to read, and because in search results, the most relevant information is the filename, which is on the left and is usually visible even without wrapping.
<p align="right"><a name="ferret-number" href="#user-content-ferret-number"><code>ferret-number</code></a></p>
-'number'
+
+### 'number'<a name="ferret-number" href="#user-content-ferret-number"></a>
Turned on to give a sense of absolute progress through the results.
<p align="right"><a name="ferret-scrolloff" href="#user-content-ferret-scrolloff"><code>ferret-scrolloff</code></a></p>
-'scrolloff'
+
+### 'scrolloff'<a name="ferret-scrolloff" href="#user-content-ferret-scrolloff"></a>
Set to 0 because the <strong>`quickfix`</strong> listing is usually small by default, so trying to keep the current line away from the edge of the viewpoint is futile; by definition it is usually near the edge.
<p align="right"><a name="ferret-nocursorline" href="#user-content-ferret-nocursorline"><code>ferret-nocursorline</code></a></p>
-'nocursorline'
+
+### 'nocursorline'<a name="ferret-nocursorline" href="#user-content-ferret-nocursorline"></a>
Turned off to reduce visual clutter.
### Why do Ferret commands start with "Ack", "Lack" and so on?<a name="ferret-why-do-ferret-commands-start-with-ack-lack-and-so-on" href="#user-content-ferret-why-do-ferret-commands-start-with-ack-lack-and-so-on"></a>
-Ferret was originally the thinnest of wrappers (7 lines of code in my <strong>`.vimrc`</strong>) around `ack`. The earliest traces of it can be seen in the initial commit to my dotfiles repo in May, 2009 (https://wt.pe/h).
+Ferret was originally the thinnest of wrappers (7 lines of code in my <strong>`.vimrc`</strong>) around `ack`. The earliest traces of it can be seen in the initial commit to my dotfiles repo in May, 2009 (https://rfr.to/h).
So, even though Ferret has a new name now and actually prefers `rg` then `ag` over `ack`/`ack-grep` when available, I prefer to keep the command names intact and benefit from years of accumulated muscle-memory.
Ferret is written and maintained by Greg Hurrell <greg@hurrell.net>.
-The idea for vim-dispatch integration was taken from Miles Sterrett's ack.vim plug-in (https://github.com/mileszs/ack.vim).
-
Other contributors that have submitted patches include (in alphabetical order):
- Daniel Silva
- Filip SzymaĆski
- Joe Lencioni
+- Jon Parise
- Nelo-Thara Wallus
- Tom Dooner
- Vaibhav Sagar
### master (not yet released)<a name="ferret-master-not-yet-released" href="#user-content-ferret-master-not-yet-released"></a>
+- Try to avoid "press ENTER to continue" prompts.
+- Put search term in <strong>`w:quickfix_title`</strong> for use in statuslines (https://github.com/wincent/ferret/pull/57).
+- Add <strong>[`g:FerretExecutableArguments`](#user-content-gferretexecutablearguments)</strong> and <strong>`ferret#get_default_arguments()`</strong> (https://github.com/wincent/ferret/pull/46).
+
+
+### 3.0.3 (23 March 2018)<a name="ferret-303-23-march-2018" href="#user-content-ferret-303-23-march-2018"></a>
+
+- Fix for <strong>[`:Lack`](#user-content-lack)</strong> results opening in quickfix listing in Neovim (https://github.com/wincent/ferret/issues/47).
+
+
+### 3.0.2 (25 October 2017)<a name="ferret-302-25-october-2017" href="#user-content-ferret-302-25-october-2017"></a>
+
+- Fix broken <strong>[`:Back`](#user-content-back)</strong> and <strong>[`:Black`](#user-content-black)</strong> commands (https://github.com/wincent/ferret/issues/48).
+
+
+### 3.0.1 (24 August 2017)<a name="ferret-301-24-august-2017" href="#user-content-ferret-301-24-august-2017"></a>
+
+- Fix failure to handle search patterns containing multiple escaped spaces (https://github.com/wincent/ferret/issues/49).
+
+
+### 3.0 (13 June 2017)<a name="ferret-30-13-june-2017" href="#user-content-ferret-30-13-june-2017"></a>
+
+- Improve handling of backslash escapes (https://github.com/wincent/ferret/issues/41).
+- Add <strong>[`g:FerretAutojump`](#user-content-gferretautojump)</strong>.
+- Drop support for vim-dispatch.
+
+
+### 2.0 (6 June 2017)<a name="ferret-20-6-june-2017" href="#user-content-ferret-20-6-june-2017"></a>
+
+- Add support for Neovim, along with <strong>[`g:FerretNvim`](#user-content-gferretnvim)</strong> setting.
+
+
+### 1.5 "Cinco de Cuatro" (4 May 2017)<a name="ferret-15-cinco-de-cuatro-4-may-2017" href="#user-content-ferret-15-cinco-de-cuatro-4-may-2017"></a>
+
- Improvements to the handling of very large result sets (due to wide lines or many results).
- Added <strong>[`g:FerretLazyInit`](#user-content-gferretlazyinit)</strong>.
- Added missing documentation for <strong>[`g:FerretJob`](#user-content-gferretjob)</strong>.
execute "normal \<C-W>\<C-P>"
endfunction
-" Returns 1 if we should/can use vim-dispatch.
-function! ferret#private#dispatch() abort
+" Returns 1 if we should use Neovim's |job-control| features.
+function! ferret#private#nvim()
""
- " @option g:FerretDispatch boolean 1
+ " @option g:FerretNvim boolean 1
"
- " Controls whether to use vim-dispatch (and specifically, |:Make|) to run
- " |:Ack| searches asynchronously, when available. To prevent vim-dispatch from
- " being used, set to 0:
+ " Controls whether to use Neovim's |job-control| features, when
+ " available, to run searches asynchronously. To prevent this from
+ " being used, set to 0, in which case Ferret will fall back to the next
+ " method in the list (Vim's built-in async primitives -- see
+ " |g:FerretJob| -- which are typically not available in Neovim, so
+ " will then fall back to the next available method).
"
" ```
- " let g:FerretDispatch=0
+ " let g:FerretNvim=0
" ```
- "
- " Note that on sufficiently recent versions of Vim with |+job| support, Ferret
- " will first try to use |+job|, falling back to vim-dispatch and consulting
- " |g:FerretDispatch| only if |g:FerretJob| is set to 0.
- "
- let l:dispatch=get(g:, 'FerretDispatch', 1)
- return l:dispatch && exists(':Make') == 2
+ let l:nvim=get(g:, 'FerretNvim', 1)
+
+ return l:nvim && has('nvim')
endfunction
" Returns 1 if we can use Vim's built-in async primitives.
"
" Controls whether to use Vim's |+job| feature, when available, to run
" searches asynchronously. To prevent |+job| from being used, set to 0, in
- " which case Ferret will fall back to vim-dispatch (see also:
- " |g:FerretDispatch|):
+ " which case Ferret will fall back to the next available method.
"
" ```
" let g:FerretJob=0
return l:async && has('patch-7-4-1829')
endfunction
-" Use `input()` to show error output to user. Ideally, we would do this in a way
-" that didn't require user interaction, but this is the only reliable mechanism
-" that works for all cases. Alternatives considered:
-"
-" (1) Using `:echomsg`
-"
-" When not using vim-dispatch, the screen is getting cleared before the
-" user sees it, even with a pre-emptive `:redraw!` beforehand. Note that
-" we can get the message to linger on the screen by making it multi-line and
-" forcing Vim to show a prompt (see `:h hit-enter-prompt`), but this is not
-" reliable because the number of lines required to force the prompt will
-" vary by system, depending on the value of `'cmdheight'`.
-"
-" When using vim-dispatch, anything we output ends up getting swallowed
-" before the user sees it, because something it is doing is clearing the
-" screen. This is true no matter how many lines we output.
-"
-" (2) Writing back into the quickfix/location list
-"
-" This interacts poorly with vim-dispatch. If we write back an error message
-" and then call `:copen 1`, vim-dispatch ends up closing the listing before
-" the user sees it.
-"
-" (3) Using `:echoerr`
-"
-" This works, but presents to the user as an exception (see `:h :echoerr`).
-"
function! ferret#private#error(message) abort
- call inputsave()
+ if has('lambda') && has('timers')
+ call timer_start(100, {-> s:print_error_with_echomsg(a:message)})
+ else
+ " Use `input()` to show error output to user. Ideally, we would do this
+ " in a way that didn't require user interaction, but this is the only
+ " reliable mechanism that works for all cases. Alternatives considered:
+ "
+ " (1) Using straight `:echomsg`
+ "
+ " The screen gets cleared before the user sees it, even with a
+ " pre-emptive `:redraw!` beforehand. Note that we can get the
+ " message to linger on the screen by making it multi-line and
+ " forcing Vim to show a prompt (see `:h hit-enter-prompt`), but
+ " this is not reliable because the number of lines required to
+ " force the prompt will vary by system, depending on the value
+ " of `'cmdheight'`.
+ "
+ " (2) Using `:echoerr`
+ "
+ " This works, but presents to the user as an exception (see `:h
+ " :echoerr`).
+ "
+ call inputsave()
+ echohl ErrorMsg
+ unsilent call input(a:message . ': press ENTER to continue')
+ echohl NONE
+ call inputrestore()
+ unsilent echo
+ redraw!
+ endif
+endfunction
+
+function! s:print_error_with_echomsg(message)
+ redraw!
echohl ErrorMsg
- unsilent call input(a:message . ': press ENTER to continue')
+ echomsg a:message
echohl NONE
- call inputrestore()
- unsilent echo
- redraw!
endfunction
" Parses arguments, extracting a search pattern (which is stored in
unlet g:ferret_lastsearch
endif
+ " Split on unescaped spaces:
+ "
+ " foo bar -> [foo, bar]
+ " foo\ bar -> [foo\ bar] (no split)
+ " foo\\ bar -> [foo\\, bar]
+ " foo\\\ bar -> [foo\\\ bar] (no split)
+ " foo\\\\ bar -> [foo\\\\, bar]
+ "
+ " We build a regex for this as follows:
+ "
+ " - match an odd number of "X": X(XX)*
+ " - add negative lookbehind (don't match after an "X"): X\@<!X(XX)*
+ " - with whitespace (for readability): X \@<! X(XX)*
+ " - add negative lookahead (don't match before an "X"): X\@<!X(XX)*X\@!
+ " - with whitespace: X \@<! X(XX)* X\@!
+ " - denote this "..."
+ " - match a "Y" not preceded by the above: (...)\@<!Y
+ " - with whitespace: (...) \@<! Y
+ " - replace "..." with actual pattern: (X\@<!X(XX)*X\@!)\@<!Y
+ " - escape ( and ): \(X\@<!X\(XX\)*X\@!\)\@<!Y
+ " - replace "X" with "\\": \(\\\@<!\\\(\\\\\)*\\\@!\)\@<!Y
+ " - replace "Y" with " ": '\(\\\@<!\\\(\\\\\)*\\\@!\)\@<! '
+ "
+ let l:odd_number_of_backslashes='\\\@<!\\\(\\\\\)*\\\@!'
+ let l:unescaped_space='\('.l:odd_number_of_backslashes.'\)\@<! '
+ let l:args=split(a:args, l:unescaped_space)
let l:expanded_args=[]
- for l:arg in a:args
+ for l:arg in l:args
+ " Because we split on unescaped spaces, we know any escaped spaces remaining
+ " inside arguments really are supposed to be just spaces.
+ let l:arg=substitute(l:arg, '\\ ', ' ', 'g')
+
if ferret#private#option(l:arg)
" Options get passed through as-is.
call add(l:expanded_args, l:arg)
endif
endfor
- if ferret#private#async()
+ if ferret#private#nvim() || ferret#private#async()
return l:expanded_args
endif
endif
endfunction
+function! s:qfsize(type) abort
+ if has('patch-8.0.1112')
+ if a:type ==# 'qf'
+ return get(getqflist({'size' : 0}), 'size', 0)
+ else
+ return get(getloclist(0, {'size' : 0}), 'size', 0)
+ endif
+ else
+ let l:qflist=a:type ==# 'qf' ? getqflist() : getloclist(0)
+ return len(l:qflist)
+ endif
+endfunction
+
function! ferret#private#post(type) abort
call ferret#private#clearautocmd()
- let l:lastsearch = get(g:, 'ferret_lastsearch', '')
- let l:qflist = a:type == 'qf' ? getqflist() : getloclist(0)
- let l:tip = ' [see `:help ferret-quotes`]'
- if len(l:qflist) == 0
- let l:base = 'No results for search pattern `' . l:lastsearch . '`'
+ let l:lastsearch=get(g:, 'ferret_lastsearch', '')
+ let l:tip=' [see `:help ferret-quotes`]'
+ let l:len=s:qfsize(a:type)
+ if l:len == 0
+ let l:base='No results for search pattern `' . l:lastsearch . '`'
" Search pattern has no spaces and is entirely enclosed in quotes;
" eg 'foo' or "bar"
endif
else
" Find any "invalid" entries in the list.
- let l:invalid = filter(copy(l:qflist), 'v:val.valid == 0')
- if len(l:invalid) == len(l:qflist)
+ let l:qflist=a:type ==# 'qf' ? getqflist() : getloclist(0)
+ let l:invalid=filter(copy(l:qflist), 'v:val.valid == 0')
+ if len(l:invalid) == l:len
" Every item in the list was invalid.
redraw!
echohl ErrorMsg
endfor
echohl NONE
- let l:base = 'Search for `' . l:lastsearch . '` failed'
-
- " When using vim-dispatch, the messages printed above get cleared, so the
- " only way to see them is with `:messages`.
- let l:suffix = a:type == 'qf' && ferret#private#dispatch() ?
- \ ' (run `:messages` to see details)' :
- \ ''
+ let l:base='Search for `' . l:lastsearch . '` failed'
" If search pattern looks like `'foo` or `"bar`, it means the user
" probably tried to search for 'foo bar' or "bar baz" etc.
if l:lastsearch =~ '\v^[' . "'" . '"].+[^' . "'" . '"]$'
- call ferret#private#error(l:base . l:tip . l:suffix)
+ call ferret#private#error(l:base . l:tip)
else
- call ferret#private#error(l:base . l:suffix)
+ call ferret#private#error(l:base)
endif
endif
endif
+ return l:len
endfunction
-function! ferret#private#ack(bang, ...) abort
- let l:command=s:parse(a:000)
+function! ferret#private#ack(bang, args) abort
+ let l:command=s:parse(a:args)
call ferret#private#hlsearch()
let l:executable=ferret#private#executable()
return
endif
- if ferret#private#async()
+ if ferret#private#nvim()
+ call ferret#private#nvim#search(l:command, 1, a:bang)
+ elseif ferret#private#async()
call ferret#private#async#search(l:command, 1, a:bang)
- elseif ferret#private#dispatch()
- call ferret#private#dispatch#search(l:command)
else
call ferret#private#vanilla#search(l:command, 1)
endif
function! ferret#private#buflist() abort
let l:buflist=getbufinfo({'buflisted': 1})
let l:bufpaths=filter(map(l:buflist, 'v:val.name'), 'v:val !=# ""')
- return l:bufpaths
+ return join(l:bufpaths, ' ')
endfunction
-function! ferret#private#back(bang, ...) abort
- call call('ferret#private#ack', a:bang, a:000 + ferret#private#buflist())
+function! ferret#private#back(bang, args) abort
+ call call('ferret#private#ack', [a:bang, a:args . ' ' . ferret#private#buflist()])
endfunction
-function! ferret#private#black(bang, ...) abort
- call call('ferret#private#lack', a:bang, a:000 + ferret#private#buflist())
+function! ferret#private#black(bang, args) abort
+ call call('ferret#private#lack', [a:bang, a:args . ' ' . ferret#private#buflist()])
endfunction
function! ferret#private#installprompt() abort
\ )
endfunction
-function! ferret#private#lack(bang, ...) abort
- let l:command=s:parse(a:000)
+function! ferret#private#lack(bang, args) abort
+ let l:command=s:parse(a:args)
call ferret#private#hlsearch()
let l:executable=ferret#private#executable()
return
endif
- if ferret#private#async()
+ if ferret#private#nvim()
+ call ferret#private#nvim#search(l:command, 0, a:bang)
+ elseif ferret#private#async()
call ferret#private#async#search(l:command, 0, a:bang)
else
call ferret#private#vanilla#search(l:command, 0)
" way for mnemonics, as it will most often be preceded by an :Ack invocation.)
function! ferret#private#acks(command) abort
" Accept any pattern allowed by E146 (crude sanity check).
- let l:matches = matchlist(a:command, '\v\C^(([^|"\\a-zA-Z0-9]).+\2.*\2)([cgeiI]*)$')
+ let l:matches=matchlist(a:command, '\v\C^(([^|"\\a-zA-Z0-9]).+\2.*\2)([cgeiI]*)$')
if !len(l:matches)
call ferret#private#error(
\ 'Ferret: Expected a substitution expression (/foo/bar/); got: ' .
" Pass through options `c`, `i`/`I` to `:substitute`.
" Add options `e` and `g` if not already present.
- let l:pattern = l:matches[1]
- let l:options = l:matches[3]
+ let l:pattern=l:matches[1]
+ let l:options=l:matches[3]
if l:options !~# 'e'
let l:options .= 'e'
endif
let l:binary=matchstr(l:executable, '\v\w+')
endfunction
-let s:options = {
+let s:options={
\ 'ack': [
\ '--ignore-ack-defaults',
\ '--ignore-case',
" ```
let s:force=get(g:, 'FerretExecutable', 'rg,ag,ack,ack-grep')
+" Base set of default arguments for each executable; these get extended by
+" ferret#private#init() upon startup.
let s:executables={
- \ 'rg': 'rg --vimgrep --no-heading',
- \ 'ag': 'ag',
- \ 'ack': 'ack --column --with-filename',
- \ 'ack-grep': 'ack-grep --column --with-filename'
+ \ 'rg': '--vimgrep --no-config --no-heading',
+ \ 'ag': '',
+ \ 'ack': '--column --with-filename',
+ \ 'ack-grep': '--column --with-filename'
\ }
let s:init_done=0
+function! ferret#private#executables() abort
+ return copy(s:executables)
+endfunction
+
function! ferret#private#init() abort
if s:init_done
return
if executable('ag')
let l:ag_help=system('ag --help')
if match(l:ag_help, '--vimgrep') != -1
- let s:executables['ag'].=' --vimgrep'
+ let s:executables['ag'].='--vimgrep'
else
- let s:executables['ag'].=' --column'
+ let s:executables['ag'].='--column'
endif
if match(l:ag_help, '--width') != -1
let s:executables['ag'].=' --width 4096'
endif
for l:executable in l:executables
if executable(l:executable)
- return s:executables[l:executable]
+ ""
+ " @option g:FerretExecutableArguments dict {}
+ "
+ " Allows you to override the default arguments that get passed to the
+ " underlying search executables. For example, to add `-s` to the default
+ " arguments passed to `ack` (`--column --with-filename`):
+ "
+ " ```
+ " let g:FerretExecutableArguments = {
+ " \ 'ack': '--column --with-filename -s'
+ " \ }
+ " ```
+ "
+ " To find out the default arguments for a given executable, see
+ " |ferret#get_default_arguments()|.
+ "
+ let l:overrides=get(g:, 'FerretExecutableArguments', {})
+ let l:type=exists('v:t_dict') ? v:t_dict : 4
+ if type(l:overrides) == l:type && has_key(l:overrides, l:executable)
+ return l:executable . ' ' . l:overrides[l:executable]
+ else
+ return l:executable . ' ' . s:executables[l:executable]
+ endif
endif
endfor
return ''
endfunction
+function! ferret#private#limit() abort
+ ""
+ " @option g:FerretMaxResults number 100000
+ "
+ " Controls the maximum number of results Ferret will attempt to gather before
+ " displaying the results. Note that this only applies when searching
+ " asynchronously; that is, on recent versions of Vim with |+job| support and
+ " when |g:FerretJob| is not set to 0.
+ "
+ " The intent of this option is to prevent runaway search processes that produce
+ " huge volumes of output (for example, searching for a common string like "test"
+ " inside a |$HOME| directory containing millions of files) from locking up Vim.
+ "
+ " In the event that Ferret aborts a search that has hit the |g:FerretMaxResults|
+ " limit, a message will be printed prompting users to run the search again
+ " with |:Ack!| or |:Lack!| if they want to bypass the limit.
+ "
+ return max([1, +get(g:, 'FerretMaxResults', 100000)]) - 1
+endfunction
+
call ferret#private#init()