]> git.wincent.com - docvim.git/commitdiff
Share integration tests inputs across output types
authorGreg Hurrell <greg@hurrell.net>
Sat, 4 Jun 2016 14:20:49 +0000 (07:20 -0700)
committerGreg Hurrell <greg@hurrell.net>
Sat, 4 Jun 2016 14:20:49 +0000 (07:20 -0700)
May eventually share other things too (I still have some
manual symlinks going on), but this is a good start.

21 files changed:
bin/update-integration-tests [new file with mode: 0755]
tests/fixtures/markdown/integration-ferret-ftplugin-qf.vim [changed from file to symlink]
tests/fixtures/markdown/integration-ferret-plugin.vim [changed from file to symlink]
tests/fixtures/markdown/integration-ferret-private.vim [changed from file to symlink]
tests/fixtures/markdown/integration-pinnacle.vim [changed from file to symlink]
tests/fixtures/parser/integration-docvim.golden [moved from tests/fixtures/parser/integration.golden with 100% similarity]
tests/fixtures/parser/integration-docvim.vim [new symlink]
tests/fixtures/parser/integration-ferret-ftplugin-qf.vim [changed from file to symlink]
tests/fixtures/parser/integration-ferret-plugin.vim [changed from file to symlink]
tests/fixtures/parser/integration-ferret-private.vim [changed from file to symlink]
tests/fixtures/parser/integration-pinnacle.golden [new file with mode: 0644]
tests/fixtures/parser/integration-pinnacle.vim [new symlink]
tests/fixtures/shared/integration-docvim.vim [moved from tests/fixtures/parser/integration.vim with 100% similarity]
tests/fixtures/shared/integration-ferret-ftplugin-qf.vim [new file with mode: 0644]
tests/fixtures/shared/integration-ferret-plugin.vim [new file with mode: 0644]
tests/fixtures/shared/integration-ferret-private.vim [new file with mode: 0644]
tests/fixtures/shared/integration-pinnacle.vim [new file with mode: 0644]
tests/fixtures/vim/integration-ferret-ftplugin-qf.vim
tests/fixtures/vim/integration-ferret-plugin.vim
tests/fixtures/vim/integration-ferret-private.vim
tests/fixtures/vim/integration-pinnacle.vim

