Skip to content
This repository

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

Closed
wants to merge 1 commit into from

3 participants

sgur mattn Kana Natsuno
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 Natsuno
Owner

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

Kana Natsuno kana closed this January 18, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Jan 18, 2012
sgur Fix error if Vim run under Windows with noshellslash. c95779d
This page is out of date. Refresh to see the latest.

Showing 1 changed file with 3 additions and 1 deletion. Show diff stats Hide diff stats

  1. 4  autoload/textobj/user.vim
4  autoload/textobj/user.vim
@@ -538,7 +538,9 @@ function! s:snr_prefix(sfile)
538 538
 
539 539
   for line in split(result, '\n')
540 540
     let _ = matchlist(line, '^\s*\(\d\+\):\s*\(.*\)$')
541  
-    if fnamemodify(a:sfile, ':p') ==# fnamemodify(_[2], ':p')
  541
+    if fnamemodify(a:sfile, ':p') ==# ((exists('+shellslash') && empty(&shellslash))
  542
+    \ ? fnamemodify(expand(_[2]), ':p')
  543
+    \ : fnamemodify(_[2], ':p'))
542 544
       return printf("\<SNR>%d_", _[1])
543 545
     endif
544 546
   endfor
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.