Skip to content

Commit 8bbf3eb

Browse files
committed
Added small detection for docstring closings
Updated README to reflect this change Normalized completions and generated snippets
1 parent e408191 commit 8bbf3eb

File tree

3 files changed

+77
-7
lines changed

3 files changed

+77
-7
lines changed

DocblockrPython.py

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,26 @@ def counter():
9595
count += 1
9696
yield count
9797

98+
def read_next_line(view, position, reverse=False):
99+
"""
100+
|||
101+
"""
102+
current_line = view.line(position)
103+
modifier = 1
104+
if reverse is True:
105+
modifier = -1
106+
107+
while True:
108+
next_line = current_line.end() + modifier
109+
110+
# Ensure within bounds of the view
111+
if not (next_line < view.size() and next_line > 0):
112+
return False
113+
114+
current_line = view.line(next_line)
115+
116+
yield current_line
117+
98118
class DocblockrPythonCommand(sublime_plugin.TextCommand):
99119
"""
100120
|||
@@ -113,6 +133,12 @@ def run(self, edit):
113133
|||
114134
"""
115135
self.initialize(self.view)
136+
137+
# If this docstring is already closed, then generate a new line
138+
if self.parser.is_docstring_closed(self.view, self.view.sel()[0].end()) is True:
139+
write(self.view, '\n')
140+
return
141+
116142
self.view.erase(edit, self.trailing_rgn)
117143

118144
output = self.parser.parse(self.line, self.contents)
@@ -159,13 +185,15 @@ def create_snippet(self, parsed_attributes):
159185
if attribute_type is 'arguments':
160186
snippet += 'Arguments:\n'
161187
for attribute in attributes:
162-
snippet += '\t@arg ' + attribute
188+
snippet += '\t' + attribute
189+
snippet += ' {${' + str(next(tab_index)) + ':[type]}} --'
163190
snippet += ' ${' + str(next(tab_index)) + ':[description]}\n'
164191
elif attribute_type is 'keyword_arguments':
165192
snippet += 'Keyword Arguments:\n'
166193
for attribute in attributes:
167-
snippet += '\t@kwarg ' + attribute
168-
snippet += '${' + str(next(tab_index)) + ':[description]}'
194+
snippet += '\t' + attribute
195+
snippet += ' {${' + str(next(tab_index)) + ':[type]}} --'
196+
snippet += ' ${' + str(next(tab_index)) + ':[description]}'
169197
snippet += ' (default ${' + str(next(tab_index)) + '})\n'
170198
elif attribute_type is 'returns':
171199
returns_snippet = ''
@@ -306,3 +334,43 @@ def parse_function(cls, line, contents):
306334
parsed_function['returns'] = {}
307335

308336
return parsed_function
337+
338+
def is_docstring_closed(self, view, position):
339+
"""
340+
Keep reading lines until we reach the end of the file, class, or function
341+
We will assume that if the indentation level is ever lower than present, and no
342+
closing docstring has been found yet, the component has ended and needs to be closed
343+
344+
Arguments:
345+
@arg view {sublime.View} Current Sublime Text View
346+
"""
347+
indentation_level = view.indentation_level(position)
348+
349+
# Check the current line first, and ignore if docstring is closed on this line
350+
line = view.substr(view.line(position))
351+
match = re.search(r'^\s*""".*"""\s*$', line)
352+
353+
if match is not None:
354+
return False
355+
356+
for current_line in read_next_line(view, position):
357+
# Not an empty line
358+
current_line_string = view.substr(current_line).rstrip()
359+
if len(current_line_string) is 0:
360+
continue
361+
362+
# Not on a more indented line
363+
current_indentation = view.indentation_level(current_line.end())
364+
if current_indentation > indentation_level:
365+
continue
366+
367+
# Still within the same indentation level
368+
if current_indentation < indentation_level:
369+
break
370+
371+
# Line only contains whitespace and """
372+
if re.search(r'^\s*"""', current_line_string) is not None:
373+
return True
374+
375+
376+
return False

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ There isn't a key command to start this plugin, it is triggerg by hitting **ente
1919

2020
Known Issues
2121
------------
22-
- Doesn't detect if a docstring is already closed
22+
- Only detects closed docstring if it is on a line of the same indentation, and has no text in front of it. Single Line docstrings are converted to block
2323
- Doesn't process module or class variables
2424

2525
Roadmap
2626
-------
2727
- Determine / Guess at variable and return value types
2828
- `Raises` section of documentation
2929
- `Decorators` section of documentation
30-
- Better README
3130
- Extended Python syntax with docstring keyword highlighting
31+
- Unit Tests!
32+
- More completions!
33+
- Better README

python.sublime-completions

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"scope": "source.python string.quoted.double.block",
33
"completions": [
44
{ "trigger": "@var", "contents": "@var ${1:[name]} {${2:[type]}} ${3:[description]}" },
5-
{ "trigger": "@arg", "contents": "@arg {${1:[type]}} ${2:[description]}" },
6-
{ "trigger": "@kwarg", "contents": "${1:[name]} -- ${2:[description]} (default ${3:[default value]})" },
5+
{ "trigger": "@arg", "contents": "${1:[name]} {${2:[type]}} -- ${3:[description]}" },
6+
{ "trigger": "@kwarg", "contents": "${1:[name]} {${2:[type]}} -- ${3:[description]} (default ${4:[default value]})" },
77
{ "trigger": "@example", "contents": ">>> ${1:[function name]}(${2:[arguments]})\n${3:[result]}" },
88
{ "trigger": "@extends", "contents": "@extends {${1:[type]}}" },
99
{ "trigger": "@returns", "contents": "@returns {${1:[type]}} ${2:[description]}" }

0 commit comments

Comments
 (0)