--- a/src/Tools/jEdit/src/isabelle_rendering.scala Fri Sep 14 12:46:33 2012 +0200
+++ b/src/Tools/jEdit/src/isabelle_rendering.scala Fri Sep 14 13:52:16 2012 +0200
@@ -20,326 +20,22 @@
object Isabelle_Rendering
{
- /* physical rendering */
+ def apply(snapshot: Document.Snapshot, options: Options): Isabelle_Rendering =
+ new Isabelle_Rendering(snapshot, options)
- def color_value(s: String): Color = Color_Value(Isabelle.options.value.string(s))
+
+ /* physical rendering */
private val writeln_pri = 1
private val warning_pri = 2
private val legacy_pri = 3
private val error_pri = 4
-
- /* command overview */
-
- def overview_color(snapshot: Document.Snapshot, range: Text.Range): Option[Color] =
- {
- if (snapshot.is_outdated) None
- else {
- val results =
- snapshot.cumulate_markup[(Protocol.Status, Int)](
- range, (Protocol.Status.init, 0),
- Some(Protocol.command_status_markup + Isabelle_Markup.WARNING + Isabelle_Markup.ERROR),
- {
- case ((status, pri), Text.Info(_, XML.Elem(markup, _))) =>
- if (markup.name == Isabelle_Markup.WARNING) (status, pri max warning_pri)
- else if (markup.name == Isabelle_Markup.ERROR) (status, pri max error_pri)
- else (Protocol.command_status(status, markup), pri)
- })
- if (results.isEmpty) None
- else {
- val (status, pri) =
- ((Protocol.Status.init, 0) /: results) {
- case ((s1, p1), Text.Info(_, (s2, p2))) => (s1 + s2, p1 max p2) }
-
- if (pri == warning_pri) Some(color_value("warning_color"))
- else if (pri == error_pri) Some(color_value("error_color"))
- else if (status.is_unprocessed) Some(color_value("unprocessed_color"))
- else if (status.is_running) Some(color_value("running_color"))
- else if (status.is_failed) Some(color_value("error_color"))
- else None
- }
- }
- }
-
-
- /* markup selectors */
-
- private val subexp_include =
- Set(Isabelle_Markup.SORT, Isabelle_Markup.TYP, Isabelle_Markup.TERM, Isabelle_Markup.PROP,
- Isabelle_Markup.ML_TYPING, Isabelle_Markup.TOKEN_RANGE, Isabelle_Markup.ENTITY,
- Isabelle_Markup.PATH, Isabelle_Markup.TYPING, Isabelle_Markup.FREE, Isabelle_Markup.SKOLEM,
- Isabelle_Markup.BOUND, Isabelle_Markup.VAR, Isabelle_Markup.TFREE, Isabelle_Markup.TVAR,
- Isabelle_Markup.ML_SOURCE, Isabelle_Markup.DOCUMENT_SOURCE)
-
- def subexp(snapshot: Document.Snapshot, range: Text.Range): Option[Text.Info[Color]] =
- {
- snapshot.select_markup(range, Some(subexp_include),
- {
- case Text.Info(info_range, XML.Elem(Markup(name, _), _)) if subexp_include(name) =>
- Text.Info(snapshot.convert(info_range), color_value("subexp_color"))
- }) match { case Text.Info(_, info) #:: _ => Some(info) case _ => None }
- }
-
-
- private val hyperlink_include = Set(Isabelle_Markup.ENTITY, Isabelle_Markup.PATH)
-
- def hyperlink(snapshot: Document.Snapshot, range: Text.Range): Option[Text.Info[Hyperlink]] =
- {
- snapshot.cumulate_markup[List[Text.Info[Hyperlink]]](range, Nil, Some(hyperlink_include),
- {
- case (links, Text.Info(info_range, XML.Elem(Isabelle_Markup.Path(name), _)))
- if Path.is_ok(name) =>
- val jedit_file = Isabelle.thy_load.append(snapshot.node_name.dir, Path.explode(name))
- Text.Info(snapshot.convert(info_range), Hyperlink(jedit_file, 0, 0)) :: links
-
- case (links, Text.Info(info_range, XML.Elem(Markup(Isabelle_Markup.ENTITY, props), _)))
- if (props.find(
- { case (Markup.KIND, Isabelle_Markup.ML_OPEN) => true
- case (Markup.KIND, Isabelle_Markup.ML_STRUCT) => true
- case _ => false }).isEmpty) =>
-
- props match {
- case Position.Line_File(line, name) if Path.is_ok(name) =>
- Isabelle_System.source_file(Path.explode(name)) match {
- case Some(path) =>
- val jedit_file = Isabelle_System.platform_path(path)
- Text.Info(snapshot.convert(info_range), Hyperlink(jedit_file, line, 0)) :: links
- case None => links
- }
-
- case Position.Id_Offset(id, offset) if !snapshot.is_outdated =>
- snapshot.state.find_command(snapshot.version, id) match {
- case Some((node, command)) =>
- val sources =
- node.commands.iterator.takeWhile(_ != command).map(_.source) ++
- Iterator.single(command.source(Text.Range(0, command.decode(offset))))
- val (line, column) = ((1, 1) /: sources)(Symbol.advance_line_column)
- Text.Info(snapshot.convert(info_range),
- Hyperlink(command.node_name.node, line, column)) :: links
- case None => links
- }
-
- case _ => links
- }
- }) match { case Text.Info(_, info :: _) #:: _ => Some(info) case _ => None }
- }
-
-
- private def tooltip_text(msg: XML.Tree): String =
- Pretty.string_of(List(msg), margin = Isabelle.options.int("jedit_tooltip_margin"))
-
- def tooltip_message(snapshot: Document.Snapshot, range: Text.Range): Option[String] =
- {
- val msgs =
- snapshot.cumulate_markup[SortedMap[Long, String]](range, SortedMap.empty,
- Some(Set(Isabelle_Markup.WRITELN, Isabelle_Markup.WARNING, Isabelle_Markup.ERROR,
- Isabelle_Markup.BAD)),
- {
- case (msgs, Text.Info(_, msg @
- XML.Elem(Markup(markup, Isabelle_Markup.Serial(serial)), _)))
- if markup == Isabelle_Markup.WRITELN ||
- markup == Isabelle_Markup.WARNING ||
- markup == Isabelle_Markup.ERROR =>
- msgs + (serial -> tooltip_text(msg))
- case (msgs, Text.Info(_, msg @ XML.Elem(Markup(Isabelle_Markup.BAD, _), body)))
- if !body.isEmpty => msgs + (Document.new_id() -> tooltip_text(msg))
- }).toList.flatMap(_.info)
- if (msgs.isEmpty) None else Some(cat_lines(msgs.iterator.map(_._2)))
- }
-
-
- private val tooltips: Map[String, String] =
- Map(
- Isabelle_Markup.SORT -> "sort",
- Isabelle_Markup.TYP -> "type",
- Isabelle_Markup.TERM -> "term",
- Isabelle_Markup.PROP -> "proposition",
- Isabelle_Markup.TOKEN_RANGE -> "inner syntax token",
- Isabelle_Markup.FREE -> "free variable",
- Isabelle_Markup.SKOLEM -> "skolem variable",
- Isabelle_Markup.BOUND -> "bound variable",
- Isabelle_Markup.VAR -> "schematic variable",
- Isabelle_Markup.TFREE -> "free type variable",
- Isabelle_Markup.TVAR -> "schematic type variable",
- Isabelle_Markup.ML_SOURCE -> "ML source",
- Isabelle_Markup.DOCUMENT_SOURCE -> "document source")
-
- private val tooltip_elements =
- Set(Isabelle_Markup.ENTITY, Isabelle_Markup.TYPING, Isabelle_Markup.ML_TYPING,
- Isabelle_Markup.PATH) ++ tooltips.keys
-
- private def string_of_typing(kind: String, body: XML.Body): String =
- Pretty.string_of(List(Pretty.block(XML.Text(kind) :: Pretty.Break(1) :: body)),
- margin = Isabelle.options.int("jedit_tooltip_margin"))
-
- def tooltip(snapshot: Document.Snapshot, range: Text.Range): Option[String] =
- {
- def add(prev: Text.Info[List[(Boolean, String)]], r: Text.Range, p: (Boolean, String)) =
- if (prev.range == r) Text.Info(r, p :: prev.info) else Text.Info(r, List(p))
-
- val tips =
- snapshot.cumulate_markup[Text.Info[(List[(Boolean, String)])]](
- range, Text.Info(range, Nil), Some(tooltip_elements),
- {
- case (prev, Text.Info(r, XML.Elem(Isabelle_Markup.Entity(kind, name), _))) =>
- val kind1 = space_explode('_', kind).mkString(" ")
- add(prev, r, (true, kind1 + " " + quote(name)))
- case (prev, Text.Info(r, XML.Elem(Isabelle_Markup.Path(name), _)))
- if Path.is_ok(name) =>
- val jedit_file = Isabelle.thy_load.append(snapshot.node_name.dir, Path.explode(name))
- add(prev, r, (true, "file " + quote(jedit_file)))
- case (prev, Text.Info(r, XML.Elem(Markup(Isabelle_Markup.TYPING, _), body))) =>
- add(prev, r, (true, string_of_typing("::", body)))
- case (prev, Text.Info(r, XML.Elem(Markup(Isabelle_Markup.ML_TYPING, _), body))) =>
- add(prev, r, (false, string_of_typing("ML:", body)))
- case (prev, Text.Info(r, XML.Elem(Markup(name, _), _)))
- if tooltips.isDefinedAt(name) => add(prev, r, (true, tooltips(name)))
- }).toList.flatMap(_.info.info)
-
- val all_tips =
- (tips.filter(_._1) ++ tips.filter(!_._1).lastOption.toList).map(_._2)
- if (all_tips.isEmpty) None else Some(cat_lines(all_tips))
- }
-
-
private val gutter_icons = Map(
warning_pri -> Isabelle.load_icon("16x16/status/dialog-information.png"),
legacy_pri -> Isabelle.load_icon("16x16/status/dialog-warning.png"),
error_pri -> Isabelle.load_icon("16x16/status/dialog-error.png"))
- def gutter_message(snapshot: Document.Snapshot, range: Text.Range): Option[Icon] =
- {
- val results =
- snapshot.cumulate_markup[Int](range, 0,
- Some(Set(Isabelle_Markup.WARNING, Isabelle_Markup.ERROR)),
- {
- case (pri, Text.Info(_, XML.Elem(Markup(Isabelle_Markup.WARNING, _), body))) =>
- body match {
- case List(XML.Elem(Markup(Isabelle_Markup.LEGACY, _), _)) => pri max legacy_pri
- case _ => pri max warning_pri
- }
- case (pri, Text.Info(_, XML.Elem(Markup(Isabelle_Markup.ERROR, _), _))) =>
- pri max error_pri
- })
- val pri = (0 /: results) { case (p1, Text.Info(_, p2)) => p1 max p2 }
- gutter_icons.get(pri)
- }
-
-
- def squiggly_underline(snapshot: Document.Snapshot, range: Text.Range): Stream[Text.Info[Color]] =
- {
- val squiggly_colors = Map(
- writeln_pri -> color_value("writeln_color"),
- warning_pri -> color_value("warning_color"),
- error_pri -> color_value("error_color"))
-
- val results =
- snapshot.cumulate_markup[Int](range, 0,
- Some(Set(Isabelle_Markup.WRITELN, Isabelle_Markup.WARNING, Isabelle_Markup.ERROR)),
- {
- case (pri, Text.Info(_, XML.Elem(Markup(name, _), _))) =>
- name match {
- case Isabelle_Markup.WRITELN => pri max writeln_pri
- case Isabelle_Markup.WARNING => pri max warning_pri
- case Isabelle_Markup.ERROR => pri max error_pri
- case _ => pri
- }
- })
- for {
- Text.Info(r, pri) <- results
- color <- squiggly_colors.get(pri)
- } yield Text.Info(r, color)
- }
-
-
- def background1(snapshot: Document.Snapshot, range: Text.Range): Stream[Text.Info[Color]] =
- {
- if (snapshot.is_outdated) Stream(Text.Info(range, color_value("outdated_color")))
- else
- for {
- Text.Info(r, result) <-
- snapshot.cumulate_markup[(Option[Protocol.Status], Option[Color])](
- range, (Some(Protocol.Status.init), None),
- Some(Protocol.command_status_markup + Isabelle_Markup.BAD + Isabelle_Markup.HILITE),
- {
- case (((Some(status), color), Text.Info(_, XML.Elem(markup, _))))
- if (Protocol.command_status_markup(markup.name)) =>
- (Some(Protocol.command_status(status, markup)), color)
- case (_, Text.Info(_, XML.Elem(Markup(Isabelle_Markup.BAD, _), _))) =>
- (None, Some(color_value("bad_color")))
- case (_, Text.Info(_, XML.Elem(Markup(Isabelle_Markup.HILITE, _), _))) =>
- (None, Some(color_value("hilite_color")))
- })
- color <-
- (result match {
- case (Some(status), opt_color) =>
- if (status.is_unprocessed) Some(color_value("unprocessed1_color"))
- else if (status.is_running) Some(color_value("running1_color"))
- else opt_color
- case (_, opt_color) => opt_color
- })
- } yield Text.Info(r, color)
- }
-
-
- def background2(snapshot: Document.Snapshot, range: Text.Range): Stream[Text.Info[Color]] =
- snapshot.select_markup(range,
- Some(Set(Isabelle_Markup.TOKEN_RANGE)),
- {
- case Text.Info(_, XML.Elem(Markup(Isabelle_Markup.TOKEN_RANGE, _), _)) =>
- color_value("light_color")
- })
-
-
- def foreground(snapshot: Document.Snapshot, range: Text.Range): Stream[Text.Info[Color]] =
- snapshot.select_markup(range,
- Some(Set(Isabelle_Markup.STRING, Isabelle_Markup.ALTSTRING, Isabelle_Markup.VERBATIM)),
- {
- case Text.Info(_, XML.Elem(Markup(Isabelle_Markup.STRING, _), _)) =>
- color_value("quoted_color")
- case Text.Info(_, XML.Elem(Markup(Isabelle_Markup.ALTSTRING, _), _)) =>
- color_value("quoted_color")
- case Text.Info(_, XML.Elem(Markup(Isabelle_Markup.VERBATIM, _), _)) =>
- color_value("quoted_color")
- })
-
-
- def text_color(snapshot: Document.Snapshot, range: Text.Range, color: Color)
- : Stream[Text.Info[Color]] =
- {
- val text_colors: Map[String, Color] = Map(
- Isabelle_Markup.STRING -> Color.BLACK,
- Isabelle_Markup.ALTSTRING -> Color.BLACK,
- Isabelle_Markup.VERBATIM -> Color.BLACK,
- Isabelle_Markup.LITERAL -> color_value("keyword1_color"),
- Isabelle_Markup.DELIMITER -> Color.BLACK,
- Isabelle_Markup.TFREE -> color_value("tfree_color"),
- Isabelle_Markup.TVAR -> color_value("tvar_color"),
- Isabelle_Markup.FREE -> color_value("free_color"),
- Isabelle_Markup.SKOLEM -> color_value("skolem_color"),
- Isabelle_Markup.BOUND -> color_value("bound_color"),
- Isabelle_Markup.VAR -> color_value("var_color"),
- Isabelle_Markup.INNER_STRING -> color_value("inner_quoted_color"),
- Isabelle_Markup.INNER_COMMENT -> color_value("inner_comment_color"),
- Isabelle_Markup.DYNAMIC_FACT -> color_value("dynamic_color"),
- Isabelle_Markup.ML_KEYWORD -> color_value("keyword1_color"),
- Isabelle_Markup.ML_DELIMITER -> Color.BLACK,
- Isabelle_Markup.ML_NUMERAL -> color_value("inner_numeral_color"),
- Isabelle_Markup.ML_CHAR -> color_value("inner_quoted_color"),
- Isabelle_Markup.ML_STRING -> color_value("inner_quoted_color"),
- Isabelle_Markup.ML_COMMENT -> color_value("inner_comment_color"),
- Isabelle_Markup.ANTIQ -> color_value("antiquotation_color"))
-
- val text_color_elements = Set.empty[String] ++ text_colors.keys
-
- snapshot.cumulate_markup(range, color, Some(text_color_elements),
- {
- case (_, Text.Info(_, XML.Elem(Markup(m, _), _)))
- if text_colors.isDefinedAt(m) => text_colors(m)
- })
- }
-
/* token markup -- text styles */
@@ -382,3 +78,346 @@
else if (token.is_operator) JEditToken.OPERATOR
else token_style(token.kind)
}
+
+
+class Isabelle_Rendering private(val snapshot: Document.Snapshot, val options: Options)
+{
+ /* colors */
+
+ def color_value(s: String): Color = Color_Value(options.string(s))
+
+ val outdated_color = color_value("outdated_color")
+ val unprocessed_color = color_value("unprocessed_color")
+ val unprocessed1_color = color_value("unprocessed1_color")
+ val running_color = color_value("running_color")
+ val running1_color = color_value("running1_color")
+ val light_color = color_value("light_color")
+ val writeln_color = color_value("writeln_color")
+ val warning_color = color_value("warning_color")
+ val error_color = color_value("error_color")
+ val error1_color = color_value("error1_color")
+ val bad_color = color_value("bad_color")
+ val hilite_color = color_value("hilite_color")
+ val quoted_color = color_value("quoted_color")
+ val subexp_color = color_value("subexp_color")
+ val hyperlink_color = color_value("hyperlink_color")
+ val keyword1_color = color_value("keyword1_color")
+ val keyword2_color = color_value("keyword2_color")
+
+ val tfree_color = color_value("tfree_color")
+ val tvar_color = color_value("tvar_color")
+ val free_color = color_value("free_color")
+ val skolem_color = color_value("skolem_color")
+ val bound_color = color_value("bound_color")
+ val var_color = color_value("var_color")
+ val inner_numeral_color = color_value("inner_numeral_color")
+ val inner_quoted_color = color_value("inner_quoted_color")
+ val inner_comment_color = color_value("inner_comment_color")
+ val antiquotation_color = color_value("antiquotation_color")
+ val dynamic_color = color_value("dynamic_color")
+
+
+ /* command overview */
+
+ def overview_color(range: Text.Range): Option[Color] =
+ {
+ if (snapshot.is_outdated) None
+ else {
+ val results =
+ snapshot.cumulate_markup[(Protocol.Status, Int)](
+ range, (Protocol.Status.init, 0),
+ Some(Protocol.command_status_markup + Isabelle_Markup.WARNING + Isabelle_Markup.ERROR),
+ {
+ case ((status, pri), Text.Info(_, XML.Elem(markup, _))) =>
+ if (markup.name == Isabelle_Markup.WARNING)
+ (status, pri max Isabelle_Rendering.warning_pri)
+ else if (markup.name == Isabelle_Markup.ERROR)
+ (status, pri max Isabelle_Rendering.error_pri)
+ else (Protocol.command_status(status, markup), pri)
+ })
+ if (results.isEmpty) None
+ else {
+ val (status, pri) =
+ ((Protocol.Status.init, 0) /: results) {
+ case ((s1, p1), Text.Info(_, (s2, p2))) => (s1 + s2, p1 max p2) }
+
+ if (pri == Isabelle_Rendering.warning_pri) Some(warning_color)
+ else if (pri == Isabelle_Rendering.error_pri) Some(error_color)
+ else if (status.is_unprocessed) Some(unprocessed_color)
+ else if (status.is_running) Some(running_color)
+ else if (status.is_failed) Some(error_color)
+ else None
+ }
+ }
+ }
+
+
+ /* markup selectors */
+
+ private val subexp_include =
+ Set(Isabelle_Markup.SORT, Isabelle_Markup.TYP, Isabelle_Markup.TERM, Isabelle_Markup.PROP,
+ Isabelle_Markup.ML_TYPING, Isabelle_Markup.TOKEN_RANGE, Isabelle_Markup.ENTITY,
+ Isabelle_Markup.PATH, Isabelle_Markup.TYPING, Isabelle_Markup.FREE, Isabelle_Markup.SKOLEM,
+ Isabelle_Markup.BOUND, Isabelle_Markup.VAR, Isabelle_Markup.TFREE, Isabelle_Markup.TVAR,
+ Isabelle_Markup.ML_SOURCE, Isabelle_Markup.DOCUMENT_SOURCE)
+
+ def subexp(range: Text.Range): Option[Text.Info[Color]] =
+ {
+ snapshot.select_markup(range, Some(subexp_include),
+ {
+ case Text.Info(info_range, XML.Elem(Markup(name, _), _)) if subexp_include(name) =>
+ Text.Info(snapshot.convert(info_range), subexp_color)
+ }) match { case Text.Info(_, info) #:: _ => Some(info) case _ => None }
+ }
+
+
+ private val hyperlink_include = Set(Isabelle_Markup.ENTITY, Isabelle_Markup.PATH)
+
+ def hyperlink(range: Text.Range): Option[Text.Info[Hyperlink]] =
+ {
+ snapshot.cumulate_markup[List[Text.Info[Hyperlink]]](range, Nil, Some(hyperlink_include),
+ {
+ case (links, Text.Info(info_range, XML.Elem(Isabelle_Markup.Path(name), _)))
+ if Path.is_ok(name) =>
+ val jedit_file = Isabelle.thy_load.append(snapshot.node_name.dir, Path.explode(name))
+ Text.Info(snapshot.convert(info_range), Hyperlink(jedit_file, 0, 0)) :: links
+
+ case (links, Text.Info(info_range, XML.Elem(Markup(Isabelle_Markup.ENTITY, props), _)))
+ if (props.find(
+ { case (Markup.KIND, Isabelle_Markup.ML_OPEN) => true
+ case (Markup.KIND, Isabelle_Markup.ML_STRUCT) => true
+ case _ => false }).isEmpty) =>
+
+ props match {
+ case Position.Line_File(line, name) if Path.is_ok(name) =>
+ Isabelle_System.source_file(Path.explode(name)) match {
+ case Some(path) =>
+ val jedit_file = Isabelle_System.platform_path(path)
+ Text.Info(snapshot.convert(info_range), Hyperlink(jedit_file, line, 0)) :: links
+ case None => links
+ }
+
+ case Position.Id_Offset(id, offset) if !snapshot.is_outdated =>
+ snapshot.state.find_command(snapshot.version, id) match {
+ case Some((node, command)) =>
+ val sources =
+ node.commands.iterator.takeWhile(_ != command).map(_.source) ++
+ Iterator.single(command.source(Text.Range(0, command.decode(offset))))
+ val (line, column) = ((1, 1) /: sources)(Symbol.advance_line_column)
+ Text.Info(snapshot.convert(info_range),
+ Hyperlink(command.node_name.node, line, column)) :: links
+ case None => links
+ }
+
+ case _ => links
+ }
+ }) match { case Text.Info(_, info :: _) #:: _ => Some(info) case _ => None }
+ }
+
+
+ private def tooltip_text(msg: XML.Tree): String =
+ Pretty.string_of(List(msg), margin = options.int("jedit_tooltip_margin"))
+
+ def tooltip_message(range: Text.Range): Option[String] =
+ {
+ val msgs =
+ snapshot.cumulate_markup[SortedMap[Long, String]](range, SortedMap.empty,
+ Some(Set(Isabelle_Markup.WRITELN, Isabelle_Markup.WARNING, Isabelle_Markup.ERROR,
+ Isabelle_Markup.BAD)),
+ {
+ case (msgs, Text.Info(_, msg @
+ XML.Elem(Markup(markup, Isabelle_Markup.Serial(serial)), _)))
+ if markup == Isabelle_Markup.WRITELN ||
+ markup == Isabelle_Markup.WARNING ||
+ markup == Isabelle_Markup.ERROR =>
+ msgs + (serial -> tooltip_text(msg))
+ case (msgs, Text.Info(_, msg @ XML.Elem(Markup(Isabelle_Markup.BAD, _), body)))
+ if !body.isEmpty => msgs + (Document.new_id() -> tooltip_text(msg))
+ }).toList.flatMap(_.info)
+ if (msgs.isEmpty) None else Some(cat_lines(msgs.iterator.map(_._2)))
+ }
+
+
+ private val tooltips: Map[String, String] =
+ Map(
+ Isabelle_Markup.SORT -> "sort",
+ Isabelle_Markup.TYP -> "type",
+ Isabelle_Markup.TERM -> "term",
+ Isabelle_Markup.PROP -> "proposition",
+ Isabelle_Markup.TOKEN_RANGE -> "inner syntax token",
+ Isabelle_Markup.FREE -> "free variable",
+ Isabelle_Markup.SKOLEM -> "skolem variable",
+ Isabelle_Markup.BOUND -> "bound variable",
+ Isabelle_Markup.VAR -> "schematic variable",
+ Isabelle_Markup.TFREE -> "free type variable",
+ Isabelle_Markup.TVAR -> "schematic type variable",
+ Isabelle_Markup.ML_SOURCE -> "ML source",
+ Isabelle_Markup.DOCUMENT_SOURCE -> "document source")
+
+ private val tooltip_elements =
+ Set(Isabelle_Markup.ENTITY, Isabelle_Markup.TYPING, Isabelle_Markup.ML_TYPING,
+ Isabelle_Markup.PATH) ++ tooltips.keys
+
+ private def string_of_typing(kind: String, body: XML.Body): String =
+ Pretty.string_of(List(Pretty.block(XML.Text(kind) :: Pretty.Break(1) :: body)),
+ margin = options.int("jedit_tooltip_margin"))
+
+ def tooltip(range: Text.Range): Option[String] =
+ {
+ def add(prev: Text.Info[List[(Boolean, String)]], r: Text.Range, p: (Boolean, String)) =
+ if (prev.range == r) Text.Info(r, p :: prev.info) else Text.Info(r, List(p))
+
+ val tips =
+ snapshot.cumulate_markup[Text.Info[(List[(Boolean, String)])]](
+ range, Text.Info(range, Nil), Some(tooltip_elements),
+ {
+ case (prev, Text.Info(r, XML.Elem(Isabelle_Markup.Entity(kind, name), _))) =>
+ val kind1 = space_explode('_', kind).mkString(" ")
+ add(prev, r, (true, kind1 + " " + quote(name)))
+ case (prev, Text.Info(r, XML.Elem(Isabelle_Markup.Path(name), _)))
+ if Path.is_ok(name) =>
+ val jedit_file = Isabelle.thy_load.append(snapshot.node_name.dir, Path.explode(name))
+ add(prev, r, (true, "file " + quote(jedit_file)))
+ case (prev, Text.Info(r, XML.Elem(Markup(Isabelle_Markup.TYPING, _), body))) =>
+ add(prev, r, (true, string_of_typing("::", body)))
+ case (prev, Text.Info(r, XML.Elem(Markup(Isabelle_Markup.ML_TYPING, _), body))) =>
+ add(prev, r, (false, string_of_typing("ML:", body)))
+ case (prev, Text.Info(r, XML.Elem(Markup(name, _), _)))
+ if tooltips.isDefinedAt(name) => add(prev, r, (true, tooltips(name)))
+ }).toList.flatMap(_.info.info)
+
+ val all_tips =
+ (tips.filter(_._1) ++ tips.filter(!_._1).lastOption.toList).map(_._2)
+ if (all_tips.isEmpty) None else Some(cat_lines(all_tips))
+ }
+
+
+ def gutter_message(range: Text.Range): Option[Icon] =
+ {
+ val results =
+ snapshot.cumulate_markup[Int](range, 0,
+ Some(Set(Isabelle_Markup.WARNING, Isabelle_Markup.ERROR)),
+ {
+ case (pri, Text.Info(_, XML.Elem(Markup(Isabelle_Markup.WARNING, _), body))) =>
+ body match {
+ case List(XML.Elem(Markup(Isabelle_Markup.LEGACY, _), _)) =>
+ pri max Isabelle_Rendering.legacy_pri
+ case _ => pri max Isabelle_Rendering.warning_pri
+ }
+ case (pri, Text.Info(_, XML.Elem(Markup(Isabelle_Markup.ERROR, _), _))) =>
+ pri max Isabelle_Rendering.error_pri
+ })
+ val pri = (0 /: results) { case (p1, Text.Info(_, p2)) => p1 max p2 }
+ Isabelle_Rendering.gutter_icons.get(pri)
+ }
+
+
+ private val squiggly_colors = Map(
+ Isabelle_Rendering.writeln_pri -> writeln_color,
+ Isabelle_Rendering.warning_pri -> warning_color,
+ Isabelle_Rendering.error_pri -> error_color)
+
+ def squiggly_underline(range: Text.Range): Stream[Text.Info[Color]] =
+ {
+ val results =
+ snapshot.cumulate_markup[Int](range, 0,
+ Some(Set(Isabelle_Markup.WRITELN, Isabelle_Markup.WARNING, Isabelle_Markup.ERROR)),
+ {
+ case (pri, Text.Info(_, XML.Elem(Markup(name, _), _))) =>
+ name match {
+ case Isabelle_Markup.WRITELN => pri max Isabelle_Rendering.writeln_pri
+ case Isabelle_Markup.WARNING => pri max Isabelle_Rendering.warning_pri
+ case Isabelle_Markup.ERROR => pri max Isabelle_Rendering.error_pri
+ case _ => pri
+ }
+ })
+ for {
+ Text.Info(r, pri) <- results
+ color <- squiggly_colors.get(pri)
+ } yield Text.Info(r, color)
+ }
+
+
+ def background1(range: Text.Range): Stream[Text.Info[Color]] =
+ {
+ if (snapshot.is_outdated) Stream(Text.Info(range, outdated_color))
+ else
+ for {
+ Text.Info(r, result) <-
+ snapshot.cumulate_markup[(Option[Protocol.Status], Option[Color])](
+ range, (Some(Protocol.Status.init), None),
+ Some(Protocol.command_status_markup + Isabelle_Markup.BAD + Isabelle_Markup.HILITE),
+ {
+ case (((Some(status), color), Text.Info(_, XML.Elem(markup, _))))
+ if (Protocol.command_status_markup(markup.name)) =>
+ (Some(Protocol.command_status(status, markup)), color)
+ case (_, Text.Info(_, XML.Elem(Markup(Isabelle_Markup.BAD, _), _))) =>
+ (None, Some(bad_color))
+ case (_, Text.Info(_, XML.Elem(Markup(Isabelle_Markup.HILITE, _), _))) =>
+ (None, Some(hilite_color))
+ })
+ color <-
+ (result match {
+ case (Some(status), opt_color) =>
+ if (status.is_unprocessed) Some(unprocessed1_color)
+ else if (status.is_running) Some(running1_color)
+ else opt_color
+ case (_, opt_color) => opt_color
+ })
+ } yield Text.Info(r, color)
+ }
+
+
+ def background2(range: Text.Range): Stream[Text.Info[Color]] =
+ snapshot.select_markup(range,
+ Some(Set(Isabelle_Markup.TOKEN_RANGE)),
+ {
+ case Text.Info(_, XML.Elem(Markup(Isabelle_Markup.TOKEN_RANGE, _), _)) => light_color
+ })
+
+
+ def foreground(range: Text.Range): Stream[Text.Info[Color]] =
+ snapshot.select_markup(range,
+ Some(Set(Isabelle_Markup.STRING, Isabelle_Markup.ALTSTRING, Isabelle_Markup.VERBATIM)),
+ {
+ case Text.Info(_, XML.Elem(Markup(Isabelle_Markup.STRING, _), _)) => quoted_color
+ case Text.Info(_, XML.Elem(Markup(Isabelle_Markup.ALTSTRING, _), _)) => quoted_color
+ case Text.Info(_, XML.Elem(Markup(Isabelle_Markup.VERBATIM, _), _)) => quoted_color
+ })
+
+
+ private val text_colors: Map[String, Color] = Map(
+ Isabelle_Markup.STRING -> Color.BLACK,
+ Isabelle_Markup.ALTSTRING -> Color.BLACK,
+ Isabelle_Markup.VERBATIM -> Color.BLACK,
+ Isabelle_Markup.LITERAL -> keyword1_color,
+ Isabelle_Markup.DELIMITER -> Color.BLACK,
+ Isabelle_Markup.TFREE -> tfree_color,
+ Isabelle_Markup.TVAR -> tvar_color,
+ Isabelle_Markup.FREE -> free_color,
+ Isabelle_Markup.SKOLEM -> skolem_color,
+ Isabelle_Markup.BOUND -> bound_color,
+ Isabelle_Markup.VAR -> var_color,
+ Isabelle_Markup.INNER_STRING -> inner_quoted_color,
+ Isabelle_Markup.INNER_COMMENT -> inner_comment_color,
+ Isabelle_Markup.DYNAMIC_FACT -> dynamic_color,
+ Isabelle_Markup.ML_KEYWORD -> keyword1_color,
+ Isabelle_Markup.ML_DELIMITER -> Color.BLACK,
+ Isabelle_Markup.ML_NUMERAL -> inner_numeral_color,
+ Isabelle_Markup.ML_CHAR -> inner_quoted_color,
+ Isabelle_Markup.ML_STRING -> inner_quoted_color,
+ Isabelle_Markup.ML_COMMENT -> inner_comment_color,
+ Isabelle_Markup.ANTIQ -> antiquotation_color)
+
+ private val text_color_elements = Set.empty[String] ++ text_colors.keys
+
+ def text_color(range: Text.Range, color: Color)
+ : Stream[Text.Info[Color]] =
+ {
+ snapshot.cumulate_markup(range, color, Some(text_color_elements),
+ {
+ case (_, Text.Info(_, XML.Elem(Markup(m, _), _)))
+ if text_colors.isDefinedAt(m) => text_colors(m)
+ })
+ }
+}
--- a/src/Tools/jEdit/src/text_area_painter.scala Fri Sep 14 12:46:33 2012 +0200
+++ b/src/Tools/jEdit/src/text_area_painter.scala Fri Sep 14 13:52:16 2012 +0200
@@ -75,7 +75,7 @@
/* common painter state */
- @volatile private var painter_snapshot: Document.Snapshot = null
+ @volatile private var painter_rendering: Isabelle_Rendering = null
@volatile private var painter_clip: Shape = null
private val set_state = new TextAreaExtension
@@ -84,7 +84,7 @@
first_line: Int, last_line: Int, physical_lines: Array[Int],
start: Array[Int], end: Array[Int], y: Int, line_height: Int)
{
- painter_snapshot = model.snapshot()
+ painter_rendering = Isabelle_Rendering(model.snapshot(), Isabelle.options.value)
painter_clip = gfx.getClip
}
}
@@ -95,14 +95,14 @@
first_line: Int, last_line: Int, physical_lines: Array[Int],
start: Array[Int], end: Array[Int], y: Int, line_height: Int)
{
- painter_snapshot = null
+ painter_rendering = null
painter_clip = null
}
}
- private def robust_snapshot(body: Document.Snapshot => Unit)
+ private def robust_rendering(body: Isabelle_Rendering => Unit)
{
- doc_view.robust_body(()) { body(painter_snapshot) }
+ doc_view.robust_body(()) { body(painter_rendering) }
}
@@ -114,7 +114,7 @@
first_line: Int, last_line: Int, physical_lines: Array[Int],
start: Array[Int], end: Array[Int], y: Int, line_height: Int)
{
- robust_snapshot { snapshot =>
+ robust_rendering { rendering =>
val ascent = text_area.getPainter.getFontMetrics.getAscent
for (i <- 0 until physical_lines.length) {
@@ -123,7 +123,7 @@
// background color (1)
for {
- Text.Info(range, color) <- Isabelle_Rendering.background1(snapshot, line_range)
+ Text.Info(range, color) <- rendering.background1(line_range)
r <- gfx_range(range)
} {
gfx.setColor(color)
@@ -132,7 +132,7 @@
// background color (2)
for {
- Text.Info(range, color) <- Isabelle_Rendering.background2(snapshot, line_range)
+ Text.Info(range, color) <- rendering.background2(line_range)
r <- gfx_range(range)
} {
gfx.setColor(color)
@@ -141,7 +141,7 @@
// squiggly underline
for {
- Text.Info(range, color) <- Isabelle_Rendering.squiggly_underline(snapshot, line_range)
+ Text.Info(range, color) <- rendering.squiggly_underline(line_range)
r <- gfx_range(range)
} {
gfx.setColor(color)
@@ -161,7 +161,7 @@
/* text */
- private def paint_chunk_list(snapshot: Document.Snapshot,
+ private def paint_chunk_list(rendering: Isabelle_Rendering,
gfx: Graphics2D, line_start: Text.Offset, head: Chunk, x: Float, y: Float): Float =
{
val clip_rect = gfx.getClipBounds
@@ -190,7 +190,7 @@
val markup =
for {
- r1 <- Isabelle_Rendering.text_color(snapshot, chunk_range, chunk_color)
+ r1 <- rendering.text_color(chunk_range, chunk_color)
r2 <- r1.try_restrict(chunk_range)
} yield r2
@@ -246,7 +246,7 @@
first_line: Int, last_line: Int, physical_lines: Array[Int],
start: Array[Int], end: Array[Int], y: Int, line_height: Int)
{
- robust_snapshot { snapshot =>
+ robust_rendering { rendering =>
val clip = gfx.getClip
val x0 = text_area.getHorizontalOffset
val fm = text_area.getPainter.getFontMetrics
@@ -260,7 +260,7 @@
if (chunks != null) {
val line_start = text_area.getBuffer.getLineStartOffset(line)
gfx.clipRect(x0, y + line_height * i, Integer.MAX_VALUE, line_height)
- val w = paint_chunk_list(snapshot, gfx, line_start, chunks, x0, y0).toInt
+ val w = paint_chunk_list(rendering, gfx, line_start, chunks, x0, y0).toInt
gfx.clipRect(x0 + w.toInt, 0, Integer.MAX_VALUE, Integer.MAX_VALUE)
orig_text_painter.paintValidLine(gfx,
screen_line, line, start(i), end(i), y + line_height * i)
@@ -282,14 +282,14 @@
first_line: Int, last_line: Int, physical_lines: Array[Int],
start: Array[Int], end: Array[Int], y: Int, line_height: Int)
{
- robust_snapshot { snapshot =>
+ robust_rendering { rendering =>
for (i <- 0 until physical_lines.length) {
if (physical_lines(i) != -1) {
val line_range = doc_view.proper_line_range(start(i), end(i))
// foreground color
for {
- Text.Info(range, color) <- Isabelle_Rendering.foreground(snapshot, line_range)
+ Text.Info(range, color) <- rendering.foreground(line_range)
r <- gfx_range(range)
} {
gfx.setColor(color)
@@ -312,7 +312,7 @@
Text.Info(range, _) <- info.try_restrict(line_range)
r <- gfx_range(range)
} {
- gfx.setColor(Isabelle_Rendering.color_value("hyperlink_color"))
+ gfx.setColor(rendering.hyperlink_color)
gfx.drawRect(r.x, y + i * line_height, r.length - 1, line_height - 1)
}
}
@@ -329,7 +329,7 @@
override def paintValidLine(gfx: Graphics2D,
screen_line: Int, physical_line: Int, start: Int, end: Int, y: Int)
{
- robust_snapshot { _ =>
+ robust_rendering { _ =>
if (before) gfx.clipRect(0, 0, 0, 0)
else gfx.setClip(painter_clip)
}
@@ -346,7 +346,7 @@
override def paintValidLine(gfx: Graphics2D,
screen_line: Int, physical_line: Int, start: Int, end: Int, y: Int)
{
- robust_snapshot { _ =>
+ robust_rendering { _ =>
if (text_area.isCaretVisible) {
val caret = text_area.getCaretPosition
if (start <= caret && caret == end - 1) {