1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-23 12:50:04 +08:00
SpaceVim/bundle/vim-haxe/python/vaxe.py

167 lines
5.4 KiB
Python
Raw Permalink Normal View History

2022-04-23 23:06:02 +08:00
import vim, re
import string
try:
import HTMLParser
except:
from html.parser import HTMLParser
import xml.etree.ElementTree as ET
import json
# This is the python portion of the completion script. Call it with the *name*
# of the input vimscript variable, "complete_output_var". This should contain
# the output from the --display compiler directive. base_var is an optional
# partial word to use for filtering completions.
# The output is given in "output_var", which is likewise the name of the
# vimscript variable to write. This variable contains a dictionary formatted
# appropriately for an omnifunc. "base_var" contains an optional partial word
# to filter for
def complete(complete_output_var, output_var, base_var , alter_var, collapse_var):
complete_output = vim.eval(complete_output_var)
base = vim.eval(base_var)
alter_sig = vim.eval(alter_var) != '0'
collapse_overload = vim.eval(collapse_var) != '0'
if complete_output is None: complete_output = ''
completes = []
# get rid of non-printable characters that would be
# in the embedded doc (e.g. ANSI escape characters)
# thus preventing ET.XML to work
complete_output = re.sub(f'[^{re.escape(string.printable)}]', '', complete_output )
# wrap in a tag to prevent parsing errors
root = ET.XML("<output>" + complete_output + "</output>")
fields = root.findall("list/i")
types = root.findall("type")
completes = []
if len(fields) > 0: # field completion
def fieldxml2completion(x):
word = x.attrib["n"]
menu = x.find("t").text
info = x.find("d").text
menu = '' if menu is None else menu
if info is None:
info = ['']
else:
# get rid of leading/trailing ws/nl
info = info.strip()
# strip html
info = remove_html_markup(info)
# split and collapse extra whitespace
info = [re.sub(r'\s+',' ',s.strip()) for s in info.split('\n')]
abbr = word
kind = 'v'
if menu == '': kind = 'm'
elif re.search("\->", menu):
kind = 'f' # if it has a ->
if alter_sig:
menu = alter_signature(menu)
word += "("
return { 'word': word, 'info': info, 'kind': kind
,'menu': menu, 'abbr': abbr, 'dup':1 }
completes = [fieldxml2completion(f) for f in fields]
elif len(types) > 0: # function type completion
otype = types[0].text.strip()
h = HTMLParser.HTMLParser()
word = ' '
info = [h.unescape(otype)]
abbr = info[0]
if otype == "Dynamic":
completes = [{'word': word,'info':info
, 'abbr': "Dynamic (Will likely cause compiler error.)"
, 'dup':1}
]
elif alter_sig:
abbr = alter_signature(abbr)
completes= [{'word': word,'info':info, 'abbr':abbr, 'dup':1}]
if base != '' and base is not None:
completes = [c for c in completes if re.search("^" + base, c['word'])]
if collapse_overload:
dict_complete = dict()
def complete_exists(c):
if c in dict_complete:
dict_complete[c] += 1
return True
else:
dict_complete[c] = 1
return False
completes = [c for c in completes if not complete_exists(c['abbr'])]
for c in completes:
if dict_complete[c['abbr']] > 1:
c['menu'] = "@:overload " + c['menu']
vim.command("let " + output_var + " = " + json.dumps(completes))
# simple script to grab lists of locations from display-mode completions
def locations(complete_output_var, output_var):
complete_output = vim.eval(complete_output_var)
# wrap in a tag to prevent parsing errors
root = ET.XML("<output>" + complete_output + "</output>")
pos = root.findall("pos")
completes = []
if len(pos) > 0:
completes = [p.text for p in pos]
else:
completes = []
vim.command("let " + output_var + " = " + json.dumps(completes))
def alter_signature(sig):
paren = 0
last_string = ''
final_expr = ''
for i in range(len(sig)):
c = sig[i]
if c == "(":
paren += 1
final_expr += re.sub('->',",", last_string)
last_string = c
elif c == ")":
last_string += c
paren -=1
if paren == 0:
final_expr += last_string
last_string = ''
else:
last_string += c
final_expr = final_expr + re.sub('\s*->\s*', ",", last_string)
parts = final_expr.split(',')
ret_val = parts.pop()
if ret_val == "Void":
ret_val = ''
else:
ret_val = " : " + ret_val
if len(parts) ==1 and parts[0] == "Void":
parts[0] = ''
final_expr = '(' + ", ".join(parts) + ')' + ret_val
return final_expr
# simple script to strip html markup
def remove_html_markup(s):
tag = False
quote = False
out = ""
for c in s:
if c == '<' and not quote:
tag = True
elif c == '>' and not quote:
tag = False
elif (c == '"' or c == "'") and tag:
quote = not quote
elif not tag:
out = out + c
return out