My dotfiles
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

269 wiersze
7.6 KiB

  1. import re, os, vim, string, random
  2. from collections import deque, namedtuple
  3. _Placeholder = namedtuple("_FrozenPlaceholder", ["current_text", "start", "end"])
  4. _VisualContent = namedtuple("_VisualContent", ["mode", "text"])
  5. _Position = namedtuple("_Position", ["line", "col"])
  6. class _SnippetUtilCursor(object):
  7. def __init__(self, cursor):
  8. self._cursor = [cursor[0] - 1, cursor[1]]
  9. self._set = False
  10. def preserve(self):
  11. self._set = True
  12. self._cursor = [vim.buf.cursor[0], vim.buf.cursor[1]]
  13. def is_set(self):
  14. return self._set
  15. def set(self, line, column):
  16. self.__setitem__(0, line)
  17. self.__setitem__(1, column)
  18. def to_vim_cursor(self):
  19. return (self._cursor[0] + 1, self._cursor[1])
  20. def __getitem__(self, index):
  21. return self._cursor[index]
  22. def __setitem__(self, index, value):
  23. self._set = True
  24. self._cursor[index] = value
  25. def __len__(self):
  26. return 2
  27. def __str__(self):
  28. return str((self._cursor[0], self._cursor[1]))
  29. class IndentUtil(object):
  30. """Utility class for dealing properly with indentation."""
  31. def __init__(self):
  32. self.reset()
  33. def reset(self):
  34. """Gets the spacing properties from Vim."""
  35. self.shiftwidth = int(
  36. vim.eval("exists('*shiftwidth') ? shiftwidth() : &shiftwidth")
  37. )
  38. self._expandtab = vim.eval("&expandtab") == "1"
  39. self._tabstop = int(vim.eval("&tabstop"))
  40. def ntabs_to_proper_indent(self, ntabs):
  41. """Convert 'ntabs' number of tabs to the proper indent prefix."""
  42. line_ind = ntabs * self.shiftwidth * " "
  43. line_ind = self.indent_to_spaces(line_ind)
  44. line_ind = self.spaces_to_indent(line_ind)
  45. return line_ind
  46. def indent_to_spaces(self, indent):
  47. """Converts indentation to spaces respecting Vim settings."""
  48. indent = indent.expandtabs(self._tabstop)
  49. right = (len(indent) - len(indent.rstrip(" "))) * " "
  50. indent = indent.replace(" ", "")
  51. indent = indent.replace("\t", " " * self._tabstop)
  52. return indent + right
  53. def spaces_to_indent(self, indent):
  54. """Converts spaces to proper indentation respecting Vim settings."""
  55. if not self._expandtab:
  56. indent = indent.replace(" " * self._tabstop, "\t")
  57. return indent
  58. class SnippetUtil(object):
  59. """Provides easy access to indentation, etc.
  60. This is the 'snip' object in python code.
  61. """
  62. def __init__(self, _initial_indent, start, end, context):
  63. self._ind = IndentUtil()
  64. self._visual = _VisualContent(
  65. vim.eval("visualmode()"), vim.eval('get(g:,"coc_selected_text","")')
  66. )
  67. self._initial_indent = _initial_indent
  68. self._reset("")
  69. self._start = start
  70. self._end = end
  71. self._context = context
  72. def _reset(self, cur):
  73. """Gets the snippet ready for another update.
  74. :cur: the new value for c.
  75. """
  76. self._ind.reset()
  77. self._cur = cur
  78. self._rv = ""
  79. self._changed = False
  80. self.reset_indent()
  81. def shift(self, amount=1):
  82. """Shifts the indentation level. Note that this uses the shiftwidth
  83. because thats what code formatters use.
  84. :amount: the amount by which to shift.
  85. """
  86. self.indent += " " * self._ind.shiftwidth * amount
  87. def unshift(self, amount=1):
  88. """Unshift the indentation level. Note that this uses the shiftwidth
  89. because thats what code formatters use.
  90. :amount: the amount by which to unshift.
  91. """
  92. by = -self._ind.shiftwidth * amount
  93. try:
  94. self.indent = self.indent[:by]
  95. except IndexError:
  96. self.indent = ""
  97. def mkline(self, line="", indent=""):
  98. """Creates a properly set up line.
  99. :line: the text to add
  100. :indent: the indentation to have at the beginning
  101. if None, it uses the default amount
  102. """
  103. return indent + line
  104. def reset_indent(self):
  105. """Clears the indentation."""
  106. self.indent = self._initial_indent
  107. # Utility methods
  108. @property
  109. def fn(self): # pylint:disable=no-self-use,invalid-name
  110. """The filename."""
  111. return vim.eval('expand("%:t")') or ""
  112. @property
  113. def basename(self): # pylint:disable=no-self-use
  114. """The filename without extension."""
  115. return vim.eval('expand("%:t:r")') or ""
  116. @property
  117. def ft(self): # pylint:disable=invalid-name
  118. """The filetype."""
  119. return self.opt("&filetype", "")
  120. @property
  121. def rv(self): # pylint:disable=invalid-name
  122. """The return value.
  123. The text to insert at the location of the placeholder.
  124. """
  125. return self._rv
  126. @rv.setter
  127. def rv(self, value): # pylint:disable=invalid-name
  128. """See getter."""
  129. self._changed = True
  130. self._rv = value
  131. @property
  132. def _rv_changed(self):
  133. """True if rv has changed."""
  134. return self._changed
  135. @property
  136. def c(self): # pylint:disable=invalid-name
  137. """The current text of the placeholder."""
  138. return ""
  139. @property
  140. def v(self): # pylint:disable=invalid-name
  141. """Content of visual expansions."""
  142. return self._visual
  143. @property
  144. def p(self):
  145. if "coc_last_placeholder" in vim.vars:
  146. p = vim.vars["coc_last_placeholder"]
  147. start = _Position(p["start"]["line"], p["start"]["col"])
  148. end = _Position(p["end"]["line"], p["end"]["col"])
  149. return _Placeholder(p["current_text"], start, end)
  150. return None
  151. @property
  152. def context(self):
  153. return self._context
  154. def opt(self, option, default=None): # pylint:disable=no-self-use
  155. """Gets a Vim variable."""
  156. if vim.eval("exists('%s')" % option) == "1":
  157. try:
  158. return vim.eval(option)
  159. except vim.error:
  160. pass
  161. return default
  162. def __add__(self, value):
  163. """Appends the given line to rv using mkline."""
  164. self.rv += "\n" # pylint:disable=invalid-name
  165. self.rv += self.mkline(value)
  166. return self
  167. def __lshift__(self, other):
  168. """Same as unshift."""
  169. self.unshift(other)
  170. def __rshift__(self, other):
  171. """Same as shift."""
  172. self.shift(other)
  173. @property
  174. def snippet_start(self):
  175. """
  176. Returns start of the snippet in format (line, column).
  177. """
  178. return self._start
  179. @property
  180. def snippet_end(self):
  181. """
  182. Returns end of the snippet in format (line, column).
  183. """
  184. return self._end
  185. @property
  186. def buffer(self):
  187. return vim.buf
  188. class ContextSnippet(object):
  189. def __init__(self):
  190. self.buffer = vim.current.buffer
  191. self.window = vim.current.window
  192. self.cursor = _SnippetUtilCursor(vim.current.window.cursor)
  193. self.line = vim.call("line", ".") - 1
  194. self.column = vim.call("col", ".") - 1
  195. line = vim.call("getline", ".")
  196. self.after = line[self.column :]
  197. if "coc_selected_text" in vim.vars:
  198. self.visual_mode = vim.eval("visualmode()")
  199. self.visual_text = vim.vars["coc_selected_text"]
  200. else:
  201. self.visual_mode = None
  202. self.visual_text = ""
  203. if "coc_last_placeholder" in vim.vars:
  204. p = vim.vars["coc_last_placeholder"]
  205. start = _Position(p["start"]["line"], p["start"]["col"])
  206. end = _Position(p["end"]["line"], p["end"]["col"])
  207. self.last_placeholder = _Placeholder(p["current_text"], start, end)
  208. else:
  209. self.last_placeholder = None