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