string.vim 4.3 KB

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