def on_modified_async(self):
output_id = self.view.settings().get('minihtml_preview_output_view_id')
output_view = next(view for view in self.view.window().views()
if view.id() == output_id)
content = self.view.substr(sublime.Region(0, self.view.size()))
buffer_id = output_view.buffer_id()
if buffer_id in self.phantom_sets:
ps = self.phantom_sets[buffer_id]
else:
ps = sublime.PhantomSet(output_view, 'minihtml_preview_phantom')
self.phantom_sets[buffer_id] = ps
p = sublime.Phantom(sublime.Region(0), content,
sublime.LAYOUT_BLOCK, _on_navigate)
ps.update([p])
python类Phantom()的实例源码
def show_html(md_view, preview):
global windows_phantom_set
html = markdown2html(get_view_content(md_view), os.path.dirname(md_view.file_name()), md_view.settings().get('color_scheme'))
phantom_set = windows_phantom_set.setdefault(preview.window().id(),
sublime.PhantomSet(preview, 'markdown_live_preview'))
phantom_set.update([sublime.Phantom(sublime.Region(0), html, sublime.LAYOUT_BLOCK,
lambda href: sublime.run_command('open_url', {'url': href}))])
# lambda href: sublime.run_command('open_url', {'url': href})
# get the "ratio" of the markdown view's position.
# 0 < y < 1
y = md_view.text_to_layout(md_view.sel()[0].begin())[1] / md_view.layout_extent()[1]
# set the vector (position) for the preview
vector = [0, y * preview.layout_extent()[1]]
# remove half of the viewport_extent.y to center it on the screen (verticaly)
vector[1] -= preview.viewport_extent()[1] / 2
# make sure the minimum is 0
vector[1] = 0 if vector[1] < 0 else vector[1]
# the hide the first line
vector[1] += preview.line_height()
preview.set_viewport_position(vector, animate=False)
def show_phantoms(self, view):
"""Show phantoms for compilation errors.
Args:
view (sublime.View): current view
"""
view.erase_phantoms(PopupErrorVis._TAG)
if view.buffer_id() not in self.phantom_sets:
phantom_set = sublime.PhantomSet(view, PopupErrorVis._TAG)
self.phantom_sets[view.buffer_id()] = phantom_set
else:
phantom_set = self.phantom_sets[view.buffer_id()]
phantoms = []
current_error_dict = self.err_regions[view.buffer_id()]
for err in current_error_dict:
errors_dict = current_error_dict[err]
errors_html = PhantomErrorVis._as_html(errors_dict)
pt = view.text_point(err - 1, 1)
phantoms.append(sublime.Phantom(
sublime.Region(pt, view.line(pt).b),
errors_html,
sublime.LAYOUT_BELOW,
on_navigate=self._on_phantom_navigate))
phantom_set.update(phantoms)
def anim_loading(self):
if self.loading > 0:
self.loading_anim = (self.loading_anim + 1) % 8
char = '????????'[self.loading_anim]
html = '''<body id="loader">
<style>
.spinner {
display: inline;
color: var(--redish);
}
</style>
Loading <span class="spinner">%s</span></body>''' % char
self.loader = sublime.Phantom(sublime.Region(len(self.server['remote_path'])), html, sublime.LAYOUT_INLINE)
self.phantom_set.update([self.loader, self.phantom] if self.phantom else [self.loader])
sublime.set_timeout(self.anim_loading, 100)
else:
print('removing anim')
self.phantom_set.update([self.phantom] if self.phantom else [])
def run(self, edit):
print("run phantom")
view = self.view
dirname = os.path.dirname(__file__)
for tp, line in self.get_line():
m=re.search(r'!\[([^\]]*)\]\(([^)]*)\)', line)
if m:
name, file1 = m.group(1), m.group(2)
message = ""
file2 = os.path.join(os.path.dirname(view.file_name()), file1)
# print("%s = %s" % (name, file1))
region = tp
command = ['/usr/bin/python3', os.path.join(dirname, 'bin/imageutil.py'), 'size']
command.append(file2)
out = self.run_command(" ".join(command))
widthstr, heightstr = out.split(',')
# with Image.open(file2) as im:
# print("file: %s with size: %d %d" % (file1, im.width, im.height))
message = '''<body>
<img width="%s" height="%s" src="file://%s"></img>
</body>''' % (widthstr, heightstr, file2)
if len(name) == 0:
name = file1
# phantom = sublime.Phantom(region, messag e, sublime.LAYOUT_BLOCK)
print("message %s" % message)
if not self.displayed:
self.view.add_phantom(name, region, message, sublime.LAYOUT_BLOCK)
else:
self.view.erase_phantoms(name)
# self.phantom_set.update([phantom])
# view.show_popup('<img src="file://c://msys64/home/chenyu/diary/diary/diary8.jpg">')
self.displayed = not self.displayed
def _render(self):
settings = self.view.settings()
enabled = settings.get(OPT_ENABLED, True)
self._clear()
if not enabled:
return
phantoms = []
current_line = self.view.rowcol(self.view.sel()[0].begin())[0]
current_line_char = settings.get(OPT_CURRENT_CHAR, "0")
lines = self.view.lines(self.view.visible_region())
for line in lines:
line_number = self.view.rowcol(line.a)[0]
value = self._value(
line_number, current_line, current_line_char)
phantoms.append(
sublime.Phantom(
line, self._tpl(value, line_number == current_line),
sublime.LAYOUT_INLINE))
self._phantoms.update(phantoms)
self.view.set_viewport_position(
(0, self.view.viewport_position()[1]), False)
sublime.set_timeout(self._clear, settings.get(OPT_CLEAR_TIMEOUT, 1000))
def create_phantom(view: sublime.View, diagnostic: Diagnostic) -> sublime.Phantom:
region = diagnostic.range.to_region(view)
# TODO: hook up hide phantom (if keeping them)
content = create_phantom_html(diagnostic.message)
return sublime.Phantom(
region,
'<p>' + content + '</p>',
sublime.LAYOUT_BELOW,
lambda href: on_phantom_navigate(view, href, region.begin())
)
def build_phantoms(view, errs, formatter):
phantoms = []
show_focus_links = len(errs) > 1
for tbck in errs:
line = tbck['line']
text = tbck['text']
testcase = tbck.get('testcase')
if text == '':
continue
pt = view.text_point(line - 1, 0)
indentation = get_indentation_at(view, pt)
text = formatter.format_text(text, indentation)
if show_focus_links and testcase:
focus_link = (
' <a href="focus:{}">focus test</a>'.format(testcase))
lines = text.split('<br />')
text = '<br />'.join([lines[0] + focus_link] + lines[1:])
phantoms.append(sublime.Phantom(
sublime.Region(pt, view.line(pt).b),
('<body id=inline-error>' + STYLESHEET +
'<div class="error">' +
'<span class="message">' + text + '</span>' +
'</div>' +
'</body>'),
sublime.LAYOUT_BELOW, _on_navigate))
return phantoms
def createPhantom(self, doc, view):
xref_data = self.data[view.window().id()];
loc = sublime.Region(0,0);
return sublime.Phantom(loc, doc, sublime.LAYOUT_BELOW, lambda link: self.processLink(link, self.callers, view));
def rebuild_phantom(self):
html = '''<body id="tree">
<style>
body {
font-size: 12px;
line-height: 16px;
}
.file a, .dir a {
display: block;
padding-left: 4px;
}
.dir a {
padding-top: 1px;
padding-bottom: 2px;
}
.dir a {
text-decoration: none;
}
.file.active {
background-color: color(var(--background) blend(var(--foreground) 80%));
border-radius: 3px;
}
.file span {
font-size: 7px;
}
.file a {
text-decoration: none;
color: var(--foreground);
}
</style>''' + ''.join(self.render_subtree(self.tree, [])) + '</body>'
self.phantom = sublime.Phantom(sublime.Region(0), html, sublime.LAYOUT_BLOCK, on_navigate=self.on_click)
self.phantom_set.update([self.phantom])
def update(self, new_phantoms):
"""Update the list of phantoms that exist in the text buffer with their current location."""
regions = query_phantoms(self.view, [p.id for p in self.phantoms])
for i in range(len(regions)):
self.phantoms[i].region = regions[i]
count = 0
for p in new_phantoms:
if not isinstance(p, Phantom):
# Convert sublime.Phantom to mdpopups.Phantom
p = Phantom(
p.region, p.content, p.layout,
md=False, css=None, on_navigate=p.on_navigate, wrapper_class=None,
template_vars=None, template_env_options=None, nl2br=False
)
new_phantoms[count] = p
try:
# Phantom already exists, copy the id from the current one
idx = self.phantoms.index(p)
p.id = self.phantoms[idx].id
except ValueError:
p.id = add_phantom(
self.view,
self.key,
p.region,
p.content,
p.layout,
p.md,
p.css,
p.on_navigate,
p.wrapper_class,
p.template_vars,
p.template_env_options,
p.nl2br
)
count += 1
for p in self.phantoms:
# if the region is -1, then it's already been deleted, no need to call erase
if p not in new_phantoms and p.region != sublime.Region(-1):
erase_phantom_by_id(self.view, p.id)
self.phantoms = new_phantoms
def update(self, new_phantoms):
"""Update the list of phantoms that exist in the text buffer with their current location."""
regions = query_phantoms(self.view, [p.id for p in self.phantoms])
for i in range(len(regions)):
self.phantoms[i].region = regions[i]
count = 0
for p in new_phantoms:
if not isinstance(p, Phantom):
# Convert sublime.Phantom to mdpopups.Phantom
p = Phantom(
p.region, p.content, p.layout,
md=False, css=None, on_navigate=p.on_navigate, wrapper_class=None,
template_vars=None, template_env_options=None, nl2br=False
)
new_phantoms[count] = p
try:
# Phantom already exists, copy the id from the current one
idx = self.phantoms.index(p)
p.id = self.phantoms[idx].id
except ValueError:
p.id = add_phantom(
self.view,
self.key,
p.region,
p.content,
p.layout,
p.md,
p.css,
p.on_navigate,
p.wrapper_class,
p.template_vars,
p.template_env_options,
p.nl2br
)
count += 1
for p in self.phantoms:
# if the region is -1, then it's already been deleted, no need to call erase
if p not in new_phantoms and p.region != sublime.Region(-1):
erase_phantom_by_id(self.view, p.id)
self.phantoms = new_phantoms
def run(self, edit):
(viewport_x, viewport_y) = self.view.viewport_position()
path = gitPath(self.view.window())
current_path = self.view.file_name()
if current_path is not None and current_path.startswith(path):
remaining_path = current_path[len(path):]
command = ("cd '{0}';git blame --show-email '{1}'").format(path, remaining_path)
output, _ = run_bash_for_output(command)
lines = output.split('\n')
line_count = 0
regions = self.view.lines(sublime.Region(0, self.view.size()))
phantoms = []
last_hash = None
for line in lines:
matches = re.search(r'^([0-9a-z]+).*?\(<(.*?)>', line)
# print(line, ' ', matches)
if matches is not None and line_count < len(regions):
hash = matches.group(1)
email = matches.group(2)
at_position = email.find("@")
if at_position != -1:
email = email[:at_position]
if len(email) > 10:
email = email[:10]
email = "{:*>10}".format(email)
if hash == last_hash:
email = "." * 10
html = "<b>{0}</b>".format(email)
else:
html = "<a href='{0}'>{1}</a>".format(hash, email)
last_hash = hash
r = regions[line_count]
phantom = Phantom(sublime.Region(r.begin(), r.begin()), html, sublime.LAYOUT_INLINE, lambda link: self.click(link) )
phantoms.append(phantom)
line_count = line_count + 1
global phantomSet
phantomSet = PhantomSet(self.view, 'git_blame')
phantomSet.update(phantoms)
global viewIdToPhantomSet
viewIdToPhantomSet[self.view.id()] = phantomSet
self.view.set_viewport_position((0, viewport_y))
def update(self, new_phantoms):
"""Update the list of phantoms that exist in the text buffer with their current location."""
regions = query_phantoms(self.view, [p.id for p in self.phantoms])
for i in range(len(regions)):
self.phantoms[i].region = regions[i]
count = 0
for p in new_phantoms:
if not isinstance(p, Phantom):
# Convert sublime.Phantom to mdpopups.Phantom
p = Phantom(
p.region, p.content, p.layout,
md=False, css=None, on_navigate=p.on_navigate, wrapper_class=None,
template_vars=None, template_env_options=None, nl2br=False
)
new_phantoms[count] = p
try:
# Phantom already exists, copy the id from the current one
idx = self.phantoms.index(p)
p.id = self.phantoms[idx].id
except ValueError:
p.id = add_phantom(
self.view,
self.key,
p.region,
p.content,
p.layout,
p.md,
p.css,
p.on_navigate,
p.wrapper_class,
p.template_vars,
p.template_env_options,
p.nl2br
)
count += 1
for p in self.phantoms:
# if the region is -1, then it's already been deleted, no need to call erase
if p not in new_phantoms and p.region != sublime.Region(-1):
erase_phantom_by_id(self.view, p.id)
self.phantoms = new_phantoms