Skip to content

Commit 8e1e62a

Browse files
committed
Merge pull request #19 from Kapiainen/tooltip-patch
Tooltip patch
2 parents 87d1145 + b38ca6a commit 8e1e62a

File tree

2 files changed

+157
-114
lines changed

2 files changed

+157
-114
lines changed

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,15 @@ Single file build system and a batch build variant.
220220
- SKSE mod event names
221221

222222
## **Changelog**
223+
Version 2.x.x - 2016/MM/DD:
224+
225+
**Skyrim**
226+
- Code completion
227+
- Added completions for imported global functions when defining arguments in function/event calls.
228+
- Tooltips
229+
- Refactored tooltips for function/event parameters in order to reduce the amount of work that is done.
230+
- Added parameter tooltips for imported global functions.
231+
223232
Version 2.1.0 - 2016/04/19:
224233

225234
**Core**

Source/Modules/Skyrim/Plugin.py

+148-114
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,49 @@ def on_modified(self, view):
202202
syn.Process(tokens)
203203
except Linter.ExpectedIdentifierError as f:
204204
if tokens[-1].type != lex.OP_DOT:
205-
self.ShowFunctionInfo(view, tokens, syn.stack, e)
205+
stack = syn.stack[:]
206+
arguments = []
207+
for item in reversed(stack):
208+
if item.type == sem.NODE_FUNCTIONCALLARGUMENT:
209+
arguments.insert(0, stack.pop())
210+
elif item.type == sem.LEFT_PARENTHESIS:
211+
break
212+
stackLength = len(stack)
213+
func = None
214+
if stackLength >= 2 and stack[-2].type == sem.IDENTIFIER:
215+
name = stack[-2].value.upper()
216+
if stackLength >= 4 and stack[-3].type == sem.OP_DOT:
217+
try:
218+
result = sem.NodeVisitor(stack[-4])
219+
if result.type != sem.KW_SELF:
220+
try:
221+
script = sem.GetCachedScript(result.type)
222+
func = script.functions.get(name, None)
223+
except Linter.SemanticError as e:
224+
return
225+
else:
226+
for scope in reversed(e.functions):
227+
func = scope.get(name, None)
228+
if func:
229+
break
230+
except Linter.SemanticError as e:
231+
return
232+
else:
233+
for scope in reversed(e.functions):
234+
func = scope.get(name, None)
235+
if func:
236+
break
237+
for imp in e.imports:
238+
script = sem.GetCachedScript(imp)
239+
temp = script.functions.get(name, None)
240+
if temp:
241+
if func:
242+
func = None
243+
else:
244+
func = temp
245+
break
246+
if func and func.data.parameters:
247+
self.ShowFunctionInfo(view, tokens, func, len(arguments))
206248
except Linter.SyntacticError as f:
207249
pass
208250
except Linter.LexicalError as f:
@@ -213,75 +255,40 @@ def on_modified(self, view):
213255
if settings and settings.get("linter_on_modified", True):
214256
self.QueueLinter(view)
215257

