Skip to content

Commit 51ec72a

Browse files
committed
Merge pull request #25 from Kapiainen/update
Version 2.6.0
2 parents 66a085b + 1c31172 commit 51ec72a

File tree

5 files changed

+98
-54
lines changed

5 files changed

+98
-54
lines changed

README.md

+14-2
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ Settings are located in *Preferences* > *Package Settings* > *SublimePapyrus*.
7070

7171
- ***intelligent_code_completion_function_event_parameters***: Determines if function/event parameters should be included in completions for function/event calls. Default: True
7272

73-
- ***tooltip_function_parameters***: Determines if a tooltip shows up with information about the parameters of a function/event call that is being edited. Default: True
74-
73+
- ***tooltip_function_parameters***: Determines if a tooltip shows up with information about the parameters of the function/event call that is being edited. Default: True
74+
75+
- ***tooltip_function_docstring***: Determines if a tooltip shows up with the docstring of the function/event call that is being edited. Default: True
76+
7577
- ***tooltip_background_color***: Hex color code of a tooltip's background. Default: #393939
7678

7779
- ***tooltip_body_text_color***: Hex color code of a tooltip's text. Default: #747369
@@ -223,6 +225,16 @@ Single file build system and a batch build variant.
223225

224226
## **Changelog**
225227

228+
Version 2.6.0 - 2016/05/14:
229+
230+
**Core**
231+
- Added a boolean setting for displaying docstrings in function/event call tooltips.
232+
- Added a warning to the build system framework for when an import path defined in a module's settings does not actually exist on the filesystem.
233+
234+
**Skyrim**
235+
- Added docstring support to classes representing scriptheaders, functions, events, and properties in the linter.
236+
- Added support for displaying docstrings in tooltips for function/event calls.
237+
226238
Version 2.5.0 - 2016/05/05:
227239

228240
**Skyrim**

Source/Core/Plugin.py

+3
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ def run(self, **args):
261261
t = filePath.lower()
262262
if not all(t != k.lower() for k in imports) and settings.get("batch_compilation_warning", True) and not sublime.ok_cancel_dialog("Are you sure you want to batch compile all script sources in \"%s\"?\n\nThis folder is one of the import folders and may contain script sources that are a part of the base game. Compiling said script sources could lead to unintended behavior if they have been modified." % filePath):
263263
return
264+
for path in imports:
265+
if not os.path.isdir(path):
266+
return ShowMessage("The import path '%s' does not exist on the filesystem." % path)
264267
imports = ";".join(imports)
265268
else:
266269
return ShowMessage("The import path(s) setting has to be a list of strings.")

Source/Core/SublimePapyrus.sublime-settings

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"intelligent_code_completion": true,
99
"intelligent_code_completion_function_event_parameters": true,
1010
"tooltip_function_parameters": true,
11+
"tooltip_function_docstring": true,
1112
"tooltip_background_color": "#393939",
1213
"tooltip_body_text_color": "#747369",
1314
"tooltip_font_size": "12",

Source/Modules/Skyrim/Linter.py

+34-20
Original file line numberDiff line numberDiff line change
@@ -278,19 +278,20 @@ def __init__(self, aType):
278278
self.type = aType
279279

280280
class Scriptheader(object):
281-
__slots__ = ["name", "parent", "flags"]
281+
__slots__ = ["name", "parent", "flags", "docstring"]
282282
def __init__(self, aName, aParent, aFlags):
283283
self.name = aName
284284
self.parent = aParent
285285
self.flags = aFlags
286+
self.docstring = None
286287

287288
class Import(object):
288289
__slots__ = ["name"]
289290
def __init__(self, aName):
290291
self.name = aName
291292

