Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Counter utf-16 characters #284

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion autoload/lsp.vim
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,8 @@ function! lsp#get_text_document_identifier(...) abort
endfunction

function! lsp#get_position(...) abort
return { 'line': line('.') - 1, 'character': col('.') -1 }
let pos = lsp#utils#col('.')
return { 'line': line('.') - 1, 'character': pos+1 }
endfunction

function! s:get_text_document_identifier(buf) abort
Expand Down
20 changes: 20 additions & 0 deletions autoload/lsp/utils.vim
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,23 @@ function! lsp#utils#echo_with_truncation(msg) abort

exec 'echo l:msg'
endfunction

function! lsp#utils#count_utf16_code_units(str) abort
let l:rs = split(a:str, '\zs')
let l:len = len(l:rs)
return l:len + len(filter(l:rs, 'char2nr(v:val)>=0x10000'))
endfunction

function! lsp#utils#strlen(str) abort
if g:lsp_use_utf16
return lsp#utils#count_utf16_code_units(a:str)
endif
return strlen(a:str)
endfunction

function! lsp#utils#col(m) abort
if g:lsp_use_utf16
return lsp#utils#strlen(getline(a:m)[:col(a:m)])
endif
return a:m
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I met strange vim's behavior at trying to use this branch.

The behavior is col(a:m) is not match lsp#utils#strlen(getline(a:m)[:col(a:m)]) in insert-mode.

In my environment, those unmatching were fixable below code.

function! lsp#utils#col(m) abort
    if g:lsp_use_utf16
        let col = lsp#utils#strlen(getline(a:m)[:col(a:m) - 1])

        if mode() ==# 'i' && col(a:m) == col('$')
            let col = col + 1
        endif

        return col
    endif
    return col(a:m)
endfunction

(This branch is very great work for me. Thanks mattn)

endfunction
8 changes: 4 additions & 4 deletions autoload/lsp/utils/diff.vim
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function! lsp#utils#diff#compute(old, new) abort
let l:length = s:Length(a:old, l:start_line, l:start_char, l:end_line, l:end_char)

let l:adj_end_line = len(a:old) + l:end_line
let l:adj_end_char = l:end_line == 0 ? 0 : strlen(a:old[l:end_line]) + l:end_char + 1
let l:adj_end_char = l:end_line == 0 ? 0 : lsp#utils#strlen(a:old[l:end_line]) + l:end_char + 1

let l:result = { 'range': {'start': {'line': l:start_line, 'character': l:start_char},
\ 'end': {'line': l:adj_end_line, 'character': l:adj_end_char}},
Expand Down Expand Up @@ -102,15 +102,15 @@ function! s:Length(lines, start_line, start_char, end_line, end_char)
if l:adj_end_line >= len(a:lines)
let l:adj_end_char = a:end_char - 1
else
let l:adj_end_char = strlen(a:lines[l:adj_end_line]) + a:end_char
let l:adj_end_char = lsp#utils#strlen(a:lines[l:adj_end_line]) + a:end_char
endif
if a:start_line == l:adj_end_line
return l:adj_end_char - a:start_char + 1
endif
let l:result = strlen(a:lines[a:start_line]) - a:start_char + 1
let l:result = lsp#utils#strlen(a:lines[a:start_line]) - a:start_char + 1
let l:line = a:start_line + 1
while l:line < l:adj_end_line
let l:result += strlen(a:lines[l:line]) + 1
let l:result += lsp#utils#strlen(a:lines[l:line]) + 1
let l:line += 1
endwhile
let l:result += l:adj_end_char + 1
Expand Down
2 changes: 2 additions & 0 deletions plugin/lsp.vim
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ let g:lsp_preview_doubletap = get(g:, 'lsp_preview_doubletap', [function('lsp#ui
let g:lsp_get_vim_completion_item = get(g:, 'lsp_get_vim_completion_item', [function('lsp#omni#default_get_vim_completion_item')])
let g:lsp_get_supported_capabilities = get(g:, 'lsp_get_supported_capabilities', [function('lsp#default_get_supported_capabilities')])

let g:lsp_use_utf16 = get(g:, 'lsp_use_utf16', 0)

if g:lsp_auto_enable
augroup lsp_auto_enable
autocmd!
Expand Down
63 changes: 63 additions & 0 deletions test/lsp/utils/diff.vimspec
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,68 @@ Describe lsp#utils#diff
let got = lsp#utils#diff#compute(lines1, lines2)
Assert Equals(got, want)
End

It should return diff familier with utf-16 surrogate pairs
let lines1 = [
\ 'foo',
\]
let lines2 = [
\ 'f𐐀o',
\]
let want = {
\ 'range': {
\ 'start': { 'line': 0, 'character': 1 },
\ 'end': { 'line': 0, 'character': 2 }
\ },
\ 'text': '𐐀',
\ "rangeLength": 1
\}
let got = lsp#utils#diff#compute(lines1, lines2)
Assert Equals(got, want)

let old_lsp_use_utf16 = get(g:, 'lsp_use_utf16', 0)

try
let g:lsp_use_utf16 = 0

let lines1 = [
\ 'f𐐀o',
\]
let lines2 = [
\ 'foo',
\]
let want = {
\ 'range': {
\ 'start': { 'line': 0, 'character': 1 },
\ 'end': { 'line': 0, 'character': 5 }
\ },
\ 'text': 'o',
\ "rangeLength": 4
\}
let got = lsp#utils#diff#compute(lines1, lines2)
Assert Equals(got, want)

let g:lsp_use_utf16 = 1

let lines1 = [
\ 'f𐐀o',
\]
let lines2 = [
\ 'foo',
\]
let want = {
\ 'range': {
\ 'start': { 'line': 0, 'character': 1 },
\ 'end': { 'line': 0, 'character': 3 }
\ },
\ 'text': 'o',
\ "rangeLength": 2
\}
let got = lsp#utils#diff#compute(lines1, lines2)
Assert Equals(got, want)
finally
let g:lsp_use_utf16 = old_lsp_use_utf16
endtry
End
End
End