justinmk / vim-dirvish

Directory viewer for Vim :zap:
Other
1.19k stars 64 forks source link

backslash in pathname causes inconsistent bahaviors #189

Closed lxhillwind closed 4 years ago

lxhillwind commented 4 years ago

OS: any system using / instead of \ as path sep (so \ is valid in path component).

step to produce

# prepare
mkdir -p /tmp/'a\dir'/1  # backslash in path component

use vim to open /tmp/ if plugin netrw is disabled, or call :Dirvish /tmp/ in vim. (or neovim)

expected behavior(s)

  1. a\dir/ will be in buffer (if conceal is enabled);
  2. Type /a or ?a will match it;
  3. After entering it (by typing i or <CR>), corresponding sub dir 1/ will be listed.

actual behavior(s)

  1. /tmp/a\dir/ is in buffer (even if conceal is enabled), and only dir/ is highlighted;
  2. Type /a or ?a does not match it;
  3. After entering it, nothing is shown.

possible patches

I have forked this repo and added 3 commits, which handle one of these behaviors (the commit / patch can be applied individually).

It's here: https://github.com/lxhillwind/vim-dirvish

The patches are also included below:

  1. highlight
diff --git a/syntax/dirvish.vim b/syntax/dirvish.vim
index df56928..dfab0aa 100644
--- a/syntax/dirvish.vim
+++ b/syntax/dirvish.vim
@@ -3,13 +3,14 @@ if 'dirvish' !=# get(b:, 'current_syntax', 'dirvish')
 endif

 let s:sep = exists('+shellslash') && !&shellslash ? '\' : '/'
+let s:sep_escaped = s:sep == '\' ? '\\' : '/'
 let s:escape = 'substitute(escape(v:val, ".$~"), "*", ".*", "g")'

 " Define once (per buffer).
 if !exists('b:current_syntax')
-  exe 'syntax match DirvishPathHead =.*\'.s:sep.'\ze[^\'.s:sep.']\+\'.s:sep.'\?$= conceal'
-  exe 'syntax match DirvishPathTail =[^\'.s:sep.']\+\'.s:sep.'$='
-  exe 'syntax match DirvishSuffix   =[^\'.s:sep.']*\%('.join(map(split(&suffixes, ','), s:escape), '\|') . '\)$='
+  exe 'syntax match DirvishPathHead =.*'.s:sep_escaped.'\ze[^'.s:sep.']\+'.s:sep_escaped.'\?$= conceal'
+  exe 'syntax match DirvishPathTail =[^'.s:sep.']\+'.s:sep_escaped.'$='
+  exe 'syntax match DirvishSuffix   =[^'.s:sep.']*\%('.join(map(split(&suffixes, ','), s:escape), '\|') . '\)$='
 endif

 " Define (again). Other windows (different arglists) need the old definitions.
  1. key mapping
diff --git a/ftplugin/dirvish.vim b/ftplugin/dirvish.vim
index 47bf62c..5bfea85 100644
--- a/ftplugin/dirvish.vim
+++ b/ftplugin/dirvish.vim
@@ -5,6 +5,8 @@ let b:did_ftplugin = 1

 let s:nowait = (v:version > 703 ? '<nowait>' : '')

+let s:sep = exists('+shellslash') && !&shellslash ? '\' : '/'
+
 if !hasmapto('<Plug>(dirvish_quit)', 'n')
   execute 'nmap '.s:nowait.'<buffer> q :echohl WarningMsg<Bar>echo "q is deprecated, use gq instead"<Bar>echohl NONE<cr>'
   execute 'nmap '.s:nowait.'<buffer> gq <Plug>(dirvish_quit)'
@@ -48,8 +50,13 @@ execute 'nnoremap <expr>'.s:nowait.'<buffer> . ":<C-u>".(v:count ? "Shdo".(v:cou
 execute 'xnoremap <expr>'.s:nowait.'<buffer> . ":Shdo".(v:count?"!":" ")." {}<Left><Left><Left>"'

 " Buffer-local / and ? mappings to skip the concealed path fragment.
-nnoremap <buffer> / /\ze[^\/]*[\/]\=$<Home>
-nnoremap <buffer> ? ?\ze[^\/]*[\/]\=$<Home>
+if s:sep == '\'
+  nnoremap <buffer> / /\ze[^\/]*[\/]\=$<Home>
+  nnoremap <buffer> ? ?\ze[^\/]*[\/]\=$<Home>
+else
+  nnoremap <buffer> / /\ze[^/]*[/]\=$<Home>
+  nnoremap <buffer> ? ?\ze[^/]*[/]\=$<Home>
+endif

 " Force autoload if `ft=dirvish`
 if !exists('*dirvish#open')|try|call dirvish#open()|catch|endtry|endif
  1. listdir (glob)
diff --git a/autoload/dirvish.vim b/autoload/dirvish.vim
index 4fd26a2..1c98f5c 100644
--- a/autoload/dirvish.vim
+++ b/autoload/dirvish.vim
@@ -53,7 +53,7 @@ endif

 function! s:list_dir(dir) abort
   " Escape for glob().
-  let dir_esc = escape(substitute(a:dir,'\[','[[]','g'),'{}')
+  let dir_esc = escape(substitute(a:dir,'\[','[[]','g'),'{}\')
   let paths = s:globlist(dir_esc.'*')
   "Append dot-prefixed files. glob() cannot do both in 1 pass.
   let paths = paths + s:globlist(dir_esc.'.[^.]*')