Просмотр исходного кода

Update plugins

Sclarki user on github appears to no longer exist (or, perhaps less
likely, has been renamed to MidnaPeach?), hence repositories for
Neonwave and Surarken no longer exist, and these are now pointed to
alternatives.
cinaeco 7 лет назад
Родитель
Сommit
3f36ee8e96
7 измененных файлов с 126 добавлено и 307 удалено
  1. 1 1
      docs/man/man1/z.1
  2. 1 1
      shell/common/coloured-man-pages.sh
  3. 25 23
      shell/common/z.sh
  4. 0 25
      shell/zsh/completions/_ack
  5. 1 217
      shell/zsh/completions/_ag
  6. 95 37
      vim/autoload/plug.vim
  7. 3 3
      vim/plugins.vim

+ 1 - 1
docs/man/man1/z.1

@@ -155,7 +155,7 @@ directory trees to exclude from tracking. \fB$HOME\fR is always excluded.
 Directories must be full paths without trailing slashes.
 Directories must be full paths without trailing slashes.
 .P
 .P
 The environment variable \fB$_Z_OWNER\fR can be set to your username, to
 The environment variable \fB$_Z_OWNER\fR can be set to your username, to
-allow usage of \fBz\fR when your sudo enviroment keeps \fB$HOME\fR set.
+allow usage of \fBz\fR when your sudo environment keeps \fB$HOME\fR set.
 .SH
 .SH
 FILES
 FILES
 Data is stored in \fB$HOME/.z\fR. This can be overridden by setting the
 Data is stored in \fB$HOME/.z\fR. This can be overridden by setting the

+ 1 - 1
shell/common/coloured-man-pages.sh

@@ -16,7 +16,7 @@ EOF
 	fi
 	fi
 fi
 fi
 
 
