-
Notifications
You must be signed in to change notification settings - Fork 11
/
commands.py
165 lines (119 loc) · 4.83 KB
/
commands.py
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
"""DocBlockr for Python.
Author: Adam Bullmer <adam.bullmer@gmail.com>
Website: https://github.com/adambullmer/sublime-docblockr-python
Credit to `spadgos` and the team at DocBlockr for providing some source code
to support this project
"""
import logging
import re
import sublime
import sublime_plugin
from .formatters.utils import get_formatter, get_setting
from .parsers.parser import get_parser
log = logging.getLogger(__name__)
def write(view, string):
"""Write a string to the view as a snippet.
Arguments:
view {sublime.View} -- view to have content written to
string {String} -- String representation of a snippet to be
written to the view
"""
view.run_command('insert_snippet', {'contents': string})
def escape(string):
r"""Escape the special characters.
Escapes characters that are also in snippet tab fields so that inserting into the view
doesn't accidentally create another tabbable field
Arguments:
string {String} -- String to be excaped
Examples:
>>> escape('function $test() {}')
'function \$test() \{\}'
Returns:
{String} String with escaped characters
"""
return string.replace('$', r'\$').replace('{', r'\{').replace('}', r'\}')
class DocblockrPythonCommand(sublime_plugin.TextCommand):
"""Sublime Text Command.
Command to be run by Sublime Text
Extends:
sublime_plugin.TextCommand
Variables:
position {Integer}
trailing_rgn {String}
trailing_string {String}
settings {String}
indent_spaces {String}
parser {Object}
line {String}
contents {String}
"""
position = 0
trailing_rgn = ''
trailing_string = ''
settings = ''
indent_spaces = ''
parser = object
line = ''
contents = ''
view_settings = None
project_settings = None
def run(self, edit):
"""Sublime Command Entrypoint.
Entrypoint for the Sublime Text Command. Outputs the result of the parsing to
the view.
Arguments:
edit {sublime.edit} -- Sublime Edit buffer
"""
self.initialize(self.view)
# If this docstring is already closed, then generate a new line
if self.parser.is_docstring_closed(self.view, self.view.sel()[0].end()) is True:
write(self.view, '\n')
return
self.view.erase(edit, self.trailing_rgn)
output = self.parser.parse(self.line, self.contents)
snippet = self.create_snippet(output)
write(self.view, snippet)
def initialize(self, view):
"""Set up the command's settings.
Begins preparsing the file to gather some basic information.
- Which parser to use
- Store any trailing characters
Arguments:
view {sublime.View} -- The view to be edited
"""
self.view_settings = view.settings()
project_data = view.window().project_data() or {}
self.project_settings = project_data.get('DocblockrPython', {})
position = view.sel()[0].end()
# trailing characters are put inside the body of the comment
self.trailing_rgn = sublime.Region(position, view.line(position).end())
self.trailing_string = view.substr(self.trailing_rgn).strip()
# drop trailing '"""'
self.trailing_string = escape(re.sub(r'\s*("""|\'\'\')\s*$', '', self.trailing_string))
self.parser = parser = get_parser(view)
# read the previous line
self.line = parser.get_definition(view, position)
self.contents = parser.get_definition_contents(view, view.line(position).end())
log.debug('contents -- {}'.format(self.contents))
def create_snippet(self, parsed_attributes):
"""Format a Sublime Text snippet syntax string.
Iterates through the list of field groups, and then through each item
in the group to create the snippets using the user specified formatter.
Arguments:
parsed_attributes {dict} -- key value of attributes groups
Returns:
str -- sublime text formatted snippet string
"""
project_formatter = self.project_settings.get('formatter', None)
formatter = get_formatter(project_formatter or get_setting('formatter'))()
# Make sure the summary line has the trailing text, or a placeholder
if not self.trailing_string:
self.trailing_string = formatter.summary()
snippet = self.trailing_string + formatter.description()
for attribute_type, attributes in parsed_attributes:
if len(attributes) is 0:
continue
segment = getattr(formatter, attribute_type)
snippet += segment(attributes)
snippet += self.parser.closing_string
return snippet