292293
class FunctionDef(object):
293-
__slots__ = ["type", "typeIdentifier", "array", "name", "identifier", "parameters", "flags"]
294+
__slots__ = ["type", "typeIdentifier", "array", "name", "identifier", "parameters", "flags", "docstring"]
294295
def __init__(self, aType, aTypeIdentifier, aArray, aName, aIdentifier, aParameters, aFlags):
295296
self.type = aType
296297
self.typeIdentifier = aTypeIdentifier
@@ -299,15 +300,17 @@ def __init__(self, aType, aTypeIdentifier, aArray, aName, aIdentifier, aParamete
299300
self.identifier = aIdentifier
300301
self.parameters = aParameters
301302
self.flags = aFlags
303+
self.docstring = None
302304

303305
class EventDef(object):
304-
__slots__ = ["type", "name", "identifier", "parameters", "flags"]
306+
__slots__ = ["type", "name", "identifier", "parameters", "flags", "docstring"]
305307
def __init__(self, aType, aName, aIdentifier, aParameters, aFlags):
306308
self.type = aType
307309
self.name = aName
308310
self.identifier = aIdentifier
309311
self.parameters = aParameters
310312
self.flags = aFlags
313+
self.docstring = None
311314

312315
class ParameterDef(object):
313316
__slots__ = ["type", "typeIdentifier", "array", "name", "identifier", "expression"]
@@ -346,7 +349,7 @@ def __init__(self, aType, aTypeIdentifier, aArray, aName, aIdentifier, aValue, a
346349
self.flags = aFlags
347350

348351
class PropertyDef(object):
349-
__slots__ = ["type", "typeIdentifier", "array", "name", "identifier", "value", "flags"]
352+
__slots__ = ["type", "typeIdentifier", "array", "name", "identifier", "value", "flags", "docstring"]
350353
def __init__(self, aType, aTypeIdentifier, aArray, aName, aIdentifier, aValue, aFlags):
351354
self.type = aType
352355
self.typeIdentifier = aTypeIdentifier
@@ -355,6 +358,7 @@ def __init__(self, aType, aTypeIdentifier, aArray, aName, aIdentifier, aValue, a
355358
self.identifier = aIdentifier
356359
self.value = aValue
357360
self.flags = aFlags
361+
self.docstring = None
358362

359363
class Return(object):
360364
__slots__ = ["expression"]
@@ -1586,17 +1590,34 @@ def CacheScript(self, name, path = None, line = None):
15861590
i = 0
15871591
while i < len(statements):
15881592
if statements[i].type == self.STAT_FUNCTIONDEF or statements[i].type == self.STAT_EVENTDEF:
1589-
functions[statements[i].data.name] = statements[i]
1593+
start = statements[i]
1594+
functions[statements[i].data.name] = start
15901595
if not self.KW_NATIVE in statements[i].data.flags:
15911596
while i < len(statements) and not (statements[i].type == self.STAT_KEYWORD and (statements[i].data.type == self.KW_ENDFUNCTION or statements[i].data.type == self.KW_ENDEVENT)):
1597+
if start.type == self.STAT_FUNCTIONDEF and not start.data.docstring:
1598+
if statements[i].type == self.STAT_DOCUMENTATION:
1599+
start.data.docstring = statements[i]
1600+
i += 1
1601+
else:
1602+
if start.type == self.STAT_FUNCTIONDEF and i + 1 < len(statements) and statements[i + 1].type == self.STAT_DOCUMENTATION:
1603+
start.data.docstring = statements[i + 1]
15921604
i += 1
15931605
elif statements[i].type == self.STAT_PROPERTYDEF:
1594-
properties[statements[i].data.name] = statements[i]
1606+
start = statements[i]
1607+
properties[statements[i].data.name] = start
15951608
if not self.KW_AUTO in statements[i].data.flags and not self.KW_AUTOREADONLY in statements[i].data.flags:
15961609
while i < len(statements) and not (statements[i].type == self.STAT_KEYWORD and statements[i].data.type == self.KW_ENDPROPERTY):
1610+
if not start.data.docstring:
1611+
if statements[i].type == self.STAT_DOCUMENTATION:
1612+
start.data.docstring = statements[i]
1613+
i += 1
1614+
else:
1615+
if i + 1 < len(statements) and statements[i + 1].type == self.STAT_DOCUMENTATION:
1616+
start.data.docstring = statements[i + 1]
15971617
i += 1
15981618
elif statements[i].type == self.STAT_STATEDEF:
1599-
states[statements[i].data.name] = statements[i]
1619+
start = statements[i]
1620+
states[statements[i].data.name] = start
16001621
while i < len(statements) and not (statements[i].type == self.STAT_KEYWORD and statements[i].data.type == self.KW_ENDSTATE):
16011622
i += 1
16021623
elif statements[i].type == self.STAT_SCRIPTHEADER:
@@ -1645,11 +1666,9 @@ def Process(self, statements, paths): # Return True if successful, False if fail
16451666
self.states[0].update(parentScript.states)
16461667
else:
16471668
self.Abort("Failed to process the parent script.", self.header.line)
1648-
# Doc string
1649-
docString = None
16501669
if len(statements) > 0:
16511670
if statements[0].type == self.STAT_DOCUMENTATION:
1652-
docString = statements.pop(0)
1671+
self.header.data.docstring = statements.pop(0)
16531672
else:
16541673
self.Abort("The first line has to be a script header.", statements[0].line)
16551674
if not self.functions[0].get("GOTOSTATE", None):
@@ -1692,10 +1711,9 @@ def Process(self, statements, paths): # Return True if successful, False if fail
16921711
else:
16931712
raise UnterminatedPropertyError(prop[0].line)
16941713
else:
1695-
docString = None
16961714
if len(statements) > 0:
16971715
if statements[0].type == self.STAT_DOCUMENTATION:
1698-
docString = statements.pop(0)
1716+
stat.data.docstring = statements.pop(0)
16991717
elif stat.type == self.STAT_VARIABLEDEF:
17001718
self.AddVariable(stat)
17011719
if stat.data.value:
@@ -1725,10 +1743,9 @@ def Process(self, statements, paths): # Return True if successful, False if fail
17251743
self.PushVariableScope()
17261744
self.AddVariable(stat)
17271745
self.PopVariableScope()
1728-
docString = None
17291746
if len(statements) > 0:
17301747
if statements[0].type == self.STAT_DOCUMENTATION:
1731-
docString = statements.pop(0)
1748+
stat.data.docstring = statements.pop(0)
17321749
elif stat.type == self.STAT_EVENTDEF:
17331750
self.AddFunction(stat)
17341751
if not self.KW_NATIVE in stat.data.flags:
@@ -1744,10 +1761,9 @@ def Process(self, statements, paths): # Return True if successful, False if fail
17441761
self.PushVariableScope()
17451762
self.AddVariable(stat)
17461763
self.PopVariableScope()
1747-
docString = None
17481764
if len(statements) > 0:
17491765
if statements[0].type == self.STAT_DOCUMENTATION:
1750-
docString = statements.pop(0)
1766+
stat.data.docstring = statements.pop(0)
17511767
elif stat.type == self.STAT_IMPORT:
17521768
if not stat.data.name in self.imports:
17531769
self.imports.append(stat.data.name)
@@ -1821,10 +1837,9 @@ def PropertyBlock(self, statements):
18211837
i = 0
18221838
start = statements[i]
18231839
i += 1
1824-
docString = None
18251840
if i < statementsLength:
18261841
if statements[i].type == self.STAT_DOCUMENTATION:
1827-
docString = statements[i]
1842+
start.data.docstring = statements[i]
18281843
i += 1
18291844
functions = {}
18301845
while i < statementsLength:
@@ -1896,10 +1911,9 @@ def FunctionBlock(self, statements):
18961911
self.statementsLength = len(statements)
18971912
self.statementsIndex = 1
18981913
start = self.statements[0]
1899-
docString = None
19001914
if self.statementsIndex < self.statementsLength:
19011915
if self.statements[self.statementsIndex].type == self.STAT_DOCUMENTATION:
1902-
docString = statements[self.statementsIndex]
1916+
start.data.docstring = statements[self.statementsIndex]
19031917
self.statementsIndex += 1
19041918
self.AddVariable(start)
19051919
if start.type == self.STAT_FUNCTIONDEF:

Source/Modules/Skyrim/Plugin.py

+46-32
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,9 @@ def on_modified(self, view):
170170
settings = SublimePapyrus.GetSettings()
171171

172172
global SUBLIME_VERSION
173-
if SUBLIME_VERSION >= 3070 and settings.get("tooltip_function_parameters", True):
173+
tooltipParameters = settings.get("tooltip_function_parameters", True)
174+
tooltipDocstring = settings.get("tooltip_function_docstring", True)
175+
if SUBLIME_VERSION >= 3070 and (tooltipParameters or tooltipDocstring):
174176
if self.linterRunning:
175177
return
176178
elif self.completionRunning:
@@ -243,8 +245,8 @@ def on_modified(self, view):
243245
else:
244246
func = temp
245247
break
246-
if func and func.data.parameters:
247-
self.ShowFunctionInfo(view, tokens, func, len(arguments))
248+
if func:# and func.data.parameters:
249+
self.ShowFunctionInfo(view, tokens, func, len(arguments), tooltipParameters, tooltipDocstring)
248250
except Linter.SyntacticError as f:
249251
pass
250252
except Linter.LexicalError as f:
@@ -255,32 +257,42 @@ def on_modified(self, view):
255257
if settings and settings.get("linter_on_modified", True):
256258
self.QueueLinter(view)
257259

258-
def ShowFunctionInfo(self, view, tokens, func, argumentCount):
259-
funcName = func.data.identifier
260+
def ShowFunctionInfo(self, aView, aTokens, aFunction, aArgumentCount, aParameters, aDocstring):
261+
funcName = aFunction.data.identifier
260262
currentParameter = None
261-
if len(tokens) > 2 and tokens[-1].type == lex.OP_ASSIGN and tokens[-2].type == lex.IDENTIFIER:
262-
currentParameter = tokens[-2].value.upper()
263+
if len(aTokens) > 2 and aTokens[-1].type == lex.OP_ASSIGN and aTokens[-2].type == lex.IDENTIFIER:
264+
currentParameter = aTokens[-2].value.upper()
263265
paramIndex = 0
264266
funcParameters = []
265-
for param in func.data.parameters:
266-
paramName = param.identifier
267-
paramType = param.typeIdentifier
268-
if param.array:
269-
paramType = "%s[]" % paramType
270-
paramContent = None
271-
if param.expression:
272-
paramDefaultValue = sem.GetLiteral(param.expression, True)
273-
paramContent = "%s %s = %s" % (paramType, paramName, paramDefaultValue)
274-
else:
275-
paramContent = "%s %s" % (paramType, paramName)
276-
if currentParameter:
277-
if currentParameter == paramName.upper():
278-
paramContent = "<b>%s</b>" % paramContent
279-
else:
280-
if paramIndex == argumentCount:
281-
paramContent = "<b>%s</b>" % paramContent
282-
paramIndex += 1
283-
funcParameters.append(paramContent)
267+
if aParameters:
268+
for param in aFunction.data.parameters:
269+
paramName = param.identifier
270+
paramType = param.typeIdentifier
271+
if param.array:
272+
paramType = "%s[]" % paramType
273+
paramContent = None
274+
if param.expression:
275+
paramDefaultValue = sem.GetLiteral(param.expression, True)
276+
paramContent = "%s %s = %s" % (paramType, paramName, paramDefaultValue)
277+
else:
278+
paramContent = "%s %s" % (paramType, paramName)
279+
if currentParameter:
280+
if currentParameter == paramName.upper():
281+
paramContent = "<b>%s</b>" % paramContent
282+
else:
283+
if paramIndex == aArgumentCount:
284+
paramContent = "<b>%s</b>" % paramContent
285+
paramIndex += 1
286+
funcParameters.append(paramContent)
287+
288+
docstring = ""
289+
if aDocstring:
290+
if aFunction.data.docstring:
291+
if funcParameters:
292+
docstring = "<br><br>%s" % "<br>".join(aFunction.data.docstring.data.value.split("\n"))
293+
else:
294+
docstring = "<br>".join(aFunction.data.docstring.data.value.split("\n"))
295+
284296
settings = SublimePapyrus.GetSettings()
285297
backgroundColor = settings.get("tooltip_background_color", "#393939")
286298
bodyTextColor = settings.get("tooltip_body_text_color", "#747369")
@@ -307,11 +319,11 @@ def ShowFunctionInfo(self, view, tokens, func, argumentCount):
307319
font-size: %spx;
308320
}
309321
</style>""" % (backgroundColor, bodyFontSize, bodyTextColor, boldTextColor, headingTextColor, headingFontSize)
310-
content = "%s<h1>%s</h1>%s" % (css, funcName, "<br>".join(funcParameters))
311-
if view.is_popup_visible():
312-
view.update_popup(content)
322+
content = "%s<h1>%s</h1>%s%s" % (css, funcName, "<br>".join(funcParameters), docstring)
323+
if aView.is_popup_visible():
324+
aView.update_popup(content)
313325
else:
314-
view.show_popup(content, flags=sublime.COOPERATE_WITH_AUTO_COMPLETE, max_width=int(settings.get("tooltip_max_width", 600)), max_height=int(settings.get("tooltip_max_height", 300)))
326+
aView.show_popup(content, flags=sublime.COOPERATE_WITH_AUTO_COMPLETE, max_width=int(settings.get("tooltip_max_width", 600)), max_height=int(settings.get("tooltip_max_height", 300)))
315327

316328
def QueueLinter(self, view):
317329
if self.linterRunning: # If an instance of the linter is running, then cancel
@@ -977,9 +989,11 @@ def Completions(self, view, prefix, locations):
977989
for param in func.data.parameters:
978990
completions.append(SublimePapyrus.MakeParameterCompletion(Linter.Statement(sem.STAT_PARAMETER, 0, param)))
979991
global SUBLIME_VERSION
980-
if SUBLIME_VERSION >= 3070 and prefix == "" and settings.get("tooltip_function_parameters", True):
992+
tooltipParameters = settings.get("tooltip_function_parameters", True)
993+
tooltipDocstring = settings.get("tooltip_function_docstring", True)
994+
if SUBLIME_VERSION >= 3070 and prefix == "" and (tooltipParameters or tooltipDocstring):
981995
if not view.is_popup_visible():
982-
self.ShowFunctionInfo(view, tokens, func, len(arguments))
996+
self.ShowFunctionInfo(view, tokens, func, len(arguments), tooltipParameters, tooltipDocstring)
983997

984998
return completions
985999
except Linter.SyntacticError as f:

0 commit comments

Comments
 (0)