-man() {
+function man() {
 	env \
 	env \
 		LESS_TERMCAP_mb=$(printf "\e[1;31m") \
 		LESS_TERMCAP_mb=$(printf "\e[1;31m") \
 		LESS_TERMCAP_md=$(printf "\e[1;31m") \
 		LESS_TERMCAP_md=$(printf "\e[1;31m") \

+ 25 - 23
shell/common/z.sh

@@ -1,4 +1,4 @@
-# Copyright (c) 2009 rupa deadwyler under the WTFPL license
+# Copyright (c) 2009 rupa deadwyler. Licensed under the WTFPL license, Version 2
 
 
 # maintains a jump-list of the directories you actually use
 # maintains a jump-list of the directories you actually use
 #
 #
@@ -31,15 +31,19 @@ _z() {
 
 
     local datafile="${_Z_DATA:-$HOME/.z}"
     local datafile="${_Z_DATA:-$HOME/.z}"
 
 
+    # if symlink, dereference
+    [ -h "$datafile" ] && datafile=$(readlink "$datafile")
+
     # bail if we don't own ~/.z and $_Z_OWNER not set
     # bail if we don't own ~/.z and $_Z_OWNER not set
     [ -z "$_Z_OWNER" -a -f "$datafile" -a ! -O "$datafile" ] && return
     [ -z "$_Z_OWNER" -a -f "$datafile" -a ! -O "$datafile" ] && return
 
 
     _z_dirs () {
     _z_dirs () {
-      while read line; do
-        # only count directories
-        [ -d "${line%%\|*}" ] && echo $line
-      done < "$datafile"
-      return 0
+        local line
+        while read line; do
+            # only count directories
+            [ -d "${line%%\|*}" ] && echo "$line"
+        done < "$datafile"
+        return 0
     }
     }
 
 
     # add entries
     # add entries
@@ -57,7 +61,7 @@ _z() {
 
 
         # maintain the data file
         # maintain the data file
         local tempfile="$datafile.$RANDOM"
         local tempfile="$datafile.$RANDOM"
-        awk < <(_z_dirs 2>/dev/null) -v path="$*" -v now="$(date +%s)" -F"|" '
+        _z_dirs | awk -v path="$*" -v now="$(date +%s)" -F"|" '
             BEGIN {
             BEGIN {
                 rank[path] = 1
                 rank[path] = 1
                 time[path] = now
                 time[path] = now
@@ -90,17 +94,15 @@ _z() {
 
 
     # tab completion
     # tab completion
     elif [ "$1" = "--complete" -a -s "$datafile" ]; then
     elif [ "$1" = "--complete" -a -s "$datafile" ]; then
-        while read line; do
-            [ -d "${line%%\|*}" ] && echo $line
-        done < "$datafile" | awk -v q="$2" -F"|" '
+        _z_dirs | awk -v q="$2" -F"|" '
             BEGIN {
             BEGIN {
-                if( q == tolower(q) ) imatch = 1
                 q = substr(q, 3)
                 q = substr(q, 3)
-                gsub(" ", ".*", q)
+                if( q == tolower(q) ) imatch = 1
+                gsub(/ /, ".*", q)
             }
             }
             {
             {
                 if( imatch ) {
                 if( imatch ) {
-                    if( tolower($1) ~ tolower(q) ) print $1
+                    if( tolower($1) ~ q ) print $1
                 } else if( $1 ~ q ) print $1
                 } else if( $1 ~ q ) print $1
             }
             }
         ' 2>/dev/null
         ' 2>/dev/null
@@ -141,19 +143,21 @@ _z() {
                 if( dx < 604800 ) return rank / 2
                 if( dx < 604800 ) return rank / 2
                 return rank / 4
                 return rank / 4
             }
             }
-            function output(files, out, common) {
+            function output(matches, best_match, common) {
                 # list or return the desired directory
                 # list or return the desired directory
                 if( list ) {
                 if( list ) {
                     cmd = "sort -n >&2"
                     cmd = "sort -n >&2"
-                    for( x in files ) {
-                        if( files[x] ) printf "%-10s %s\n", files[x], x | cmd
+                    for( x in matches ) {
+                        if( matches[x] ) {
+                            printf "%-10s %s\n", matches[x], x | cmd
+                        }
                     }
                     }
                     if( common ) {
                     if( common ) {
                         printf "%-10s %s\n", "common:", common > "/dev/stderr"
                         printf "%-10s %s\n", "common:", common > "/dev/stderr"
                     }
                     }
                 } else {
                 } else {
-                    if( common ) out = common
-                    print out
+                    if( common ) best_match = common
+                    print best_match
                 }
                 }
             }
             }
             function common(matches) {
             function common(matches) {
@@ -164,11 +168,9 @@ _z() {
                     }
                     }
                 }
                 }
                 if( short == "/" ) return
                 if( short == "/" ) return
-                # use a copy to escape special characters, as we want to return
-                # the original. yeah, this escaping is awful.
-                clean_short = short
-                gsub(/\[\(\)\[\]\|\]/, "\\\\&", clean_short)
-                for( x in matches ) if( matches[x] && x !~ clean_short ) return
+                for( x in matches ) if( matches[x] && index(x, short) != 1 ) {
+                    return
+                }
                 return short
                 return short
             }
             }
             BEGIN {
             BEGIN {

+ 0 - 25
shell/zsh/completions/_ack

@@ -1,30 +1,5 @@
 #compdef ack ack2 ack-grep ack-standalone
 #compdef ack ack2 ack-grep ack-standalone
 # ------------------------------------------------------------------------------
 # ------------------------------------------------------------------------------
-# Copyright (c) 2011 Github zsh-users - http://github.com/zsh-users
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * 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.
-#     * Neither the name of the zsh-users nor the
-#       names of its contributors may be used to endorse or promote products
-#       derived from this software without specific prior written permission.
-#
-# 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 ZSH-USERS 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.
-# ------------------------------------------------------------------------------
 # Description
 # Description
 # -----------
 # -----------
 #
 #

+ 1 - 217
shell/zsh/completions/_ag

@@ -1,217 +1 @@
-#compdef ag
-# ------------------------------------------------------------------------------
-# Copyright (c) 2015 Github zsh-users - http://github.com/zsh-users
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * 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.
-#     * Neither the name of the zsh-users nor the
-#       names of its contributors may be used to endorse or promote products
-#       derived from this software without specific prior written permission.
-#
-# 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 ZSH-USERS 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.
-# ------------------------------------------------------------------------------
-# Description
-# -----------
-#
-#  Completion script for ag (https://github.com/ggreer/the_silver_searcher)
-#
-# ------------------------------------------------------------------------------
-# Authors
-# -------
-#
-#  * Akira Maeda <https://github.com/glidenote>
-#
-# ------------------------------------------------------------------------------
-# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
-# vim: ft=zsh sw=2 ts=2 et
-# ------------------------------------------------------------------------------
-_ag_version() {
-  local version
-  version=( $($words[1] --version) )
-  version=${version[@]:2:1}
-  version=( "${(@s/./)version}" )
-  echo "${version[2]}"
-}
-
-# Dynamically build the file type completion
-# Modifies the global $AG_OPTS array
-_ag_add_file_types() {
-  local typ exts
-  for i in $($words[1] --list-file-types); do
-    if [[ "${i:0:2}" = '--' ]]; then
-      if [[ "${typ}x" != "x" ]]; then
-        AG_OPTS+="${typ}[${exts}]"
-      fi
-      typ=$i
-      exts=
-    else
-      exts+=$i
-    fi
-  done
-  AG_OPTS+="${typ}[${exts}]"
-}
-
-# Add version appropriate options above base
-# Modifies the global $AG_OPTS array
-_ag_add_version_opts() {
-  local minor=$(_ag_version)
-
-  if [[ $minor -gt 21 ]];then
-    _ag_add_file_types
-    AG_OPTS+=(
-      '(- 1 *)--list-file-types[list supported filetypes to search]'
-      '--silent[suppress all log messages, including errors]'
-    )
-  fi
-
-  if [[ $minor -gt 22 ]];then
-    AG_OPTS+=(
-      '(-z --search-zip)'{-z,--search-zip}'[search contents of compressed files]'
-    )
-  fi
-
-  if [[ $minor -le 24 ]];then
-    AG_OPTS+=(
-      '(-s --case-sensitive)'{-s,--case-sensitive}'[match case sensitively]'
-      '(--noheading --heading)'{--noheading,--heading}'[print file names above matching contents]'
-    )
-  fi
-  if [[ $minor -gt 24 ]];then
-    AG_OPTS+=(
-      '(-s --case-sensitive)'{-s,--case-sensitive}'[Match case sensitively. Default on.]'
-      '(-H --noheading --heading)'{-H,--noheading,--heading}'[print file names above matching contents]'
-      '--vimgrep[output results like vim''s, :vimgrep /pattern/g would (report every match on the line)]'
-    )
-  fi
-
-  if [[ $minor -gt 26 ]];then
-    AG_OPTS+=(
-      '(-0 --null --print0)'{-0,--null,--print0}'[separate the filenames with \\0, rather than \\n]'
-    )
-  fi
-
-  if [[ $minor -le 27 ]];then
-    AG_OPTS+=(
-      '--depth[Search up to NUM directories deep. Default is 25.]:number'
-    )
-  fi
-  if [[ $minor -gt 27 ]];then
-    AG_OPTS+=(
-      '(-c --count)'{-c,--count}'[only print the number of matches in each file]'
-      '--depth[Search up to NUM directories deep, -1 for unlimited. Default is 25.]:number'
-      '(-F --fixed-strings)'{-F,--fixed-strings}'[alias for --literal for compatibility with grep]'
-    )
-  fi
-
-  if [[ $minor -le 28 ]];then
-    AG_OPTS+=(
-      '(--no-numbers)--no-numbers[don´t show line numbers]'
-    )
-  fi
-  if [[ $minor -gt 28 ]];then
-    AG_OPTS+=(
-      '(--nofilename --filename)'{--nofilename,--filename}'[Print file names. Default on, except when searching a single file.]'
-      '(--nonumbers --numbers)'{--nonumbers,--numbers}'[Print line numbers. Default is to omit line numbers when searching streams]'
-      '(-o --only-matching)'{-o,--only-matching}'[print only the matching part of the lines]'
-    )
-  fi
-}
-
-_ag() {
-  local curcontext="$curcontext" state line cmds update_policy ret=1
-
-  zstyle -s ":completion:${curcontext}:" cache-policy update_policy
-  [[ -z "$update_policy" ]] && zstyle ":completion:${curcontext}:" cache-policy _ag_types_caching_policy
-
-  # Don't complete if command doesn't exist
-  [[ ${+commands[${words[1]}]} -eq 0 ]] && return 0
-
-  if ( [[ ${+AG_OPTS} -eq 0 ]] || _cache_invalid "_AG_OPTS" ) && ! _retrieve_cache "_AG_OPTS"; then
-    # Base opts starts at ag version 0.20
-    AG_OPTS=(
-      '(- 1 *)--help[print a short help statement]'
-      '(- 1 *)--man[print the manual page]'
-      '(- 1 *)--version[display version and copyright information]'
-      '--ackmate[output results in a format parseable by AckMate]'
-      '(-A --after)'{-A,--after}'[Print NUM lines before match. Default is 2]:number'
-      '(-t --all-text -a --all-types -u --unrestricted)'{-t,--all-text}"[search all text files, excluding hidden ones]"
-      '(-a --all-types -t --all-text -u --unrestricted)'{-a,--all-types}"[search all text files, excluding hidden ones and not obeying ignore files (.agignore, .gitignore...)]"
-      '(-B --before)'{-B,--before}'[Print NUM lines after match. Defaults is 2]:number'
-      '(--nobreak --break)'{--nobreak,--break}'[Print a newline between matches in different files. Default on.]'
-      '(--color --nocolor)--color[Print color codes in results. Default on.]'
-      '(--nocolor --color --color-line-number --color-match --color-path)--nocolor[Do not print color codes in results. Default on.]'
-      '(--nocolor)--color-line-number[Color codes for line numbers. Default is 1;33.]'
-      '(--nocolor)--color-match[Color codes for result match numbers. Default is 30;43.]'
-      '(--nocolor)--color-path[Color codes for path names. Default is 1;32.]'
-      '--column[print column numbers in results]'
-      '(-C --context)'{-C,--context}'[Print NUM lines before and after matches. Default is 2.]:number'
-      '(-D --debug)'{-D,--debug}'[enable debug logging]'
-      '(-G --file-search-regex)'{-G,--file-search-regex}'[only search file names matching PATTERN]:pattern'
-      '(-l --files-with-matches)'{-l,--files-with-matches}'[only print filenames containing matches, not matching lines]'
-      '(-L --files-without-matches)'{-L,--files-without-matches}"[only print filenames that don't contain matches]"
-      '(-f --follow)'{-f,--follow}'[follow symlinks]'
-      '(-g)-g[print filenames that match PATTERN]:pattern'
-      '(--nogroup --group)'{--nogroup,--group}'[same as --\[no\]break --\[no\]heading]'
-      '--hidden[search hidden files, still obeys ignore files.]'
-      '*--ignore[Ignore files/directories matching this pattern. Literal file and directory names are also allowed.]:files:_files'
-      '(-i --ignore-case)'{-i,--ignore-case}'[match case insensitively]:pattern'
-      '*--ignore-dir[alias for --ignore for compatibility with ack]:files:_files'
-      '(-v --invert-match)'{-v,--invert-match}'[invert match]'
-      '(-Q --literal)'{-Q,--literal}'[match PATTERN literally, no regular expression]'
-      '(-m --max-count)'{-m,--max-count}'[Skip the rest of a file after NUM matches. Default is 10,000.]:number'
-      '(--pager --nopager)'{--pager,--nopager}'[Display results with PAGER. Disabled by default.]:pager program:_command_names'
-      '(--passthrough)--passthrough[when searching a stream, print all lines even if they don''t match]'
-      '(-p --path-to-agignore)'{-p,--path-to-agignore}'[provide a path to a specific .agignore file]:files:_files'
-      '--print-long-lines[print matches on very long lines, > 2k characters by default]'
-      '--search-binary[search binary files]'
-      '(-U --skip-vcs-ignores)'{-U,--skip-vcs-ignores}'[ignore VCS ignore files (.gitigore, .hgignore, svn:ignore), but still use .agignore]'
-      '(-S --smart-case)'{-S,--smart-case}'[match case sensitively if PATTERN contains any uppercase letters, else match case insensitively]'
-      '--stats[print stats (files scanned, time taken, etc)]'
-      '(-u --unrestricted -t --all-text -a --all-types)'{-u,--unrestricted}'[search ALL files, includes: hidden, binary & ignored files (.agignore, .gitignore...)]'
-      '(-w --word-regexp)'{-w,--word-regexp}'[only match whole words]'
-    )
-    _ag_add_version_opts
-    AG_OPTS+=(
-      '*: :_files'
-    )
-    [[ $#AG_OPTS -gt 0 ]] && _store_cache '_AG_OPTS' AG_OPTS
-  fi
-
-  _arguments -C -s -S ${AG_OPTS} && ret=0
-  unset AG_OPTS
-
-  case $state in
-    # placeholder
-  esac
-
-  return ret
-}
-
-_ag_types_caching_policy() {
-  # Rebuild if .agignore more recent than cache.
-  [[ -f $HOME/.agignore && $$HOME/.agignore -nt "$1" ]] && return 0
-
-  # Rebuild if cache is older than one week.
-  local -a oldp
-  oldp=( "$1"(Nmw+1) )
-  (( $#oldp )) && return 0
-
-  return 1
-}
-
-_ag "$@"
+404: Not Found

+ 95 - 37
vim/autoload/plug.vim

@@ -97,7 +97,7 @@ let s:plug_tab = get(s:, 'plug_tab', -1)
 let s:plug_buf = get(s:, 'plug_buf', -1)
 let s:plug_buf = get(s:, 'plug_buf', -1)
 let s:mac_gui = has('gui_macvim') && has('gui_running')
 let s:mac_gui = has('gui_macvim') && has('gui_running')
 let s:is_win = has('win32') || has('win64')
 let s:is_win = has('win32') || has('win64')
-let s:nvim = has('nvim') && exists('*jobwait') && !s:is_win
+let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win)
 let s:vim8 = has('patch-8.0.0039') && exists('*job_start')
 let s:vim8 = has('patch-8.0.0039') && exists('*job_start')
 let s:me = resolve(expand('<sfile>:p'))
 let s:me = resolve(expand('<sfile>:p'))
 let s:base_spec = { 'branch': 'master', 'frozen': 0 }
 let s:base_spec = { 'branch': 'master', 'frozen': 0 }
@@ -121,6 +121,9 @@ function! plug#begin(...)
   else
   else
     return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.')
     return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.')
   endif
   endif
+  if fnamemodify(home, ':t') ==# 'plugin' && fnamemodify(home, ':h') ==# s:first_rtp
+    return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.')
+  endif
 
 
   let g:plug_home = home
   let g:plug_home = home
   let g:plugs = {}
   let g:plugs = {}
@@ -442,16 +445,21 @@ function! plug#load(...)
   if !exists('g:plugs')
   if !exists('g:plugs')
     return s:err('plug#begin was not called')
     return s:err('plug#begin was not called')
   endif
   endif
-  let unknowns = filter(copy(a:000), '!has_key(g:plugs, v:val)')
+  let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000
+  let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)')
   if !empty(unknowns)
   if !empty(unknowns)
     let s = len(unknowns) > 1 ? 's' : ''
     let s = len(unknowns) > 1 ? 's' : ''
     return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', ')))
     return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', ')))
   end
   end
-  for name in a:000
-    call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
-  endfor
-  call s:dobufread(a:000)
-  return 1
+  let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)')
+  if !empty(unloaded)
+    for name in unloaded
+      call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+    endfor
+    call s:dobufread(unloaded)
+    return 1
+  end
+  return 0
 endfunction
 endfunction
 
 
 function! s:remove_triggers(name)
 function! s:remove_triggers(name)
