Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix error if Vim run under Windows with noshellslash. #5

Closed
wants to merge 1 commit into from

3 participants

@sgur

ごく一部のWindows環境でs:snr_prefix()が正常に動作せず、一部の textobj-user プラグインが動作しないのを修正します。

発生条件

  • Windows で Vim 7.3.233 以降を使っている (kaoriya版もしくは独自ビルド)
  • set noshellslash
  • 利用するtextobj-user プラグイン が、 ’*sfile*' : 'expand('<sfile>:p')している (textobj-user-comment など)
  • Windows の msysgit に含まれる Git Bash を利用し、そこから該当するバージョンのVimを起動している

不具合内容

Vim 7.3.233 以降では、:scriptnamesの$HOMEを'~'に短縮する処理が追加されました。
Windows環境では殆どの場合において短縮処理が正常に働かないので、問題はなかったのですが、
msysgitのGit Bash上から(g)Vimを起動した場合のみ、
このパス短縮処理が正常に働いてしまいます。

該関数で、expand('<sfile>:p')した結果(これはvim-textobj-userプラグインの'sfile'プロパティで指定されています)と:scriptnamesの結果をfnamemodify(, ':p')しますが、
このとき、set shellslashしていない場合には、パス区切り文字が '/' と '\' で異なってしまい、正常に<SNR>を取得できなくなります。

@mattn

横から失礼

shellslashは大昔からあるオプションなのでexists()による判別は不要かと思います。あと文字列の長さをチェックする場合はempty()ではなくlen()strlen()lhs == ''を使います。あと個人的な感想としてはfnamemodify(expand(..という風に条件判断無しに書いても良いんじゃないかと思います。

@sgur

Windows 以外で &shellslash == 0 とかやるとエラーになると思ってました…。
Windows のみで効果があるだけで、存在しないわけではないんですね。

@mattn

すみません。cygwin入れてないので想像に過ぎませんが...
expand()を挟まない場合、WindowsXPだと<sfile>C:\Documents and Settings\mattn\_vimrcになります。
またscriptnamesから得られる~/_vimrcexpand('~/_vimrc')してもHOMEから展開してしまい、違う結果を生み兼ねます。
例えば僕の場合、C:\Documents and Settings...が空白を含まない様にHOMEをc:/docme~1/mattnにしているので、expand('~/_vimrc')c:/docme~1/mattn/_vimrcになり、かつfnamemodify()しても既にフルパスなのでifの中に入らない事になります。おそらくそれと同じ様な現象がcygwinでも起きているんじゃないかなーと思います。
つまりexpand()されている物とexpand()されていない物をfnamemodify()しても同じ結果にならないという事ですかね。
windowsの場合は以下のパッチの様に必ずexpand()してからfnamemodify()する様にすれば大丈夫な気がします。
あとwindowsの場合、パスの大文字小文字問題もあるのでこの様にした方がいいかもしれませんね。

diff --git a/autoload/textobj/user.vim b/autoload/textobj/user.vim
index cf8431a..83bc76c 100644
--- a/autoload/textobj/user.vim
+++ b/autoload/textobj/user.vim
@@ -531,14 +531,22 @@ function! s:cancel_selection(previous_mode, orig_pos)
 endfunction


+function! s:normalize_path(path)
+  return has('win32') || has('win64') ?
+  \ tolower(substitute(fnamemodify(expand(a:path), ':p'), '\\', '/', 'g'))
+  \ : fnamemodify(a:path, ':p')
+endfunction    
+
+
 function! s:snr_prefix(sfile)
   redir => result
   silent scriptnames
   redir END

+  let sfile = s:normalize_path(a:sfile)
   for line in split(result, '\n')
     let _ = matchlist(line, '^\s*\(\d\+\):\s*\(.*\)$')
-    if fnamemodify(a:sfile, ':p') ==# fnamemodify(_[2], ':p')
+    if sfile ==# s:normalize_path(_[2])
       return printf("\<SNR>%d_", _[1])
     endif
   endfor
@mattn

ちょっとcygwin入れて検証するので待って下さい。

@kana
Owner

@sgur Thank you for reporting the problem. I confirmed the problem. I've pushed a fixed version. Please check it out.

@kana kana closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 18, 2012
  1. @sgur
This page is out of date. Refresh to see the latest.
Showing with 3 additions and 1 deletion.
  1. +3 −1 autoload/textobj/user.vim
View
4 autoload/textobj/user.vim
@@ -538,7 +538,9 @@ function! s:snr_prefix(sfile)
for line in split(result, '\n')
let _ = matchlist(line, '^\s*\(\d\+\):\s*\(.*\)$')
- if fnamemodify(a:sfile, ':p') ==# fnamemodify(_[2], ':p')
+ if fnamemodify(a:sfile, ':p') ==# ((exists('+shellslash') && empty(&shellslash))
+ \ ? fnamemodify(expand(_[2]), ':p')
+ \ : fnamemodify(_[2], ':p'))
return printf("\<SNR>%d_", _[1])
endif
endfor
Something went wrong with that request. Please try again.