helper.vim 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. scriptencoding utf-8
  2. " Helper methods for viml
  3. function! coc#helper#get_charactor(line, col) abort
  4. return strchars(strpart(a:line, 0, a:col - 1))
  5. endfunction
  6. function! coc#helper#last_character(line) abort
  7. return strcharpart(a:line, strchars(a:line) - 1, 1)
  8. endfunction
  9. function! coc#helper#obj_equal(one, two) abort
  10. for key in keys(a:one)
  11. if a:one[key] != a:two[key]
  12. return 0
  13. endif
  14. endfor
  15. return 1
  16. endfunction
  17. " get change between two lines
  18. function! coc#helper#str_diff(curr, previous, col) abort
  19. let end = strpart(a:curr, a:col - 1)
  20. let start = strpart(a:curr, 0, a:col -1)
  21. let endOffset = 0
  22. let startOffset = 0
  23. let currLen = strchars(a:curr)
  24. let prevLen = strchars(a:previous)
  25. if len(end)
  26. let endLen = strchars(end)
  27. for i in range(min([prevLen, endLen]))
  28. if strcharpart(end, endLen - 1 - i, 1) ==# strcharpart(a:previous, prevLen -1 -i, 1)
  29. let endOffset = endOffset + 1
  30. else
  31. break
  32. endif
  33. endfor
  34. endif
  35. let remain = endOffset == 0 ? a:previous : strcharpart(a:previous, 0, prevLen - endOffset)
  36. if len(remain)
  37. for i in range(min([strchars(remain), strchars(start)]))
  38. if strcharpart(remain, i, 1) ==# strcharpart(start, i ,1)
  39. let startOffset = startOffset + 1
  40. else
  41. break
  42. endif
  43. endfor
  44. endif
  45. return {
  46. \ 'start': startOffset,
  47. \ 'end': prevLen - endOffset,
  48. \ 'text': strcharpart(a:curr, startOffset, currLen - startOffset - endOffset)
  49. \ }
  50. endfunction
  51. function! coc#helper#str_apply(content, diff) abort
  52. let totalLen = strchars(a:content)
  53. let endLen = totalLen - a:diff['end']
  54. return strcharpart(a:content, 0, a:diff['start']).a:diff['text'].strcharpart(a:content, a:diff['end'], endLen)
  55. endfunction
  56. " insert inserted to line at position, use ... when result is too long
  57. " line should only contains character has strwidth equals 1
  58. function! coc#helper#str_compose(line, position, inserted) abort
  59. let width = strwidth(a:line)
  60. let text = a:inserted
  61. let res = a:line
  62. let need_truncate = a:position + strwidth(text) + 1 > width
  63. if need_truncate
  64. let remain = width - a:position - 3
  65. if remain < 2
  66. " use text for full line, use first & end of a:line, ignore position
  67. let res = strcharpart(a:line, 0, 1)
  68. let w = strwidth(res)
  69. for i in range(strchars(text))
  70. let c = strcharpart(text, i, 1)
  71. let a = strwidth(c)
  72. if w + a <= width - 1
  73. let w = w + a
  74. let res = res.c
  75. endif
  76. endfor
  77. let res = res.strcharpart(a:line, w)
  78. else
  79. let res = strcharpart(a:line, 0, a:position)
  80. let w = strwidth(res)
  81. for i in range(strchars(text))
  82. let c = strcharpart(text, i, 1)
  83. let a = strwidth(c)
  84. if w + a <= width - 3
  85. let w = w + a
  86. let res = res.c
  87. endif
  88. endfor
  89. let res = res.'..'
  90. let w = w + 2
  91. let res = res.strcharpart(a:line, w)
  92. endif
  93. else
  94. let first = strcharpart(a:line, 0, a:position)
  95. let res = first.text.strcharpart(a:line, a:position + strwidth(text))
  96. endif
  97. return res
  98. endfunction
  99. " Return new dict with keys removed
  100. function! coc#helper#dict_omit(dict, keys) abort
  101. let res = {}
  102. for key in keys(a:dict)
  103. if index(a:keys, key) == -1
  104. let res[key] = a:dict[key]
  105. endif
  106. endfor
  107. return res
  108. endfunction
  109. " Return new dict with keys only
  110. function! coc#helper#dict_pick(dict, keys) abort
  111. let res = {}
  112. for key in keys(a:dict)
  113. if index(a:keys, key) != -1
  114. let res[key] = a:dict[key]
  115. endif
  116. endfor
  117. return res
  118. endfunction
  119. " support for float values
  120. function! coc#helper#min(first, ...) abort
  121. let val = a:first
  122. for i in range(0, len(a:000) - 1)
  123. if a:000[i] < val
  124. let val = a:000[i]
  125. endif
  126. endfor
  127. return val
  128. endfunction
  129. " support for float values
  130. function! coc#helper#max(first, ...) abort
  131. let val = a:first
  132. for i in range(0, len(a:000) - 1)
  133. if a:000[i] > val
  134. let val = a:000[i]
  135. endif
  136. endfor
  137. return val
  138. endfunction