@@ -575,7 +583,7 @@ function! s:infer_properties(name, repo)
       let uri = repo
       let uri = repo
     else
     else
       if repo !~ '/'
       if repo !~ '/'
-        let repo = 'vim-scripts/'. repo
+        throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo)
       endif
       endif
       let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git')
       let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git')
       let uri = printf(fmt, repo)
       let uri = printf(fmt, repo)
@@ -597,7 +605,7 @@ function! plug#helptags()
     return s:err('plug#begin was not called')
     return s:err('plug#begin was not called')
   endif
   endif
   for spec in values(g:plugs)
   for spec in values(g:plugs)
-    let docd = join([spec.dir, 'doc'], '/')
+    let docd = join([s:rtp(spec), 'doc'], '/')
     if isdirectory(docd)
     if isdirectory(docd)
       silent! execute 'helptags' s:esc(docd)
       silent! execute 'helptags' s:esc(docd)
     endif
     endif
@@ -621,10 +629,10 @@ function! s:syntax()
   syn match plugTag /(tag: [^)]\+)/
   syn match plugTag /(tag: [^)]\+)/
   syn match plugInstall /\(^+ \)\@<=[^:]*/
   syn match plugInstall /\(^+ \)\@<=[^:]*/
   syn match plugUpdate /\(^* \)\@<=[^:]*/
   syn match plugUpdate /\(^* \)\@<=[^:]*/
