33import sublime
44
55import collections
6+ import functools
67import html
78import itertools
89import os
2728# attached detailed diagnostic information, child notes, etc.
2829# - `path`: Absolute path to the file.
2930# - `text`: The raw text of the message without any minihtml markup.
30- # - `phantom_text `: The string used for showing phantoms that includes the
31+ # - `minihtml_text `: The string used for showing phantoms that includes the
3132# minihtml markup.
3233# - `output_panel_region`: Optional Sublime Region object that indicates the
3334# region in the build output panel that corresponds with this message.
3738LINK_PATTERN = r'(https?://[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-zA-Z]{2,6}\b[-a-zA-Z0-9@:%_+.~#?&/=]*)'
3839
3940
40- PHANTOM_TEMPLATE = """
41+ CSS_TEMPLATE = """
42+ <style>
43+ span {{
44+ font-family: monospace;
45+ }}
46+ .rust-error {{
47+ color: {error_color};
48+ }}
49+ .rust-warning {{
50+ color: {warning_color};
51+ }}
52+ .rust-note {{
53+ color: {note_color};
54+ }}
55+ .rust-help {{
56+ color: {help_color};
57+ }}
58+ .rust-link {{
59+ background-color: var(--background);
60+ color: var(--bluish);
61+ text-decoration: none;
62+ border-radius: 0.5rem;
63+ padding: 0.1rem 0.3rem;
64+ border: 1px solid var(--bluish);
65+ }}
66+ .rust-links {{
67+ margin: 0.4rem 0rem;
68+ }}
69+ a {{
70+ text-decoration: inherit;
71+ padding: 0.35rem 0.5rem 0.45rem 0.5rem;
72+ position: relative;
73+ font-weight: bold;
74+ }}
75+ {extra_css}
76+ </style>
4177<body id="rust-message">
42- <style>
43- span {{
44- font-family: monospace;
45- }}
46- .rust-error {{
47- color: {error_color};
48- }}
49- .rust-warning {{
50- color: {warning_color};
51- }}
52- .rust-note {{
53- color: {note_color};
54- }}
55- .rust-help {{
56- color: {help_color};
57- }}
58- .rust-link {{
59- background-color: var(--background);
60- color: var(--bluish);
61- text-decoration: none;
62- border-radius: 0.5rem;
63- padding: 0.1rem 0.3rem;
64- border: 1px solid var(--bluish);
65- }}
66- .rust-links {{
67- margin: 0.4rem 0rem;
68- }}
69- a {{
70- text-decoration: inherit;
71- padding: 0.35rem 0.5rem 0.45rem 0.5rem;
72- position: relative;
73- font-weight: bold;
74- }}
75- </style>
7678{content}
7779</body>
7880"""
7981
82+ POPUP_CSS = """
83+ body {
84+ margin: 0.25em;
85+ }
86+ """
87+
8088
8189def clear_messages (window ):
8290 WINDOW_MESSAGES .pop (window .id (), None )
@@ -88,7 +96,7 @@ def clear_messages(window):
8896 view .erase_regions ('rust-help' )
8997
9098
91- def add_message (window , path , span , level , is_main , text , markup_text , msg_cb ):
99+ def add_message (window , path , span , level , is_main , text , minihtml_text , msg_cb ):
92100 """Add a message to be displayed.
93101
94102 :param window: The Sublime window.
@@ -100,7 +108,7 @@ def add_message(window, path, span, level, is_main, text, markup_text, msg_cb):
100108 :param is_main: If True, this is a top-level message. False is used for
101109 attached detailed diagnostic information, child notes, etc.
102110 :param text: The raw text of the message without any minihtml markup.
103- :param markup_text : The message to display with minihtml markup.
111+ :param minihtml_text : The message to display with minihtml markup.
104112 :param msg_cb: Callback that will be given the message. May be None.
105113 """
106114 if 'macros>' in path :
@@ -119,30 +127,21 @@ def add_message(window, path, span, level, is_main, text, markup_text, msg_cb):
119127 }
120128 messages = messages_by_path .setdefault (path , [])
121129
122- if markup_text :
123- phantom_text = PHANTOM_TEMPLATE .format (content = markup_text ,
124- error_color = util .get_setting ('rust_syntax_error_color' , 'var(--redish)' ),
125- warning_color = util .get_setting ('rust_syntax_warning_color' , 'var(--yellowish)' ),
126- note_color = util .get_setting ('rust_syntax_note_color' , 'var(--greenish)' ),
127- help_color = util .get_setting ('rust_syntax_help_color' , 'var(--bluish)' ),
128- )
129- else :
130- phantom_text = None
131130 to_add = {
132131 'path' : path ,
133132 'level' : level ,
134133 'span' : span ,
135134 'is_main' : is_main ,
136135 'text' : text ,
137- 'phantom_text ' : phantom_text ,
136+ 'minihtml_text ' : minihtml_text ,
138137 }
139138 if _is_duplicate (to_add , messages ):
140139 # Don't add duplicates.
141140 return
142141 messages .append (to_add )
143142 view = window .find_open_file (path )
144143 if view :
145- _show_phantom (view , level , span , phantom_text )
144+ _show_phantom (view , level , span , minihtml_text )
146145 if msg_cb :
147146 msg_cb (to_add )
148147
@@ -238,11 +237,75 @@ def check_in(region):
238237 sublime .DRAW_NO_FILL | sublime .DRAW_EMPTY )
239238
240239
241- def _show_phantom (view , level , span , message ):
242- if util .get_setting ('rust_phantom_style' , 'normal' ) == 'none' :
240+ def _wrap_css (content , extra_css = '' ):
241+ """Takes the given minihtml content and places it inside a <body> with the
242+ appropriate CSS."""
243+ return CSS_TEMPLATE .format (content = content ,
244+ error_color = util .get_setting ('rust_syntax_error_color' , 'var(--redish)' ),
245+ warning_color = util .get_setting ('rust_syntax_warning_color' , 'var(--yellowish)' ),
246+ note_color = util .get_setting ('rust_syntax_note_color' , 'var(--greenish)' ),
247+ help_color = util .get_setting ('rust_syntax_help_color' , 'var(--bluish)' ),
248+ extra_css = extra_css ,
249+ )
250+
251+
252+ def message_popup (view , point , hover_zone ):
253+ """Displays a popup if there is a message at the given point."""
254+ paths = WINDOW_MESSAGES .get (view .window ().id (), {}).get ('paths' , {})
255+ msgs = paths .get (view .file_name (), [])
256+
257+ if hover_zone == sublime .HOVER_GUTTER :
258+ # Collect all messages on this line.
259+ row = view .rowcol (point )[0 ]
260+
261+ def filter_row (msg ):
262+ span = msg ['span' ]
263+ if span :
264+ return row >= span [0 ][0 ] and row <= span [1 ][0 ]
265+ else :
266+ last_row = view .rowcol (view .size ())[0 ]
267+ return row == last_row
268+
269+ msgs = filter (filter_row , msgs )
270+ else :
271+ # Collect all messages covering this point.
272+ def filter_point (msg ):
273+ span = msg ['span' ]
274+ if span :
275+ start_pt = view .text_point (* span [0 ])
276+ end_pt = view .text_point (* span [1 ])
277+ return point >= start_pt and point <= end_pt
278+ else :
279+ return point == view .size ()
280+
281+ msgs = filter (filter_point , msgs )
282+
283+ if msgs :
284+ to_show = '\n ' .join (msg ['minihtml_text' ] for msg in msgs )
285+ minihtml = _wrap_css (to_show , extra_css = POPUP_CSS )
286+ on_nav = functools .partial (_click_handler , view , hide_popup = True )
287+ max_width = view .em_width () * 79
288+ view .show_popup (minihtml , sublime .COOPERATE_WITH_AUTO_COMPLETE ,
289+ point , max_width = max_width , on_navigate = on_nav )
290+
291+
292+ def _click_handler (view , url , hide_popup = False ):
293+ if url == 'hide' :
294+ clear_messages (view .window ())
295+ if hide_popup :
296+ view .hide_popup ()
297+ elif url .startswith ('file:///' ):
298+ view .window ().open_file (url [8 :], sublime .ENCODED_POSITION )
299+ else :
300+ webbrowser .open_new (url )
301+
302+
303+ def _show_phantom (view , level , span , minihtml_text ):
304+ if util .get_setting ('rust_phantom_style' , 'normal' ) != 'normal' :
243305 return
244- if not message :
306+ if not minihtml_text :
245307 return
308+
246309 region = _span_to_region (view , span )
247310 # For some reason if you have a multi-line region, the phantom is only
248311 # displayed under the first line. I think it makes more sense for the
@@ -256,20 +319,12 @@ def _show_phantom(view, level, span, message):
256319 region .end ()
257320 )
258321
259- def click_handler (url ):
260- if url == 'hide' :
261- clear_messages (view .window ())
262- elif url .startswith ('file:///' ):
263- view .window ().open_file (url [8 :], sublime .ENCODED_POSITION )
264- else :
265- webbrowser .open_new (url )
266-
267322 _sublime_add_phantom (
268323 view ,
269324 'rust-syntax-phantom' , region ,
270- message ,
325+ _wrap_css ( minihtml_text ) ,
271326 sublime .LAYOUT_BLOCK ,
272- click_handler
327+ functools . partial ( _click_handler , view )
273328 )
274329
275330
@@ -437,7 +492,7 @@ def _show_messages_for_view(view, messages):
437492 _show_phantom (view ,
438493 message ['level' ],
439494 message ['span' ],
440- message ['phantom_text ' ])
495+ message ['minihtml_text ' ])
441496 _draw_region_highlights (view , messages )
442497
443498
0 commit comments