aboutsummaryrefslogtreecommitdiff
path: root/autoload/prettier/utils/buffer.vim
blob: edd30ddf31559b31dabac631976663488a4a67fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
function! prettier#utils#buffer#replace(lines, startSelection, endSelection) abort
  " store view
  let l:winview = winsaveview()
  let l:newBuffer = prettier#utils#buffer#createBufferFromUpdatedLines(a:lines, a:startSelection, a:endSelection)

  " we should not replace contents if the newBuffer is empty
  if empty(l:newBuffer)
    return
  endif

  " https://vim.fandom.com/wiki/Restore_the_cursor_position_after_undoing_text_change_made_by_a_script
  " create a fake change entry and merge with undo stack prior to do formating
  execute "normal! i "
  execute "normal! a\<BS>"
  try | silent undojoin | catch | endtry

  " delete all lines on the current buffer
  silent! execute '%delete _'

  " replace all lines from the current buffer with output from prettier
  let l:idx = 0
  for l:line in l:newBuffer
    silent! call append(l:idx, l:line)
    let l:idx += 1
  endfor
  
  " delete trailing newline introduced by the above append procedure
  silent! execute '$delete _'

  " Restore view
  call winrestview(l:winview)

endfunction

" Replace and save the buffer
function! prettier#utils#buffer#replaceAndSave(lines, startSelection, endSelection) abort
  call prettier#utils#buffer#replace(a:lines, a:startSelection, a:endSelection)
  noautocmd write
endfunction

" Returns 1 if content has changed
function! prettier#utils#buffer#willUpdatedLinesChangeBuffer(lines, start, end) abort
  return getbufline(bufnr('%'), 1, line('$')) == prettier#utils#buffer#createBufferFromUpdatedLines(a:lines, a:start, a:end) ? 0 : 1
endfunction

" Returns a new buffer with lines replacing start and end of the contents of the current buffer
function! prettier#utils#buffer#createBufferFromUpdatedLines(lines, start, end) abort
  return getbufline(bufnr('%'), 1, a:start - 1) + a:lines + getbufline(bufnr('%'), a:end + 1, '$')
endfunction

" Adapted from https://github.com/farazdagi/vim-go-ide
function! s:getCharPosition(line, col) abort
    if &encoding !=# 'utf-8'
        " On utf-8 enconding we can't just use bytes so we need to make sure we can count the
        " characters, we do that by adding the text into a temporary buffer and counting the chars
        let l:buf = a:line == 1 ? '' : (join(getline(1, a:line - 1), "\n") . "\n")
        let l:buf .= a:col == 1 ? '' : getline('.')[:a:col - 2]
        return len(iconv(l:buf, &encoding, 'utf-8'))
    endif
    " On non utf-8 the line byte should match the character
    return line2byte(a:line) + (a:col - 2)
endfun

" Returns [start, end] byte range when on visual mode
function! prettier#utils#buffer#getCharRange(startSelection, endSelection) abort
  let l:range = []
  call add(l:range, s:getCharPosition(a:startSelection, col("'<")))
  call add(l:range, s:getCharPosition(a:endSelection, col("'>")))
  return l:range
endfunction