-  syn match plugCommit /^  \X*[0-9a-f]\{7} .*/ contains=plugRelDate,plugEdge,plugTag
+  syn match plugCommit /^  \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag
   syn match plugEdge /^  \X\+$/
   syn match plugEdge /^  \X\+$/
   syn match plugEdge /^  \X*/ contained nextgroup=plugSha
   syn match plugEdge /^  \X*/ contained nextgroup=plugSha
-  syn match plugSha /[0-9a-f]\{7}/ contained
+  syn match plugSha /[0-9a-f]\{7,9}/ contained
   syn match plugRelDate /([^)]*)$/ contained
   syn match plugRelDate /([^)]*)$/ contained
   syn match plugNotLoaded /(not loaded)$/
   syn match plugNotLoaded /(not loaded)$/
   syn match plugError /^x.*/
   syn match plugError /^x.*/
@@ -774,8 +782,10 @@ function! s:assign_name()
 endfunction
 endfunction
 
 
 function! s:chsh(swap)
 function! s:chsh(swap)
-  let prev = [&shell, &shellredir]
-  if !s:is_win && a:swap
+  let prev = [&shell, &shellcmdflag, &shellredir]
+  if s:is_win
+    set shell=cmd.exe shellcmdflag=/c shellredir=>%s\ 2>&1
+  elseif a:swap
     set shell=sh shellredir=>%s\ 2>&1
     set shell=sh shellredir=>%s\ 2>&1
   endif
   endif
   return prev
   return prev
