I'm working in Vim on WSL, editing files that often contain Windows file paths, such as:
<Command>C:\Python\trunk\windows\scripts\RunBackup.bat</Command>
When I place my cursor on a Windows path like the one above, I'd like to open the corresponding file using Vim. In Linux paths, I can use gf, but for Windows paths, this doesn't work because of backslashes () and other characters like colons (:) in the path, which are not considered part of a "file name" by default.
I tried modifying Vim's isfname setting to include characters like :, , and spaces dynamically within a function. My approach temporarily adds these characters to isfname, uses to get the path, and then restores isfname to its original value after extracting the path. Here's the function I wrote:
function! OpenWindowsPath()
" Save the original 'isfname' value
let l:original_isfname = &isfname
" Define the characters to ensure are in 'isfname'
let l:required_chars = [':', '\\', ' ']
let l:added_chars = []
" Loop through required characters and add if missing
for char in l:required_chars
if index(split(&isfname, ','), char) == -1
let &isfname .= ',' . char
call add(l:added_chars, char) " Track added characters
endif
endfor
" Get the file path under the cursor using <cfile>
let l:win_path = expand('<cfile>')
" Restore the original 'isfname' value
for char in l:added_chars
let &isfname = substitute(&isfname, ',' . char, '', '')
endfor
" Convert Windows path to WSL path
let l:linux_path = system('wslpath -u ' . shellescape(l:win_path))
" Trim any trailing newline from the result
let l:linux_path = substitute(l:linux_path, '\n', '', 'g')
" Open the file in Vim
if filereadable(l:linux_path)
execute 'edit ' . l:linux_path
else
echoerr 'File not found: ' . l:linux_path
endif
endfunction
" Map a keybinding (e.g., <Leader>o) to call the function
nnoremap <Leader>o :call OpenWindowsPath()<CR>
Even after modifying isfname, doesn't always return the full Windows path under the cursor. For example:
Is there a reliable way to extract the full Windows path under the cursor, regardless of cursor position, with support for Windows path that contains spaces?
so it turned out my modification to the isfname
wasn't working because I was adding characters, a useful hint came from the vim wiki for adding a space using its ascii number :set isfname+=32
.
So the correct manipulation of the isfname look like below::
" Define the ASCII codes for required characters
let l:required_chars_ascii = [58, 92, 32] " 58 = ':', 92 = '\', 32 = space
" Loop through required characters and add if missing
for char_ascii in l:required_chars_ascii
if index(split(&isfname, ','), nr2char(char_ascii)) == -1
execute 'set isfname+=' . char_ascii
endif
endfor
The full function looks like below::
function! OpenWindowsPath()
" Save the original 'isfname' value
let l:original_isfname = &isfname
" Define the ASCII codes for required characters
let l:required_chars_ascii = [58, 92, 32] " 58 = ':', 92 = '\', 32 = space
" Loop through required characters and add if missing
for char_ascii in l:required_chars_ascii
if index(split(&isfname, ','), nr2char(char_ascii)) == -1
execute 'set isfname+=' . char_ascii
endif
endfor
" Get the file path under the cursor using <cfile>
let l:win_path = expand('<cfile>')
" Restore the original 'isfname' value
let &isfname = l:original_isfname
" Convert Windows path to WSL path
let l:linux_path = system('wslpath -u ' . shellescape(l:win_path))
" Trim any trailing newline from the result
let l:linux_path = substitute(l:linux_path, '\n', '', 'g')
" Open the file in Vim
if filereadable(l:linux_path)
execute 'edit ' . l:linux_path
else
echoerr 'File not found: ' . l:linux_path
endif
endfunction
" Map a keybinding (e.g., <Leader>o) to call the function
nnoremap <Leader>o :call OpenWindowsPath()<CR>