X-Git-Url: http://nitlanguage.org diff --git a/src/highlight.nit b/src/highlight.nit index dd9ceff..863f811 100644 --- a/src/highlight.nit +++ b/src/highlight.nit @@ -43,18 +43,73 @@ class HighlightVisitor # The last line to generate, null if finish at the last line var last_line: nullable Int = null is writable + # When highlighting a node, show its messages (errors, warnings), if any. + # + # default: true + var show_messages = true is writable + + # When highlighting a node, attach a full popupable infobox, if any. + # + # If `false`, only a simple `title` tooltip is used. + # + # default: true + var show_infobox = true is writable + init do html.add_class("nitcode") end + # When highlighting a node, also consider the loose tokens around it. + # + # Loose tokens are tokens discarded from the AST but attached before + # or after some non-loose tokens. See `Token::is_loose`. + # + # When this flag is set to `true`, the loose tokens that are before the + # first token and after the last token are also highlighted. + # + # Default: false. + var include_loose_tokens = false is writable + + # When highlighting a node, the first and the last lines are fully included. + # + # If the highlighted node starts (or ends) in the middle of a line, + # this flags forces the whole line to be highlighted. + # + # Default: false + var include_whole_lines = false is writable + # The entry-point of the highlighting. # Will fill `html` with the generated HTML content. fun enter_visit(n: ANode) do n.parentize_tokens - var s = n.location.file - htmlize(s.first_token.as(not null), s.last_token.as(not null)) + + var f + var l + + if n isa Token then + f = n + l = n + else + assert n isa Prod + f = n.first_token + if f == null then return + l = n.last_token + if l == null then return + end + + if include_loose_tokens then + if f.prev_looses.not_empty then f = f.prev_looses.first + if l.next_looses.not_empty then l = l.next_looses.last + end + + if include_whole_lines then + f = f.first_real_token_in_line + l = l.last_real_token_in_line + end + + htmlize(f, l) end private fun full_tag(anode: ANode, hv: HighlightVisitor): nullable HTMLTag @@ -65,14 +120,16 @@ class HighlightVisitor if infobox == null and anode isa Token then var pa = anode.parent if pa != null then - var c = anode - if c isa TId or c isa TClassid or c isa TAttrid or c isa TokenLiteral or c isa TokenOperator or c isa TComment and pa isa ADoc then - infobox = pa.decorate_tag(hv, tag, anode) - end + infobox = pa.decorate_tag(hv, tag, anode) end end + if infobox != null and not show_infobox then + tag.attr("title", infobox.title) + tag.classes.add "titled" + infobox = null + end var messages = anode.location.messages - if messages != null then + if messages != null and show_messages then tag.css("border-bottom", "solid 2px red") if infobox == null then infobox = new HInfoBox(hv, "Messages") @@ -193,6 +250,7 @@ class HighlightVisitor do return """ .nitcode a { color: inherit; cursor:pointer; } +.nitcode .titled:hover { text-decoration: underline; } /* underline titles */ .nitcode .popupable:hover { text-decoration: underline; cursor:help; } /* underline titles */ .nitcode .foldable { display: block } /* for block productions*/ .nitcode .line{ display: block } /* for lines */ @@ -352,7 +410,7 @@ redef class MModule # The module HTML page fun href: String do - return name + ".html" + return c_name + ".html" end redef fun linkto do return linkto_text(name) @@ -644,6 +702,22 @@ redef class ANode fun infobox(v: HighlightVisitor): nullable HInfoBox do return null end +redef class AQclassid + redef fun decorate_tag(v, res, token) + do + if token != n_id then return null + return parent.decorate_tag(v, res, token) + end +end + +redef class AQid + redef fun decorate_tag(v, res, token) + do + if token != n_id then return null + return parent.decorate_tag(v, res, token) + end +end + redef class AStdClassdef redef fun make_tag(v) do @@ -714,8 +788,6 @@ redef class TokenOperator redef fun make_tag(v) do var res = super - var p = parent - if p != null then p.decorate_tag(v, res, self) res.add_class("nc_o") return res end @@ -724,6 +796,7 @@ end redef class AVarFormExpr redef fun decorate_tag(v, res, token) do + if token != n_id then return null var variable = self.variable if variable == null then return null res.add_class("nc_v") @@ -734,6 +807,7 @@ end redef class AVardeclExpr redef fun decorate_tag(v, res, token) do + if token != n_id then return null var variable = self.variable if variable == null then return null res.add_class("nc_v") @@ -741,7 +815,7 @@ redef class AVardeclExpr end end -redef class AForExpr +redef class AForGroup redef fun decorate_tag(v, res, token) do if not token isa TId then return null @@ -757,6 +831,7 @@ end redef class AParam redef fun decorate_tag(v, res, token) do + if token != n_id then return null var mp = mparameter if mp == null then return null var variable = self.variable @@ -769,6 +844,7 @@ end redef class AAssertExpr redef fun decorate_tag(v, res, token) do + if not token isa TId then return null res.add_class("nc_ast") return null end @@ -777,6 +853,7 @@ end redef class ALabel redef fun decorate_tag(v, res, token) do + if not token isa TId then return null res.add_class("nc_la") return null end @@ -820,6 +897,7 @@ end redef class AModuledecl redef fun decorate_tag(v, res, token) do + if not token isa TId then return null res.add_class("nc_def") res.add_class("nc_m") var p = parent @@ -833,6 +911,7 @@ end redef class AStdImport redef fun decorate_tag(v, res, token) do + if not token isa TId then return null res.add_class("nc_m") var mm = mmodule if mm == null then return null @@ -842,6 +921,7 @@ end redef class AAttrPropdef redef fun decorate_tag(v, res, token) do + if not token isa TId then return null res.add_class("nc_def") var mpd: nullable MPropDef mpd = mreadpropdef @@ -855,8 +935,6 @@ redef class TId redef fun make_tag(v) do var res = super - var p = parent - if p != null then p.decorate_tag(v, res, self) res.add_class("nc_i") return res end @@ -886,8 +964,6 @@ redef class TAttrid redef fun make_tag(v) do var res = super - var p = parent - if p != null then p.decorate_tag(v, res, self) res.add_class("nc_a") return res end @@ -895,6 +971,7 @@ end redef class AAttrFormExpr redef fun decorate_tag(v, res, token) do + if not token isa TAttrid then return null var p = mproperty if p == null then return null return p.intro.infobox(v) @@ -904,8 +981,6 @@ redef class TClassid redef fun make_tag(v) do var res = super - var p = parent - if p != null then p.decorate_tag(v, res, self) res.add_class("nc_t") return res end @@ -913,6 +988,7 @@ end redef class AType redef fun decorate_tag(v, res, token) do + if not token isa TClassid then return null var mt = mtype if mt == null then return null mt = mt.undecorate @@ -925,6 +1001,7 @@ end redef class AFormaldef redef fun decorate_tag(v, res, token) do + if not token isa TClassid then return null res.add_class("nc_vt") if mtype == null then return null return mtype.infobox(v) @@ -933,6 +1010,7 @@ end redef class ATypePropdef redef fun decorate_tag(v, res, token) do + if not token isa TClassid then return null res.add_class("nc_def") var md = mpropdef if md == null then return null @@ -943,7 +1021,7 @@ redef class TComment redef fun make_tag(v) do var res = super - if not parent isa ADoc then + if is_loose then res.add_class("nc_c") end return res @@ -962,8 +1040,6 @@ redef class TokenLiteral do var res = super res.add_class("nc_l") - var p = parent - if p != null then p.decorate_tag(v, res, self) return res end end @@ -981,7 +1057,7 @@ redef class AStringFormExpr # Workaround to tag strings res.classes.remove("nc_l") res.add_class("nc_s") - return null + return super end end redef class AExpr