PageRenderTime 34ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/pack/bundle/opt/ferret/plugin/ferret.vim

https://bitbucket.org/skeept/dotvim
Vim Script | 877 lines | 54 code | 26 blank | 797 comment | 27 complexity | 25a3675ad7ea120c3c486d56a05a7591 MD5 | raw file
Possible License(s): GPL-3.0, WTFPL, BSD-3-Clause, CC-BY-SA-4.0, AGPL-3.0, LGPL-3.0, BSD-2-Clause, MIT, AGPL-1.0
  1. " Copyright 2015-present Greg Hurrell. All rights reserved.
  2. " Licensed under the terms of the BSD 2-clause license.
  3. ""
  4. " @header
  5. "
  6. " @image https://raw.githubusercontent.com/wincent/ferret/media/ferret.jpg center
  7. " @image https://raw.githubusercontent.com/wincent/ferret/media/ferret.gif center
  8. "
  9. ""
  10. " @plugin ferret Ferret plug-in for Vim
  11. "
  12. " # Intro
  13. "
  14. " > "ferret (verb)<br />
  15. " > (ferret something out) search tenaciously for and find something: she had
  16. " > the ability to ferret out the facts."
  17. "
  18. " *ferret-features*
  19. " Ferret improves Vim's multi-file search in four ways:
  20. "
  21. " ## 1. Powerful multi-file search
  22. "
  23. " Ferret provides an |:Ack| command for searching across multiple files using
  24. " ripgrep (https://github.com/BurntSushi/ripgrep), The Silver Searcher
  25. " (https://github.com/ggreer/the_silver_searcher), or Ack
  26. " (http://beyondgrep.com/). Support for passing options through to the
  27. " underlying search command exists, along with the ability to use full regular
  28. " expression syntax without doing special escaping. On modern versions
  29. " of Vim (version 8 or higher, or Neovim), searches are performed
  30. " asynchronously (without blocking the UI).
  31. "
  32. " Shortcut mappings are provided to start an |:Ack| search (<leader>a) or to
  33. " search for the word currently under the cursor (<leader>s).
  34. "
  35. " Results are normally displayed in the |quickfix| window, but Ferret also
  36. " provides a |:Lack| command that behaves like |:Ack| but uses the
  37. " |location-list| instead, and a <leader>l mapping as a shortcut to |:Lack|.
  38. "
  39. " |:Back| and |:Black| are analogous to |:Ack| and |:Lack|, but scoped to search
  40. " within currently open buffers only. |:Quack| is scoped to search among the
  41. " files currently in the |quickfix| list.
  42. "
  43. " ## 2. Streamlined multi-file replace
  44. "
  45. " The companion to |:Ack| is |:Acks| (mnemonic: "Ack substitute", accessible via
  46. " shortcut <leader>r), which allows you to run a multi-file replace across all
  47. " the files placed in the |quickfix| window by a previous invocation of |:Ack|
  48. " (or |:Back|, or |:Quack|).
  49. "
  50. " Correspondingly, results obtained by |:Lack| can be targeted for replacement
  51. " with |:Lacks|.
  52. "
  53. " ## 3. Quickfix listing enhancements
  54. "
  55. " The |quickfix| listing itself is enhanced with settings to improve its
  56. " usability, and natural mappings that allow quick removal of items from the
  57. " list (for example, you can reduce clutter in the listing by removing lines
  58. " that you don't intend to make changes to).
  59. "
  60. " Additionally, Vim's |:cn|, |:cp|, |:cnf| and |:cpf| commands are tweaked to
  61. " make it easier to immediately identify matches by centering them within the
  62. " viewport.
  63. "
  64. " ## 4. Easy operations on files in the quickfix listing
  65. "
  66. " Finally, Ferret provides a |:Qargs| command that puts the files currently in
  67. " the |quickfix| listing into the |:args| list, where they can be operated on in
  68. " bulk via the |:argdo| command. This is what's used under the covers on older
  69. " versions of Vim by |:Acks| to do its work (on newer versions the built-in
  70. " |:cdo| or |:cfdo| are used instead).
  71. "
  72. " Ferret also provides a |:Largs| command, which is a |location-list| analog
  73. " for |:Qargs|.
  74. "
  75. " # Installation
  76. "
  77. " To install Ferret, use your plug-in management system of choice.
  78. "
  79. " If you don't have a "plug-in management system of choice", I recommend
  80. " Pathogen (https://github.com/tpope/vim-pathogen) due to its simplicity and
  81. " robustness. Assuming that you have Pathogen installed and configured, and that
  82. " you want to install Ferret into `~/.vim/bundle`, you can do so with:
  83. "
  84. " ```
  85. " git clone https://github.com/wincent/ferret.git ~/.vim/bundle/ferret
  86. " ```
  87. "
  88. " Alternatively, if you use a Git submodule for each Vim plug-in, you could do
  89. " the following after `cd`-ing into the top-level of your Git superproject:
  90. "
  91. " ```
  92. " git submodule add https://github.com/wincent/ferret.git ~/vim/bundle/ferret
  93. " git submodule init
  94. " ```
  95. "
  96. " To generate help tags under Pathogen, you can do so from inside Vim with:
  97. "
  98. " ```
  99. " :call pathogen#helptags()
  100. " ```
  101. "
  102. " @mappings
  103. "
  104. " ## Circumstances where mappings do not get set up
  105. "
  106. " Note that Ferret will not try to set up the <leader> mappings if any of the
  107. " following are true:
  108. "
  109. " - A mapping with the same |{lhs}| already exists.
  110. " - An alternative mapping for the same functionality has already been set up
  111. " from a |.vimrc|.
  112. " - The mapping has been suppressed by setting |g:FerretMap| to 0 in your
  113. " |.vimrc|.
  114. "
  115. " ## Mappings specific to the quickfix window
  116. "
  117. " Additionally, Ferret will set up special mappings in |quickfix| listings,
  118. " unless prevented from doing so by |g:FerretQFMap|:
  119. "
  120. " - `d` (|visual-mode|): delete visual selection
  121. " - `dd` (|Normal-mode|): delete current line
  122. " - `d`{motion} (|Normal-mode|): delete range indicated by {motion}
  123. "
  124. "
  125. " @footer
  126. "
  127. " # Custom autocommands
  128. "
  129. " *FerretWillWrite* *FerretDidWrite*
  130. " For maximum compatibility with other plug-ins, Ferret runs the following
  131. " "User" autocommands before and after running the file writing operations
  132. " during |:Acks| or |:Lacks|:
  133. "
  134. " - FerretWillWrite
  135. " - FerretDidWrite
  136. "
  137. " For example, to call a pair of custom functions in response to these events,
  138. " you might do:
  139. "
  140. " ```
  141. " autocmd! User FerretWillWrite
  142. " autocmd User FerretWillWrite call CustomWillWrite()
  143. " autocmd! User FerretDidWrite
  144. " autocmd User FerretDidWrite call CustomDidWrite()
  145. " ```
  146. "
  147. "
  148. " # Overrides
  149. "
  150. " Ferret overrides the 'grepformat' and 'grepprg' settings, preferentially
  151. " setting `rg`, `ag`, `ack` or `ack-grep` as the 'grepprg' (in that order) and
  152. " configuring a suitable 'grepformat'.
  153. "
  154. " Additionally, Ferret includes an |ftplugin| for the |quickfix| listing that
  155. " adjusts a number of settings to improve the usability of search results.
  156. "
  157. " @indent
  158. " *ferret-nolist*
  159. " ## 'nolist'
  160. "
  161. " Turned off to reduce visual clutter in the search results, and because
  162. " 'list' is most useful in files that are being actively edited, which is not
  163. " the case for |quickfix| results.
  164. "
  165. " *ferret-norelativenumber*
  166. " ## 'norelativenumber'
  167. "
  168. " Turned off, because it is more useful to have a sense of absolute progress
  169. " through the results list than to have the ability to jump to nearby results
  170. " (especially seeing as the most common operations are moving to the next or
  171. " previous file, which are both handled nicely by |:cnf| and |:cpf|
  172. " respectively).
  173. "
  174. " *ferret-nowrap*
  175. " ## 'nowrap'
  176. "
  177. " Turned off to avoid ugly wrapping that makes the results list hard to read,
  178. " and because in search results, the most relevant information is the
  179. " filename, which is on the left and is usually visible even without wrapping.
  180. "
  181. " *ferret-number*
  182. " ## 'number'
  183. "
  184. " Turned on to give a sense of absolute progress through the results.
  185. "
  186. " *ferret-scrolloff*
  187. " ## 'scrolloff'
  188. "
  189. " Set to 0 because the |quickfix| listing is usually small by default, so
  190. " trying to keep the current line away from the edge of the viewpoint is
  191. " futile; by definition it is usually near the edge.
  192. "
  193. " *ferret-nocursorline*
  194. " ## 'nocursorline'
  195. "
  196. " Turned off to reduce visual clutter.
  197. "
  198. " @dedent
  199. "
  200. " To prevent any of these |quickfix|-specific overrides from being set up, you
  201. " can set |g:FerretQFOptions| to 0 in your |.vimrc|:
  202. "
  203. " ```
  204. " let g:FerretQFOptions=0
  205. " ```
  206. "
  207. "
  208. " # Troubleshooting
  209. "
  210. " *ferret-quotes*
  211. " ## Ferret fails to find patterns containing spaces
  212. "
  213. " As described in the documentation for |:Ack|, the search pattern is passed
  214. " through as-is to the underlying search command, and no escaping is required
  215. " other than preceding spaces by a single backslash.
  216. "
  217. " So, to find "foo bar", you would search like:
  218. "
  219. " ```
  220. " :Ack foo\ bar
  221. " ```
  222. "
  223. " Unescaped spaces in the search are treated as argument separators, so a
  224. " command like the following means pass the `-w` option through, search for
  225. " pattern "foo", and limit search to the "bar" directory:
  226. "
  227. " ```
  228. " :Ack -w foo bar
  229. " ```
  230. "
  231. " Note that including quotes will not do what you intend.
  232. "
  233. " ```
  234. " " Search for '"foo' in the 'bar"' directory:
  235. " :Ack "foo bar"
  236. "
  237. " " Search for "'foo' in the "bar'" directory:
  238. " :Ack 'foo bar'
  239. " ```
  240. "
  241. " This approach to escaping is taken in order to make it straightfoward to use
  242. " powerful Perl-compatible regular expression syntax in an unambiguous way
  243. " without having to worry about shell escaping rules:
  244. "
  245. " ```
  246. " :Ack \blog\((['"]).*?\1\) -i --ignore-dir=src/vendor src dist build
  247. " ```
  248. "
  249. " # FAQ
  250. "
  251. " ## Why do Ferret commands start with "Ack", "Lack" and so on?
  252. "
  253. " Ferret was originally the thinnest of wrappers (7 lines of code in my
  254. " |.vimrc|) around `ack`. The earliest traces of it can be seen in the initial
  255. " commit to my dotfiles repo in May, 2009 (https://wincent.com/h).
  256. "
  257. " So, even though Ferret has a new name now and actually prefers `rg` then `ag`
  258. " over `ack`/`ack-grep` when available, I prefer to keep the command names
  259. " intact and benefit from years of accumulated muscle-memory.
  260. "
  261. "
  262. " # Related
  263. "
  264. " Just as Ferret aims to improve the multi-file search and replace experience,
  265. " Loupe does the same for within-file searching:
  266. "
  267. " https://github.com/wincent/loupe
  268. "
  269. "
  270. " # Website
  271. "
  272. " The official Ferret source code repo is at:
  273. "
  274. " http://git.wincent.com/ferret.git
  275. "
  276. " A mirror exists at:
  277. "
  278. " https://github.com/wincent/ferret
  279. "
  280. " Official releases are listed at:
  281. "
  282. " http://www.vim.org/scripts/script.php?script_id=5220
  283. "
  284. "
  285. " # License
  286. "
  287. " Copyright 2015-present Greg Hurrell. All rights reserved.
  288. "
  289. " Redistribution and use in source and binary forms, with or without
  290. " modification, are permitted provided that the following conditions are met:
  291. "
  292. " 1. Redistributions of source code must retain the above copyright notice,
  293. " this list of conditions and the following disclaimer.
  294. "
  295. " 2. Redistributions in binary form must reproduce the above copyright notice,
  296. " this list of conditions and the following disclaimer in the documentation
  297. " and/or other materials provided with the distribution.
  298. "
  299. " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  300. " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  301. " IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  302. " ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  303. " LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  304. " CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  305. " SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  306. " INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  307. " CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  308. " ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  309. " POSSIBILITY OF SUCH DAMAGE.
  310. "
  311. "
  312. " # Development
  313. "
  314. " ## Contributing patches
  315. "
  316. " Patches can be sent via mail to greg@hurrell.net, or as GitHub pull requests
  317. " at: https://github.com/wincent/ferret/pulls
  318. "
  319. " ## Cutting a new release
  320. "
  321. " At the moment the release process is manual:
  322. "
  323. " - Perform final sanity checks and manual testing
  324. " - Update the |ferret-history| section of the documentation
  325. " - Verify clean work tree:
  326. "
  327. " ```
  328. " git status
  329. " ```
  330. "
  331. " - Tag the release:
  332. "
  333. " ```
  334. " git tag -s -m "$VERSION release" $VERSION
  335. " ```
  336. "
  337. " - Publish the code:
  338. "
  339. " ```
  340. " git push origin master --follow-tags
  341. " git push github master --follow-tags
  342. " ```
  343. "
  344. " - Produce the release archive:
  345. "
  346. " ```
  347. " git archive -o ferret-$VERSION.zip HEAD -- .
  348. " ```
  349. "
  350. " - Upload to http://www.vim.org/scripts/script.php?script_id=5220
  351. "
  352. "
  353. " # Authors
  354. "
  355. " Ferret is written and maintained by Greg Hurrell <greg@hurrell.net>.
  356. "
  357. " Other contributors that have submitted patches include (in alphabetical
  358. " order):
  359. "
  360. " - Daniel Silva
  361. " - Filip SzymaƄski
  362. " - Joe Lencioni
  363. " - Jon Parise
  364. " - Nelo Wallus
  365. " - Tom Dooner
  366. " - Vaibhav Sagar
  367. " - Yoni Weill
  368. "
  369. " This list produced with:
  370. "
  371. " ```
  372. " :read !git shortlog -s HEAD | grep -v 'Greg Hurrell' | cut -f 2-3 | sed -e 's/^/- /'
  373. " ```
  374. "
  375. " # History
  376. "
  377. " ## master (not yet released)
  378. "
  379. " - Add |g:FerretAckWordWord| setting, to pass `-w` to the underlying search
  380. " tool when |<Plug>(FerretAckWord)| is pressed
  381. " (https://github.com/wincent/ferret/issues/66).
  382. " - Use `:normal!` instead of |:normal| to avoid running custom mappings
  383. " (patch from Yoni Weill, https://github.com/wincent/ferret/pull/67).
  384. " - Append a trailing slash when autocompleting a directory name
  385. " (https://github.com/wincent/ferret/issues/69).
  386. "
  387. " ## 5.0 (8 June 2019)
  388. "
  389. " - The |<Plug>(FerretAcks)| mapping now uses |/\v| "very magic" mode by
  390. " default. This default can be changed using the |g:FerretVeryMagic| option.
  391. " - |:Acks| now preferentially uses |:cdo| (rather than |:cfdo|) to make
  392. " replacements, which means that it no longer operates on a per-file level and
  393. " instead targets individual entries within the |quickfix| window. This is
  394. " relevant if you've used Ferrets mappings to delete entries from the window.
  395. " The old behavior can be restored with the |g:FerretAcksCommand| option.
  396. " - Ferret now has a |:Lacks| command, an analog to |:Acks| which applies to the
  397. " |location-list|.
  398. " - Likewise, Ferret now has a |:Largs| command, analogous to |:Qargs|, which
  399. " applies to the |location-list| instead of the |quickfix| window.
  400. " - The Ferret bindings that are set-up in the |quickfix| window when
  401. " |g:FerretQFMap| is enabled now also apply to the |location-list|.
  402. "
  403. " ## 4.1 (31 January 2019)
  404. "
  405. " - Added |:Quack| command, analogous to |:Ack| but scoped to the files
  406. " currently listed in the |quickfix| window.
  407. " - Fixed option autocompletion.
  408. "
  409. " ## 4.0.2 (11 January 2019)
  410. "
  411. " - Restore compatibility with versions of `rg` prior to v0.8
  412. " (https://github.com/wincent/ferret/issues/59).
  413. "
  414. " ## 4.0.1 (8 January 2019)
  415. "
  416. " - Make |:Acks| behavior the same irrespective of the |'gdefault'| setting.
  417. "
  418. " ## 4.0 (25 December 2018)
  419. "
  420. " - Try to avoid "press ENTER to continue" prompts.
  421. " - Put search term in |w:quickfix_title| for use in statuslines
  422. " (https://github.com/wincent/ferret/pull/57).
  423. " - Add |g:FerretExecutableArguments| and |ferret#get_default_arguments()|
  424. " (https://github.com/wincent/ferret/pull/46).
  425. "
  426. " ## 3.0.3 (23 March 2018)
  427. "
  428. " - Fix for |:Lack| results opening in quickfix listing in Neovim
  429. " (https://github.com/wincent/ferret/issues/47).
  430. "
  431. " ## 3.0.2 (25 October 2017)
  432. "
  433. " - Fix broken |:Back| and |:Black| commands
  434. " (https://github.com/wincent/ferret/issues/48).
  435. "
  436. " ## 3.0.1 (24 August 2017)
  437. "
  438. " - Fix failure to handle search patterns containing multiple escaped spaces
  439. " (https://github.com/wincent/ferret/issues/49).
  440. "
  441. " ## 3.0 (13 June 2017)
  442. "
  443. " - Improve handling of backslash escapes
  444. " (https://github.com/wincent/ferret/issues/41).
  445. " - Add |g:FerretAutojump|.
  446. " - Drop support for vim-dispatch.
  447. "
  448. " ## 2.0 (6 June 2017)
  449. "
  450. " - Add support for Neovim, along with |g:FerretNvim| setting.
  451. "
  452. " ## 1.5 "Cinco de Cuatro" (4 May 2017)
  453. "
  454. " - Improvements to the handling of very large result sets (due to wide lines or
  455. " many results).
  456. " - Added |g:FerretLazyInit|.
  457. " - Added missing documentation for |g:FerretJob|.
  458. " - Added |g:FerretMaxResults|.
  459. " - Added feature-detection for `rg` and `ag`, allowing Ferret to gracefully
  460. " work with older versions of those tools that do not support all desired
  461. " command-line switches.
  462. "
  463. " ## 1.4 (21 January 2017)
  464. "
  465. " - Drop broken support for `grep`, printing a prompt to install `rg`, `ag`, or
  466. " `ack`/`ack-grep` instead.
  467. " - If an `ack` executable is not found, search for `ack-grep`, which is the
  468. " name used on Debian-derived distros.
  469. "
  470. " ## 1.3 (8 January 2017)
  471. "
  472. " - Reset |'errorformat'| before each search (fixes issue #31).
  473. " - Added |:Back| and |:Black| commands, analogous to |:Ack| and |:Lack| but
  474. " scoped to search within currently open buffers only.
  475. " - Change |:Acks| to use |:cfdo| when available rather than |:Qargs| and
  476. " |:argdo|, to avoid polluting the |arglist|.
  477. " - Remove superfluous |QuickFixCmdPost| autocommands, resolving clash with
  478. " Neomake plug-in (patch from Tom Dooner, #36).
  479. " - Add support for searching with ripgrep (`rg`).
  480. "
  481. " ## 1.2a (16 May 2016)
  482. "
  483. " - Add optional support for running searches asynchronously using Vim's |+job|
  484. " feature (enabled by default in sufficiently recent versions of Vim); see
  485. " |g:FerretJob|, |:FerretCancelAsync| and |:FerretPullAsync|.
  486. "
  487. " ## 1.1.1 (7 March 2016)
  488. "
  489. " - Fix another edge case when searching for patterns containing "#", only
  490. " manifesting under dispatch.vim.
  491. "
  492. " ## 1.1 (7 March 2016)
  493. "
  494. " - Fix edge case when searching for strings of the form "<foo>".
  495. " - Fix edge case when searching for patterns containing "#" and "%".
  496. " - Provide completion for `ag` and `ack` options when using |:Ack| and |:Lack|.
  497. " - Fix display of error messages under dispatch.vim.
  498. "
  499. " ## 1.0 (28 December 2015)
  500. "
  501. " - Fix broken |:Qargs| command (patch from Daniel Silva).
  502. " - Add |g:FerretQFHandler| and |g:FerretLLHandler| options (patch from Daniel
  503. " Silva).
  504. " - Make |<Plug>| mappings accessible even |g:FerretMap| is set to 0.
  505. " - Fix failure to report filename when using `ack` and explicitly scoping
  506. " search to a single file (patch from Daniel Silva).
  507. " - When using `ag`, report multiple matches per line instead of just the first
  508. " (patch from Daniel Silva).
  509. " - Improve content and display of error messages.
  510. "
  511. " ## 0.3 (24 July 2015)
  512. "
  513. " - Added highlighting of search pattern and related |g:FerretHlsearch| option
  514. " (patch from Nelo-Thara Wallus).
  515. " - Add better error reporting for failed or incorrect searches.
  516. "
  517. " ## 0.2 (16 July 2015)
  518. "
  519. " - Added |FerretDidWrite| and |FerretWillWrite| autocommands (patch from Joe
  520. " Lencioni).
  521. " - Add |<Plug>(FerretAcks)| mapping (patch from Nelo-Thara Wallus).
  522. "
  523. " ## 0.1 (8 July 2015)
  524. "
  525. " - Initial release, extracted from my dotfiles
  526. " (https://github.com/wincent/wincent).
  527. ""
  528. " @option g:FerretLoaded any
  529. "
  530. " To prevent Ferret from being loaded, set |g:FerretLoaded| to any value in your
  531. " |.vimrc|. For example:
  532. "
  533. " ```
  534. " let g:FerretLoaded=1
  535. " ```
  536. if exists('g:FerretLoaded') || &compatible || v:version < 700
  537. finish
  538. endif
  539. let g:FerretLoaded = 1
  540. " Temporarily set 'cpoptions' to Vim default as per `:h use-cpo-save`.
  541. let s:cpoptions = &cpoptions
  542. set cpoptions&vim
  543. ""
  544. " @option g:FerretLazyInit boolean 1
  545. "
  546. " In order to minimize impact on Vim start-up time Ferret will initialize itself
  547. " lazily on first use by default. If you wish to force immediate initialization
  548. " (for example, to cause |'grepprg'| and |'grepformat'| to be set as soon as Vim
  549. " launches), then set |g:FerretLazyInit| to 0 in your |.vimrc|:
  550. "
  551. " ```
  552. " let g:FerrerLazyInit=0
  553. " ```
  554. if !get(g:, 'FerretLazyInit', 1)
  555. call ferret#private#init()
  556. endif
  557. ""
  558. " @command :Ack {pattern} {options}
  559. "
  560. " Searches for {pattern} in all the files under the current directory (see
  561. " |:pwd|), unless otherwise overridden via {options}, and displays the results
  562. " in the |quickfix| listing.
  563. "
  564. " `rg` (ripgrep) then `ag` (The Silver Searcher) will be used preferentially if
  565. " present on the system, because they are faster, falling back to
  566. " `ack`/`ack-grep` as needed.
  567. "
  568. " On newer versions of Vim (version 8 and above), the search process runs
  569. " asynchronously in the background and does not block the UI.
  570. "
  571. " Asynchronous searches are preferred because they do not block, despite the
  572. " fact that Vim itself is single threaded.
  573. "
  574. " The {pattern} is passed through as-is to the underlying search program, and no
  575. " escaping is required other than preceding spaces by a single backslash. For
  576. " example, to search for "\bfoo[0-9]{2} bar\b" (ie. using `ag`'s Perl-style
  577. " regular expression syntax), you could do:
  578. "
  579. " ```
  580. " :Ack \bfoo[0-9]{2}\ bar\b
  581. " ```
  582. "
  583. " Likewise, {options} are passed through. In this example, we pass the `-w`
  584. " option (to search on word boundaries), and scope the search to the "foo" and
  585. " "bar" subdirectories:
  586. "
  587. " ```
  588. " :Ack -w something foo bar
  589. " ```
  590. "
  591. " As a convenience <leader>a is set-up (|<Plug>(FerretAck)|) as a shortcut to
  592. " enter |Cmdline-mode| with `:Ack` inserted on the |Cmdline|. Likewise <leader>s
  593. " (|<Plug>(FerretAckWord)|) is a shortcut for running |:Ack| with the word
  594. " currently under the cursor.
  595. "
  596. " @command :Ack! {pattern} {options}
  597. "
  598. " Like |:Ack|, but returns all results irrespective of the value of
  599. " |g:FerretMaxResults|.
  600. "
  601. command! -bang -nargs=1 -complete=customlist,ferret#private#ackcomplete Ack call ferret#private#ack(<bang>0, <q-args>)
  602. ""
  603. " @command :Lack {pattern} {options}
  604. "
  605. " Just like |:Ack|, but instead of using the |quickfix| listing, which is global
  606. " across an entire Vim instance, it uses the |location-list|, which is a
  607. " per-window construct.
  608. "
  609. " Note that |:Lack| always runs synchronously via |:cexpr|.
  610. "
  611. " @command :Lack! {pattern} {options}
  612. "
  613. " Like |:Lack|, but returns all results irrespective of the value of
  614. " |g:FerretMaxResults|.
  615. "
  616. command! -bang -nargs=1 -complete=customlist,ferret#private#lackcomplete Lack call ferret#private#lack(<bang>0, <q-args>)
  617. ""
  618. " @command :Back {pattern} {options}
  619. "
  620. " Like |:Ack|, but searches only listed buffers. Note that the search is still
  621. " delegated to the underlying |'grepprg'| (`rg`, `ag`, `ack` or `ack-grep`),
  622. " which means that only buffers written to disk will be searched. If no buffers
  623. " are written to disk, then |:Back| behaves exactly like |:Ack| and will search
  624. " all files in the current directory.
  625. "
  626. " @command :Back! {pattern} {options}
  627. "
  628. " Like |:Back|, but returns all results irrespective of the value of
  629. " |g:FerretMaxResults|.
  630. "
  631. command! -bang -nargs=1 -complete=customlist,ferret#private#backcomplete Back call ferret#private#back(<bang>0, <q-args>)
  632. ""
  633. " @command :Black {pattern} {options}
  634. "
  635. " Like |:Lack|, but searches only listed buffers. As with |:Back|, the search is
  636. " still delegated to the underlying |'grepprg'| (`rg`, `ag`, `ack` or
  637. " `ack-grep`), which means that only buffers written to disk will be searched.
  638. " Likewise, If no buffers are written to disk, then |:Black| behaves exactly
  639. " like |:Lack| and will search all files in the current directory.
  640. "
  641. " @command :Black! {pattern} {options}
  642. "
  643. " Like |:Black|, but returns all results irrespective of the value of
  644. " |g:FerretMaxResults|.
  645. "
  646. command! -bang -nargs=1 -complete=customlist,ferret#private#blackcomplete Black call ferret#private#black(<bang>0, <q-args>)
  647. ""
  648. " @command :Quack {pattern} {options}
  649. "
  650. " Like |:Ack|, but searches only among files currently in the |quickfix|
  651. " listing. Note that the search is still delegated to the underlying
  652. " |'grepprg'| (`rg`, `ag`, `ack` or `ack-grep`), which means that only
  653. " buffers written to disk will be searched. If no buffers are written
  654. " to disk, then |:Quack| behaves exactly like |:Ack| and will search all
  655. " files in the current directory.
  656. "
  657. " @command :Quack! {pattern} {options}
  658. "
  659. " Like |:Quack|, but returns all results irrespective of the value of
  660. " |g:FerretMaxResults|.
  661. "
  662. command! -bang -nargs=1 -complete=customlist,ferret#private#quackcomplete Quack call ferret#private#quack(<bang>0, <q-args>)
  663. ""
  664. " @command :Acks /{pattern}/{replacement}/
  665. "
  666. " Takes all of the files currently in the |quickfix| listing and performs a
  667. " substitution of all instances of {pattern} (a standard Vim search |pattern|)
  668. " by {replacement}.
  669. "
  670. " A typical sequence consists of an |:Ack| invocation to populate the |quickfix|
  671. " listing and then |:Acks| (mnemonic: "Ack substitute") to perform replacements.
  672. " For example, to replace "foo" with "bar" across all files in the current
  673. " directory:
  674. "
  675. " ```
  676. " :Ack foo
  677. " :Acks /foo/bar/
  678. " ```
  679. "
  680. " The pattern and replacement are passed through literally to Vim's
  681. " |:substitute| command, preserving all characters and escapes,
  682. " including references to matches in the pattern. For example, the
  683. " following could be used to swap the order of "foo123" and "bar":
  684. "
  685. " ```
  686. " :Acks /\v(foo\d+)(bar)/\2\1/
  687. " ```
  688. command! -nargs=1 Acks call ferret#private#acks(<q-args>, 'qf')
  689. ""
  690. " @command :Lacks /{pattern}/{replacement}/
  691. "
  692. " Takes all of the files in the current |location-list| and performs a
  693. " substitution of all instances of {pattern} by {replacement}. This is an analog
  694. " of the |:Acks| command, but operates on the |location-list| instead of the
  695. " |quickfix| listing.
  696. "
  697. command! -nargs=1 Lacks call ferret#private#acks(<q-args>, 'location')
  698. ""
  699. " @command :FerretCancelAsync
  700. "
  701. " Cancels any asynchronous search that may be in progress in the background.
  702. "
  703. command! FerretCancelAsync call ferret#private#async#cancel()
  704. ""
  705. " @command :FerretPullAsync
  706. "
  707. " Eagerly populates the |quickfix| (or |location-list|) window with any results
  708. " that may have been produced by a long-running asynchronous search in progress
  709. " in the background.
  710. "
  711. command! FerretPullAsync call ferret#private#async#pull()
  712. nnoremap <Plug>(FerretAck) :Ack<space>
  713. nnoremap <Plug>(FerretLack) :Lack<space>
  714. ""
  715. " @option g:FerretAckWordWord boolean 0
  716. "
  717. " When set to 1, passes the `-w` option to the underlying search tool whenever
  718. " |<Plug>(FerretAckWord)| is pressed. This forces the tool to match only on word
  719. " boundaries (ie. analagous to Vim's |star| mapping).
  720. "
  721. " The default is 0, which means the `-w` option is not passed and matches need
  722. " not occur on word boundaries (ie. analagous to Vim's |gstar| mapping).
  723. "
  724. " To override the default:
  725. "
  726. " ```
  727. " let g:FerretAckWordWord=1
  728. " ```
  729. let s:word=get(g:, 'FerretAckWordWord', 0)
  730. if s:word
  731. nnoremap <Plug>(FerretAckWord) :Ack -w <C-r><C-w><CR>
  732. else
  733. nnoremap <Plug>(FerretAckWord) :Ack <C-r><C-w><CR>
  734. endif
  735. nnoremap <Plug>(FerretAcks) :Acks <c-r>=(ferret#private#acks_prompt())<CR><Left><Left>
  736. ""
  737. " @option g:FerretMap boolean 1
  738. "
  739. " Controls whether to set up the Ferret mappings, such as |<Plug>(FerretAck)|
  740. " (see |ferret-mappings| for a full list). To prevent any mapping from being
  741. " configured, set to 0:
  742. "
  743. " ```
  744. " let g:FerretMap=0
  745. " ```
  746. let s:map=get(g:, 'FerretMap', 1)
  747. if s:map
  748. if !hasmapto('<Plug>(FerretAck)') && maparg('<leader>a', 'n') ==# ''
  749. ""
  750. " @mapping <Plug>(FerretAck)
  751. "
  752. " Ferret maps <leader>a to |<Plug>(FerretAck)|, which triggers the |:Ack|
  753. " command. To use an alternative mapping instead, create a different one in
  754. " your |.vimrc| instead using |:nmap|:
  755. "
  756. " ```
  757. " " Instead of <leader>a, use <leader>x.
  758. " nmap <leader>x <Plug>(FerretAck)
  759. " ```
  760. nmap <unique> <leader>a <Plug>(FerretAck)
  761. endif
  762. if !hasmapto('<Plug>FerretLack') && maparg('<leader>l', 'n') ==# ''
  763. ""
  764. " @mapping <Plug>(FerretLack)
  765. "
  766. " Ferret maps <leader>l to |<Plug>(FerretLack)|, which triggers the |:Lack|
  767. " command. To use an alternative mapping instead, create a different one in
  768. " your |.vimrc| instead using |:nmap|:
  769. "
  770. " ```
  771. " " Instead of <leader>l, use <leader>y.
  772. " nmap <leader>y <Plug>(FerretLack)
  773. " ```
  774. nmap <unique> <leader>l <Plug>(FerretLack)
  775. endif
  776. if !hasmapto('<Plug>(FerretAckWord)') && maparg('<leader>s', 'n') ==# ''
  777. ""
  778. " @mapping <Plug>(FerretAckWord)
  779. "
  780. " Ferret maps <leader>s (mnemonic: "selection) to |<Plug>(FerretAckWord)|,
  781. " which uses |:Ack| to search for the word currently under the cursor. To
  782. " use an alternative mapping instead, create a different one in your
  783. " |.vimrc| instead using |:nmap|:
  784. "
  785. " ```
  786. " " Instead of <leader>s, use <leader>z.
  787. " nmap <leader>z <Plug>(FerretAckWord)
  788. " ```
  789. nmap <unique> <leader>s <Plug>(FerretAckWord)
  790. endif
  791. if !hasmapto('<Plug>(FerretAcks)') && maparg('<leader>r', 'n') ==# ''
  792. ""
  793. " @mapping <Plug>(FerretAcks)
  794. "
  795. " Ferret maps <leader>r (mnemonic: "replace") to |<Plug>(FerretAcks)|, which
  796. " triggers the |:Acks| command and fills the prompt with the last search
  797. " term from Ferret. to use an alternative mapping instead, create a
  798. " different one in your |.vimrc| instead using |:nmap|:
  799. "
  800. " ```
  801. " " Instead of <leader>r, use <leader>u.
  802. " nmap <leader>u <Plug>(FerretAcks)
  803. " ```
  804. nmap <unique> <leader>r <Plug>(FerretAcks)
  805. endif
  806. endif
  807. ""
  808. " @command :Qargs
  809. "
  810. " This is a utility function that is used internally when running on older
  811. " versions of Vim (prior to version 8) but is also generally useful enough to
  812. " warrant being exposed publicly.
  813. "
  814. " It takes the files currently in the |quickfix| listing and sets them as
  815. " |:args| so that they can be operated on en masse via the |:argdo| command.
  816. command! -bar Qargs execute 'args' ferret#private#args('qf')
  817. ""
  818. " @command :Largs
  819. "
  820. " Just like |:Qargs|, but applies to the current |location-list|.
  821. "
  822. " It takes the files in the current |location-list| and sets them as
  823. " |:args| so that they can be operated on en masse via the |:argdo| command.
  824. command! -bar Largs execute 'args' ferret#private#args('location')
  825. ""
  826. " @option g:FerretQFCommands boolean 1
  827. "
  828. " Controls whether to set up custom versions of the |quickfix| commands, |:cn|,
  829. " |:cnf|, |:cp| an |:cpf|. These overrides vertically center the match within
  830. " the viewport on each jump. To prevent the custom versions from being
  831. " configured, set to 0:
  832. "
  833. " ```
  834. " let g:FerretQFCommands=0
  835. " ```
  836. let s:commands=get(g:, 'FerretQFCommands', 1)
  837. if s:commands
  838. " Keep quickfix result centered, if possible, when jumping from result to result.
  839. cabbrev <silent> <expr> cn ((getcmdtype() == ':' && getcmdpos() == 3) ? 'cn <bar> normal! zz' : 'cn')
  840. cabbrev <silent> <expr> cnf ((getcmdtype() == ':' && getcmdpos() == 4) ? 'cnf <bar> normal! zz' : 'cnf')
  841. cabbrev <silent> <expr> cp ((getcmdtype() == ':' && getcmdpos() == 3) ? 'cp <bar> normal! zz' : 'cp')
  842. cabbrev <silent> <expr> cpf ((getcmdtype() == ':' && getcmdpos() == 4) ? 'cpf <bar> normal! zz' : 'cpf')
  843. endif
  844. ""
  845. " @option g:FerretFormat string "%f:%l:%c:%m"
  846. "
  847. " Sets the '|grepformat|' used by Ferret.
  848. let g:FerretFormat=get(g:, 'FerretFormat', '%f:%l:%c:%m')
  849. " Restore 'cpoptions' to its former value.
  850. let &cpoptions = s:cpoptions
  851. unlet s:cpoptions