Skip to content

Commit

Permalink
fix(files): workaround buffer name limitation on Windows (Neovim)
Browse files Browse the repository at this point in the history
On Windows, due to Vim's bug, you can't correctly `fnameescape()`
special characters in buffer name.
(reference: vim/vim#541)

Therefore, you can't open a buffer whose name contains some special
character with `:edit`, preventing correctly jump to definition in some
LSPs. For example, jdtls returns custom URI (jdt://...) if the
definition is inside metadata. This URI contains `?`, so it can't be
opened in Windows (neoclide/coc-java#82).

I found that you can workaround this bug using Neovim API to set a
buffer name directly, though it's Neovim-only solution.
  • Loading branch information
statiolake committed Jun 28, 2022
1 parent b5950ac commit d2f19e0
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
44 changes: 37 additions & 7 deletions autoload/coc/util.vim
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,10 @@ function! coc#util#jump(cmd, filepath, ...) abort
else
exec 'drop '.fnameescape(file)
endif
elseif a:cmd == 'edit'
if bufloaded(file)
exe 'b '.bufnr(file)
else
exe a:cmd.' '.fnameescape(file)
endif
elseif a:cmd == 'edit' && bufloaded(file)
exe 'b '.bufnr(file)
else
exe a:cmd.' '.fnameescape(file)
call s:safer_open(a:cmd, file)
endif
if !empty(get(a:, 1, []))
let line = getline(a:1[0] + 1)
Expand All @@ -208,6 +204,40 @@ function! coc#util#jump(cmd, filepath, ...) abort
endif
endfunction

function! s:safer_open(cmd, file) abort
" How to support :pedit and :drop?
let is_supported_cmd = index(["edit", "split", "vsplit", "tabe"], a:cmd)

if is_supported_cmd && has('win32') && has('nvim')
if bufloaded(a:file)
let buf = bufnr(a:file)
" Do not reload existing buffer
let reload_buffer = v:false
else
" Workaround a bug for Win32 paths (works in Neovim only).
"
" reference:
" - https://github.com/vim/vim/issues/541
" - https://github.com/neoclide/coc-java/issues/82
let buf = nvim_create_buf(v:true, v:false)
" Ignore swap file error occuring when, for example, file is a URI.
silent! call nvim_buf_set_name(buf, a:file)
let reload_buffer = v:true
end
if a:cmd != 'edit'
" Open split, tab, etc. by a:cmd.
exe a:cmd
end
" Set filename and reload file (or URI) contents by :edit.
exe 'keepjumps buffer ' . buf
if reload_buffer
exe 'keepjumps edit'
end
else
exe a:cmd.' '.fnameescape(file)
endif
endfunction

function! coc#util#variables(bufnr) abort
let info = getbufinfo(a:bufnr)
let variables = empty(info) ? {} : copy(info[0]['variables'])
Expand Down
2 changes: 1 addition & 1 deletion src/core/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export default class Files {
let bufname = fixDriver(path.normalize(fsPath))
await this.nvim.call('coc#util#jump', [jumpCommand, bufname, pos])
} else {
if (os.platform() == 'win32') {
if (nvim.isVim && os.platform() == 'win32') {
uri = uri.replace(/\/?/, '?')
}
await this.nvim.call('coc#util#jump', [jumpCommand, uri, pos])
Expand Down

0 comments on commit d2f19e0

Please sign in to comment.