マージされました ->previm をWSLから使えるようにwsl_modeを追加/pull reqしてみた


はじめに

vim でマークダウンを書くときに、previm を利用している。
WSL 上に環境を作ったが、previm がうまく動かなかったので、修正して動くようにしてみた。

2019/11/08追記
add previm_wsl_mode by hirano00o · Pull Request #135 · previm/previm
昨日マージされました!
WSLモードの有効化は、使い方を参照ください。

環境

key value
OS Win 10 Pro
WSL ver. 2
WSL OS Ubuntu 18.04.3 LTS
vim ver. 8.0 (デフォルト)
open-browser.vim 未利用
Windowsで使うブラウザ Google Chrome

previm on .vimrc

previm/previm: Realtime preview by Vim. (Markdown, reStructuredText, textile)
によると、.vimrc では下記を指定する必要がある。
ちなみに指定していない場合は、open-browser が呼ばれる。
open-browser もない場合は、エラーとなるみたい。

.vimrc
let g:previm_open_cmd = 'ブラウザを開くコマンド'

ブラウザを開くコマンド on WSL

さて、WSL でブラウザを開くコマンドは何だろうかと。

WSL では、Windowsのディレクトリがマウントされている。
デフォルトだと、/mnt にマウントされている。
ということは、Chrome の exe ファイルも見つけることが可能。

% ll /mnt/c/Program\ Files\ \(x86\)/Google/Chrome/Application/chrome.exe
-r-xr-xr-x 1 hirano00o hirano00o 1694704 10月  9 12:52 '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe'

これを bash 上で実行すると、新規ウィンドウで Chrome が開く。
引数に、相対パスでファイルを渡すと、新規タブでそのファイルが開かれる。

% /mnt/c/Program\ Files\ \(x86\)/Google/Chrome/Application/chrome.exe .vim/plugged/previm/README.mkd

Chrome の URL に見慣れない文字列が
wsl%24/Ubuntu/home/... とは?

WSL のパスと Windows のパス

WSL/Linux環境のファイルシステムは、“¥¥wsl\$¥(ディストリビューションの名前)¥”というUNCパスで表現される。たとえば、「Debian」を利用している場合は“¥¥wsl$¥Debian¥”となる。
WindowsからLinuxファイルへのアクセスが可能に ~「Windows 10 19H1」におけるWSLの改善 - 窓の杜

とのことで、つまり Windows の Chrome から WSL 上のファイルを開くためには、上記の形にパスを変える必要がある。

Ubuntu on WSL 上の previm では、ファイルパスは /homeから始まるため、これに何とかして \\wsl$\Ubuntu を付与する必要がある。

ところで WSL にはデフォルトで wslpath という WSL <-> Windows パス変換するコマンドがインストールされているらしい。
【WSL】パスのフォーマットを変換する wslpath コマンドの使い方 | ラボラジアン

これを使うと、

% wslpath -w .vimrc
\\wsl$\Ubuntu\home\hirano00o\.vimrc

見事変換される。

previm の修正

まず、どのように追加するかだが、せっかくなので汎用的にしたい。
vim では、Linux かどうかの判別はできても、WSL かどうかの判別はできない。
通常の Linux では、wslpath はない。
ということで、オプションを追加することにする。

% grep open_cmd */*.vim
autoload/previm.vim:  if exists('g:previm_open_cmd') && !empty(g:previm_open_cmd)
autoload/previm.vim:    if has('win32') && g:previm_open_cmd =~? 'firefox'
autoload/previm.vim:      call s:system(g:previm_open_cmd . ' "file:///'  . fnamemodify(a:preview_html_file, ':p:gs?\\?/?g') . '"')
autoload/previm.vim:      call s:system(g:previm_open_cmd . ' '''  . system('cygpath -w ' . a:preview_html_file) . '''')
autoload/previm.vim:      call s:system(g:previm_open_cmd . ' '''  . a:preview_html_file . '''')

autoload/previm.vim を修正すれば良さそう。
で、追記してみた。

% git diff HEAD
diff --git a/autoload/previm.vim b/autoload/previm.vim
index cc1b473..53786e9 100644
--- a/autoload/previm.vim
+++ b/autoload/previm.vim
@@ -17,6 +17,8 @@ function! previm#open(preview_html_file) abort
       call s:system(g:previm_open_cmd . ' "file:///'  . fnamemodify(a:preview_html_file, ':p:gs?\\?/?g') . '"')
     elseif has('win32unix')
       call s:system(g:previm_open_cmd . ' '''  . system('cygpath -w ' . a:preview_html_file) . '''')
+    elseif get(g:, 'previm_wsl_mode', 0) ==# 1
+      call s:system(g:previm_open_cmd . ' '''  . system('wslpath -w ' . a:preview_html_file) . '''')
     else
       call s:system(g:previm_open_cmd . ' '''  . a:preview_html_file . '''')
     endif

使い方

.vimrc には下記のように、記述することで無事に動いた。

.vimrc
let g:previm_open_cmd = '/mnt/c/Program\ Files\ \(x86\)/Google/Chrome/Application/chrome.exe'
let g:previm_wsl_mode = 1

せっかく WSL に対応させたので、プルリク出してみた。
果たしてマージされるかな..マージ済
add previm_wsl_mode by hirano00o · Pull Request #135 · previm/previm