Skip to content

Commit 3c835a2

Browse files
committed
Merge pull request #13 from hrnr/master
Added Error panel.
2 parents 232c782 + 21c9056 commit 3c835a2

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

Completion.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
COMPLETION_ERROR_MSG = "[Ycmd][Completion] Error {}"
2323
COMPLETION_NOT_AVAILABLE_MSG = "[Ycmd] No completion available"
2424
ERROR_MESSAGE_TEMPLATE = "[{kind}] {text}"
25+
PANEL_ERROR_MESSAGE_TEMPLATE = "{:<5} {}"
2526
GET_PATH_ERROR_MSG = "[Ycmd][Path] Failed to replace '{}' -> '{}'"
2627
NO_HMAC_MESSAGE = "[Ycmd] You should generate HMAC throug the menu before using plugin"
2728
NOTIFY_ERROR_MSG = "[Ycmd][Notify] Error {}"
@@ -223,6 +224,9 @@ class YcmdCompletionEventListener(sublime_plugin.EventListener):
223224
view_line = dict()
224225

225226
def on_selection_modified_async(self, view):
227+
if view.id() == ERROR_PANEL.id():
228+
ERROR_PANEL.show_code_for_error()
229+
return
226230
if lang(view) is None or view.is_scratch():
227231
return
228232
self.update_statusbar(view)
@@ -250,6 +254,11 @@ def on_pre_close(self, view):
250254
if view_id in self.view_cache:
251255
del self.view_cache[view_id]
252256

257+
def on_activated_async(self, view):
258+
if lang(view) is None or view.is_scratch():
259+
return
260+
ERROR_PANEL.update(self.view_cache)
261+
253262
def on_query_completions(self, view, prefix, locations):
254263
'''Sublime Text autocompletion event handler'''
255264
filetype = lang(view)
@@ -306,6 +315,7 @@ def _on_errors(self, data):
306315
[_ for _ in data
307316
if get_file_path(_['location']['filepath']) == filepath])
308317
self.update_statusbar(active_view(), force=True)
318+
ERROR_PANEL.update(self.view_cache)
309319

310320
def update_statusbar(self, view, force=False):
311321
row, col = get_selected_pos(view)
@@ -390,3 +400,91 @@ def _completer_cb(self, data, command):
390400
sublime.ENCODED_POSITION)
391401
else:
392402
print_status("[Ycmd][{}]: {}".format(command, jsonResp.get('message', '')))
403+
404+
class YcmdErrorPanelRefresh(sublime_plugin.TextCommand):
405+
def run(self, edit, data):
406+
self.view.erase(edit, sublime.Region(0, self.view.size()))
407+
self.view.insert(edit, 0, data)
408+
409+
class YcmdErrorPanel(object):
410+
# view of this error panel
411+
view = None
412+
# text currently in panel
413+
text = ""
414+
# view with code, for with panel show errors
415+
code_view = None
416+
lines_to_errors = []
417+
418+
def id(self):
419+
if self.view != None:
420+
return self.view.id()
421+
else:
422+
return None
423+
424+
def update_async(self, view_cache, view=None):
425+
t = Thread(None, self.update, 'PanelUpdateAsync', [view_cache, view])
426+
t.daemon = True
427+
t.start()
428+
429+
def update(self, view_cache, view=None):
430+
if view == None:
431+
view = active_view()
432+
433+
messages = []
434+
self.lines_to_errors = []
435+
lines = view_cache.get(view.id(), {})
436+
for line_num, line_regions in sorted(lines.items()):
437+
for region, msg in line_regions.items():
438+
messages.append(PANEL_ERROR_MESSAGE_TEMPLATE.format(str(line_num)+':', msg))
439+
self.lines_to_errors.append(region)
440+
self.text = '\n'.join(messages)
441+
self.code_view = view
442+
if self.is_visible():
443+
self._refresh()
444+
445+
def is_visible(self):
446+
return self.view != None and self.view.window() != None
447+
448+
def _refresh(self):
449+
self.view.set_read_only(False)
450+
self.view.set_scratch(True)
451+
self.view.run_command("ycmd_error_panel_refresh", {"data": self.text})
452+
self.view.set_read_only(True)
453+
454+
def show_code_for_error(self):
455+
if not self.is_visible() or self.code_view == None:
456+
return
457+
458+
# get rid of false positive (non-user interaction)
459+
last_command_name, _, _ = self.view.command_history(0, False)
460+
if last_command_name == 'ycmd_error_panel_refresh':
461+
return
462+
463+
row, _ = get_selected_pos(self.view)
464+
if row < len(self.lines_to_errors):
465+
region = self.lines_to_errors[row]
466+
# we must create sublime region, because cached region is just tuple
467+
sublime_region = sublime.Region(region[0], region[1])
468+
self.code_view.show_at_center(sublime_region)
469+
470+
def open(self):
471+
window = sublime.active_window()
472+
if not self.is_visible():
473+
self.view = window.create_output_panel("clang-errors")
474+
syntax_file = "Packages/YcmdCompletion/ErrorPanel.tmLanguage"
475+
self.view.set_syntax_file(syntax_file)
476+
self._refresh()
477+
window.run_command("show_panel", {"panel": "output.clang-errors"})
478+
479+
def close(self):
480+
sublime.active_window().run_command("hide_panel", {"panel": "output.clang-errors"})
481+
482+
ERROR_PANEL = YcmdErrorPanel()
483+
484+
class YcmdErrorPanelShow(sublime_plugin.WindowCommand):
485+
def run(self):
486+
ERROR_PANEL.open()
487+
488+
class YcmdErrorPanelHide(sublime_plugin.WindowCommand):
489+
def run(self):
490+
ERROR_PANEL.close()

Default.sublime-commands

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,13 @@
3535
"caption": "Ycmd: Get Parent For Current Statement",
3636
"command": "ycmd_execute_completer_func",
3737
"args": {"command": "GetParent"}
38+
},
39+
{
40+
"caption": "Ycmd: Show Error Panel",
41+
"command": "ycmd_error_panel_show"
42+
},
43+
{
44+
"caption": "Ycmd: Hide Error Panel",
45+
"command": "ycmd_error_panel_hide"
3846
}
3947
]

ErrorPanel.tmLanguage

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>fileTypes</key>
6+
<array>
7+
</array>
8+
<key>name</key>
9+
<string>YcmdErrorPanel</string>
10+
<key>patterns</key>
11+
<array>
12+
<dict>
13+
<key>comment</key>
14+
<string>Warnings</string>
15+
<key>match</key>
16+
<string>^.* \[WARNING\].*$</string>
17+
<key>name</key>
18+
<string>string.quoted.double.c</string>
19+
</dict>
20+
<dict>
21+
<key>comment</key>
22+
<string>Errors</string>
23+
<key>match</key>
24+
<string>^.* \[ERROR\].*$</string>
25+
<key>name</key>
26+
<string>keyword.control.c</string>
27+
</dict>
28+
</array>
29+
<key>scopeName</key>
30+
<string>text.ycmdcompletion</string>
31+
<key>uuid</key>
32+
<string>1a8564ce-f89e-4e0d-8f14-40c5d2a202e5</string>
33+
</dict>
34+
</plist>

0 commit comments

Comments
 (0)