diff --git a/bin/update-integration-tests b/bin/update-integration-tests
new file mode 100755 (executable)
index 0000000..78fada4
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+for TYPE in tests/fixtures/*; do
+  if [ $TYPE != "tests/fixtures/shared" ]; then
+    (
+      echo "In $TYPE:"
+      cd $TYPE
+      for TEST in ../shared/integration-*; do
+        echo "Linking: $TEST"
+        ln -sf $TEST
+      done
+    )
+  fi
+done
deleted file mode 100644 (file)
index 2d277d9ba309046b62db88fadac86f25d70228a7..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,64 +0,0 @@
-" Copyright 2015-present Greg Hurrell. All rights reserved.
-" Licensed under the terms of the BSD 2-clause license.
-
-""
-" @option g:FerretQFOptions boolean 1
-"
-" Controls whether to set up setting overrides for |quickfix| windows. These are
-" various settings, such as |norelativenumber|, |nolist| and |nowrap|, that are
-" intended to make the |quickfix| window, which is typically very small relative
-" to other windows, more usable.
-"
-" A full list of overridden settings can be found in |ferret-overrides|.
-"
-" To prevent the custom settings from being applied, set |g:FerretQFOptions|
-" to 0:
-"
-" ```
-" let g:FerretQFOptions=0
-" ```
-let s:options=get(g:, 'FerretQFOptions', 1)
-if s:options
-  setlocal nolist
-  if exists('+relativenumber')
-    setlocal norelativenumber
-  endif
-  setlocal nowrap
-  setlocal number
-
-  " Want to set scrolloff only for the qf window, but it is a global option.
-  let s:original_scrolloff=&scrolloff
-  set scrolloff=0
-
-  if has('autocmd')
-    augroup FerretQF
-      autocmd!
-      autocmd BufLeave <buffer> execute 'set scrolloff=' . s:original_scrolloff
-      autocmd BufEnter <buffer> set scrolloff=0 | setlocal nocursorline
-    augroup END
-  endif
-endif
-
-""
-" @option g:FerretQFMap boolean 1
-"
-" Controls whether to set up mappings in the |quickfix| results window for
-" deleting results. The mappings include:
-"
-" - `d` (|visual-mode|): delete visual selection
-" - `dd` (|Normal-mode|): delete current line
-" - `d`{motion} (|Normal-mode|): delete range indicated by {motion}
-"
-" To prevent these mappings from being set up, set to 0:
-"
-" ```
-" let g:FerretQFMap=0
-" ```
-let s:map=get(g:, 'FerretQFMap', 1)
-if s:map
-  " Make it easy to remove entries from the quickfix listing.
-  " TODO: distinguish between quickfix and location list
-  nnoremap <buffer> <silent> d :set operatorfunc=ferret#private#qf_delete_motion<CR>g@
-  nnoremap <buffer> <silent> dd :call ferret#private#qf_delete()<CR>
-  vnoremap <buffer> <silent> d :call ferret#private#qf_delete()<CR>
-endif
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..4051b06dee54232870b47194800f6aa804c78e63
--- /dev/null
@@ -0,0 +1 @@
+../shared/integration-ferret-ftplugin-qf.vim
\ No newline at end of file
deleted file mode 100644 (file)
index e41107d9393d7dd7f6f5c2ca5bfe63ae4705d33c..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,601 +0,0 @@
-" Copyright 2015-present Greg Hurrell. All rights reserved.
-" Licensed under the terms of the BSD 2-clause license.
-
-""
-" @plugin ferret Ferret plug-in for Vim
-"
-" # Intro
-"
-" > "ferret (verb)<br />
-" > (ferret something out) search tenaciously for and find something: she had
-" > the ability to ferret out the facts."
-"
-"                                                               *ferret-features*
-" Ferret improves Vim's multi-file search in four ways:
-"
-" ## 1. Powerful multi-file search
-"
-" Ferret provides an |:Ack| command for searching across multiple files using
-" The Silver Searcher (https://github.com/ggreer/the_silver_searcher), Ack
-" (http://beyondgrep.com/), or Grep (http://www.gnu.org/software/grep/). 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.
-"
-" Shortcut mappings are provided to start an |:Ack| search (<leader>a) or to
-" search for the word currently under the cursor (<leader>s).
-"
-" Results are normally displayed in the |quickfix| window, but Ferret also
-" provides a |:Lack| command that behaves like |:Ack| but uses the
-" |location-list| instead, and a <leader>l mapping as a shortcut to |:Lack|.
-"
-" Finally, Ferret offers integration with dispatch.vim
-" (https://github.com/tpope/vim-dispatch), which enables asynchronous searching
-" despite the fact that Vim itself is single-threaded.
-"
-" ## 2. Streamlined multi-file replace
-"
-" The companion to |:Ack| is |:Acks| (mnemonic: "Ack substitute", accessible via
-" shortcut <leader>r), which allows you to run a multi-file replace across all
-" the files placed in the |quickfix| window by a previous invocation of |:Ack|.
-"
-" ## 3. Quickfix listing enhancements
-"
-" The |quickfix| listing itself is enhanced with settings to improve its
-" usability, and natural mappings that allow quick removal of items from the
-" list (for example, you can reduce clutter in the listing by removing lines
-" that you don't intend to make changes to).
-"
-" Additionally, Vim's |:cn|, |:cp|, |:cnf| and |:cpf| commands are tweaked to
-" make it easier to immediately identify matches by centering them within the
-" viewport.
-"
-" ## 4. Easy operations on files in the quickfix listing
-"
-" Finally, Ferret provides a |:Qargs| command that puts the files currently in
-" the |quickfix| listing into the |:args| list, where they can be operated on in
-" bulk via the |:argdo| command. This is what's used under the covers by |:Acks|
-" to do its work.
-"
-"
-" # Installation
-"
-" To install Ferret, use your plug-in management system of choice.
-"
-" If you don't have a "plug-in management system of choice", I recommend
-" Pathogen (https://github.com/tpope/vim-pathogen) due to its simplicity and
-" robustness. Assuming that you have Pathogen installed and configured, and that
-" you want to install Ferret into `~/.vim/bundle`, you can do so with:
-"
-" ```
-" git clone https://github.com/wincent/ferret.git ~/.vim/bundle/ferret
-" ```
-"
-" Alternatively, if you use a Git submodule for each Vim plug-in, you could do
-" the following after `cd`-ing into the top-level of your Git superproject:
-"
-" ```
-" git submodule add https://github.com/wincent/ferret.git ~/vim/bundle/ferret
-" git submodule init
-" ```
-"
-" To generate help tags under Pathogen, you can do so from inside Vim with:
-"
-" ```
-" :call pathogen#helptags()
-" ```
-"
-" @mappings
-"
-" ## Circumstances where mappings do not get set up
-"
-" Note that Ferret will not try to set up the <leader> mappings if any of the
-" following are true:
-"
-" - A mapping for already exists.
-" - An alternative mapping for the same functionality has already been set up
-"   from a |.vimrc|.
-" - The mapping has been suppressed by setting |g:FerretMap| to 1 in your
-"   |.vimrc|.
-"
-" ## Mappings specific to the quickfix window
-"
-" Additionally, Ferret will set up special mappings in |quickfix| listings,
-" unless prevented from doing so by |g:FerretQFMap|:
-"
-" - `d` (|visual-mode|): delete visual selection
-" - `dd` (|Normal-mode|): delete current line
-" - `d`{motion} (|Normal-mode|): delete range indicated by {motion}
-"
-"
-" @footer
-"
-" # Custom autocommands
-"
-"                                                *FerretWillWrite* *FerretDidWrite*
-" For maximum compatibility with other plug-ins, Ferret runs the following
-" "User" autocommands before and after running the file writing operations
-" during |:Acks|:
-"
-" - FerretWillWrite
-" - FerretDidWrite
-"
-" For example, to call a pair of custom functions in response to these events,
-" you might do:
-"
-" ```
-" autocmd! User FerretWillWrite
-" autocmd User FerretWillWrite call CustomWillWrite()
-" autocmd! User FerretDidWrite
-" autocmd User FerretDidWrite call CustomDidWrite()
-" ```
-"
-"
-" # Overrides
-"
-" Ferret overrides the 'grepformat' and 'grepprg' settings, preferentially
-" setting `ag`, `ack` or `grep` as the 'grepprg' (in that order) and configuring
-" a suitable 'grepformat'.
-"
-" Additionally, Ferret includes an |ftplugin| for the |quickfix| listing that
-" adjusts a number of settings to improve the usability of search results.
-"
-" @indent
-"                                                                 *ferret-nolist*
-"   'nolist'
-"
-"   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 |quickfix| results.
-"
-"                                                       *ferret-norelativenumber*
-"   'norelativenumber'
-"
-"   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 |:cnf| and |:cpf|
-"   respectively).
-"
-"                                                                 *ferret-nowrap*
-"   'nowrap'
-"
-"   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.
-"
-"                                                                 *ferret-number*
-"   'number'
-"
-"   Turned on to give a sense of absolute progress through the results.
-"
-"                                                              *ferret-scrolloff*
-"   'scrolloff'
-"
-"   Set to 0 because the |quickfix| 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.
-"
-"                                                           *ferret-nocursorline*
-"   'nocursorline'
-"
-"   Turned off to reduce visual clutter.
-"
-" @dedent
-"
-" To prevent any of these |quickfix|-specific overrides from being set up, you
-" can set |g:FerretQFOptions| to 0 in your |.vimrc|:
-"
-" ```
-" let g:FerretQFOptions=0
-" ```
-"
-"
-" # Troubleshooting
-"
-"                                                                 *ferret-quotes*
-" ## Ferret fails to find patterns containing spaces
-"
-" As described in the documentation for |:Ack|, the search pattern is passed
-" through as-is to the underlying search command, and no escaping is required
-" other than preceding spaces by a single backslash.
-"
-" So, to find "foo bar", you would search like:
-"
-" ```
-" :Ack foo\ bar
-" ```
-"
-" Unescaped spaces in the search are treated as argument separators, so a
-" command like the following means pass the `-w` option through, search for
-" pattern "foo", and limit search to the "bar" directory:
-"
-" ```
-" :Ack -w foo bar
-" ```
-"
-" Note that including quotes will not do what you intend.
-"
-" ```
-" " Search for '"foo' in the 'bar"' directory:
-" :Ack "foo bar"
-"
-" " Search for "'foo' in the "bar'" directory:
-" :Ack 'foo bar'
-" ```
-"
-" This approach to escaping is taken in order to make it straightfoward to use
-" powerful Perl-compatible regular expression syntax in an unambiguous way
-" without having to worry about shell escaping rules:
-"
-" ```
-" :Ack \blog\((['"]).*?\1\) -i --ignore-dir=src/vendor src dist build
-" ```
-"
-"
-" # FAQ
-"
-" ## Why do Ferret commands start with "Ack", "Lack" and so on?
-"
-" Ferret was originally the thinnest of wrappers (7 lines of code in my
-" |.vimrc|) 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).
-"
-" So, even though Ferret has a new name now and actually prefers `ag` over `ack`
-" when available, I prefer to keep the command names intact and benefit from
-" years of accumulated muscle-memory.
-"
-"
-"
-" # Related
-"
-" Just as Ferret aims to improve the multi-file search and replace experience,
-" Loupe does the same for within-file searching:
-"
-"   https://github.com/wincent/loupe
-"
-"
-" # Website
-"
-" The official Ferret source code repo is at:
-"
-"   http://git.wincent.com/ferret.git
-"
-" A mirror exists at:
-"
-"   https://github.com/wincent/ferret
-"
-" Official releases are listed at:
-"
-"   http://www.vim.org/scripts/script.php?script_id=5220
-"
-"
-" # License
-"
-" Copyright 2015-present Greg Hurrell. All rights reserved.
-"
-" Redistribution and use in source and binary forms, with or without
-" modification, are permitted provided that the following conditions are met:
-"
-" 1. Redistributions of source code must retain the above copyright notice,
-"    this list of conditions and the following disclaimer.
-" 2. Redistributions in binary form must reproduce the above copyright notice,
-"    this list of conditions and the following disclaimer in the documentation
-"    and/or other materials provided with the distribution.
-"
-" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-" POSSIBILITY OF SUCH DAMAGE.
-"
-"
-" # Development
-"
-" ## Contributing patches
-"
-" Patches can be sent via mail to greg@hurrell.net, or as GitHub pull requests
-" at: https://github.com/wincent/ferret/pulls
-"
-" ## Cutting a new release
-"
-" At the moment the release process is manual:
-"
-" - Perform final sanity checks and manual testing
-" - Update the |ferret-history| section of the documentation
-" - Verify clean work tree:
-"
-" ```
-" git status
-" ```
-"
-" - Tag the release:
-"
-" ```
-" git tag -s -m "$VERSION release" $VERSION
-" ```
-"
-" - Publish the code:
-"
-" ```
-" git push origin master --follow-tags
-" git push github master --follow-tags
-" ```
-"
-" - Produce the release archive:
-"
-" ```
-" git archive -o ferret-$VERSION.zip HEAD -- .
-" ```
-"
-" - Upload to http://www.vim.org/scripts/script.php?script_id=5220
-"
-"
-" # Authors
-"
-" 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
-" - Joe Lencioni
-" - Nelo-Thara Wallus
-" - Vaibhav Sagar
-"
-"
-" # History
-"
-" 0.3.1 (not yet released)
-"
-" - Fix broken |:Qargs| command (patch from Daniel Silva).
-"
-" 0.3 (24 July 2015)
-"
-" - Added highlighting of search pattern and related |g:FerretHlsearch| option
-"   (patch from Nelo-Thara Wallus).
-" - Add better error reporting for failed or incorrect searches.
-"
-" 0.2 (16 July 2015)
-"
-" - Added |FerretDidWrite| and |FerretWillWrite| autocommands (patch from Joe
-"   Lencioni).
-" - Add |<Plug>(FerretAcks)| mapping (patch from Nelo-Thara Wallus).
-"
-" 0.1 (8 July 2015)
-"
-" - Initial release, extracted from my dotfiles
-"   (https://github.com/wincent/wincent).
-
-""
-" @option g:FerretLoaded any
-"
-" To prevent Ferret from being loaded, set |g:FerretLoaded| to any value in your
-" |.vimrc|. For example:
-"
-" ```
-" let g:FerretLoaded=1
-" ```
-if exists('g:FerretLoaded') || &compatible || v:version < 700
-  finish
-endif
-let g:FerretLoaded = 1
-
-" Temporarily set 'cpoptions' to Vim default as per `:h use-cpo-save`.
-let s:cpoptions = &cpoptions
-set cpoptions&vim
-
-if executable('ag') " The Silver Searcher: faster than ack.
-  let s:ackprg = 'ag --column --nocolor --nogroup'
-elseif executable('ack') " Ack: better than grep.
-  let s:ackprg = 'ack --column'
-elseif executable('grep') " Grep: it's just grep.
-  let s:ackprg = &grepprg " default is: grep -n $* /dev/null
-endif
-
-if !empty(s:ackprg)
-  let &grepprg=s:ackprg
-  set grepformat=%f:%l:%c:%m
-endif
-
-if has('autocmd')
-  augroup Ferret
-    autocmd!
-    autocmd QuickFixCmdPost [^l]* nested cwindow
-    autocmd QuickFixCmdPost l* nested lwindow
-  augroup END
-endif
-
-""
-" @command :Ack {pattern} {options}
-"
-" Searches for {pattern} in all the files under the current directory (see
-" |:pwd|), unless otherwise overridden via {options}, and displays the results
-" in the |quickfix| listing.
-"
-" `ag` (The Silver Searcher) will be used preferentially if present on the
-" system, because it is faster, falling back to `ack` and then `grep` as needed.
-"
-" If dispatch.vim is installed the search process will run asynchronously via
-" the |:Make| command, otherwise it will be run synchronously via |:cexpr|.
-" Asynchronous searches are preferred because they do not block, despite the
-" fact that Vim itself is single threaded. The |g:FerretDispatch| option can be
-" used to prevent the use of dispatch.vim.
-"
-" 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: >
-"
-" ```
-" :Ack -w something foo bar
-" ```
-"
-" As a convenience <leader>a is set-up (|<Plug>(FerretAck)|) as a shortcut to
-" enter |Cmdline-mode| with `:Ack` inserted on the |Cmdline|. Likewise <leader>s
-" (|<Plug>(FerretAckWord)|) is a shortcut for running |:Ack| with the word
-" currently under the cursor.
-command! -nargs=+ -complete=file Ack call ferret#private#ack(<q-args>)
-
-""
-" @command :Lack {pattern} {options}
-"
-" Just like |:Ack|, but instead of using the |quickfix| listing, which is global
-" across an entire Vim instance, it uses the |location-list|, which is a
-" per-window construct.
-"
-" Note that |:Lack| always runs synchronously via |:cexpr|, because dispatch.vim
-" doesn't currently support the |location-list|.
-command! -nargs=+ -complete=file Lack call ferret#private#lack(<q-args>)
-
-""
-" @command :Acks /{pattern}/{replacement}/
-"
-" Takes all of the files currently in the |quickfix| listing and performs a
-" substitution of all instances of {pattern} (a standard Vim search |pattern|)
-" by {replacement}.
-"
-" A typical sequence consists of an |:Ack| invocation to populate the |quickfix|
-" listing and then |:Acks| (mnemonic: "Ack substitute") to perform replacements.
-" For example, to replace "foo" with "bar" across all files in the current
-" directory:
-"
-" ```
-" :Ack foo
-" :Acks /foo/bar/
-" ```
-command! -nargs=1 Acks call ferret#private#acks(<q-args>)
-
-""
-" @option g:FerretMap boolean 1
-"
-" Controls whether to set up the Ferret mappings, such as |<Plug>(FerretAck)|
-" (see |ferret-mappings| for a full list). To prevent any mapping from being
-" configured, set to 0:
-"
-" ```
-" let g:FerretMap=0
-" ```
-let s:map=get(g:, 'FerretMap', 1)
-if s:map
-  if !hasmapto('<Plug>(FerretAck)') && maparg('<leader>a', 'n') ==# ''
-    ""
-    " @mapping <Plug>(FerretAck)
-    "
-    " Ferret maps <leader>a to |<Plug>(FerretAck)|, which triggers the |:Ack|
-    " command. To use an alternative mapping instead, create a different one in
-    " your |.vimrc| instead using |:nmap|:
-    "
-    " ```
-    " " Instead of <leader>a, use <leader>x.
-    " nmap <leader>x <Plug>(FerretAck)
-    " ```
-    nmap <unique> <leader>a <Plug>(FerretAck)
-  endif
-  nnoremap <Plug>(FerretAck) :Ack<space>
-
-  if !hasmapto('<Plug>FerretLack') && maparg('<leader>l', 'n') ==# ''
-    ""
-    " @mapping <Plug>(FerretLack)
-    "
-    " Ferret maps <leader>l to |<Plug>(FerretLack)|, which triggers the |:Lack|
-    " command. To use an alternative mapping instead, create a different one in
-    " your |.vimrc| instead using |:nmap|:
-    "
-    " ```
-    " " Instead of <leader>l, use <leader>y.
-    " nmap <leader>y <Plug>(FerretLack)
-    " ```
-    nmap <unique> <leader>l <Plug>(FerretLack)
-  endif
-  nnoremap <Plug>(FerretLack) :Lack<space>
-
-  if !hasmapto('<Plug>(FerretAckWord)') && maparg('<leader>s', 'n') ==# ''
-    " Call :Ack with word currently under cursor (mnemonic: selection).
-
-
-    ""
-    " @mapping <Plug>(FerretAckWord)
-    "
-    " Ferret maps <leader>s (mnemonix: "selection) to |<Plug>(FerretAckWord)|,
-    " which uses |:Ack| to search for the word currently under the cursor. To
-    " use an alternative mapping instead, create a different one in your
-    " |.vimrc| instead using |:nmap|:
-    "
-    " ```
-    " " Instead of <leader>s, use <leader>z.
-    " nmap <leader>z <Plug>(FerretAckWord)
-    " ```
-    nmap <unique> <leader>s <Plug>(FerretAckWord)
-  endif
-  nnoremap <Plug>(FerretAckWord) :Ack <C-r><C-w><CR>
-
-  if !hasmapto('<Plug>(FerretAcks)') && maparg('<leader>r', 'n') ==# ''
-    ""
-    " @mapping *<Plug>(FerretAcks)*
-    "
-    " Ferret maps <leader>r (mnemonic: "replace") to |<Plug>(FerretAcks)|, which
-    " triggers the |:Acks| command and fills the prompt with the last search
-    " term from Ferret. to use an alternative mapping instead, create a
-    " different one in your |.vimrc| instead using |:nmap|:
-    "
-    " ```
-    " " Instead of <leader>r, use <leader>u.
-    " nmap <leader>u <Plug>(FerretAcks)
-    " ```
-    nmap <unique> <leader>r <Plug>(FerretAcks)
-  endif
-  nnoremap <Plug>(FerretAcks)
-        \ :Acks <c-r>=(exists('g:ferret_lastsearch') ? '/' . g:ferret_lastsearch . '//' : ' ')<CR><Left>
-endif
-
-""
-" @command :Qargs
-"
-" This is a utility function that is used by the |:Acks| command but is also
-" generally useful enough to warrant being exposed publicly.
-"
-" It takes the files currently in the |quickfix| listing and sets them as
-" |:args| so that they can be operated on en masse via the |:argdo| command.
-command! -bar Qargs execute 'args' ferret#private#qargs()
-
-""
-" @option g:FerretQFCommands boolean 1
-"
-" Controls whether to set up custom versions of the |quickfix| commands, |:cn|,
-" |:cnf|, |:cp| an |:cpf|. These overrides vertically center the match within
-" the viewport on each jump. To prevent the custom versions from being
-" configured, set to 0:
-"
-" ```
-" let g:FerretQFCommands=0
-" ```
-let s:commands=get(g:, 'FerretQFCommands', 1)
-if s:commands
-  " Keep quickfix result centered, if possible, when jumping from result to result.
-  cabbrev <silent> <expr> cn ((getcmdtype() == ':' && getcmdpos() == 3) ? 'cn <bar> normal zz' : 'cn')
-  cabbrev <silent> <expr> cnf ((getcmdtype() == ':' && getcmdpos() == 4) ? 'cnf <bar> normal zz' : 'cnf')
-  cabbrev <silent> <expr> cp ((getcmdtype() == ':' && getcmdpos() == 3) ? 'cp <bar> normal zz' : 'cp')
-  cabbrev <silent> <expr> cpf ((getcmdtype() == ':' && getcmdpos() == 4) ? 'cpf <bar> normal zz' : 'cpf')
-endif
-
-" Restore 'cpoptions' to its former value.
-let &cpoptions = s:cpoptions
-unlet s:cpoptions
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..4634fa0a49e91bd7a0b6dc6183e78033daf1c759
--- /dev/null
@@ -0,0 +1 @@
+../shared/integration-ferret-plugin.vim
\ No newline at end of file
deleted file mode 100644 (file)
index 72b68b451d5e22e4a934ff9d4d80d04bbc4fe047..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,315 +0,0 @@
-" Copyright 2015-present Greg Hurrell. All rights reserved.
-" Licensed under the terms of the BSD 2-clause license.
-
-" Remove lines a:first through a:last from the quickfix listing.
-function! s:delete(first, last)
-  let l:list=getqflist()
-  let l:line=a:first
-
-  while l:line >= a:first && l:line <= a:last
-    " Non-dictionary items will be ignored. This effectively deletes the line.
-    let l:list[l:line - 1]=0
-    let l:line=l:line + 1
-  endwhile
-  call setqflist(l:list, 'r')
-
-  " Show to next entry.
-  execute 'cc ' . a:first
-
-  " Move focus back to quickfix listing.
-  execute "normal \<C-W>\<C-P>"
-endfunction
-
-" Returns 1 if we should/can use vim-dispatch.
-function! s:dispatch()
-  ""
-  " @option g:FerretDispatch 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:
-  "
-  " ```
-  " let g:FerretDispatch=0
-  " ```
-  let l:dispatch=get(g:, 'FerretDispatch', 1)
-  return l:dispatch && exists(':Make') == 2
-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! s:error(message) abort
-  call inputsave()
-  echohl ErrorMsg
-  call input(a:message . ': press ENTER to continue')
-  echohl NONE
-  call inputrestore()
-  echo
-endfunction
-
-" Parses arguments, extracting a search pattern (which is stored in
-" g:ferret_lastsearch) and escaping space-delimited arguments for use by
-" `system()`. A string containing all the escaped arguments is returned.
-"
-" The basic strategy is to split on spaces, expand wildcards for non-option
-" arguments, shellescape each word, and join.
-"
-" To support an edge-case (the ability to search for strings with spaces in
-" them, however, we swap out escaped spaces first (subsituting the unlikely
-" "<!!S!!>") and then swap them back in at the end. This allows us to perform
-" searches like:
-"
-"   :Ack -i \bFoo_?Bar\b
-"   :Ack that's\ nice\ dear
-"
-" and so on...
-function! s:parse(arg) abort
-  if exists('g:ferret_lastsearch')
-    unlet g:ferret_lastsearch
-  endif
-
-  let l:escaped_spaces_replaced_with_markers=substitute(a:arg, '\\ ', '<!!S!!>', 'g')
-  let l:split_on_spaces=split(l:escaped_spaces_replaced_with_markers)
-  let l:expanded_args=[]
-
-  for l:arg in l:split_on_spaces
-    if l:arg =~# '^-'
-      " Options get passed through as-is.
-      call add(l:expanded_args, l:arg)
-    elseif exists('g:ferret_lastsearch')
-      let l:file_args=glob(l:arg, 1, 1) " Ignore 'wildignore', return a list.
-      if len(l:file_args)
-        call extend(l:expanded_args, l:file_args)
-      else
-        " Let through to `ag`/`ack`/`grep`, which will throw ENOENT.
-        call add(l:expanded_args, l:arg)
-      endif
-    else
-      " First non-option arg is considered to be search pattern.
-      let g:ferret_lastsearch=substitute(l:arg, '<!!S!!>', ' ', 'g')
-      call add(l:expanded_args, l:arg)
-    endif
-  endfor
-
-  let l:each_word_shell_escaped=map(l:expanded_args, 'shellescape(v:val)')
-  let l:joined=join(l:each_word_shell_escaped)
-  return substitute(l:joined, '<!!S!!>', ' ', 'g')
-endfunction
-
-function! ferret#private#post(type) abort
-  if has('autocmd')
-    augroup FerretPostQF
-      autocmd!
-    augroup END
-  endif
-
-  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 . '`'
-
-    " Search pattern has no spaces and is entirely enclosed in quotes;
-    " eg 'foo' or "bar"
-    if l:lastsearch =~ '\v^([' . "'" . '"])[^ \1]+\1$'
-      call s:error(l:base . l:tip)
-    else
-      call s:error(l:base)
-    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)
-      " Every item in the list was invalid.
-      redraw!
-      echohl ErrorMsg
-      for l:item in l:invalid
-        echomsg l:item.text
-      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' && s:dispatch() ?
-            \ ' (run `:messages` to see details)' :
-            \ ''
-
-      " 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 s:error(l:base . l:tip . l:suffix)
-      else
-        call s:error(l:base . l:suffix)
-      endif
-    endif
-  endif
-endfunction
-
-function! ferret#private#ack(command) abort
-  let l:command=s:parse(a:command)
-  call ferret#private#hlsearch()
-
-  if empty(&grepprg)
-    return
-  endif
-
-  " Prefer vim-dispatch unless otherwise instructed.
-  if s:dispatch()
-    if has('autocmd')
-      augroup FerretPostQF
-        autocmd!
-        autocmd QuickfixCmdPost cgetfile call ferret#private#post('qf')
-      augroup END
-    endif
-    let l:original_makeprg=&l:makeprg
-    let l:original_errorformat=&l:errorformat
-    try
-      let &l:makeprg=&grepprg . ' ' . l:command
-      let &l:errorformat=&grepformat
-      Make
-    catch
-      if has('autocmd')
-        augroup! FerretPostQF
-      endif
-    finally
-      let &l:makeprg=l:original_makeprg
-      let &l:errorformat=l:original_errorformat
-    endtry
-  else
-    cexpr system(&grepprg . ' ' . l:command)
-    cwindow
-    call ferret#private#post('qf')
-  endif
-endfunction
-
-function! ferret#private#lack(command) abort
-  let l:command=s:parse(a:command)
-  call ferret#private#hlsearch()
-
-  if empty(&grepprg)
-    return
-  endif
-
-  lexpr system(&grepprg . ' ' . l:command)
-  lwindow
-  call ferret#private#post('location')
-endfunction
-
-function! ferret#private#hlsearch() abort
-  if has('extra_search')
-    ""
-    " @option g:FerretHlsearch boolean
-    "
-    " Controls whether Ferret should attempt to highlight the search pattern
-    " when running |:Ack| or |:Lack|. If left unset, Ferret will respect the
-    " current 'hlsearch' setting. To force highlighting on or off irrespective
-    " of 'hlsearch', set |g:FerretHlsearch| to 1 (on) or 0 (off):
-    "
-    " ```
-    " let g:FerretHlsearch=0
-    " ```
-    let l:hlsearch=get(g:, 'FerretHlsearch', &hlsearch)
-    if l:hlsearch
-      let @/=g:ferret_lastsearch
-      call feedkeys(":let &hlsearch=1 | echo \<CR>", 'n')
-    endif
-  endif
-endfunction
-
-" Run the specified substitution command on all the files in the quickfix list
-" (mnemonic: "Ack substitute").
-"
-" Specifically, the sequence:
-"
-"   :Ack foo
-"   :Acks /foo/bar/
-"
-" is equivalent to:
-"
-"   :Ack foo
-"   :Qargs
-"   :argdo %s/foo/bar/ge | update
-"
-" (Note: there's nothing specific to Ack in this function; it's just named this
-" way for mnemonics, as it will most often be preceded by an :Ack invocation.)
-function! ferret#private#acks(command) abort
-  if match(a:command, '\v^/.+/.*/$') == -1 " crude sanity check
-    echoerr 'Ferret: Expected a substitution expression (/foo/bar/); got: ' . a:command
-    return
-  endif
-
-  let l:filenames=ferret#private#qargs()
-  if l:filenames ==# ''
-    echoerr 'Ferret: Quickfix filenames must be present, but there are none'
-    return
-  endif
-
-  execute 'args' l:filenames
-
-  if v:version > 703 || v:version == 703 && has('patch438')
-    silent doautocmd <nomodeline> User FerretWillWrite
-  else
-    silent doautocmd User FerretWillWrite
-  endif
-  execute 'argdo' '%s' . a:command . 'ge | update'
-  if v:version > 703 || v:version == 703 && has('patch438')
-    silent doautocmd <nomodeline> User FerretDidWrite
-  else
-    silent doautocmd User FerretDidWrite
-  endif
-endfunction
-
-" Populate the :args list with the filenames currently in the quickfix window.
-function! ferret#private#qargs() abort
-  let l:buffer_numbers={}
-  for l:item in getqflist()
-    let l:buffer_numbers[l:item['bufnr']]=bufname(l:item['bufnr'])
-  endfor
-  return join(map(values(l:buffer_numbers), 'fnameescape(v:val)'))
-endfunction
-
-" Visual mode deletion and `dd` mapping (special case).
-function! ferret#private#qf_delete() range
-  call s:delete(a:firstline, a:lastline)
-endfunction
-
-" Motion-based deletion from quickfix listing.
-function! ferret#private#qf_delete_motion(type, ...)
-  " Save.
-  let l:selection=&selection
-  let &selection='inclusive'
-
-  let l:firstline=line("'[")
-  let l:lastline=line("']")
-  call s:delete(l:firstline, l:lastline)
-
-  " Restore.
-  let &selection=l:selection
-endfunction
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..b19e38c3145dbd7ab0b231c2b4210bbc9af114e7
--- /dev/null
@@ -0,0 +1 @@
+../shared/integration-ferret-private.vim
\ No newline at end of file
deleted file mode 100644 (file)
index 66db7889fb87b1bd1234065793ffe7dae9a3e90a..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,128 +0,0 @@
-""
-" @plugin Pinnacle Highlight group manipulation for Vim
-"
-" # Intro
-"
-" Pinnacle provides functions for manipulating |:highlight| groups.
-"
-"
-" # Installation
-"
-" To install Pinnacle, use your plug-in management system of choice.
-"
-" If you don't have a "plug-in management system of choice", I recommend
-" Pathogen (https://github.com/tpope/vim-pathogen) due to its simplicity and
-" robustness. Assuming that you have Pathogen installed and configured, and that
-" you want to install vim-docvim into `~/.vim/bundle`, you can do so with:
-"
-" ```
-" git clone https://github.com/wincent/pinnacle.git ~/.vim/bundle/pinnacle
-" ```
-"
-" Alternatively, if you use a Git submodule for each Vim plug-in, you could do
-" the following after `cd`-ing into the top-level of your Git superproject:
-"
-" ```
-" git submodule add https://github.com/wincent/pinnacle.git ~/vim/bundle/pinnacle
-" git submodule init
-" ```
-"
-" To generate help tags under Pathogen, you can do so from inside Vim with:
-"
-" ```
-" :call pathogen#helptags()
-" ```
-"
-"
-" # Website
-"
-" The official Pinnacle source code repo is at:
-"
-"   http://git.wincent.com/pinnacle.git
-"
-" Mirrors exist at:
-"
-"   - https://github.com/wincent/pinnacle
-"   - https://gitlab.com/wincent/pinnacle
-"   - https://bitbucket.org/ghurrell/pinnacle
-"
-" Official releases are listed at:
-"
-"   http://www.vim.org/scripts/script.php?script_id=[TODO]
-"
-"
-" # License
-"
-" Copyright (c) 2016-present Greg Hurrell
-"
-" Permission is hereby granted, free of charge, to any person obtaining
-" a copy of this software and associated documentation files (the
-" "Software"), to deal in the Software without restriction, including
-" without limitation the rights to use, copy, modify, merge, publish,
-" distribute, sublicense, and/or sell copies of the Software, and to
-" permit persons to whom the Software is furnished to do so, subject to
-" the following conditions:
-"
-" The above copyright notice and this permission notice shall be
-" included in all copies or substantial portions of the Software.
-"
-" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-"
-"
-" # Development
-"
-" ## Contributing patches
-"
-" Patches can be sent via mail to greg@hurrell.net, or as GitHub pull requests
-" at: https://github.com/wincent/pinnacle/pulls
-"
-" ## Cutting a new release
-"
-" At the moment the release process is manual:
-"
-" - Perform final sanity checks and manual testing
-" - Update the |pinnacle-history| section of the documentation
-" - Verify clean work tree:
-"
-" ```
-" git status
-" ```
-"
-" - Tag the release:
-"
-" ```
-" git tag -s -m "$VERSION release" $VERSION
-" ```
-"
-" - Publish the code:
-"
-" ```
-" git push origin master --follow-tags
-" git push github master --follow-tags
-" ```
-"
-" - Produce the release archive:
-"
-" ```
-" git archive -o vim-docvim-$VERSION.zip HEAD -- .
-" ```
-"
-" - Upload to http://www.vim.org/scripts/script.php?script_id=[TODO]
-"
-"
-" # Authors
-"
-" Pinnacle is written and maintained by Greg Hurrell <greg@hurrell.net>.
-"
-"
-" # History
-"
-" ## 0.1 (30 March 2016)
-"
-" - Initial release.
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..e209dd245d84805fdbbf03c011d5e26e331551a5
--- /dev/null
@@ -0,0 +1 @@
+../shared/integration-pinnacle.vim
\ No newline at end of file
diff --git a/tests/fixtures/parser/integration-docvim.vim b/tests/fixtures/parser/integration-docvim.vim
new file mode 120000 (symlink)
index 0000000..bd13891
--- /dev/null
@@ -0,0 +1 @@
+../shared/integration-docvim.vim
\ No newline at end of file
deleted file mode 100644 (file)
index 2d277d9ba309046b62db88fadac86f25d70228a7..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,64 +0,0 @@
-" Copyright 2015-present Greg Hurrell. All rights reserved.
-" Licensed under the terms of the BSD 2-clause license.
-
-""
-" @option g:FerretQFOptions boolean 1
-"
-" Controls whether to set up setting overrides for |quickfix| windows. These are
-" various settings, such as |norelativenumber|, |nolist| and |nowrap|, that are
-" intended to make the |quickfix| window, which is typically very small relative
-" to other windows, more usable.
-"
-" A full list of overridden settings can be found in |ferret-overrides|.
-"
-" To prevent the custom settings from being applied, set |g:FerretQFOptions|
-" to 0:
-"
-" ```
-" let g:FerretQFOptions=0
-" ```
-let s:options=get(g:, 'FerretQFOptions', 1)
-if s:options
-  setlocal nolist
-  if exists('+relativenumber')
-    setlocal norelativenumber
-  endif
-  setlocal nowrap
-  setlocal number
-
-  " Want to set scrolloff only for the qf window, but it is a global option.
-  let s:original_scrolloff=&scrolloff
-  set scrolloff=0
-
-  if has('autocmd')
-    augroup FerretQF
-      autocmd!
-      autocmd BufLeave <buffer> execute 'set scrolloff=' . s:original_scrolloff
-      autocmd BufEnter <buffer> set scrolloff=0 | setlocal nocursorline
-    augroup END
-  endif
-endif
-
-""
-" @option g:FerretQFMap boolean 1
-"
-" Controls whether to set up mappings in the |quickfix| results window for
-" deleting results. The mappings include:
-"
-" - `d` (|visual-mode|): delete visual selection
-" - `dd` (|Normal-mode|): delete current line
-" - `d`{motion} (|Normal-mode|): delete range indicated by {motion}
-"
-" To prevent these mappings from being set up, set to 0:
-"
-" ```
-" let g:FerretQFMap=0
-" ```
-let s:map=get(g:, 'FerretQFMap', 1)
-if s:map
-  " Make it easy to remove entries from the quickfix listing.
-  " TODO: distinguish between quickfix and location list
-  nnoremap <buffer> <silent> d :set operatorfunc=ferret#private#qf_delete_motion<CR>g@
-  nnoremap <buffer> <silent> dd :call ferret#private#qf_delete()<CR>
-  vnoremap <buffer> <silent> d :call ferret#private#qf_delete()<CR>
-endif
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..4051b06dee54232870b47194800f6aa804c78e63
--- /dev/null
@@ -0,0 +1 @@
+../shared/integration-ferret-ftplugin-qf.vim
\ No newline at end of file
deleted file mode 100644 (file)
index e41107d9393d7dd7f6f5c2ca5bfe63ae4705d33c..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,601 +0,0 @@
-" Copyright 2015-present Greg Hurrell. All rights reserved.
-" Licensed under the terms of the BSD 2-clause license.
-
-""
-" @plugin ferret Ferret plug-in for Vim
-"
-" # Intro
-"
-" > "ferret (verb)<br />
-" > (ferret something out) search tenaciously for and find something: she had
-" > the ability to ferret out the facts."
-"
-"                                                               *ferret-features*
-" Ferret improves Vim's multi-file search in four ways:
-"
-" ## 1. Powerful multi-file search
-"
-" Ferret provides an |:Ack| command for searching across multiple files using
-" The Silver Searcher (https://github.com/ggreer/the_silver_searcher), Ack
-" (http://beyondgrep.com/), or Grep (http://www.gnu.org/software/grep/). 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.
-"
-" Shortcut mappings are provided to start an |:Ack| search (<leader>a) or to
-" search for the word currently under the cursor (<leader>s).
-"
-" Results are normally displayed in the |quickfix| window, but Ferret also
-" provides a |:Lack| command that behaves like |:Ack| but uses the
-" |location-list| instead, and a <leader>l mapping as a shortcut to |:Lack|.
-"
-" Finally, Ferret offers integration with dispatch.vim
-" (https://github.com/tpope/vim-dispatch), which enables asynchronous searching
-" despite the fact that Vim itself is single-threaded.
-"
-" ## 2. Streamlined multi-file replace
-"
-" The companion to |:Ack| is |:Acks| (mnemonic: "Ack substitute", accessible via
-" shortcut <leader>r), which allows you to run a multi-file replace across all
-" the files placed in the |quickfix| window by a previous invocation of |:Ack|.
-"
-" ## 3. Quickfix listing enhancements
-"
-" The |quickfix| listing itself is enhanced with settings to improve its
-" usability, and natural mappings that allow quick removal of items from the
-" list (for example, you can reduce clutter in the listing by removing lines
-" that you don't intend to make changes to).
-"
-" Additionally, Vim's |:cn|, |:cp|, |:cnf| and |:cpf| commands are tweaked to
-" make it easier to immediately identify matches by centering them within the
-" viewport.
-"
-" ## 4. Easy operations on files in the quickfix listing
-"
-" Finally, Ferret provides a |:Qargs| command that puts the files currently in
-" the |quickfix| listing into the |:args| list, where they can be operated on in
-" bulk via the |:argdo| command. This is what's used under the covers by |:Acks|
-" to do its work.
-"
-"
-" # Installation
-"
-" To install Ferret, use your plug-in management system of choice.
-"
-" If you don't have a "plug-in management system of choice", I recommend
-" Pathogen (https://github.com/tpope/vim-pathogen) due to its simplicity and
-" robustness. Assuming that you have Pathogen installed and configured, and that
-" you want to install Ferret into `~/.vim/bundle`, you can do so with:
-"
-" ```
-" git clone https://github.com/wincent/ferret.git ~/.vim/bundle/ferret
-" ```
-"
-" Alternatively, if you use a Git submodule for each Vim plug-in, you could do
-" the following after `cd`-ing into the top-level of your Git superproject:
-"
-" ```
-" git submodule add https://github.com/wincent/ferret.git ~/vim/bundle/ferret
-" git submodule init
-" ```
-"
-" To generate help tags under Pathogen, you can do so from inside Vim with:
-"
-" ```
-" :call pathogen#helptags()
-" ```
-"
-" @mappings
-"
-" ## Circumstances where mappings do not get set up
-"
-" Note that Ferret will not try to set up the <leader> mappings if any of the
-" following are true:
-"
-" - A mapping for already exists.
-" - An alternative mapping for the same functionality has already been set up
-"   from a |.vimrc|.
-" - The mapping has been suppressed by setting |g:FerretMap| to 1 in your
-"   |.vimrc|.
-"
-" ## Mappings specific to the quickfix window
-"
-" Additionally, Ferret will set up special mappings in |quickfix| listings,
-" unless prevented from doing so by |g:FerretQFMap|:
-"
-" - `d` (|visual-mode|): delete visual selection
-" - `dd` (|Normal-mode|): delete current line
-" - `d`{motion} (|Normal-mode|): delete range indicated by {motion}
-"
-"
-" @footer
-"
-" # Custom autocommands
-"
-"                                                *FerretWillWrite* *FerretDidWrite*
-" For maximum compatibility with other plug-ins, Ferret runs the following
-" "User" autocommands before and after running the file writing operations
-" during |:Acks|:
-"
-" - FerretWillWrite
-" - FerretDidWrite
-"
-" For example, to call a pair of custom functions in response to these events,
-" you might do:
-"
-" ```
-" autocmd! User FerretWillWrite
-" autocmd User FerretWillWrite call CustomWillWrite()
-" autocmd! User FerretDidWrite
-" autocmd User FerretDidWrite call CustomDidWrite()
-" ```
-"
-"
-" # Overrides
-"
-" Ferret overrides the 'grepformat' and 'grepprg' settings, preferentially
-" setting `ag`, `ack` or `grep` as the 'grepprg' (in that order) and configuring
-" a suitable 'grepformat'.
-"
-" Additionally, Ferret includes an |ftplugin| for the |quickfix| listing that
-" adjusts a number of settings to improve the usability of search results.
-"
-" @indent
-"                                                                 *ferret-nolist*
-"   'nolist'
-"
-"   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 |quickfix| results.
-"
-"                                                       *ferret-norelativenumber*
-"   'norelativenumber'
-"
-"   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 |:cnf| and |:cpf|
-"   respectively).
-"
-"                                                                 *ferret-nowrap*
-"   'nowrap'
-"
-"   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.
-"
-"                                                                 *ferret-number*
-"   'number'
-"
-"   Turned on to give a sense of absolute progress through the results.
-"
-"                                                              *ferret-scrolloff*
-"   'scrolloff'
-"
-"   Set to 0 because the |quickfix| 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.
-"
-"                                                           *ferret-nocursorline*
-"   'nocursorline'
-"
-"   Turned off to reduce visual clutter.
-"
-" @dedent
-"
-" To prevent any of these |quickfix|-specific overrides from being set up, you
-" can set |g:FerretQFOptions| to 0 in your |.vimrc|:
-"
-" ```
-" let g:FerretQFOptions=0
-" ```
-"
-"
-" # Troubleshooting
-"
-"                                                                 *ferret-quotes*
-" ## Ferret fails to find patterns containing spaces
-"
-" As described in the documentation for |:Ack|, the search pattern is passed
-" through as-is to the underlying search command, and no escaping is required
-" other than preceding spaces by a single backslash.
-"
-" So, to find "foo bar", you would search like:
-"
-" ```
-" :Ack foo\ bar
-" ```
-"
-" Unescaped spaces in the search are treated as argument separators, so a
-" command like the following means pass the `-w` option through, search for
-" pattern "foo", and limit search to the "bar" directory:
-"
-" ```
-" :Ack -w foo bar
-" ```
-"
-" Note that including quotes will not do what you intend.
-"
-" ```
-" " Search for '"foo' in the 'bar"' directory:
-" :Ack "foo bar"
-"
-" " Search for "'foo' in the "bar'" directory:
-" :Ack 'foo bar'
-" ```
-"
-" This approach to escaping is taken in order to make it straightfoward to use
-" powerful Perl-compatible regular expression syntax in an unambiguous way
-" without having to worry about shell escaping rules:
-"
-" ```
-" :Ack \blog\((['"]).*?\1\) -i --ignore-dir=src/vendor src dist build
-" ```
-"
-"
-" # FAQ
-"
-" ## Why do Ferret commands start with "Ack", "Lack" and so on?
-"
-" Ferret was originally the thinnest of wrappers (7 lines of code in my
-" |.vimrc|) 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).
-"
-" So, even though Ferret has a new name now and actually prefers `ag` over `ack`
-" when available, I prefer to keep the command names intact and benefit from
-" years of accumulated muscle-memory.
-"
-"
-"
-" # Related
-"
-" Just as Ferret aims to improve the multi-file search and replace experience,
-" Loupe does the same for within-file searching:
-"
-"   https://github.com/wincent/loupe
-"
-"
-" # Website
-"
-" The official Ferret source code repo is at:
-"
-"   http://git.wincent.com/ferret.git
-"
-" A mirror exists at:
-"
-"   https://github.com/wincent/ferret
-"
-" Official releases are listed at:
-"
-"   http://www.vim.org/scripts/script.php?script_id=5220
-"
-"
-" # License
-"
-" Copyright 2015-present Greg Hurrell. All rights reserved.
-"
-" Redistribution and use in source and binary forms, with or without
-" modification, are permitted provided that the following conditions are met:
-"
-" 1. Redistributions of source code must retain the above copyright notice,
-"    this list of conditions and the following disclaimer.
-" 2. Redistributions in binary form must reproduce the above copyright notice,
-"    this list of conditions and the following disclaimer in the documentation
-"    and/or other materials provided with the distribution.
-"
-" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-" POSSIBILITY OF SUCH DAMAGE.
-"
-"
-" # Development
-"
-" ## Contributing patches
-"
-" Patches can be sent via mail to greg@hurrell.net, or as GitHub pull requests
-" at: https://github.com/wincent/ferret/pulls
-"
-" ## Cutting a new release
-"
-" At the moment the release process is manual:
-"
-" - Perform final sanity checks and manual testing
-" - Update the |ferret-history| section of the documentation
-" - Verify clean work tree:
-"
-" ```
-" git status
-" ```
-"
-" - Tag the release:
-"
-" ```
-" git tag -s -m "$VERSION release" $VERSION
-" ```
-"
-" - Publish the code:
-"
-" ```
-" git push origin master --follow-tags
-" git push github master --follow-tags
-" ```
-"
-" - Produce the release archive:
-"
-" ```
-" git archive -o ferret-$VERSION.zip HEAD -- .
-" ```
-"
-" - Upload to http://www.vim.org/scripts/script.php?script_id=5220
-"
-"
-" # Authors
-"
-" 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
-" - Joe Lencioni
-" - Nelo-Thara Wallus
-" - Vaibhav Sagar
-"
-"
-" # History
-"
-" 0.3.1 (not yet released)
-"
-" - Fix broken |:Qargs| command (patch from Daniel Silva).
-"
-" 0.3 (24 July 2015)
-"
-" - Added highlighting of search pattern and related |g:FerretHlsearch| option
-"   (patch from Nelo-Thara Wallus).
-" - Add better error reporting for failed or incorrect searches.
-"
-" 0.2 (16 July 2015)
-"
-" - Added |FerretDidWrite| and |FerretWillWrite| autocommands (patch from Joe
-"   Lencioni).
-" - Add |<Plug>(FerretAcks)| mapping (patch from Nelo-Thara Wallus).
-"
-" 0.1 (8 July 2015)
-"
-" - Initial release, extracted from my dotfiles
-"   (https://github.com/wincent/wincent).
-
-""
-" @option g:FerretLoaded any
-"
-" To prevent Ferret from being loaded, set |g:FerretLoaded| to any value in your
-" |.vimrc|. For example:
-"
-" ```
-" let g:FerretLoaded=1
-" ```
-if exists('g:FerretLoaded') || &compatible || v:version < 700
-  finish
-endif
-let g:FerretLoaded = 1
-
-" Temporarily set 'cpoptions' to Vim default as per `:h use-cpo-save`.
-let s:cpoptions = &cpoptions
-set cpoptions&vim
-
-if executable('ag') " The Silver Searcher: faster than ack.
-  let s:ackprg = 'ag --column --nocolor --nogroup'
-elseif executable('ack') " Ack: better than grep.
-  let s:ackprg = 'ack --column'
-elseif executable('grep') " Grep: it's just grep.
-  let s:ackprg = &grepprg " default is: grep -n $* /dev/null
-endif
-
-if !empty(s:ackprg)
-  let &grepprg=s:ackprg
-  set grepformat=%f:%l:%c:%m
-endif
-
-if has('autocmd')
-  augroup Ferret
-    autocmd!
-    autocmd QuickFixCmdPost [^l]* nested cwindow
-    autocmd QuickFixCmdPost l* nested lwindow
-  augroup END
-endif
-
-""
-" @command :Ack {pattern} {options}
-"
-" Searches for {pattern} in all the files under the current directory (see
-" |:pwd|), unless otherwise overridden via {options}, and displays the results
-" in the |quickfix| listing.
-"
-" `ag` (The Silver Searcher) will be used preferentially if present on the
-" system, because it is faster, falling back to `ack` and then `grep` as needed.
-"
-" If dispatch.vim is installed the search process will run asynchronously via
-" the |:Make| command, otherwise it will be run synchronously via |:cexpr|.
-" Asynchronous searches are preferred because they do not block, despite the
-" fact that Vim itself is single threaded. The |g:FerretDispatch| option can be
-" used to prevent the use of dispatch.vim.
-"
-" 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: >
-"
-" ```
-" :Ack -w something foo bar
-" ```
-"
-" As a convenience <leader>a is set-up (|<Plug>(FerretAck)|) as a shortcut to
-" enter |Cmdline-mode| with `:Ack` inserted on the |Cmdline|. Likewise <leader>s
-" (|<Plug>(FerretAckWord)|) is a shortcut for running |:Ack| with the word
-" currently under the cursor.
-command! -nargs=+ -complete=file Ack call ferret#private#ack(<q-args>)
-
-""
-" @command :Lack {pattern} {options}
-"
-" Just like |:Ack|, but instead of using the |quickfix| listing, which is global
-" across an entire Vim instance, it uses the |location-list|, which is a
-" per-window construct.
-"
-" Note that |:Lack| always runs synchronously via |:cexpr|, because dispatch.vim
-" doesn't currently support the |location-list|.
-command! -nargs=+ -complete=file Lack call ferret#private#lack(<q-args>)
-
-""
-" @command :Acks /{pattern}/{replacement}/
-"
-" Takes all of the files currently in the |quickfix| listing and performs a
-" substitution of all instances of {pattern} (a standard Vim search |pattern|)
-" by {replacement}.
-"
-" A typical sequence consists of an |:Ack| invocation to populate the |quickfix|
-" listing and then |:Acks| (mnemonic: "Ack substitute") to perform replacements.
-" For example, to replace "foo" with "bar" across all files in the current
-" directory:
-"
-" ```
-" :Ack foo
-" :Acks /foo/bar/
-" ```
-command! -nargs=1 Acks call ferret#private#acks(<q-args>)
-
-""
-" @option g:FerretMap boolean 1
-"
-" Controls whether to set up the Ferret mappings, such as |<Plug>(FerretAck)|
-" (see |ferret-mappings| for a full list). To prevent any mapping from being
-" configured, set to 0:
-"
-" ```
-" let g:FerretMap=0
-" ```
-let s:map=get(g:, 'FerretMap', 1)
-if s:map
-  if !hasmapto('<Plug>(FerretAck)') && maparg('<leader>a', 'n') ==# ''
-    ""
-    " @mapping <Plug>(FerretAck)
-    "
-    " Ferret maps <leader>a to |<Plug>(FerretAck)|, which triggers the |:Ack|
-    " command. To use an alternative mapping instead, create a different one in
-    " your |.vimrc| instead using |:nmap|:
-    "
-    " ```
-    " " Instead of <leader>a, use <leader>x.
-    " nmap <leader>x <Plug>(FerretAck)
-    " ```
-    nmap <unique> <leader>a <Plug>(FerretAck)
-  endif
-  nnoremap <Plug>(FerretAck) :Ack<space>
-
-  if !hasmapto('<Plug>FerretLack') && maparg('<leader>l', 'n') ==# ''
-    ""
-    " @mapping <Plug>(FerretLack)
-    "
-    " Ferret maps <leader>l to |<Plug>(FerretLack)|, which triggers the |:Lack|
-    " command. To use an alternative mapping instead, create a different one in
-    " your |.vimrc| instead using |:nmap|:
-    "
-    " ```
-    " " Instead of <leader>l, use <leader>y.
-    " nmap <leader>y <Plug>(FerretLack)
-    " ```
-    nmap <unique> <leader>l <Plug>(FerretLack)
-  endif
-  nnoremap <Plug>(FerretLack) :Lack<space>
-
-  if !hasmapto('<Plug>(FerretAckWord)') && maparg('<leader>s', 'n') ==# ''
-    " Call :Ack with word currently under cursor (mnemonic: selection).
-
-
-    ""
-    " @mapping <Plug>(FerretAckWord)
-    "
-    " Ferret maps <leader>s (mnemonix: "selection) to |<Plug>(FerretAckWord)|,
-    " which uses |:Ack| to search for the word currently under the cursor. To
-    " use an alternative mapping instead, create a different one in your
-    " |.vimrc| instead using |:nmap|:
-    "
-    " ```
-    " " Instead of <leader>s, use <leader>z.
-    " nmap <leader>z <Plug>(FerretAckWord)
-    " ```
-    nmap <unique> <leader>s <Plug>(FerretAckWord)
-  endif
-  nnoremap <Plug>(FerretAckWord) :Ack <C-r><C-w><CR>
-
-  if !hasmapto('<Plug>(FerretAcks)') && maparg('<leader>r', 'n') ==# ''
-    ""
-    " @mapping *<Plug>(FerretAcks)*
-    "
-    " Ferret maps <leader>r (mnemonic: "replace") to |<Plug>(FerretAcks)|, which
-    " triggers the |:Acks| command and fills the prompt with the last search
-    " term from Ferret. to use an alternative mapping instead, create a
-    " different one in your |.vimrc| instead using |:nmap|:
-    "
-    " ```
-    " " Instead of <leader>r, use <leader>u.
-    " nmap <leader>u <Plug>(FerretAcks)
-    " ```
-    nmap <unique> <leader>r <Plug>(FerretAcks)
-  endif
-  nnoremap <Plug>(FerretAcks)
-        \ :Acks <c-r>=(exists('g:ferret_lastsearch') ? '/' . g:ferret_lastsearch . '//' : ' ')<CR><Left>
-endif
-
-""
-" @command :Qargs
-"
-" This is a utility function that is used by the |:Acks| command but is also
-" generally useful enough to warrant being exposed publicly.
-"
-" It takes the files currently in the |quickfix| listing and sets them as
-" |:args| so that they can be operated on en masse via the |:argdo| command.
-command! -bar Qargs execute 'args' ferret#private#qargs()
-
-""
-" @option g:FerretQFCommands boolean 1
-"
-" Controls whether to set up custom versions of the |quickfix| commands, |:cn|,
-" |:cnf|, |:cp| an |:cpf|. These overrides vertically center the match within
-" the viewport on each jump. To prevent the custom versions from being
-" configured, set to 0:
-"
-" ```
-" let g:FerretQFCommands=0
-" ```
-let s:commands=get(g:, 'FerretQFCommands', 1)
-if s:commands
-  " Keep quickfix result centered, if possible, when jumping from result to result.
-  cabbrev <silent> <expr> cn ((getcmdtype() == ':' && getcmdpos() == 3) ? 'cn <bar> normal zz' : 'cn')
-  cabbrev <silent> <expr> cnf ((getcmdtype() == ':' && getcmdpos() == 4) ? 'cnf <bar> normal zz' : 'cnf')
-  cabbrev <silent> <expr> cp ((getcmdtype() == ':' && getcmdpos() == 3) ? 'cp <bar> normal zz' : 'cp')
-  cabbrev <silent> <expr> cpf ((getcmdtype() == ':' && getcmdpos() == 4) ? 'cpf <bar> normal zz' : 'cpf')
-endif
-
-" Restore 'cpoptions' to its former value.
-let &cpoptions = s:cpoptions
-unlet s:cpoptions
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..4634fa0a49e91bd7a0b6dc6183e78033daf1c759
--- /dev/null
@@ -0,0 +1 @@
+../shared/integration-ferret-plugin.vim
\ No newline at end of file
deleted file mode 100644 (file)
index 72b68b451d5e22e4a934ff9d4d80d04bbc4fe047..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,315 +0,0 @@
-" Copyright 2015-present Greg Hurrell. All rights reserved.
-" Licensed under the terms of the BSD 2-clause license.
-
-" Remove lines a:first through a:last from the quickfix listing.
-function! s:delete(first, last)
-  let l:list=getqflist()
-  let l:line=a:first
-
-  while l:line >= a:first && l:line <= a:last
-    " Non-dictionary items will be ignored. This effectively deletes the line.
-    let l:list[l:line - 1]=0
-    let l:line=l:line + 1
-  endwhile
-  call setqflist(l:list, 'r')
-
-  " Show to next entry.
-  execute 'cc ' . a:first
-
-  " Move focus back to quickfix listing.
-  execute "normal \<C-W>\<C-P>"
-endfunction
-
-" Returns 1 if we should/can use vim-dispatch.
-function! s:dispatch()
-  ""
-  " @option g:FerretDispatch 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:
-  "
-  " ```
-  " let g:FerretDispatch=0
-  " ```
-  let l:dispatch=get(g:, 'FerretDispatch', 1)
-  return l:dispatch && exists(':Make') == 2
-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! s:error(message) abort
-  call inputsave()
-  echohl ErrorMsg
-  call input(a:message . ': press ENTER to continue')
-  echohl NONE
-  call inputrestore()
-  echo
-endfunction
-
-" Parses arguments, extracting a search pattern (which is stored in
-" g:ferret_lastsearch) and escaping space-delimited arguments for use by
-" `system()`. A string containing all the escaped arguments is returned.
-"
-" The basic strategy is to split on spaces, expand wildcards for non-option
-" arguments, shellescape each word, and join.
-"
-" To support an edge-case (the ability to search for strings with spaces in
-" them, however, we swap out escaped spaces first (subsituting the unlikely
-" "<!!S!!>") and then swap them back in at the end. This allows us to perform
-" searches like:
-"
-"   :Ack -i \bFoo_?Bar\b
-"   :Ack that's\ nice\ dear
-"
-" and so on...
-function! s:parse(arg) abort
-  if exists('g:ferret_lastsearch')
-    unlet g:ferret_lastsearch
-  endif
-
-  let l:escaped_spaces_replaced_with_markers=substitute(a:arg, '\\ ', '<!!S!!>', 'g')
-  let l:split_on_spaces=split(l:escaped_spaces_replaced_with_markers)
-  let l:expanded_args=[]
-
-  for l:arg in l:split_on_spaces
-    if l:arg =~# '^-'
-      " Options get passed through as-is.
-      call add(l:expanded_args, l:arg)
-    elseif exists('g:ferret_lastsearch')
-      let l:file_args=glob(l:arg, 1, 1) " Ignore 'wildignore', return a list.
-      if len(l:file_args)
-        call extend(l:expanded_args, l:file_args)
-      else
-        " Let through to `ag`/`ack`/`grep`, which will throw ENOENT.
-        call add(l:expanded_args, l:arg)
-      endif
-    else
-      " First non-option arg is considered to be search pattern.
-      let g:ferret_lastsearch=substitute(l:arg, '<!!S!!>', ' ', 'g')
-      call add(l:expanded_args, l:arg)
-    endif
-  endfor
-
-  let l:each_word_shell_escaped=map(l:expanded_args, 'shellescape(v:val)')
-  let l:joined=join(l:each_word_shell_escaped)
-  return substitute(l:joined, '<!!S!!>', ' ', 'g')
-endfunction
-
-function! ferret#private#post(type) abort
-  if has('autocmd')
-    augroup FerretPostQF
-      autocmd!
-    augroup END
-  endif
-
-  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 . '`'
-
-    " Search pattern has no spaces and is entirely enclosed in quotes;
-    " eg 'foo' or "bar"
-    if l:lastsearch =~ '\v^([' . "'" . '"])[^ \1]+\1$'
-      call s:error(l:base . l:tip)
-    else
-      call s:error(l:base)
-    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)
-      " Every item in the list was invalid.
-      redraw!
-      echohl ErrorMsg
-      for l:item in l:invalid
-        echomsg l:item.text
-      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' && s:dispatch() ?
-            \ ' (run `:messages` to see details)' :
-            \ ''
-
-      " 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 s:error(l:base . l:tip . l:suffix)
-      else
-        call s:error(l:base . l:suffix)
-      endif
-    endif
-  endif
-endfunction
-
-function! ferret#private#ack(command) abort
-  let l:command=s:parse(a:command)
-  call ferret#private#hlsearch()
-
-  if empty(&grepprg)
-    return
-  endif
-
-  " Prefer vim-dispatch unless otherwise instructed.
-  if s:dispatch()
-    if has('autocmd')
-      augroup FerretPostQF
-        autocmd!
-        autocmd QuickfixCmdPost cgetfile call ferret#private#post('qf')
-      augroup END
-    endif
-    let l:original_makeprg=&l:makeprg
-    let l:original_errorformat=&l:errorformat
-    try
-      let &l:makeprg=&grepprg . ' ' . l:command
-      let &l:errorformat=&grepformat
-      Make
-    catch
-      if has('autocmd')
-        augroup! FerretPostQF
-      endif
-    finally
-      let &l:makeprg=l:original_makeprg
-      let &l:errorformat=l:original_errorformat
-    endtry
-  else
-    cexpr system(&grepprg . ' ' . l:command)
-    cwindow
-    call ferret#private#post('qf')
-  endif
-endfunction
-
-function! ferret#private#lack(command) abort
-  let l:command=s:parse(a:command)
-  call ferret#private#hlsearch()
-
-  if empty(&grepprg)
-    return
-  endif
-
-  lexpr system(&grepprg . ' ' . l:command)
-  lwindow
-  call ferret#private#post('location')
-endfunction
-
-function! ferret#private#hlsearch() abort
-  if has('extra_search')
-    ""
-    " @option g:FerretHlsearch boolean
-    "
-    " Controls whether Ferret should attempt to highlight the search pattern
-    " when running |:Ack| or |:Lack|. If left unset, Ferret will respect the
-    " current 'hlsearch' setting. To force highlighting on or off irrespective
-    " of 'hlsearch', set |g:FerretHlsearch| to 1 (on) or 0 (off):
-    "
-    " ```
-    " let g:FerretHlsearch=0
-    " ```
-    let l:hlsearch=get(g:, 'FerretHlsearch', &hlsearch)
-    if l:hlsearch
-      let @/=g:ferret_lastsearch
-      call feedkeys(":let &hlsearch=1 | echo \<CR>", 'n')
-    endif
-  endif
-endfunction
-
-" Run the specified substitution command on all the files in the quickfix list
-" (mnemonic: "Ack substitute").
-"
-" Specifically, the sequence:
-"
-"   :Ack foo
-"   :Acks /foo/bar/
-"
-" is equivalent to:
-"
-"   :Ack foo
-"   :Qargs
-"   :argdo %s/foo/bar/ge | update
-"
-" (Note: there's nothing specific to Ack in this function; it's just named this
-" way for mnemonics, as it will most often be preceded by an :Ack invocation.)
-function! ferret#private#acks(command) abort
-  if match(a:command, '\v^/.+/.*/$') == -1 " crude sanity check
-    echoerr 'Ferret: Expected a substitution expression (/foo/bar/); got: ' . a:command
-    return
-  endif
-
-  let l:filenames=ferret#private#qargs()
-  if l:filenames ==# ''
-    echoerr 'Ferret: Quickfix filenames must be present, but there are none'
-    return
-  endif
-
-  execute 'args' l:filenames
-
-  if v:version > 703 || v:version == 703 && has('patch438')
-    silent doautocmd <nomodeline> User FerretWillWrite
-  else
-    silent doautocmd User FerretWillWrite
-  endif
-  execute 'argdo' '%s' . a:command . 'ge | update'
-  if v:version > 703 || v:version == 703 && has('patch438')
-    silent doautocmd <nomodeline> User FerretDidWrite
-  else
-    silent doautocmd User FerretDidWrite
-  endif
-endfunction
-
-" Populate the :args list with the filenames currently in the quickfix window.
-function! ferret#private#qargs() abort
-  let l:buffer_numbers={}
-  for l:item in getqflist()
-    let l:buffer_numbers[l:item['bufnr']]=bufname(l:item['bufnr'])
-  endfor
-  return join(map(values(l:buffer_numbers), 'fnameescape(v:val)'))
-endfunction
-
-" Visual mode deletion and `dd` mapping (special case).
-function! ferret#private#qf_delete() range
-  call s:delete(a:firstline, a:lastline)
-endfunction
-
-" Motion-based deletion from quickfix listing.
-function! ferret#private#qf_delete_motion(type, ...)
-  " Save.
-  let l:selection=&selection
-  let &selection='inclusive'
-
-  let l:firstline=line("'[")
-  let l:lastline=line("']")
-  call s:delete(l:firstline, l:lastline)
-
-  " Restore.
-  let &selection=l:selection
-endfunction
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..b19e38c3145dbd7ab0b231c2b4210bbc9af114e7
--- /dev/null
@@ -0,0 +1 @@
+../shared/integration-ferret-private.vim
\ No newline at end of file
diff --git a/tests/fixtures/parser/integration-pinnacle.golden b/tests/fixtures/parser/integration-pinnacle.golden
new file mode 100644 (file)
index 0000000..cd93e41
--- /dev/null
@@ -0,0 +1,768 @@
+Unit
+  [ DocBlock
+      [ PluginAnnotation
+          "Pinnacle" "Highlight group manipulation for Vim"
+      , HeadingAnnotation "Intro"
+      , Paragraph
+          [ Plaintext "Pinnacle"
+          , Whitespace
+          , Plaintext "provides"
+          , Whitespace
+          , Plaintext "functions"
+          , Whitespace
+          , Plaintext "for"
+          , Whitespace
+          , Plaintext "manipulating"
+          , Whitespace
+          , Link ":highlight"
+          , Whitespace
+          , Plaintext "groups."
+          ]
+      , HeadingAnnotation "Installation"
+      , Paragraph
+          [ Plaintext "To"
+          , Whitespace
+          , Plaintext "install"
+          , Whitespace
+          , Plaintext "Pinnacle,"
+          , Whitespace
+          , Plaintext "use"
+          , Whitespace
+          , Plaintext "your"
+          , Whitespace
+          , Plaintext "plug-in"
+          , Whitespace
+          , Plaintext "management"
+          , Whitespace
+          , Plaintext "system"
+          , Whitespace
+          , Plaintext "of"
+          , Whitespace
+          , Plaintext "choice."
+          ]
+      , Paragraph
+          [ Plaintext "If"
+          , Whitespace
+          , Plaintext "you"
+          , Whitespace
+          , Plaintext "don't"
+          , Whitespace
+          , Plaintext "have"
+          , Whitespace
+          , Plaintext "a"
+          , Whitespace
+          , Plaintext "\"plug-in"
+          , Whitespace
+          , Plaintext "management"
+          , Whitespace
+          , Plaintext "system"
+          , Whitespace
+          , Plaintext "of"
+          , Whitespace
+          , Plaintext "choice\","
+          , Whitespace
+          , Plaintext "I"
+          , Whitespace
+          , Plaintext "recommend"
+          , Whitespace
+          , Plaintext "Pathogen"
+          , Whitespace
+          , Plaintext "(https://github.com/tpope/vim-pathogen)"
+          , Whitespace
+          , Plaintext "due"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "its"
+          , Whitespace
+          , Plaintext "simplicity"
+          , Whitespace
+          , Plaintext "and"
+          , Whitespace
+          , Plaintext "robustness."
+          , Whitespace
+          , Plaintext "Assuming"
+          , Whitespace
+          , Plaintext "that"
+          , Whitespace
+          , Plaintext "you"
+          , Whitespace
+          , Plaintext "have"
+          , Whitespace
+          , Plaintext "Pathogen"
+          , Whitespace
+          , Plaintext "installed"
+          , Whitespace
+          , Plaintext "and"
+          , Whitespace
+          , Plaintext "configured,"
+          , Whitespace
+          , Plaintext "and"
+          , Whitespace
+          , Plaintext "that"
+          , Whitespace
+          , Plaintext "you"
+          , Whitespace
+          , Plaintext "want"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "install"
+          , Whitespace
+          , Plaintext "vim-docvim"
+          , Whitespace
+          , Plaintext "into"
+          , Whitespace
+          , Code "~/.vim/bundle"
+          , Plaintext ","
+          , Whitespace
+          , Plaintext "you"
+          , Whitespace
+          , Plaintext "can"
+          , Whitespace
+          , Plaintext "do"
+          , Whitespace
+          , Plaintext "so"
+          , Whitespace
+          , Plaintext "with:"
+          ]
+      , Fenced
+          [ "git clone https://github.com/wincent/pinnacle.git ~/.vim/bundle/pinnacle"
+          ]
+      , Paragraph
+          [ Plaintext "Alternatively,"
+          , Whitespace
+          , Plaintext "if"
+          , Whitespace
+          , Plaintext "you"
+          , Whitespace
+          , Plaintext "use"
+          , Whitespace
+          , Plaintext "a"
+          , Whitespace
+          , Plaintext "Git"
+          , Whitespace
+          , Plaintext "submodule"
+          , Whitespace
+          , Plaintext "for"
+          , Whitespace
+          , Plaintext "each"
+          , Whitespace
+          , Plaintext "Vim"
+          , Whitespace
+          , Plaintext "plug-in,"
+          , Whitespace
+          , Plaintext "you"
+          , Whitespace
+          , Plaintext "could"
+          , Whitespace
+          , Plaintext "do"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "following"
+          , Whitespace
+          , Plaintext "after"
+          , Whitespace
+          , Code "cd"
+          , Plaintext "-ing"
+          , Whitespace
+          , Plaintext "into"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "top-level"
+          , Whitespace
+          , Plaintext "of"
+          , Whitespace
+          , Plaintext "your"
+          , Whitespace
+          , Plaintext "Git"
+          , Whitespace
+          , Plaintext "superproject:"
+          ]
+      , Fenced
+          [ "git submodule add https://github.com/wincent/pinnacle.git ~/vim/bundle/pinnacle"
+          , "git submodule init"
+          ]
+      , Paragraph
+          [ Plaintext "To"
+          , Whitespace
+          , Plaintext "generate"
+          , Whitespace
+          , Plaintext "help"
+          , Whitespace
+          , Plaintext "tags"
+          , Whitespace
+          , Plaintext "under"
+          , Whitespace
+          , Plaintext "Pathogen,"
+          , Whitespace
+          , Plaintext "you"
+          , Whitespace
+          , Plaintext "can"
+          , Whitespace
+          , Plaintext "do"
+          , Whitespace
+          , Plaintext "so"
+          , Whitespace
+          , Plaintext "from"
+          , Whitespace
+          , Plaintext "inside"
+          , Whitespace
+          , Plaintext "Vim"
+          , Whitespace
+          , Plaintext "with:"
+          ]
+      , Fenced [ ":call pathogen#helptags()" ]
+      , HeadingAnnotation "Website"
+      , Paragraph
+          [ Plaintext "The"
+          , Whitespace
+          , Plaintext "official"
+          , Whitespace
+          , Plaintext "Pinnacle"
+          , Whitespace
+          , Plaintext "source"
+          , Whitespace
+          , Plaintext "code"
+          , Whitespace
+          , Plaintext "repo"
+          , Whitespace
+          , Plaintext "is"
+          , Whitespace
+          , Plaintext "at:"
+          ]
+      , Paragraph [ Plaintext "http://git.wincent.com/pinnacle.git" ]
+      , Paragraph
+          [ Plaintext "Mirrors"
+          , Whitespace
+          , Plaintext "exist"
+          , Whitespace
+          , Plaintext "at:"
+          ]
+      , List
+          [ ListItem [ Plaintext "https://github.com/wincent/pinnacle" ]
+          , ListItem [ Plaintext "https://gitlab.com/wincent/pinnacle" ]
+          , ListItem [ Plaintext "https://bitbucket.org/ghurrell/pinnacle" ]
+          ]
+      , Paragraph
+          [ Plaintext "Official"
+          , Whitespace
+          , Plaintext "releases"
+          , Whitespace
+          , Plaintext "are"
+          , Whitespace
+          , Plaintext "listed"
+          , Whitespace
+          , Plaintext "at:"
+          ]
+      , Paragraph
+          [ Plaintext
+              "http://www.vim.org/scripts/script.php?script_id=[TODO]"
+          ]
+      , HeadingAnnotation "License"
+      , Paragraph
+          [ Plaintext "Copyright"
+          , Whitespace
+          , Plaintext "(c)"
+          , Whitespace
+          , Plaintext "2016-present"
+          , Whitespace
+          , Plaintext "Greg"
+          , Whitespace
+          , Plaintext "Hurrell"
+          ]
+      , Paragraph
+          [ Plaintext "Permission"
+          , Whitespace
+          , Plaintext "is"
+          , Whitespace
+          , Plaintext "hereby"
+          , Whitespace
+          , Plaintext "granted,"
+          , Whitespace
+          , Plaintext "free"
+          , Whitespace
+          , Plaintext "of"
+          , Whitespace
+          , Plaintext "charge,"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "any"
+          , Whitespace
+          , Plaintext "person"
+          , Whitespace
+          , Plaintext "obtaining"
+          , Whitespace
+          , Plaintext "a"
+          , Whitespace
+          , Plaintext "copy"
+          , Whitespace
+          , Plaintext "of"
+          , Whitespace
+          , Plaintext "this"
+          , Whitespace
+          , Plaintext "software"
+          , Whitespace
+          , Plaintext "and"
+          , Whitespace
+          , Plaintext "associated"
+          , Whitespace
+          , Plaintext "documentation"
+          , Whitespace
+          , Plaintext "files"
+          , Whitespace
+          , Plaintext "(the"
+          , Whitespace
+          , Plaintext "\"Software\"),"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "deal"
+          , Whitespace
+          , Plaintext "in"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "Software"
+          , Whitespace
+          , Plaintext "without"
+          , Whitespace
+          , Plaintext "restriction,"
+          , Whitespace
+          , Plaintext "including"
+          , Whitespace
+          , Plaintext "without"
+          , Whitespace
+          , Plaintext "limitation"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "rights"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "use,"
+          , Whitespace
+          , Plaintext "copy,"
+          , Whitespace
+          , Plaintext "modify,"
+          , Whitespace
+          , Plaintext "merge,"
+          , Whitespace
+          , Plaintext "publish,"
+          , Whitespace
+          , Plaintext "distribute,"
+          , Whitespace
+          , Plaintext "sublicense,"
+          , Whitespace
+          , Plaintext "and/or"
+          , Whitespace
+          , Plaintext "sell"
+          , Whitespace
+          , Plaintext "copies"
+          , Whitespace
+          , Plaintext "of"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "Software,"
+          , Whitespace
+          , Plaintext "and"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "permit"
+          , Whitespace
+          , Plaintext "persons"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "whom"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "Software"
+          , Whitespace
+          , Plaintext "is"
+          , Whitespace
+          , Plaintext "furnished"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "do"
+          , Whitespace
+          , Plaintext "so,"
+          , Whitespace
+          , Plaintext "subject"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "following"
+          , Whitespace
+          , Plaintext "conditions:"
+          ]
+      , Paragraph
+          [ Plaintext "The"
+          , Whitespace
+          , Plaintext "above"
+          , Whitespace
+          , Plaintext "copyright"
+          , Whitespace
+          , Plaintext "notice"
+          , Whitespace
+          , Plaintext "and"
+          , Whitespace
+          , Plaintext "this"
+          , Whitespace
+          , Plaintext "permission"
+          , Whitespace
+          , Plaintext "notice"
+          , Whitespace
+          , Plaintext "shall"
+          , Whitespace
+          , Plaintext "be"
+          , Whitespace
+          , Plaintext "included"
+          , Whitespace
+          , Plaintext "in"
+          , Whitespace
+          , Plaintext "all"
+          , Whitespace
+          , Plaintext "copies"
+          , Whitespace
+          , Plaintext "or"
+          , Whitespace
+          , Plaintext "substantial"
+          , Whitespace
+          , Plaintext "portions"
+          , Whitespace
+          , Plaintext "of"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "Software."
+          ]
+      , Paragraph
+          [ Plaintext "THE"
+          , Whitespace
+          , Plaintext "SOFTWARE"
+          , Whitespace
+          , Plaintext "IS"
+          , Whitespace
+          , Plaintext "PROVIDED"
+          , Whitespace
+          , Plaintext "\"AS"
+          , Whitespace
+          , Plaintext "IS\","
+          , Whitespace
+          , Plaintext "WITHOUT"
+          , Whitespace
+          , Plaintext "WARRANTY"
+          , Whitespace
+          , Plaintext "OF"
+          , Whitespace
+          , Plaintext "ANY"
+          , Whitespace
+          , Plaintext "KIND,"
+          , Whitespace
+          , Plaintext "EXPRESS"
+          , Whitespace
+          , Plaintext "OR"
+          , Whitespace
+          , Plaintext "IMPLIED,"
+          , Whitespace
+          , Plaintext "INCLUDING"
+          , Whitespace
+          , Plaintext "BUT"
+          , Whitespace
+          , Plaintext "NOT"
+          , Whitespace
+          , Plaintext "LIMITED"
+          , Whitespace
+          , Plaintext "TO"
+          , Whitespace
+          , Plaintext "THE"
+          , Whitespace
+          , Plaintext "WARRANTIES"
+          , Whitespace
+          , Plaintext "OF"
+          , Whitespace
+          , Plaintext "MERCHANTABILITY,"
+          , Whitespace
+          , Plaintext "FITNESS"
+          , Whitespace
+          , Plaintext "FOR"
+          , Whitespace
+          , Plaintext "A"
+          , Whitespace
+          , Plaintext "PARTICULAR"
+          , Whitespace
+          , Plaintext "PURPOSE"
+          , Whitespace
+          , Plaintext "AND"
+          , Whitespace
+          , Plaintext "NONINFRINGEMENT."
+          , Whitespace
+          , Plaintext "IN"
+          , Whitespace
+          , Plaintext "NO"
+          , Whitespace
+          , Plaintext "EVENT"
+          , Whitespace
+          , Plaintext "SHALL"
+          , Whitespace
+          , Plaintext "THE"
+          , Whitespace
+          , Plaintext "AUTHORS"
+          , Whitespace
+          , Plaintext "OR"
+          , Whitespace
+          , Plaintext "COPYRIGHT"
+          , Whitespace
+          , Plaintext "HOLDERS"
+          , Whitespace
+          , Plaintext "BE"
+          , Whitespace
+          , Plaintext "LIABLE"
+          , Whitespace
+          , Plaintext "FOR"
+          , Whitespace
+          , Plaintext "ANY"
+          , Whitespace
+          , Plaintext "CLAIM,"
+          , Whitespace
+          , Plaintext "DAMAGES"
+          , Whitespace
+          , Plaintext "OR"
+          , Whitespace
+          , Plaintext "OTHER"
+          , Whitespace
+          , Plaintext "LIABILITY,"
+          , Whitespace
+          , Plaintext "WHETHER"
+          , Whitespace
+          , Plaintext "IN"
+          , Whitespace
+          , Plaintext "AN"
+          , Whitespace
+          , Plaintext "ACTION"
+          , Whitespace
+          , Plaintext "OF"
+          , Whitespace
+          , Plaintext "CONTRACT,"
+          , Whitespace
+          , Plaintext "TORT"
+          , Whitespace
+          , Plaintext "OR"
+          , Whitespace
+          , Plaintext "OTHERWISE,"
+          , Whitespace
+          , Plaintext "ARISING"
+          , Whitespace
+          , Plaintext "FROM,"
+          , Whitespace
+          , Plaintext "OUT"
+          , Whitespace
+          , Plaintext "OF"
+          , Whitespace
+          , Plaintext "OR"
+          , Whitespace
+          , Plaintext "IN"
+          , Whitespace
+          , Plaintext "CONNECTION"
+          , Whitespace
+          , Plaintext "WITH"
+          , Whitespace
+          , Plaintext "THE"
+          , Whitespace
+          , Plaintext "SOFTWARE"
+          , Whitespace
+          , Plaintext "OR"
+          , Whitespace
+          , Plaintext "THE"
+          , Whitespace
+          , Plaintext "USE"
+          , Whitespace
+          , Plaintext "OR"
+          , Whitespace
+          , Plaintext "OTHER"
+          , Whitespace
+          , Plaintext "DEALINGS"
+          , Whitespace
+          , Plaintext "IN"
+          , Whitespace
+          , Plaintext "THE"
+          , Whitespace
+          , Plaintext "SOFTWARE."
+          ]
+      , HeadingAnnotation "Development"
+      , SubheadingAnnotation "Contributing patches"
+      , Paragraph
+          [ Plaintext "Patches"
+          , Whitespace
+          , Plaintext "can"
+          , Whitespace
+          , Plaintext "be"
+          , Whitespace
+          , Plaintext "sent"
+          , Whitespace
+          , Plaintext "via"
+          , Whitespace
+          , Plaintext "mail"
+          , Whitespace
+          , Plaintext "to"
+          , Whitespace
+          , Plaintext "greg@hurrell.net,"
+          , Whitespace
+          , Plaintext "or"
+          , Whitespace
+          , Plaintext "as"
+          , Whitespace
+          , Plaintext "GitHub"
+          , Whitespace
+          , Plaintext "pull"
+          , Whitespace
+          , Plaintext "requests"
+          , Whitespace
+          , Plaintext "at:"
+          , Whitespace
+          , Plaintext "https://github.com/wincent/pinnacle/pulls"
+          ]
+      , SubheadingAnnotation "Cutting a new release"
+      , Paragraph
+          [ Plaintext "At"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "moment"
+          , Whitespace
+          , Plaintext "the"
+          , Whitespace
+          , Plaintext "release"
+          , Whitespace
+          , Plaintext "process"
+          , Whitespace
+          , Plaintext "is"
+          , Whitespace
+          , Plaintext "manual:"
+          ]
+      , List
+          [ ListItem
+              [ Plaintext "Perform"
+              , Whitespace
+              , Plaintext "final"
+              , Whitespace
+              , Plaintext "sanity"
+              , Whitespace
+              , Plaintext "checks"
+              , Whitespace
+              , Plaintext "and"
+              , Whitespace
+              , Plaintext "manual"
+              , Whitespace
+              , Plaintext "testing"
+              ]
+          , ListItem
+              [ Plaintext "Update"
+              , Whitespace
+              , Plaintext "the"
+              , Whitespace
+              , Link "pinnacle-history"
+              , Whitespace
+              , Plaintext "section"
+              , Whitespace
+              , Plaintext "of"
+              , Whitespace
+              , Plaintext "the"
+              , Whitespace
+              , Plaintext "documentation"
+              ]
+          , ListItem
+              [ Plaintext "Verify"
+              , Whitespace
+              , Plaintext "clean"
+              , Whitespace
+              , Plaintext "work"
+              , Whitespace
+              , Plaintext "tree:"
+              ]
+          ]
+      , Fenced [ "git status" ]
+      , List
+          [ ListItem
+              [ Plaintext "Tag"
+              , Whitespace
+              , Plaintext "the"
+              , Whitespace
+              , Plaintext "release:"
+              ]
+          ]
+      , Fenced [ "git tag -s -m \"$VERSION release\" $VERSION" ]
+      , List
+          [ ListItem
+              [ Plaintext "Publish"
+              , Whitespace
+              , Plaintext "the"
+              , Whitespace
+              , Plaintext "code:"
+              ]
+          ]
+      , Fenced
+          [ "git push origin master --follow-tags"
+          , "git push github master --follow-tags"
+          ]
+      , List
+          [ ListItem
+              [ Plaintext "Produce"
+              , Whitespace
+              , Plaintext "the"
+              , Whitespace
+              , Plaintext "release"
+              , Whitespace
+              , Plaintext "archive:"
+              ]
+          ]
+      , Fenced [ "git archive -o vim-docvim-$VERSION.zip HEAD -- ." ]
+      , List
+          [ ListItem
+              [ Plaintext "Upload"
+              , Whitespace
+              , Plaintext "to"
+              , Whitespace
+              , Plaintext
+                  "http://www.vim.org/scripts/script.php?script_id=[TODO]"
+              ]
+          ]
+      , HeadingAnnotation "Authors"
+      , Paragraph
+          [ Plaintext "Pinnacle"
+          , Whitespace
+          , Plaintext "is"
+          , Whitespace
+          , Plaintext "written"
+          , Whitespace
+          , Plaintext "and"
+          , Whitespace
+          , Plaintext "maintained"
+          , Whitespace
+          , Plaintext "by"
+          , Whitespace
+          , Plaintext "Greg"
+          , Whitespace
+          , Plaintext "Hurrell"
+          , Whitespace
+          , Plaintext "<greg@hurrell.net>."
+          ]
+      , HeadingAnnotation "History"
+      , SubheadingAnnotation "0.1 (30 March 2016)"
+      , List
+          [ ListItem
+              [ Plaintext "Initial" , Whitespace , Plaintext "release." ]
+          ]
+      ]
+  ]
diff --git a/tests/fixtures/parser/integration-pinnacle.vim b/tests/fixtures/parser/integration-pinnacle.vim
new file mode 120000 (symlink)
index 0000000..e209dd2
--- /dev/null
@@ -0,0 +1 @@
+../shared/integration-pinnacle.vim
\ No newline at end of file
diff --git a/tests/fixtures/shared/integration-ferret-ftplugin-qf.vim b/tests/fixtures/shared/integration-ferret-ftplugin-qf.vim
new file mode 100644 (file)
index 0000000..2d277d9
--- /dev/null
@@ -0,0 +1,64 @@
+" Copyright 2015-present Greg Hurrell. All rights reserved.
+" Licensed under the terms of the BSD 2-clause license.
+
+""
+" @option g:FerretQFOptions boolean 1
+"
+" Controls whether to set up setting overrides for |quickfix| windows. These are
+" various settings, such as |norelativenumber|, |nolist| and |nowrap|, that are
+" intended to make the |quickfix| window, which is typically very small relative
+" to other windows, more usable.
+"
+" A full list of overridden settings can be found in |ferret-overrides|.
+"
+" To prevent the custom settings from being applied, set |g:FerretQFOptions|
+" to 0:
+"
+" ```
+" let g:FerretQFOptions=0
+" ```
+let s:options=get(g:, 'FerretQFOptions', 1)
+if s:options
+  setlocal nolist
+  if exists('+relativenumber')
+    setlocal norelativenumber
+  endif
+  setlocal nowrap
+  setlocal number
+
+  " Want to set scrolloff only for the qf window, but it is a global option.
+  let s:original_scrolloff=&scrolloff
+  set scrolloff=0
+
+  if has('autocmd')
+    augroup FerretQF
+      autocmd!
+      autocmd BufLeave <buffer> execute 'set scrolloff=' . s:original_scrolloff
+      autocmd BufEnter <buffer> set scrolloff=0 | setlocal nocursorline
+    augroup END
+  endif
+endif
+
+""
+" @option g:FerretQFMap boolean 1
+"
+" Controls whether to set up mappings in the |quickfix| results window for
+" deleting results. The mappings include:
+"
+" - `d` (|visual-mode|): delete visual selection
+" - `dd` (|Normal-mode|): delete current line
+" - `d`{motion} (|Normal-mode|): delete range indicated by {motion}
+"
+" To prevent these mappings from being set up, set to 0:
+"
+" ```
+" let g:FerretQFMap=0
+" ```
+let s:map=get(g:, 'FerretQFMap', 1)
+if s:map
+  " Make it easy to remove entries from the quickfix listing.
+  " TODO: distinguish between quickfix and location list
+  nnoremap <buffer> <silent> d :set operatorfunc=ferret#private#qf_delete_motion<CR>g@
+  nnoremap <buffer> <silent> dd :call ferret#private#qf_delete()<CR>
+  vnoremap <buffer> <silent> d :call ferret#private#qf_delete()<CR>
+endif
diff --git a/tests/fixtures/shared/integration-ferret-plugin.vim b/tests/fixtures/shared/integration-ferret-plugin.vim
new file mode 100644 (file)
index 0000000..e41107d
--- /dev/null
@@ -0,0 +1,601 @@
+" Copyright 2015-present Greg Hurrell. All rights reserved.
+" Licensed under the terms of the BSD 2-clause license.
+
+""
+" @plugin ferret Ferret plug-in for Vim
+"
+" # Intro
+"
+" > "ferret (verb)<br />
+" > (ferret something out) search tenaciously for and find something: she had
+" > the ability to ferret out the facts."
+"
+"                                                               *ferret-features*
+" Ferret improves Vim's multi-file search in four ways:
+"
+" ## 1. Powerful multi-file search
+"
+" Ferret provides an |:Ack| command for searching across multiple files using
+" The Silver Searcher (https://github.com/ggreer/the_silver_searcher), Ack
+" (http://beyondgrep.com/), or Grep (http://www.gnu.org/software/grep/). 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.
+"
+" Shortcut mappings are provided to start an |:Ack| search (<leader>a) or to
+" search for the word currently under the cursor (<leader>s).
+"
+" Results are normally displayed in the |quickfix| window, but Ferret also
+" provides a |:Lack| command that behaves like |:Ack| but uses the
+" |location-list| instead, and a <leader>l mapping as a shortcut to |:Lack|.
+"
+" Finally, Ferret offers integration with dispatch.vim
+" (https://github.com/tpope/vim-dispatch), which enables asynchronous searching
+" despite the fact that Vim itself is single-threaded.
+"
+" ## 2. Streamlined multi-file replace
+"
+" The companion to |:Ack| is |:Acks| (mnemonic: "Ack substitute", accessible via
+" shortcut <leader>r), which allows you to run a multi-file replace across all
+" the files placed in the |quickfix| window by a previous invocation of |:Ack|.
+"
+" ## 3. Quickfix listing enhancements
+"
+" The |quickfix| listing itself is enhanced with settings to improve its
+" usability, and natural mappings that allow quick removal of items from the
+" list (for example, you can reduce clutter in the listing by removing lines
+" that you don't intend to make changes to).
+"
+" Additionally, Vim's |:cn|, |:cp|, |:cnf| and |:cpf| commands are tweaked to
+" make it easier to immediately identify matches by centering them within the
+" viewport.
+"
+" ## 4. Easy operations on files in the quickfix listing
+"
+" Finally, Ferret provides a |:Qargs| command that puts the files currently in
+" the |quickfix| listing into the |:args| list, where they can be operated on in
+" bulk via the |:argdo| command. This is what's used under the covers by |:Acks|
+" to do its work.
+"
+"
+" # Installation
+"
+" To install Ferret, use your plug-in management system of choice.
+"
+" If you don't have a "plug-in management system of choice", I recommend
+" Pathogen (https://github.com/tpope/vim-pathogen) due to its simplicity and
+" robustness. Assuming that you have Pathogen installed and configured, and that
+" you want to install Ferret into `~/.vim/bundle`, you can do so with:
+"
+" ```
+" git clone https://github.com/wincent/ferret.git ~/.vim/bundle/ferret
+" ```
+"
+" Alternatively, if you use a Git submodule for each Vim plug-in, you could do
+" the following after `cd`-ing into the top-level of your Git superproject:
+"
+" ```
+" git submodule add https://github.com/wincent/ferret.git ~/vim/bundle/ferret
+" git submodule init
+" ```
+"
+" To generate help tags under Pathogen, you can do so from inside Vim with:
+"
+" ```
+" :call pathogen#helptags()
+" ```
+"
+" @mappings
+"
+" ## Circumstances where mappings do not get set up
+"
+" Note that Ferret will not try to set up the <leader> mappings if any of the
+" following are true:
+"
+" - A mapping for already exists.
+" - An alternative mapping for the same functionality has already been set up
+"   from a |.vimrc|.
+" - The mapping has been suppressed by setting |g:FerretMap| to 1 in your
+"   |.vimrc|.
+"
+" ## Mappings specific to the quickfix window
+"
+" Additionally, Ferret will set up special mappings in |quickfix| listings,
+" unless prevented from doing so by |g:FerretQFMap|:
+"
+" - `d` (|visual-mode|): delete visual selection
+" - `dd` (|Normal-mode|): delete current line
+" - `d`{motion} (|Normal-mode|): delete range indicated by {motion}
+"
+"
+" @footer
+"
+" # Custom autocommands
+"
+"                                                *FerretWillWrite* *FerretDidWrite*
+" For maximum compatibility with other plug-ins, Ferret runs the following
+" "User" autocommands before and after running the file writing operations
+" during |:Acks|:
+"
+" - FerretWillWrite
+" - FerretDidWrite
+"
+" For example, to call a pair of custom functions in response to these events,
+" you might do:
+"
+" ```
+" autocmd! User FerretWillWrite
+" autocmd User FerretWillWrite call CustomWillWrite()
+" autocmd! User FerretDidWrite
+" autocmd User FerretDidWrite call CustomDidWrite()
+" ```
+"
+"
+" # Overrides
+"
+" Ferret overrides the 'grepformat' and 'grepprg' settings, preferentially
+" setting `ag`, `ack` or `grep` as the 'grepprg' (in that order) and configuring
+" a suitable 'grepformat'.
+"
+" Additionally, Ferret includes an |ftplugin| for the |quickfix| listing that
+" adjusts a number of settings to improve the usability of search results.
+"
+" @indent
+"                                                                 *ferret-nolist*
+"   'nolist'
+"
+"   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 |quickfix| results.
+"
+"                                                       *ferret-norelativenumber*
+"   'norelativenumber'
+"
+"   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 |:cnf| and |:cpf|
+"   respectively).
+"
+"                                                                 *ferret-nowrap*
+"   'nowrap'
+"
+"   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.
+"
+"                                                                 *ferret-number*
+"   'number'
+"
+"   Turned on to give a sense of absolute progress through the results.
+"
+"                                                              *ferret-scrolloff*
+"   'scrolloff'
+"
+"   Set to 0 because the |quickfix| 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.
+"
+"                                                           *ferret-nocursorline*
+"   'nocursorline'
+"
+"   Turned off to reduce visual clutter.
+"
+" @dedent
+"
+" To prevent any of these |quickfix|-specific overrides from being set up, you
+" can set |g:FerretQFOptions| to 0 in your |.vimrc|:
+"
+" ```
+" let g:FerretQFOptions=0
+" ```
+"
+"
+" # Troubleshooting
+"
+"                                                                 *ferret-quotes*
+" ## Ferret fails to find patterns containing spaces
+"
+" As described in the documentation for |:Ack|, the search pattern is passed
+" through as-is to the underlying search command, and no escaping is required
+" other than preceding spaces by a single backslash.
+"
+" So, to find "foo bar", you would search like:
+"
+" ```
+" :Ack foo\ bar
+" ```
+"
+" Unescaped spaces in the search are treated as argument separators, so a
+" command like the following means pass the `-w` option through, search for
+" pattern "foo", and limit search to the "bar" directory:
+"
+" ```
+" :Ack -w foo bar
+" ```
+"
+" Note that including quotes will not do what you intend.
+"
+" ```
+" " Search for '"foo' in the 'bar"' directory:
+" :Ack "foo bar"
+"
+" " Search for "'foo' in the "bar'" directory:
+" :Ack 'foo bar'
+" ```
+"
+" This approach to escaping is taken in order to make it straightfoward to use
+" powerful Perl-compatible regular expression syntax in an unambiguous way
+" without having to worry about shell escaping rules:
+"
+" ```
+" :Ack \blog\((['"]).*?\1\) -i --ignore-dir=src/vendor src dist build
+" ```
+"
+"
+" # FAQ
+"
+" ## Why do Ferret commands start with "Ack", "Lack" and so on?
+"
+" Ferret was originally the thinnest of wrappers (7 lines of code in my
+" |.vimrc|) 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).
+"
+" So, even though Ferret has a new name now and actually prefers `ag` over `ack`
+" when available, I prefer to keep the command names intact and benefit from
+" years of accumulated muscle-memory.
+"
+"
+"
+" # Related
+"
+" Just as Ferret aims to improve the multi-file search and replace experience,
+" Loupe does the same for within-file searching:
+"
+"   https://github.com/wincent/loupe
+"
+"
+" # Website
+"
+" The official Ferret source code repo is at:
+"
+"   http://git.wincent.com/ferret.git
+"
+" A mirror exists at:
+"
+"   https://github.com/wincent/ferret
+"
+" Official releases are listed at:
+"
+"   http://www.vim.org/scripts/script.php?script_id=5220
+"
+"
+" # License
+"
+" Copyright 2015-present Greg Hurrell. All rights reserved.
+"
+" Redistribution and use in source and binary forms, with or without
+" modification, are permitted provided that the following conditions are met:
+"
+" 1. Redistributions of source code must retain the above copyright notice,
+"    this list of conditions and the following disclaimer.
+" 2. Redistributions in binary form must reproduce the above copyright notice,
+"    this list of conditions and the following disclaimer in the documentation
+"    and/or other materials provided with the distribution.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+" POSSIBILITY OF SUCH DAMAGE.
+"
+"
+" # Development
+"
+" ## Contributing patches
+"
+" Patches can be sent via mail to greg@hurrell.net, or as GitHub pull requests
+" at: https://github.com/wincent/ferret/pulls
+"
+" ## Cutting a new release
+"
+" At the moment the release process is manual:
+"
+" - Perform final sanity checks and manual testing
+" - Update the |ferret-history| section of the documentation
+" - Verify clean work tree:
+"
+" ```
+" git status
+" ```
+"
+" - Tag the release:
+"
+" ```
+" git tag -s -m "$VERSION release" $VERSION
+" ```
+"
+" - Publish the code:
+"
+" ```
+" git push origin master --follow-tags
+" git push github master --follow-tags
+" ```
+"
+" - Produce the release archive:
+"
+" ```
+" git archive -o ferret-$VERSION.zip HEAD -- .
+" ```
+"
+" - Upload to http://www.vim.org/scripts/script.php?script_id=5220
+"
+"
+" # Authors
+"
+" 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
+" - Joe Lencioni
+" - Nelo-Thara Wallus
+" - Vaibhav Sagar
+"
+"
+" # History
+"
+" 0.3.1 (not yet released)
+"
+" - Fix broken |:Qargs| command (patch from Daniel Silva).
+"
+" 0.3 (24 July 2015)
+"
+" - Added highlighting of search pattern and related |g:FerretHlsearch| option
+"   (patch from Nelo-Thara Wallus).
+" - Add better error reporting for failed or incorrect searches.
+"
+" 0.2 (16 July 2015)
+"
+" - Added |FerretDidWrite| and |FerretWillWrite| autocommands (patch from Joe
+"   Lencioni).
+" - Add |<Plug>(FerretAcks)| mapping (patch from Nelo-Thara Wallus).
+"
+" 0.1 (8 July 2015)
+"
+" - Initial release, extracted from my dotfiles
+"   (https://github.com/wincent/wincent).
+
+""
+" @option g:FerretLoaded any
+"
+" To prevent Ferret from being loaded, set |g:FerretLoaded| to any value in your
+" |.vimrc|. For example:
+"
+" ```
+" let g:FerretLoaded=1
+" ```
+if exists('g:FerretLoaded') || &compatible || v:version < 700
+  finish
+endif
+let g:FerretLoaded = 1
+
+" Temporarily set 'cpoptions' to Vim default as per `:h use-cpo-save`.
+let s:cpoptions = &cpoptions
+set cpoptions&vim
+
+if executable('ag') " The Silver Searcher: faster than ack.
+  let s:ackprg = 'ag --column --nocolor --nogroup'
+elseif executable('ack') " Ack: better than grep.
+  let s:ackprg = 'ack --column'
+elseif executable('grep') " Grep: it's just grep.
+  let s:ackprg = &grepprg " default is: grep -n $* /dev/null
+endif
+
+if !empty(s:ackprg)
+  let &grepprg=s:ackprg
+  set grepformat=%f:%l:%c:%m
+endif
+
+if has('autocmd')
+  augroup Ferret
+    autocmd!
+    autocmd QuickFixCmdPost [^l]* nested cwindow
+    autocmd QuickFixCmdPost l* nested lwindow
+  augroup END
+endif
+
+""
+" @command :Ack {pattern} {options}
+"
+" Searches for {pattern} in all the files under the current directory (see
+" |:pwd|), unless otherwise overridden via {options}, and displays the results
+" in the |quickfix| listing.
+"
+" `ag` (The Silver Searcher) will be used preferentially if present on the
+" system, because it is faster, falling back to `ack` and then `grep` as needed.
+"
+" If dispatch.vim is installed the search process will run asynchronously via
+" the |:Make| command, otherwise it will be run synchronously via |:cexpr|.
+" Asynchronous searches are preferred because they do not block, despite the
+" fact that Vim itself is single threaded. The |g:FerretDispatch| option can be
+" used to prevent the use of dispatch.vim.
+"
+" 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: >
+"
+" ```
+" :Ack -w something foo bar
+" ```
+"
+" As a convenience <leader>a is set-up (|<Plug>(FerretAck)|) as a shortcut to
+" enter |Cmdline-mode| with `:Ack` inserted on the |Cmdline|. Likewise <leader>s
+" (|<Plug>(FerretAckWord)|) is a shortcut for running |:Ack| with the word
+" currently under the cursor.
+command! -nargs=+ -complete=file Ack call ferret#private#ack(<q-args>)
+
+""
+" @command :Lack {pattern} {options}
+"
+" Just like |:Ack|, but instead of using the |quickfix| listing, which is global
+" across an entire Vim instance, it uses the |location-list|, which is a
+" per-window construct.
+"
+" Note that |:Lack| always runs synchronously via |:cexpr|, because dispatch.vim
+" doesn't currently support the |location-list|.
+command! -nargs=+ -complete=file Lack call ferret#private#lack(<q-args>)
+
+""
+" @command :Acks /{pattern}/{replacement}/
+"
+" Takes all of the files currently in the |quickfix| listing and performs a
+" substitution of all instances of {pattern} (a standard Vim search |pattern|)
+" by {replacement}.
+"
+" A typical sequence consists of an |:Ack| invocation to populate the |quickfix|
+" listing and then |:Acks| (mnemonic: "Ack substitute") to perform replacements.
+" For example, to replace "foo" with "bar" across all files in the current
+" directory:
+"
+" ```
+" :Ack foo
+" :Acks /foo/bar/
+" ```
+command! -nargs=1 Acks call ferret#private#acks(<q-args>)
+
+""
+" @option g:FerretMap boolean 1
+"
+" Controls whether to set up the Ferret mappings, such as |<Plug>(FerretAck)|
+" (see |ferret-mappings| for a full list). To prevent any mapping from being
+" configured, set to 0:
+"
+" ```
+" let g:FerretMap=0
+" ```
+let s:map=get(g:, 'FerretMap', 1)
+if s:map
+  if !hasmapto('<Plug>(FerretAck)') && maparg('<leader>a', 'n') ==# ''
+    ""
+    " @mapping <Plug>(FerretAck)
+    "
+    " Ferret maps <leader>a to |<Plug>(FerretAck)|, which triggers the |:Ack|
+    " command. To use an alternative mapping instead, create a different one in
+    " your |.vimrc| instead using |:nmap|:
+    "
+    " ```
+    " " Instead of <leader>a, use <leader>x.
+    " nmap <leader>x <Plug>(FerretAck)
+    " ```
+    nmap <unique> <leader>a <Plug>(FerretAck)
+  endif
+  nnoremap <Plug>(FerretAck) :Ack<space>
+
+  if !hasmapto('<Plug>FerretLack') && maparg('<leader>l', 'n') ==# ''
+    ""
+    " @mapping <Plug>(FerretLack)
+    "
+    " Ferret maps <leader>l to |<Plug>(FerretLack)|, which triggers the |:Lack|
+    " command. To use an alternative mapping instead, create a different one in
+    " your |.vimrc| instead using |:nmap|:
+    "
+    " ```
+    " " Instead of <leader>l, use <leader>y.
+    " nmap <leader>y <Plug>(FerretLack)
+    " ```
+    nmap <unique> <leader>l <Plug>(FerretLack)
+  endif
+  nnoremap <Plug>(FerretLack) :Lack<space>
+
+  if !hasmapto('<Plug>(FerretAckWord)') && maparg('<leader>s', 'n') ==# ''
+    " Call :Ack with word currently under cursor (mnemonic: selection).
+
+
+    ""
+    " @mapping <Plug>(FerretAckWord)
+    "
+    " Ferret maps <leader>s (mnemonix: "selection) to |<Plug>(FerretAckWord)|,
+    " which uses |:Ack| to search for the word currently under the cursor. To
+    " use an alternative mapping instead, create a different one in your
+    " |.vimrc| instead using |:nmap|:
+    "
+    " ```
+    " " Instead of <leader>s, use <leader>z.
+    " nmap <leader>z <Plug>(FerretAckWord)
+    " ```
+    nmap <unique> <leader>s <Plug>(FerretAckWord)
+  endif
+  nnoremap <Plug>(FerretAckWord) :Ack <C-r><C-w><CR>
+
+  if !hasmapto('<Plug>(FerretAcks)') && maparg('<leader>r', 'n') ==# ''
+    ""
+    " @mapping *<Plug>(FerretAcks)*
+    "
+    " Ferret maps <leader>r (mnemonic: "replace") to |<Plug>(FerretAcks)|, which
+    " triggers the |:Acks| command and fills the prompt with the last search
+    " term from Ferret. to use an alternative mapping instead, create a
+    " different one in your |.vimrc| instead using |:nmap|:
+    "
+    " ```
+    " " Instead of <leader>r, use <leader>u.
+    " nmap <leader>u <Plug>(FerretAcks)
+    " ```
+    nmap <unique> <leader>r <Plug>(FerretAcks)
+  endif
+  nnoremap <Plug>(FerretAcks)
+        \ :Acks <c-r>=(exists('g:ferret_lastsearch') ? '/' . g:ferret_lastsearch . '//' : ' ')<CR><Left>
+endif
+
+""
+" @command :Qargs
+"
+" This is a utility function that is used by the |:Acks| command but is also
+" generally useful enough to warrant being exposed publicly.
+"
+" It takes the files currently in the |quickfix| listing and sets them as
+" |:args| so that they can be operated on en masse via the |:argdo| command.
+command! -bar Qargs execute 'args' ferret#private#qargs()
+
+""
+" @option g:FerretQFCommands boolean 1
+"
+" Controls whether to set up custom versions of the |quickfix| commands, |:cn|,
+" |:cnf|, |:cp| an |:cpf|. These overrides vertically center the match within
+" the viewport on each jump. To prevent the custom versions from being
+" configured, set to 0:
+"
+" ```
+" let g:FerretQFCommands=0
+" ```
+let s:commands=get(g:, 'FerretQFCommands', 1)
+if s:commands
+  " Keep quickfix result centered, if possible, when jumping from result to result.
+  cabbrev <silent> <expr> cn ((getcmdtype() == ':' && getcmdpos() == 3) ? 'cn <bar> normal zz' : 'cn')
+  cabbrev <silent> <expr> cnf ((getcmdtype() == ':' && getcmdpos() == 4) ? 'cnf <bar> normal zz' : 'cnf')
+  cabbrev <silent> <expr> cp ((getcmdtype() == ':' && getcmdpos() == 3) ? 'cp <bar> normal zz' : 'cp')
+  cabbrev <silent> <expr> cpf ((getcmdtype() == ':' && getcmdpos() == 4) ? 'cpf <bar> normal zz' : 'cpf')
+endif
+
+" Restore 'cpoptions' to its former value.
+let &cpoptions = s:cpoptions
+unlet s:cpoptions
diff --git a/tests/fixtures/shared/integration-ferret-private.vim b/tests/fixtures/shared/integration-ferret-private.vim
new file mode 100644 (file)
index 0000000..72b68b4
--- /dev/null
@@ -0,0 +1,315 @@
+" Copyright 2015-present Greg Hurrell. All rights reserved.
+" Licensed under the terms of the BSD 2-clause license.
+
+" Remove lines a:first through a:last from the quickfix listing.
+function! s:delete(first, last)
+  let l:list=getqflist()
+  let l:line=a:first
+
+  while l:line >= a:first && l:line <= a:last
+    " Non-dictionary items will be ignored. This effectively deletes the line.
+    let l:list[l:line - 1]=0
+    let l:line=l:line + 1
+  endwhile
+  call setqflist(l:list, 'r')
+
+  " Show to next entry.
+  execute 'cc ' . a:first
+
+  " Move focus back to quickfix listing.
+  execute "normal \<C-W>\<C-P>"
+endfunction
+
+" Returns 1 if we should/can use vim-dispatch.
+function! s:dispatch()
+  ""
+  " @option g:FerretDispatch 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:
+  "
+  " ```
+  " let g:FerretDispatch=0
+  " ```
+  let l:dispatch=get(g:, 'FerretDispatch', 1)
+  return l:dispatch && exists(':Make') == 2
+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! s:error(message) abort
+  call inputsave()
+  echohl ErrorMsg
+  call input(a:message . ': press ENTER to continue')
+  echohl NONE
+  call inputrestore()
+  echo
+endfunction
+
+" Parses arguments, extracting a search pattern (which is stored in
+" g:ferret_lastsearch) and escaping space-delimited arguments for use by
+" `system()`. A string containing all the escaped arguments is returned.
+"
+" The basic strategy is to split on spaces, expand wildcards for non-option
+" arguments, shellescape each word, and join.
+"
+" To support an edge-case (the ability to search for strings with spaces in
+" them, however, we swap out escaped spaces first (subsituting the unlikely
+" "<!!S!!>") and then swap them back in at the end. This allows us to perform
+" searches like:
+"
+"   :Ack -i \bFoo_?Bar\b
+"   :Ack that's\ nice\ dear
+"
+" and so on...
+function! s:parse(arg) abort
+  if exists('g:ferret_lastsearch')
+    unlet g:ferret_lastsearch
+  endif
+
+  let l:escaped_spaces_replaced_with_markers=substitute(a:arg, '\\ ', '<!!S!!>', 'g')
+  let l:split_on_spaces=split(l:escaped_spaces_replaced_with_markers)
+  let l:expanded_args=[]
+
+  for l:arg in l:split_on_spaces
+    if l:arg =~# '^-'
+      " Options get passed through as-is.
+      call add(l:expanded_args, l:arg)
+    elseif exists('g:ferret_lastsearch')
+      let l:file_args=glob(l:arg, 1, 1) " Ignore 'wildignore', return a list.
+      if len(l:file_args)
+        call extend(l:expanded_args, l:file_args)
+      else
+        " Let through to `ag`/`ack`/`grep`, which will throw ENOENT.
+        call add(l:expanded_args, l:arg)
+      endif
+    else
+      " First non-option arg is considered to be search pattern.
+      let g:ferret_lastsearch=substitute(l:arg, '<!!S!!>', ' ', 'g')
+      call add(l:expanded_args, l:arg)
+    endif
+  endfor
+
+  let l:each_word_shell_escaped=map(l:expanded_args, 'shellescape(v:val)')
+  let l:joined=join(l:each_word_shell_escaped)
+  return substitute(l:joined, '<!!S!!>', ' ', 'g')
+endfunction
+
+function! ferret#private#post(type) abort
+  if has('autocmd')
+    augroup FerretPostQF
+      autocmd!
+    augroup END
+  endif
+
+  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 . '`'
+
+    " Search pattern has no spaces and is entirely enclosed in quotes;
+    " eg 'foo' or "bar"
+    if l:lastsearch =~ '\v^([' . "'" . '"])[^ \1]+\1$'
+      call s:error(l:base . l:tip)
+    else
+      call s:error(l:base)
+    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)
+      " Every item in the list was invalid.
+      redraw!
+      echohl ErrorMsg
+      for l:item in l:invalid
+        echomsg l:item.text
+      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' && s:dispatch() ?
+            \ ' (run `:messages` to see details)' :
+            \ ''
+
+      " 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 s:error(l:base . l:tip . l:suffix)
+      else
+        call s:error(l:base . l:suffix)
+      endif
+    endif
+  endif
+endfunction
+
+function! ferret#private#ack(command) abort
+  let l:command=s:parse(a:command)
+  call ferret#private#hlsearch()
+
+  if empty(&grepprg)
+    return
+  endif
+
+  " Prefer vim-dispatch unless otherwise instructed.
+  if s:dispatch()
+    if has('autocmd')
+      augroup FerretPostQF
+        autocmd!
+        autocmd QuickfixCmdPost cgetfile call ferret#private#post('qf')
+      augroup END
+    endif
+    let l:original_makeprg=&l:makeprg
+    let l:original_errorformat=&l:errorformat
+    try
+      let &l:makeprg=&grepprg . ' ' . l:command
+      let &l:errorformat=&grepformat
+      Make
+    catch
+      if has('autocmd')
+        augroup! FerretPostQF
+      endif
+    finally
+      let &l:makeprg=l:original_makeprg
+      let &l:errorformat=l:original_errorformat
+    endtry
+  else
+    cexpr system(&grepprg . ' ' . l:command)
+    cwindow
+    call ferret#private#post('qf')
+  endif
+endfunction
+
+function! ferret#private#lack(command) abort
+  let l:command=s:parse(a:command)
+  call ferret#private#hlsearch()
+
+  if empty(&grepprg)
+    return
+  endif
+
+  lexpr system(&grepprg . ' ' . l:command)
+  lwindow
+  call ferret#private#post('location')
+endfunction
+
+function! ferret#private#hlsearch() abort
+  if has('extra_search')
+    ""
+    " @option g:FerretHlsearch boolean
+    "
+    " Controls whether Ferret should attempt to highlight the search pattern
+    " when running |:Ack| or |:Lack|. If left unset, Ferret will respect the
+    " current 'hlsearch' setting. To force highlighting on or off irrespective
+    " of 'hlsearch', set |g:FerretHlsearch| to 1 (on) or 0 (off):
+    "
+    " ```
+    " let g:FerretHlsearch=0
+    " ```
+    let l:hlsearch=get(g:, 'FerretHlsearch', &hlsearch)
+    if l:hlsearch
+      let @/=g:ferret_lastsearch
+      call feedkeys(":let &hlsearch=1 | echo \<CR>", 'n')
+    endif
+  endif
+endfunction
+
+" Run the specified substitution command on all the files in the quickfix list
+" (mnemonic: "Ack substitute").
+"
+" Specifically, the sequence:
+"
+"   :Ack foo
+"   :Acks /foo/bar/
+"
+" is equivalent to:
+"
+"   :Ack foo
+"   :Qargs
+"   :argdo %s/foo/bar/ge | update
+"
+" (Note: there's nothing specific to Ack in this function; it's just named this
+" way for mnemonics, as it will most often be preceded by an :Ack invocation.)
+function! ferret#private#acks(command) abort
+  if match(a:command, '\v^/.+/.*/$') == -1 " crude sanity check
+    echoerr 'Ferret: Expected a substitution expression (/foo/bar/); got: ' . a:command
+    return
+  endif
+
+  let l:filenames=ferret#private#qargs()
+  if l:filenames ==# ''
+    echoerr 'Ferret: Quickfix filenames must be present, but there are none'
+    return
+  endif
+
+  execute 'args' l:filenames
+
+  if v:version > 703 || v:version == 703 && has('patch438')
+    silent doautocmd <nomodeline> User FerretWillWrite
+  else
+    silent doautocmd User FerretWillWrite
+  endif
+  execute 'argdo' '%s' . a:command . 'ge | update'
+  if v:version > 703 || v:version == 703 && has('patch438')
+    silent doautocmd <nomodeline> User FerretDidWrite
+  else
+    silent doautocmd User FerretDidWrite
+  endif
+endfunction
+
+" Populate the :args list with the filenames currently in the quickfix window.
+function! ferret#private#qargs() abort
+  let l:buffer_numbers={}
+  for l:item in getqflist()
+    let l:buffer_numbers[l:item['bufnr']]=bufname(l:item['bufnr'])
+  endfor
+  return join(map(values(l:buffer_numbers), 'fnameescape(v:val)'))
+endfunction
+
+" Visual mode deletion and `dd` mapping (special case).
+function! ferret#private#qf_delete() range
+  call s:delete(a:firstline, a:lastline)
+endfunction
+
+" Motion-based deletion from quickfix listing.
+function! ferret#private#qf_delete_motion(type, ...)
+  " Save.
+  let l:selection=&selection
+  let &selection='inclusive'
+
+  let l:firstline=line("'[")
+  let l:lastline=line("']")
+  call s:delete(l:firstline, l:lastline)
+
+  " Restore.
+  let &selection=l:selection
+endfunction
diff --git a/tests/fixtures/shared/integration-pinnacle.vim b/tests/fixtures/shared/integration-pinnacle.vim
new file mode 100644 (file)
index 0000000..66db788
--- /dev/null
@@ -0,0 +1,128 @@
+""
+" @plugin Pinnacle Highlight group manipulation for Vim
+"
+" # Intro
+"
+" Pinnacle provides functions for manipulating |:highlight| groups.
+"
+"
+" # Installation
+"
+" To install Pinnacle, use your plug-in management system of choice.
+"
+" If you don't have a "plug-in management system of choice", I recommend
+" Pathogen (https://github.com/tpope/vim-pathogen) due to its simplicity and
+" robustness. Assuming that you have Pathogen installed and configured, and that
+" you want to install vim-docvim into `~/.vim/bundle`, you can do so with:
+"
+" ```
+" git clone https://github.com/wincent/pinnacle.git ~/.vim/bundle/pinnacle
+" ```
+"
+" Alternatively, if you use a Git submodule for each Vim plug-in, you could do
+" the following after `cd`-ing into the top-level of your Git superproject:
+"
+" ```
+" git submodule add https://github.com/wincent/pinnacle.git ~/vim/bundle/pinnacle
+" git submodule init
+" ```
+"
+" To generate help tags under Pathogen, you can do so from inside Vim with:
+"
+" ```
+" :call pathogen#helptags()
+" ```
+"
+"
+" # Website
+"
+" The official Pinnacle source code repo is at:
+"
+"   http://git.wincent.com/pinnacle.git
+"
+" Mirrors exist at:
+"
+"   - https://github.com/wincent/pinnacle
+"   - https://gitlab.com/wincent/pinnacle
+"   - https://bitbucket.org/ghurrell/pinnacle
+"
+" Official releases are listed at:
+"
+"   http://www.vim.org/scripts/script.php?script_id=[TODO]
+"
+"
+" # License
+"
+" Copyright (c) 2016-present Greg Hurrell
+"
+" Permission is hereby granted, free of charge, to any person obtaining
+" a copy of this software and associated documentation files (the
+" "Software"), to deal in the Software without restriction, including
+" without limitation the rights to use, copy, modify, merge, publish,
+" distribute, sublicense, and/or sell copies of the Software, and to
+" permit persons to whom the Software is furnished to do so, subject to
+" the following conditions:
+"
+" The above copyright notice and this permission notice shall be
+" included in all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+"
+"
+" # Development
+"
+" ## Contributing patches
+"
+" Patches can be sent via mail to greg@hurrell.net, or as GitHub pull requests
+" at: https://github.com/wincent/pinnacle/pulls
+"
+" ## Cutting a new release
+"
+" At the moment the release process is manual:
+"
+" - Perform final sanity checks and manual testing
+" - Update the |pinnacle-history| section of the documentation
+" - Verify clean work tree:
+"
+" ```
+" git status
+" ```
+"
+" - Tag the release:
+"
+" ```
+" git tag -s -m "$VERSION release" $VERSION
+" ```
+"
+" - Publish the code:
+"
+" ```
+" git push origin master --follow-tags
+" git push github master --follow-tags
+" ```
+"
+" - Produce the release archive:
+"
+" ```
+" git archive -o vim-docvim-$VERSION.zip HEAD -- .
+" ```
+"
+" - Upload to http://www.vim.org/scripts/script.php?script_id=[TODO]
+"
+"
+" # Authors
+"
+" Pinnacle is written and maintained by Greg Hurrell <greg@hurrell.net>.
+"
+"
+" # History
+"
+" ## 0.1 (30 March 2016)
+"
+" - Initial release.
index ba5fb85dff7e9bd829f4b3b17fd7420d2b08fdaf..4051b06dee54232870b47194800f6aa804c78e63 120000 (symlink)
@@ -1 +1 @@
-../markdown/integration-ferret-ftplugin-qf.vim
\ No newline at end of file
+../shared/integration-ferret-ftplugin-qf.vim
\ No newline at end of file
index 1c956b4d4d86e2e12f58c92d1a1d89f6ad95ef5a..4634fa0a49e91bd7a0b6dc6183e78033daf1c759 120000 (symlink)
@@ -1 +1 @@
-../markdown/integration-ferret-plugin.vim
\ No newline at end of file
+../shared/integration-ferret-plugin.vim
\ No newline at end of file
index 46719bc2ecfaa9b7e6c439da2e2ca3db45cb7bac..b19e38c3145dbd7ab0b231c2b4210bbc9af114e7 120000 (symlink)
@@ -1 +1 @@
-../markdown/integration-ferret-private.vim
\ No newline at end of file
+../shared/integration-ferret-private.vim
\ No newline at end of file
index 0d3a4d6f1255bb680858b303de28fc1eb94e02fc..e209dd245d84805fdbbf03c011d5e26e331551a5 120000 (symlink)
@@ -1 +1 @@
-../markdown/integration-pinnacle.vim
\ No newline at end of file
+../shared/integration-pinnacle.vim
\ No newline at end of file