266 Markup.Elements(Markup.NOTATION, Markup.EXPRESSION, Markup.LANGUAGE, Markup.ML_TYPING, |
266 Markup.Elements(Markup.NOTATION, Markup.EXPRESSION, Markup.LANGUAGE, Markup.ML_TYPING, |
267 Markup.MARKDOWN_PARAGRAPH, Markup.MARKDOWN_ITEM, Markup.Markdown_List.name, Markup.ENTITY, |
267 Markup.MARKDOWN_PARAGRAPH, Markup.MARKDOWN_ITEM, Markup.Markdown_List.name, Markup.ENTITY, |
268 Markup.COMMAND_SPAN) |
268 Markup.COMMAND_SPAN) |
269 |
269 |
270 val tooltip_elements: Markup.Elements = |
270 val tooltip_elements: Markup.Elements = |
271 Markup.Elements(Markup.LANGUAGE, Markup.NOTATION, Markup.EXPRESSION, Markup.TIMING, |
271 Markup.Elements(Markup.LANGUAGE, Markup.NOTATION, Markup.EXPRESSION, |
272 Markup.ENTITY, Markup.SORTING, Markup.TYPING, Markup.CLASS_PARAMETER, Markup.ML_TYPING, |
272 Markup.ENTITY, Markup.SORTING, Markup.TYPING, Markup.CLASS_PARAMETER, Markup.ML_TYPING, |
273 Markup.ML_BREAKPOINT, Markup.PATH, Markup.DOC, Markup.URL, Markup.COMMAND_SPAN, |
273 Markup.ML_BREAKPOINT, Markup.PATH, Markup.DOC, Markup.URL, Markup.COMMAND_SPAN, |
274 Markup.MARKDOWN_PARAGRAPH, Markup.MARKDOWN_ITEM, Markup.Markdown_List.name) ++ |
274 Markup.MARKDOWN_PARAGRAPH, Markup.MARKDOWN_ITEM, Markup.Markdown_List.name) ++ |
275 Markup.Elements(tooltip_description.keySet) |
275 Markup.Elements(tooltip_description.keySet) |
276 |
276 |
619 |
619 |
620 def timing_threshold: Double = options.real("editor_timing_threshold") |
620 def timing_threshold: Double = options.real("editor_timing_threshold") |
621 |
621 |
622 private sealed case class Tooltip_Info( |
622 private sealed case class Tooltip_Info( |
623 range: Text.Range, |
623 range: Text.Range, |
624 timing: Timing = Timing.zero, |
|
625 messages: List[(Long, XML.Elem)] = Nil, |
624 messages: List[(Long, XML.Elem)] = Nil, |
626 rev_infos: List[(Boolean, Int, XML.Elem)] = Nil |
625 rev_infos: List[(Boolean, Int, XML.Elem)] = Nil |
627 ) { |
626 ) { |
628 def add_timing(t: Timing): Tooltip_Info = copy(timing = timing + t) |
|
629 def add_message(r0: Text.Range, serial: Long, msg: XML.Elem): Tooltip_Info = { |
627 def add_message(r0: Text.Range, serial: Long, msg: XML.Elem): Tooltip_Info = { |
630 val r = snapshot.convert(r0) |
628 val r = snapshot.convert(r0) |
631 if (range == r) copy(messages = (serial -> msg) :: messages) |
629 if (range == r) copy(messages = (serial -> msg) :: messages) |
632 else copy(range = r, messages = List(serial -> msg)) |
630 else copy(range = r, messages = List(serial -> msg)) |
633 } |
631 } |
641 else copy (range = r, rev_infos = List(entry)) |
639 else copy (range = r, rev_infos = List(entry)) |
642 } |
640 } |
643 def add_info_text(r0: Text.Range, text: String, ord: Int = 0): Tooltip_Info = |
641 def add_info_text(r0: Text.Range, text: String, ord: Int = 0): Tooltip_Info = |
644 add_info(r0, Pretty.string(text), ord = ord) |
642 add_info(r0, Pretty.string(text), ord = ord) |
645 |
643 |
646 def timing_info(elem: XML.Elem): Option[XML.Elem] = |
|
647 if (elem.markup.name == Markup.TIMING) { |
|
648 if (timing.is_relevant && timing.elapsed.seconds >= timing_threshold) { |
|
649 Some(Pretty.string(timing.message)) |
|
650 } |
|
651 else None |
|
652 } |
|
653 else Some(elem) |
|
654 def infos(important: Boolean = true): List[XML.Elem] = |
644 def infos(important: Boolean = true): List[XML.Elem] = |
655 for { |
645 for ((imp, _, elem) <- rev_infos.reverse.sortBy(_._2) if imp == important) yield elem |
656 (is_important, _, elem) <- rev_infos.reverse.sortBy(_._2) if is_important == important |
|
657 elem1 <- timing_info(elem) |
|
658 } yield elem1 |
|
659 } |
646 } |
660 |
647 |
661 def perhaps_append_file(node_name: Document.Node.Name, name: String): String = |
648 def perhaps_append_file(node_name: Document.Node.Name, name: String): String = |
662 if (Path.is_valid(name)) session.resources.append_path(node_name.master_dir, Path.explode(name)) |
649 if (Path.is_valid(name)) session.resources.append_path(node_name.master_dir, Path.explode(name)) |
663 else name |
650 else name |
664 |
651 |
665 def tooltips(elements: Markup.Elements, range: Text.Range): Option[Text.Info[List[XML.Elem]]] = { |
652 def tooltips(elements: Markup.Elements, range: Text.Range): Option[Text.Info[List[XML.Elem]]] = { |
666 val results = |
653 val results = |
667 snapshot.cumulate[Tooltip_Info](range, Tooltip_Info(range), elements, command_states => |
654 snapshot.cumulate[Tooltip_Info](range, Tooltip_Info(range), elements, command_states => |
668 { |
655 { |
669 case (info, Text.Info(_, XML.Elem(Markup.Timing(t), _))) => Some(info.add_timing(t)) |
|
670 |
|
671 case (info, Text.Info(r0, msg @ XML.Elem(Markup.Bad(i), body))) |
656 case (info, Text.Info(r0, msg @ XML.Elem(Markup.Bad(i), body))) |
672 if body.nonEmpty => Some(info.add_message(r0, i, msg)) |
657 if body.nonEmpty => Some(info.add_message(r0, i, msg)) |
673 |
658 |
674 case (info, Text.Info(r0, XML.Elem(Markup(name, props), _))) |
659 case (info, Text.Info(r0, XML.Elem(Markup(name, props), _))) |
675 if Rendering.tooltip_message_elements(name) => |
660 if Rendering.tooltip_message_elements(name) => |
678 |
663 |
679 case (info, Text.Info(r0, XML.Elem(Markup.Entity(kind, name), _))) |
664 case (info, Text.Info(r0, XML.Elem(Markup.Entity(kind, name), _))) |
680 if kind != "" && kind != Markup.ML_DEF => |
665 if kind != "" && kind != Markup.ML_DEF => |
681 val txt = Rendering.gui_name(name, kind = kind) |
666 val txt = Rendering.gui_name(name, kind = kind) |
682 val info1 = info.add_info_text(r0, txt, ord = 2) |
667 val info1 = info.add_info_text(r0, txt, ord = 2) |
683 Some(if (kind == Markup.COMMAND) info1.add_info(r0, XML.elem(Markup.TIMING)) else info1) |
668 val info2 = |
|
669 if (kind == Markup.COMMAND) { |
|
670 val timing = Timing.merge(command_states.iterator.map(_.timing)) |
|
671 if (timing.is_relevant && timing.elapsed.seconds >= timing_threshold) { |
|
672 info1.add_info(r0, Pretty.string(timing.message)) |
|
673 } |
|
674 else info1 |
|
675 } |
|
676 else info1 |
|
677 Some(info2) |
684 |
678 |
685 case (info, Text.Info(r0, XML.Elem(Markup.Path(name), _))) => |
679 case (info, Text.Info(r0, XML.Elem(Markup.Path(name), _))) => |
686 val file = perhaps_append_file(snapshot.node_name, name) |
680 val file = perhaps_append_file(snapshot.node_name, name) |
687 val info1 = |
681 val info1 = |
688 if (name == file) info |
682 if (name == file) info |