@@ -783,15 +793,23 @@ endfunction
 
 
 function! s:bang(cmd, ...)
 function! s:bang(cmd, ...)
   try
   try
-    let [sh, shrd] = s:chsh(a:0)
+    let [sh, shellcmdflag, shrd] = s:chsh(a:0)
     " FIXME: Escaping is incomplete. We could use shellescape with eval,
     " FIXME: Escaping is incomplete. We could use shellescape with eval,
     "        but it won't work on Windows.
     "        but it won't work on Windows.
     let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd
     let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd
-    let g:_plug_bang = '!'.escape(cmd, '#!%')
+    if s:is_win
+      let batchfile = tempname().'.bat'
+      call writefile(['@echo off', cmd], batchfile)
+      let cmd = batchfile
+    endif
+    let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%')
     execute "normal! :execute g:_plug_bang\<cr>\<cr>"
     execute "normal! :execute g:_plug_bang\<cr>\<cr>"
   finally
   finally
     unlet g:_plug_bang
     unlet g:_plug_bang
-    let [&shell, &shellredir] = [sh, shrd]
+    let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+    if s:is_win
+      call delete(batchfile)
+    endif
   endtry
   endtry
   return v:shell_error ? 'Exit status: ' . v:shell_error : ''
   return v:shell_error ? 'Exit status: ' . v:shell_error : ''
 endfunction
 endfunction
