Allow hyphens in plug-in names
authorGreg Hurrell <greg@hurrell.net>
Tue, 4 Jul 2017 01:32:20 +0000 (18:32 -0700)
committerGreg Hurrell <greg@hurrell.net>
Tue, 4 Jul 2017 01:32:20 +0000 (18:32 -0700)
Discovered the need for this while extracting the vcs-jump plug-in.

lib/Text/Docvim/Parse.hs
tests/fixtures/integration/vcs-jump/golden/ast.golden [new file with mode: 0644]
tests/fixtures/integration/vcs-jump/golden/markdown.golden [new file with mode: 0644]
tests/fixtures/integration/vcs-jump/golden/plaintext.golden [new file with mode: 0644]
tests/fixtures/integration/vcs-jump/input/autoload/vcsjump.vim [new file with mode: 0644]
tests/fixtures/integration/vcs-jump/input/bin/vcs-jump [new file with mode: 0755]
tests/fixtures/integration/vcs-jump/input/plugin/vcsjump.vim [new file with mode: 0644]

index 6930e1abd42ba5eeac5744ad7ea8cba09c1d96be..12fc980305f9bba7c9b5b84a266a1cf1ca14fed8 100644 (file)
@@ -464,7 +464,7 @@ annotation = char '@' *> annotationName
     optionDefault     = optionMaybe word <?> "option default value"
 
     plugin            = string "plugin" >> ws >> PluginAnnotation <$> pluginName <*> plugInDescription
-    pluginName        = many1 alphaNum <* ws
+    pluginName        = many1 (alphaNum <|> char '-') <* ws
     plugInDescription = restOfLine
 
 -- | Parses a translation unit (file contents) into an AST.