216-
def ShowFunctionInfo(self, view, tokens, stack, context):
217-
global sem
218-
arguments = []
219-
for item in reversed(stack):
220-
if item.type == sem.NODE_FUNCTIONCALLARGUMENT:
221-
arguments.insert(0, stack.pop())
222-
elif item.type == sem.LEFT_PARENTHESIS:
223-
break
224-
argumentCount = len(arguments)
225-
stackLength = len(stack)
226-
func = None
227-
if stackLength >= 2 and stack[-1].type == sem.LEFT_PARENTHESIS and stack[-2].type == sem.IDENTIFIER:
228-
name = stack[-2].value.upper()
229-
if stackLength >= 4 and stack[-3].type == sem.OP_DOT:
230-
try:
231-
result = sem.NodeVisitor(stack[-4])
232-
if result.type != sem.KW_SELF:
233-
try:
234-
script = sem.GetCachedScript(result.type)
235-
func = script.functions.get(name, None)
236-
except Linter.SemanticError as e:
237-
return
238-
else:
239-
for scope in reversed(context.functions):
240-
func = scope.get(name, None)
241-
if func:
242-
break
243-
except Linter.SemanticError as e:
244-
return
245-
elif stackLength == 2:
246-
for scope in reversed(context.functions):
247-
func = scope.get(name, None)
248-
if func:
249-
break
250-
if func and func.data.parameters:
251-
funcName = func.data.identifier
252-
currentParameter = None
253-
if len(tokens) > 2 and tokens[-1].type == lex.OP_ASSIGN and tokens[-2].type == lex.IDENTIFIER:
254-
currentParameter = tokens[-2].value.upper()
255-
paramIndex = 0
256-
argCount = len(arguments)
257-
funcParameters = []
258-
for param in func.data.parameters:
259-
paramName = param.identifier
260-
paramType = param.typeIdentifier
261-
if param.array:
262-
paramType = "%s[]" % paramType
263-
paramContent = None
264-
if param.expression:
265-
paramDefaultValue = sem.GetLiteral(param.expression, True)
266-
paramContent = "%s %s = %s" % (paramType, paramName, paramDefaultValue)
267-
else:
268-
paramContent = "%s %s" % (paramType, paramName)
269-
if currentParameter:
270-
if currentParameter == paramName.upper():
271-
paramContent = "<b>%s</b>" % paramContent
272-
else:
273-
if paramIndex == argCount:
274-
paramContent = "<b>%s</b>" % paramContent
275-
paramIndex += 1
276-
funcParameters.append(paramContent)
277-
settings = SublimePapyrus.GetSettings()
278-
backgroundColor = settings.get("tooltip_background_color", "#393939")
279-
bodyTextColor = settings.get("tooltip_body_text_color", "#747369")
280-
bodyFontSize = settings.get("tooltip_font_size", "12")
281-
boldTextColor = settings.get("tooltip_bold_text_color", "#ffffff")
282-
headingTextColor = settings.get("tooltip_heading_text_color", "#bfbfbf")
283-
headingFontSize = settings.get("tooltip_heading_font_size", "14")
284-
css = """<style>
258+
def ShowFunctionInfo(self, view, tokens, func, argumentCount):
259+
funcName = func.data.identifier
260+
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+
paramIndex = 0
264+
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)
284+
settings = SublimePapyrus.GetSettings()
285+
backgroundColor = settings.get("tooltip_background_color", "#393939")
286+
bodyTextColor = settings.get("tooltip_body_text_color", "#747369")
287+
bodyFontSize = settings.get("tooltip_font_size", "12")
288+
boldTextColor = settings.get("tooltip_bold_text_color", "#ffffff")
289+
headingTextColor = settings.get("tooltip_heading_text_color", "#bfbfbf")
290+
headingFontSize = settings.get("tooltip_heading_font_size", "14")
291+
css = """<style>
285292
html {
286293
background-color: %s;
287294
}
@@ -300,11 +307,11 @@ def ShowFunctionInfo(self, view, tokens, stack, context):
300307
font-size: %spx;
301308
}
302309
</style>""" % (backgroundColor, bodyFontSize, bodyTextColor, boldTextColor, headingTextColor, headingFontSize)
303-
content = "%s<h1>%s</h1>%s" % (css, funcName, "<br>".join(funcParameters))
304-
if view.is_popup_visible():
305-
view.update_popup(content)
306-
else:
307-
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)))
310+
content = "%s<h1>%s</h1>%s" % (css, funcName, "<br>".join(funcParameters))
311+
if view.is_popup_visible():
312+
view.update_popup(content)
313+
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)))
308315

309316
def QueueLinter(self, view):
310317
if self.linterRunning: # If an instance of the linter is running, then cancel
@@ -906,46 +913,73 @@ def Completions(self, view, prefix, locations):
906913
completions.append(self.completionKeywordSelf)
907914
completions.append(self.completionKeywordParent)
908915

909-
if tokens[-1].type != lex.OP_ASSIGN:
910-
stack = syn.stack[:]
911-
for item in reversed(stack):
912-
if item.type == sem.NODE_FUNCTIONCALLARGUMENT:
913-
stack.pop()
914-
elif item.type == sem.LEFT_PARENTHESIS:
915-
break
916-
stackLength = len(stack)
917-
func = None
918-
if stackLength >= 2 and stack[-1].type == sem.LEFT_PARENTHESIS and stack[-2].type == sem.IDENTIFIER:
919-
name = stack[-2].value.upper()
920-
if stackLength >= 4 and stack[-3].type == sem.OP_DOT:
921-
try:
922-
result = sem.NodeVisitor(stack[-4])
923-
if result.type != sem.KW_SELF:
924-
try:
925-
script = sem.GetCachedScript(result.type)
926-
func = script.functions.get(name, None)
927-
except Linter.SemanticError as e:
928-
return
929-
else:
930-
for scope in reversed(e.functions):
931-
func = scope.get(name, None)
932-
if func:
933-
break
934-
except Linter.SemanticError as e:
935-
return
936-
elif stackLength == 2:
937-
for scope in reversed(e.functions):
938-
func = scope.get(name, None)
939-
if func:
940-
break
941-
if func and func.data.parameters:
942-
for param in func.data.parameters:
943-
completions.append(SublimePapyrus.MakeParameterCompletion(Linter.Statement(sem.STAT_PARAMETER, 0, param)))
916+
# Imported global functions
917+
for imp in e.imports:
918+
functions = self.GetFunctionCompletions(imp, True)
919+
if not functions:
920+
try:
921+
script = sem.GetCachedScript(imp)
922+
if script:
923+
functions = []
924+
impLower = imp.lower()
925+
for name, obj in script.functions.items():
926+
if lex.KW_GLOBAL in obj.data.flags:
927+
functions.append(SublimePapyrus.MakeFunctionCompletion(obj, sem, True, impLower, parameters=settingFunctionEventParameters))
928+
self.SetFunctionCompletions(imp, functions, True)
929+
except:
930+
return
931+
if functions:
932+
completions.extend(functions)
944933

945-
global SUBLIME_VERSION
946-
if SUBLIME_VERSION >= 3070 and prefix == "" and settings.get("tooltip_function_parameters", True):
947-
if not view.is_popup_visible():
948-
self.ShowFunctionInfo(view, tokens, syn.stack, e)
934+
# Show info about function/event parameters
935+
stack = syn.stack[:]
936+
arguments = []
937+
for item in reversed(stack):
938+
if item.type == sem.NODE_FUNCTIONCALLARGUMENT:
939+
arguments.insert(0, stack.pop())
940+
elif item.type == sem.LEFT_PARENTHESIS:
941+
break
942+
stackLength = len(stack)
943+
func = None
944+
if stackLength >= 2 and stack[-2].type == sem.IDENTIFIER:
945+
name = stack[-2].value.upper()
946+
if stackLength >= 4 and stack[-3].type == sem.OP_DOT:
947+
try:
948+
result = sem.NodeVisitor(stack[-4])
949+
if result.type != sem.KW_SELF:
950+
try:
951+
script = sem.GetCachedScript(result.type)
952+
func = script.functions.get(name, None)
953+
except Linter.SemanticError as e:
954+
return
955+
else:
956+
for scope in reversed(e.functions):
957+
func = scope.get(name, None)
958+
if func:
959+
break
960+
except Linter.SemanticError as e:
961+
return
962+
else:
963+
for scope in reversed(e.functions):
964+
func = scope.get(name, None)
965+
if func:
966+
break
967+
for imp in e.imports:
968+
script = sem.GetCachedScript(imp)
969+
temp = script.functions.get(name, None)
970+
if temp:
971+
if func:
972+
func = None
973+
else:
974+
func = temp
975+
break
976+
if func and func.data.parameters:
977+
for param in func.data.parameters:
978+
completions.append(SublimePapyrus.MakeParameterCompletion(Linter.Statement(sem.STAT_PARAMETER, 0, param)))
979+
global SUBLIME_VERSION
980+
if SUBLIME_VERSION >= 3070 and prefix == "" and settings.get("tooltip_function_parameters", True):
981+
if not view.is_popup_visible():
982+
self.ShowFunctionInfo(view, tokens, func, len(arguments))
949983

950984
return completions
951985
except Linter.SyntacticError as f:

0 commit comments

Comments
 (0)