@@ -868,7 +886,7 @@ function! s:checkout(spec)
   let output = s:system('git rev-parse HEAD', a:spec.dir)
   let output = s:system('git rev-parse HEAD', a:spec.dir)
   if !v:shell_error && !s:hash_match(sha, s:lines(output)[0])
   if !v:shell_error && !s:hash_match(sha, s:lines(output)[0])
     let output = s:system(
     let output = s:system(
-          \ 'git fetch --depth 999999 && git checkout '.s:esc(sha), a:spec.dir)
+          \ 'git fetch --depth 999999 && git checkout '.s:esc(sha).' --', a:spec.dir)
   endif
   endif
   return output
   return output
 endfunction
 endfunction
@@ -986,6 +1004,10 @@ function! s:update_impl(pull, force, args) abort
   let s:clone_opt = get(g:, 'plug_shallow', 1) ?
   let s:clone_opt = get(g:, 'plug_shallow', 1) ?
         \ '--depth 1' . (s:git_version_requirement(1, 7, 10) ? ' --no-single-branch' : '') : ''
         \ '--depth 1' . (s:git_version_requirement(1, 7, 10) ? ' --no-single-branch' : '') : ''
 
 
+  if has('win32unix')
+    let s:clone_opt .= ' -c core.eol=lf -c core.autocrlf=input'
+  endif
+
   " Python version requirement (>= 2.7)
   " Python version requirement (>= 2.7)
   if python && !has('python3') && !ruby && !use_job && s:update.threads > 1
   if python && !has('python3') && !ruby && !use_job && s:update.threads > 1
     redir => pyv
     redir => pyv
@@ -1059,7 +1081,7 @@ function! s:update_finish()
       elseif has_key(spec, 'tag')
       elseif has_key(spec, 'tag')
         let tag = spec.tag
         let tag = spec.tag
         if tag =~ '\*'
         if tag =~ '\*'
-          let tags = s:lines(s:system('git tag --list '.string(tag).' --sort -version:refname 2>&1', spec.dir))
+          let tags = s:lines(s:system('git tag --list '.s:shellesc(tag).' --sort -version:refname 2>&1', spec.dir))
           if !v:shell_error && !empty(tags)
           if !v:shell_error && !empty(tags)
             let tag = tags[0]
             let tag = tags[0]
             call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))
             call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))
@@ -1067,11 +1089,11 @@ function! s:update_finish()
           endif
           endif
         endif
         endif
         call s:log4(name, 'Checking out '.tag)
         call s:log4(name, 'Checking out '.tag)
-        let out = s:system('git checkout -q '.s:esc(tag).' 2>&1', spec.dir)
+        let out = s:system('git checkout -q '.s:esc(tag).' -- 2>&1', spec.dir)
       else
       else
         let branch = s:esc(get(spec, 'branch', 'master'))
         let branch = s:esc(get(spec, 'branch', 'master'))
         call s:log4(name, 'Merging origin/'.branch)
         call s:log4(name, 'Merging origin/'.branch)
-        let out = s:system('git checkout -q '.branch.' 2>&1'
+        let out = s:system('git checkout -q '.branch.' -- 2>&1'
               \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only origin/'.branch.' 2>&1')), spec.dir)
               \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only origin/'.branch.' 2>&1')), spec.dir)
       endif
       endif
       if !v:shell_error && filereadable(spec.dir.'/.gitmodules') &&
       if !v:shell_error && filereadable(spec.dir.'/.gitmodules') &&
@@ -1169,10 +1191,15 @@ endfunction
 
 
 function! s:spawn(name, cmd, opts)
 function! s:spawn(name, cmd, opts)
   let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''],
   let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''],
+            \ 'batchfile': (s:is_win && (s:nvim || s:vim8)) ? tempname().'.bat' : '',
             \ 'new': get(a:opts, 'new', 0) }
             \ 'new': get(a:opts, 'new', 0) }
   let s:jobs[a:name] = job
   let s:jobs[a:name] = job