diff --git a/tests/fixtures/integration/vcs-jump/golden/ast.golden b/tests/fixtures/integration/vcs-jump/golden/ast.golden
new file mode 100644 (file)
index 0000000..6a310da
--- /dev/null
@@ -0,0 +1,76 @@
+Project
+  [ DocBlock
+      [ PluginAnnotation "vcs-jump" "vcs-jump plug-in for Vim"
+      , TOC [ "Intro" ]
+      ]
+  , HeadingAnnotation "Intro"
+  , Paragraph
+      [ Plaintext "This"
+      , Whitespace
+      , Plaintext "plug-in"
+      , Whitespace
+      , Plaintext "allows"
+      , Whitespace
+      , Plaintext "you"
+      , Whitespace
+      , Plaintext "to"
+      , Whitespace
+      , Plaintext "jump"
+      , Whitespace
+      , Plaintext "to"
+      , Whitespace
+      , Plaintext "useful"
+      , Whitespace
+      , Plaintext "places"
+      , Whitespace
+      , Plaintext "within"
+      , Whitespace
+      , Plaintext "a"
+      , Whitespace
+      , Plaintext "Git"
+      , Whitespace
+      , Plaintext "or"
+      , Whitespace
+      , Plaintext "Mercurial"
+      , Whitespace
+      , Plaintext "repository."
+      ]
+  , Project
+      [ Unit
+          [ LetStatement
+              { letLexpr = "s:jump_path"
+              , letValue =
+                  "shellescape(simplify(fnamemodify(resolve(expand('<sfile>:p')), ':h') . '/../bin/vcs-jump'))"
+              }
+          , FunctionDeclaration
+              { functionBang = True
+              , functionName = "vcsjump#jump"
+              , functionArguments = ArgumentList [ Argument "command" ]
+              , functionAttributes = [ "abort" ]
+              , functionBody =
+                  [ GenericStatement
+                      "cexpr system(s:jump_path . ' ' . a:command . ' 2> /dev/null')"
+                  , GenericStatement "cwindow"
+                  ]
+              }
+          ]
+      , Unit
+          [ GenericStatement
+              "if exists('g:VcsJumpLoaded') || &compatible || v:version < 700"
+          , GenericStatement "finish"
+          , GenericStatement "endif"
+          , LetStatement { letLexpr = "g:VcsJumpLoaded " , letValue = "1" }
+          , LetStatement
+              { letLexpr = "s:cpoptions " , letValue = "&cpoptions" }
+          , GenericStatement "set cpoptions&vim"
+          , GenericStatement
+              "command! -nargs=+ -complete=file VcsJump call vcsjump#jump(<q-args>)"
+          , GenericStatement
+              "if !hasmapto('<Plug>(VcsJump)') && maparg('<Leader>d', 'n') ==# ''"
+          , GenericStatement "\"\""
+          , GenericStatement "nmap <unique> <Leader>d <Plug>(VcsJump)"
+          , GenericStatement "endif"
+          , GenericStatement "nnoremap <Plug>(VcsJump) :VcsJump diff<space>"
+          ]
+      ]
+  ]
diff --git a/tests/fixtures/integration/vcs-jump/golden/markdown.golden b/tests/fixtures/integration/vcs-jump/golden/markdown.golden
new file mode 100644 (file)
index 0000000..c46d7b5
--- /dev/null
@@ -0,0 +1,7 @@
+
+# vcs-jump<a name="vcs-jump-vcs-jump" href="#user-content-vcs-jump-vcs-jump"></a>
+
+
+## Intro<a name="vcs-jump-intro" href="#user-content-vcs-jump-intro"></a>
+
+This plug-in allows you to jump to useful places within a Git or Mercurial repository.
diff --git a/tests/fixtures/integration/vcs-jump/golden/plaintext.golden b/tests/fixtures/integration/vcs-jump/golden/plaintext.golden
new file mode 100644 (file)
index 0000000..a9a3f4f
--- /dev/null
@@ -0,0 +1,10 @@
+*vcs-jump.txt*                 vcs-jump plug-in for Vim                 *vcs-jump*
+
+CONTENTS                                                     *vcs-jump-contents*
+
+1. Intro      |vcs-jump-intro|
+
+INTRO                                                           *vcs-jump-intro*
+
+This plug-in allows you to jump to useful places within a Git or Mercurial
+repository.
diff --git a/tests/fixtures/integration/vcs-jump/input/autoload/vcsjump.vim b/tests/fixtures/integration/vcs-jump/input/autoload/vcsjump.vim
new file mode 100644 (file)
index 0000000..49a2a63
--- /dev/null
@@ -0,0 +1,6 @@
+let s:jump_path=shellescape(simplify(fnamemodify(resolve(expand('<sfile>:p')), ':h') . '/../bin/vcs-jump'))
+
+function! vcsjump#jump(command) abort
+  cexpr system(s:jump_path . ' ' . a:command . ' 2> /dev/null')
+  cwindow
+endfunction
diff --git a/tests/fixtures/integration/vcs-jump/input/bin/vcs-jump b/tests/fixtures/integration/vcs-jump/input/bin/vcs-jump
new file mode 100755 (executable)
index 0000000..678ec13
--- /dev/null
@@ -0,0 +1,166 @@
+#!/usr/bin/env ruby
+
+# Based on `git-jump`, that comes with Git, but works with Mercurial as well
+# (ported to Ruby to make some of the relative path manipulation easier).
+
+require 'pathname'
+require 'shellwords'
+require 'tempfile'
+
+def usage()
+  puts <<-EOF.gsub(/^ {4}/, '')
+    usage: vcs-jump <mode> [<args>]
+
+    Jump to interesting elements in an editor.
+    The <mode> parameter is one of:
+
+    diff: elements are diff hunks. Arguments are given to diff.
+    [supports: git, hg]
+
+    merge: elements are merge conflicts. Arguments are ignored.
+    [supports: git, hg]
+
+    grep: elements are grep hits. Arguments are given to grep.
+    [supports: git, hg]
+  EOF
+end
+
+def open_editor(tmp)
+  editor = `git var GIT_EDITOR 2> /dev/null`.chomp
+  editor = ENV['EDITOR'] if !$?.success?
+  editor = `which vim`.chomp unless editor
+  raise 'error: cannot locate editor' if editor == ''
+
+  if Pathname.new(editor).basename.to_s == 'vim'
+    additional_args = %w[-c :cw] # open the quickfix window
+  end
+
+  exec(editor, '-q', tmp, *additional_args)
+end
+
+def pwd
+  @pwd ||= Pathname.pwd.realpath
+end
+
+def absolutize(file)
+  Pathname.new(file).realpath
+end
+
+def relativize(file)
+  return file if git?
+  relative = pwd.relative_path_from(root).to_s
+  file.to_s.sub("#{relative}/", '')
+end
+
+def git_root
+  root = `git rev-parse --show-toplevel 2> /dev/null`.chomp
+  [absolutize(root), 'git'] if $?.success?
+end
+
+def hg_root
+  root = `hg root`.chomp
+  [absolutize(root), 'hg'] if $?.success?
+end
+
+def vcs_info
+  @info ||= begin
+    info = git_root
+    info = hg_root unless info
+
+    raise 'Unable to detect VCS info' unless info
+
+    info
+  end
+end
+
+def root
+  vcs_info[0]
+end
+
+def vcs
+  vcs_info[1]
+end
+
+def git?
+  vcs == 'git'
+end
+
+def hg?
+  vcs == 'hg'
+end
+
+def shellescape(args)
+  ARGV.map { |arg| Shellwords.shellescape(arg) }.join(' ')
+end
+
+def redir(new_fd, &block)
+  old_stdout, old_stderr = $stdout, $stderr
+  $stdout, $stderr = new_fd, new_fd
+  yield
+ensure
+  $stdout, $stderr = old_stdout, old_stderr
+end
+
+def mode_diff(args)
+  args = shellescape(args)
+  diff =  git? ? `git diff --relative #{args}` : `hg diff --git --root . #{args}`
+  idx  = nil
+  file = nil
+
+  diff.lines.each do |line|
+    # setting the inner Perl hacker free since 2007
+    (line =~ %r{^\+\+\+ b/(.*)}) ? (file = relativize($~[1])) : (next unless file)
+    (line =~ %r{^@@ .*\+(\d+)}) ? (idx = $~[1].to_i) : (next unless idx)
+    (line =~ %r{^ }) && (idx += 1; next)
+    (line =~ %r{^[-+]\s*(.*)}) && ( puts "#{file}:#{idx}: #{$~[1]}"; idx = nil)
+  end
+end
+
+def mode_merge(__args__ignored)
+  if git?
+    command = 'git ls-files -u'
+    filter = "perl -pe 's/^.*?\\t//"
+  else
+    command = 'hg resolve -l'
+    filter = "egrep -e '^U\\s+' | perl -pe 's#^U\\s+##{root}/#'"
+  end
+  puts %x{
+    #{command} |
+    #{filter} |
+    sort |
+    while IFS= read fn; do
+      grep -Hn '^<<<<<<<' "$fn"
+    done
+  }
+end
+
+# `grep -n` generates nice quickfix-looking lines by itself,
+# but let's clean up extra whitespace, so they look better if the
+# editor shows them to us in the status bar.
+def mode_grep(args)
+  if git?
+    puts %x{git grep -n #{shellescape args} | perl -pe 's/[ \t]+/ /g; s/^ *//;'}
+  else
+    puts %x{hg grep -n #{shellescape args} | perl -pe 's/[ \t]+/ /g; s/^ *//;'}
+  end
+end
+
+if ARGV.count < 1
+  usage()
+  exit 1
+end
+
+mode = ARGV.shift
+
+if STDOUT.tty?
+  begin
+    tmp = Tempfile.new('vcs-jump')
+    redir(tmp) { send("mode_#{mode}", ARGV) }
+    tmp.flush
+    open_editor(tmp.path)
+  ensure
+    tmp.close
+  end
+else
+  send("mode_#{mode}", ARGV)
+end
diff --git a/tests/fixtures/integration/vcs-jump/input/plugin/vcsjump.vim b/tests/fixtures/integration/vcs-jump/input/plugin/vcsjump.vim
new file mode 100644 (file)
index 0000000..37dd8fe
--- /dev/null
@@ -0,0 +1,29 @@
+""
+" @plugin vcs-jump vcs-jump plug-in for Vim
+"
+" # Intro
+"
+" This plug-in allows you to jump to useful places within a Git or Mercurial
+" repository.
+"
+if exists('g:VcsJumpLoaded') || &compatible || v:version < 700
+  finish
+endif
+let g:VcsJumpLoaded = 1
+
+" Temporarily set 'cpoptions' to Vim default as per `:h use-cpo-save`.
+let s:cpoptions = &cpoptions
+set cpoptions&vim
+
+command! -nargs=+ -complete=file VcsJump call vcsjump#jump(<q-args>)
+
+if !hasmapto('<Plug>(VcsJump)') && maparg('<Leader>d', 'n') ==# ''
+  ""
+  " @mappings <Plug>(VcsJump)
+  "
+  " This mapping invokes the bundled `vcs-jump` script.
+  "
+  nmap <unique> <Leader>d <Plug>(VcsJump)
+endif
+
+nnoremap <Plug>(VcsJump) :VcsJump diff<space>