-  let argv = add(s:is_win ? ['cmd', '/c'] : ['sh', '-c'],
-               \ has_key(a:opts, 'dir') ? s:with_cd(a:cmd, a:opts.dir) : a:cmd)
+  let cmd = has_key(a:opts, 'dir') ? s:with_cd(a:cmd, a:opts.dir) : a:cmd
+  if !empty(job.batchfile)
+    call writefile(['@echo off', cmd], job.batchfile)
+    let cmd = job.batchfile
+  endif
+  let argv = add(s:is_win ? ['cmd', '/c'] : ['sh', '-c'], cmd)
 
 
   if s:nvim
   if s:nvim
     call extend(job, {
     call extend(job, {
@@ -1202,8 +1229,7 @@ function! s:spawn(name, cmd, opts)
       let job.lines   = ['Failed to start job']
       let job.lines   = ['Failed to start job']
     endif
     endif
   else
   else
-    let params = has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd]
-    let job.lines = s:lines(call('s:system', params))
+    let job.lines = s:lines(call('s:system', [cmd]))
     let job.error = v:shell_error != 0
     let job.error = v:shell_error != 0
     let job.running = 0
     let job.running = 0
   endif
   endif
@@ -1223,6 +1249,9 @@ function! s:reap(name)
   call s:log(bullet, a:name, empty(result) ? 'OK' : result)
   call s:log(bullet, a:name, empty(result) ? 'OK' : result)
   call s:bar()
   call s:bar()
 
 
+  if has_key(job, 'batchfile') && !empty(job.batchfile)
+    call delete(job.batchfile)
+  endif
   call remove(s:jobs, a:name)
   call remove(s:jobs, a:name)
 endfunction
 endfunction
 
 
@@ -1940,8 +1969,19 @@ function! s:update_ruby()
 EOF
 EOF
 endfunction
 endfunction
 
 
+function! s:shellesc_cmd(arg)
+  let escaped = substitute(a:arg, '[&|<>()@^]', '^&', 'g')
+  let escaped = substitute(escaped, '%', '%%', 'g')
+  let escaped = substitute(escaped, '"', '\\^&', 'g')
+  let escaped = substitute(escaped, '\(\\\+\)\(\\^\)', '\1\1\2', 'g')
+  return '^"'.substitute(escaped, '\(\\\+\)$', '\1\1', '').'^"'
+endfunction
+
 function! s:shellesc(arg)
 function! s:shellesc(arg)
-  return '"'.escape(a:arg, '"').'"'
+  if &shell =~# 'cmd.exe$'
+    return s:shellesc_cmd(a:arg)
+  endif
+  return shellescape(a:arg)
 endfunction
 endfunction
 
 
 function! s:glob_dir(path)
 function! s:glob_dir(path)
@@ -1979,11 +2019,19 @@ endfunction
 
 
 function! s:system(cmd, ...)
 function! s:system(cmd, ...)
   try
   try
-    let [sh, shrd] = s:chsh(1)
+    let [sh, shellcmdflag, shrd] = s:chsh(1)
     let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd
     let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd
+    if s:is_win
+      let batchfile = tempname().'.bat'
+      call writefile(['@echo off', cmd], batchfile)
+      let cmd = batchfile
+    endif
     return system(s:is_win ? '('.cmd.')' : cmd)
     return system(s:is_win ? '('.cmd.')' : cmd)
   finally
   finally
-    let [&shell, &shellredir] = [sh, shrd]
+    let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+    if s:is_win
+      call delete(batchfile)
+    endif
   endtry
   endtry
 endfunction
 endfunction
 
 
@@ -2018,7 +2066,7 @@ function! s:git_validate(spec, check_branch)
       " Check tag
       " Check tag
       if has_key(a:spec, 'tag')
       if has_key(a:spec, 'tag')
         let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
         let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
-        if a:spec.tag !=# tag
+        if a:spec.tag !=# tag && a:spec.tag !~ '\*'
           let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.',
           let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.',
                 \ (empty(tag) ? 'N/A' : tag), a:spec.tag)
                 \ (empty(tag) ? 'N/A' : tag), a:spec.tag)
         endif
         endif
@@ -2198,15 +2246,16 @@ function! s:status()
   let unloaded = 0
   let unloaded = 0
   let [cnt, total] = [0, len(g:plugs)]
   let [cnt, total] = [0, len(g:plugs)]
   for [name, spec] in items(g:plugs)
   for [name, spec] in items(g:plugs)
+    let is_dir = isdirectory(spec.dir)
     if has_key(spec, 'uri')
     if has_key(spec, 'uri')
-      if isdirectory(spec.dir)
+      if is_dir
         let [err, _] = s:git_validate(spec, 1)
         let [err, _] = s:git_validate(spec, 1)
         let [valid, msg] = [empty(err), empty(err) ? 'OK' : err]
         let [valid, msg] = [empty(err), empty(err) ? 'OK' : err]
       else
       else
         let [valid, msg] = [0, 'Not found. Try PlugInstall.']
         let [valid, msg] = [0, 'Not found. Try PlugInstall.']
       endif
       endif
     else
     else
-      if isdirectory(spec.dir)
+      if is_dir
         let [valid, msg] = [1, 'OK']
         let [valid, msg] = [1, 'OK']
       else
       else
         let [valid, msg] = [0, 'Not found.']
         let [valid, msg] = [0, 'Not found.']
@@ -2215,7 +2264,7 @@ function! s:status()
     let cnt += 1
     let cnt += 1
     let ecnt += !valid
     let ecnt += !valid
     " `s:loaded` entry can be missing if PlugUpgraded
     " `s:loaded` entry can be missing if PlugUpgraded
-    if valid && get(s:loaded, name, -1) == 0
+    if is_dir && get(s:loaded, name, -1) == 0
       let unloaded = 1
       let unloaded = 1
       let msg .= ' (not loaded)'
       let msg .= ' (not loaded)'
     endif
     endif
@@ -2285,7 +2334,7 @@ function! s:preview_commit()
     let b:plug_preview = !s:is_preview_window_open()
     let b:plug_preview = !s:is_preview_window_open()
   endif
   endif
 
 
-  let sha = matchstr(getline('.'), '^  \X*\zs[0-9a-f]\{7}')
+  let sha = matchstr(getline('.'), '^  \X*\zs[0-9a-f]\{7,9}')
   if empty(sha)
   if empty(sha)
     return
     return
   endif
   endif
@@ -2304,10 +2353,19 @@ function! s:preview_commit()
   endif
   endif
   setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable
   setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable
   try
   try
-    let [sh, shrd] = s:chsh(1)
-    execute 'silent %!cd' s:shellesc(g:plugs[name].dir) '&& git show --no-color --pretty=medium' sha
+    let [sh, shellcmdflag, shrd] = s:chsh(1)
+    let cmd = 'cd '.s:shellesc(g:plugs[name].dir).' && git show --no-color --pretty=medium '.sha
+    if s:is_win
+      let batchfile = tempname().'.bat'
+      call writefile(['@echo off', cmd], batchfile)
+      let cmd = batchfile
+    endif
+    execute 'silent %!' cmd
   finally
   finally
-    let [&shell, &shellredir] = [sh, shrd]
+    let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+    if s:is_win
+      call delete(batchfile)
+    endif
   endtry
   endtry
   setlocal nomodifiable
   setlocal nomodifiable
   nnoremap <silent> <buffer> q :q<cr>
   nnoremap <silent> <buffer> q :q<cr>
@@ -2349,7 +2407,7 @@ function! s:diff()
     call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
     call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
     for [k, v] in plugs
     for [k, v] in plugs
       let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..'
       let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..'
-      let diff = s:system_chomp('git log --graph --color=never --pretty=format:"%x01%h%x01%d%x01%s%x01%cr" '.s:shellesc(range), v.dir)
+      let diff = s:system_chomp('git log --graph --color=never '.join(map(['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range], 's:shellesc(v:val)')), v.dir)
       if !empty(diff)
       if !empty(diff)
         let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : ''
         let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : ''
         call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)')))
         call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)')))
@@ -2390,7 +2448,7 @@ function! s:revert()
     return
     return
   endif
   endif
 
 
-  call s:system('git reset --hard HEAD@{1} && git checkout '.s:esc(g:plugs[name].branch), g:plugs[name].dir)
+  call s:system('git reset --hard HEAD@{1} && git checkout '.s:esc(g:plugs[name].branch).' --', g:plugs[name].dir)
   setlocal modifiable
   setlocal modifiable
   normal! "_dap
   normal! "_dap
   setlocal nomodifiable
   setlocal nomodifiable

+ 3 - 3
vim/plugins.vim

@@ -12,10 +12,10 @@ silent! call plug#begin('~/dotfiles/vim/plugged')
 
 
 " General {{{
 " General {{{
 Plug 'Raimondi/delimitMate'
 Plug 'Raimondi/delimitMate'
+Plug 'adelarsq/vim-matchit'
 Plug 'dkprice/vim-easygrep'
 Plug 'dkprice/vim-easygrep'
 Plug 'haya14busa/vim-asterisk'
 Plug 'haya14busa/vim-asterisk'
 Plug 'junegunn/vim-easy-align'
 Plug 'junegunn/vim-easy-align'
-Plug 'matchit.zip'
 Plug 'mbbill/undotree'
 Plug 'mbbill/undotree'
 Plug 'scrooloose/nerdcommenter'
 Plug 'scrooloose/nerdcommenter'
 Plug 'terryma/vim-multiple-cursors'
 Plug 'terryma/vim-multiple-cursors'
@@ -34,9 +34,9 @@ endif
 
 
 " Visual {{{
 " Visual {{{
 Plug 'AlessandroYorba/Alduin'
 Plug 'AlessandroYorba/Alduin'
-Plug 'Sclarki/airline-surarken'
-Plug 'Sclarki/neonwave.vim'
+Plug 'MidnaPeach/neonwave.vim'
 Plug 'altercation/vim-colors-solarized'
 Plug 'altercation/vim-colors-solarized'
+Plug 'cinaeco/airline-surarken'
 Plug 'junegunn/goyo.vim'
 Plug 'junegunn/goyo.vim'
 Plug 'junegunn/limelight.vim'
 Plug 'junegunn/limelight.vim'
 Plug 'vim-airline/vim-airline'
 Plug 'vim-airline/vim-airline'