src/Tools/jEdit/src/rendering.scala
changeset 55620 19dffae33cde
parent 55619 c5aeeacdd2b1
child 55622 ce575c2212fc
equal deleted inserted replaced
55619:c5aeeacdd2b1 55620:19dffae33cde
   207       Markup.COMMENT, Markup.LANGUAGE)
   207       Markup.COMMENT, Markup.LANGUAGE)
   208 
   208 
   209   def completion_context(caret: Text.Offset): Option[Completion.Context] =
   209   def completion_context(caret: Text.Offset): Option[Completion.Context] =
   210     if (caret > 0) {
   210     if (caret > 0) {
   211       val result =
   211       val result =
   212         snapshot.select_markup(Text.Range(caret - 1, caret + 1), Some(completion_elements), _ =>
   212         snapshot.select_markup(Text.Range(caret - 1, caret + 1), completion_elements, _ =>
   213           {
   213           {
   214             case Text.Info(_, XML.Elem(Markup.Language(language, symbols), _)) =>
   214             case Text.Info(_, XML.Elem(Markup.Language(language, symbols), _)) =>
   215               Some(Completion.Context(language, symbols))
   215               Some(Completion.Context(language, symbols))
   216             case Text.Info(_, XML.Elem(markup, _)) =>
   216             case Text.Info(_, XML.Elem(markup, _)) =>
   217               if (completion_elements(markup.name))
   217               Some(Completion.Context(Markup.Language.UNKNOWN, true))
   218                 Some(Completion.Context(Markup.Language.UNKNOWN, true))
       
   219               else None
       
   220           })
   218           })
   221       result match {
   219       result match {
   222         case Text.Info(_, context) :: _ => Some(context)
   220         case Text.Info(_, context) :: _ => Some(context)
   223         case Nil => None
   221         case Nil => None
   224       }
   222       }
   237   {
   235   {
   238     if (snapshot.is_outdated) None
   236     if (snapshot.is_outdated) None
   239     else {
   237     else {
   240       val results =
   238       val results =
   241         snapshot.cumulate_markup[(Protocol.Status, Int)](
   239         snapshot.cumulate_markup[(Protocol.Status, Int)](
   242           range, (Protocol.Status.init, 0), Some(overview_elements), _ =>
   240           range, (Protocol.Status.init, 0), overview_elements, _ =>
   243           {
   241           {
   244             case ((status, pri), Text.Info(_, elem)) =>
   242             case ((status, pri), Text.Info(_, elem)) =>
   245               if (elem.name == Markup.WARNING || elem.name == Markup.ERROR)
   243               if (elem.name == Markup.WARNING || elem.name == Markup.ERROR)
   246                 Some((status, pri max Rendering.message_pri(elem.name)))
   244                 Some((status, pri max Rendering.message_pri(elem.name)))
   247               else if (overview_elements(elem.name))
   245               else
   248                 Some((Protocol.command_status(status, elem.markup), pri))
   246                 Some((Protocol.command_status(status, elem.markup), pri))
   249               else None
       
   250           })
   247           })
   251       if (results.isEmpty) None
   248       if (results.isEmpty) None
   252       else {
   249       else {
   253         val (status, pri) =
   250         val (status, pri) =
   254           ((Protocol.Status.init, 0) /: results) {
   251           ((Protocol.Status.init, 0) /: results) {
   273       Markup.TYPING, Markup.FREE, Markup.SKOLEM, Markup.BOUND,
   270       Markup.TYPING, Markup.FREE, Markup.SKOLEM, Markup.BOUND,
   274       Markup.VAR, Markup.TFREE, Markup.TVAR)
   271       Markup.VAR, Markup.TFREE, Markup.TVAR)
   275 
   272 
   276   def highlight(range: Text.Range): Option[Text.Info[Color]] =
   273   def highlight(range: Text.Range): Option[Text.Info[Color]] =
   277   {
   274   {
   278     snapshot.select_markup(range, Some(highlight_elements), _ =>
   275     snapshot.select_markup(range, highlight_elements, _ =>
   279         {
   276       {
   280           case Text.Info(info_range, elem) =>
   277         case info => Some(Text.Info(snapshot.convert(info.range), highlight_color))
   281             if (highlight_elements(elem.name))
   278       }) match { case Text.Info(_, info) :: _ => Some(info) case _ => None }
   282               Some(Text.Info(snapshot.convert(info_range), highlight_color))
       
   283             else None
       
   284         }) match { case Text.Info(_, info) :: _ => Some(info) case _ => None }
       
   285   }
   279   }
   286 
   280 
   287 
   281 
   288   private val hyperlink_elements =
   282   private val hyperlink_elements =
   289     Set(Markup.ENTITY, Markup.PATH, Markup.POSITION, Markup.URL)
   283     Set(Markup.ENTITY, Markup.PATH, Markup.POSITION, Markup.URL)
   303     }
   297     }
   304 
   298 
   305   def hyperlink(range: Text.Range): Option[Text.Info[PIDE.editor.Hyperlink]] =
   299   def hyperlink(range: Text.Range): Option[Text.Info[PIDE.editor.Hyperlink]] =
   306   {
   300   {
   307     snapshot.cumulate_markup[List[Text.Info[PIDE.editor.Hyperlink]]](
   301     snapshot.cumulate_markup[List[Text.Info[PIDE.editor.Hyperlink]]](
   308       range, Nil, Some(hyperlink_elements), _ =>
   302       range, Nil, hyperlink_elements, _ =>
   309         {
   303         {
   310           case (links, Text.Info(info_range, XML.Elem(Markup.Path(name), _)))
   304           case (links, Text.Info(info_range, XML.Elem(Markup.Path(name), _)))
   311           if Path.is_ok(name) =>
   305           if Path.is_ok(name) =>
   312             val jedit_file = PIDE.thy_load.append(snapshot.node_name.master_dir, Path.explode(name))
   306             val jedit_file = PIDE.thy_load.append(snapshot.node_name.master_dir, Path.explode(name))
   313             val link = PIDE.editor.hyperlink_file(jedit_file)
   307             val link = PIDE.editor.hyperlink_file(jedit_file)
   347 
   341 
   348   private val active_elements =
   342   private val active_elements =
   349     Set(Markup.BROWSER, Markup.GRAPHVIEW, Markup.SENDBACK, Markup.DIALOG, Markup.SIMP_TRACE)
   343     Set(Markup.BROWSER, Markup.GRAPHVIEW, Markup.SENDBACK, Markup.DIALOG, Markup.SIMP_TRACE)
   350 
   344 
   351   def active(range: Text.Range): Option[Text.Info[XML.Elem]] =
   345   def active(range: Text.Range): Option[Text.Info[XML.Elem]] =
   352     snapshot.select_markup(range, Some(active_elements), command_state =>
   346     snapshot.select_markup(range, active_elements, command_state =>
   353         {
   347       {
   354           case Text.Info(info_range, elem @ Protocol.Dialog(_, serial, _))
   348         case Text.Info(info_range, elem @ Protocol.Dialog(_, serial, _))
   355           if !command_state.results.defined(serial) =>
   349         if !command_state.results.defined(serial) =>
       
   350           Some(Text.Info(snapshot.convert(info_range), elem))
       
   351         case Text.Info(info_range, elem) =>
       
   352           if (elem.name == Markup.BROWSER ||
       
   353               elem.name == Markup.GRAPHVIEW ||
       
   354               elem.name == Markup.SENDBACK ||
       
   355               elem.name == Markup.SIMP_TRACE)
   356             Some(Text.Info(snapshot.convert(info_range), elem))
   356             Some(Text.Info(snapshot.convert(info_range), elem))
   357           case Text.Info(info_range, elem) =>
   357           else None
   358             if (elem.name == Markup.BROWSER ||
   358       }) match { case Text.Info(_, info) :: _ => Some(info) case _ => None }
   359                 elem.name == Markup.GRAPHVIEW ||
       
   360                 elem.name == Markup.SENDBACK ||
       
   361                 elem.name == Markup.SIMP_TRACE)
       
   362               Some(Text.Info(snapshot.convert(info_range), elem))
       
   363             else None
       
   364         }) match { case Text.Info(_, info) :: _ => Some(info) case _ => None }
       
   365 
   359 
   366 
   360 
   367   def command_results(range: Text.Range): Command.Results =
   361   def command_results(range: Text.Range): Command.Results =
   368   {
   362   {
   369     val results =
   363     val results =
   370       snapshot.select_markup[Command.Results](range, None, command_state =>
   364       snapshot.select_markup[Command.Results](range, _ => true, command_state =>
   371         { case _ => Some(command_state.results) }).map(_.info)
   365         { case _ => Some(command_state.results) }).map(_.info)
   372     (Command.Results.empty /: results)(_ ++ _)
   366     (Command.Results.empty /: results)(_ ++ _)
   373   }
   367   }
   374 
   368 
       
   369   private val tooltip_message_elements =
       
   370     Set(Markup.WRITELN, Markup.WARNING, Markup.ERROR, Markup.BAD)
       
   371 
   375   def tooltip_message(range: Text.Range): Option[Text.Info[XML.Body]] =
   372   def tooltip_message(range: Text.Range): Option[Text.Info[XML.Body]] =
   376   {
   373   {
   377     val results =
   374     val results =
   378       snapshot.cumulate_markup[List[Text.Info[Command.Results.Entry]]](range, Nil,
   375       snapshot.cumulate_markup[List[Text.Info[Command.Results.Entry]]](
   379         Some(Set(Markup.WRITELN, Markup.WARNING, Markup.ERROR, Markup.BAD)), _ =>
   376         range, Nil, tooltip_message_elements, _ =>
   380         {
   377         {
   381           case (msgs, Text.Info(info_range,
   378           case (msgs, Text.Info(info_range,
   382             XML.Elem(Markup(name, props @ Markup.Serial(serial)), body)))
   379             XML.Elem(Markup(name, props @ Markup.Serial(serial)), body)))
   383           if name == Markup.WRITELN || name == Markup.WARNING || name == Markup.ERROR =>
   380           if name == Markup.WRITELN || name == Markup.WARNING || name == Markup.ERROR =>
   384             val entry: Command.Results.Entry =
   381             val entry: Command.Results.Entry =
   431       if (prev.range == r) Text.Info(r, (t, p :: info)) else Text.Info(r, (t, List(p)))
   428       if (prev.range == r) Text.Info(r, (t, p :: info)) else Text.Info(r, (t, List(p)))
   432     }
   429     }
   433 
   430 
   434     val results =
   431     val results =
   435       snapshot.cumulate_markup[Text.Info[(Timing, List[(Boolean, XML.Tree)])]](
   432       snapshot.cumulate_markup[Text.Info[(Timing, List[(Boolean, XML.Tree)])]](
   436         range, Text.Info(range, (Timing.zero, Nil)), Some(tooltip_elements), _ =>
   433         range, Text.Info(range, (Timing.zero, Nil)), tooltip_elements, _ =>
   437         {
   434         {
   438           case (Text.Info(r, (t1, info)), Text.Info(_, XML.Elem(Markup.Timing(t2), _))) =>
   435           case (Text.Info(r, (t1, info)), Text.Info(_, XML.Elem(Markup.Timing(t2), _))) =>
   439             Some(Text.Info(r, (t1 + t2, info)))
   436             Some(Text.Info(r, (t1 + t2, info)))
   440           case (prev, Text.Info(r, XML.Elem(Markup.Entity(kind, name), _))) =>
   437           case (prev, Text.Info(r, XML.Elem(Markup.Entity(kind, name), _))) =>
   441             val kind1 = space_explode('_', kind).mkString(" ")
   438             val kind1 = space_explode('_', kind).mkString(" ")
   484     Rendering.information_pri -> JEdit_Lib.load_icon(options.string("gutter_information_icon")),
   481     Rendering.information_pri -> JEdit_Lib.load_icon(options.string("gutter_information_icon")),
   485     Rendering.warning_pri -> JEdit_Lib.load_icon(options.string("gutter_warning_icon")),
   482     Rendering.warning_pri -> JEdit_Lib.load_icon(options.string("gutter_warning_icon")),
   486     Rendering.legacy_pri -> JEdit_Lib.load_icon(options.string("gutter_legacy_icon")),
   483     Rendering.legacy_pri -> JEdit_Lib.load_icon(options.string("gutter_legacy_icon")),
   487     Rendering.error_pri -> JEdit_Lib.load_icon(options.string("gutter_error_icon")))
   484     Rendering.error_pri -> JEdit_Lib.load_icon(options.string("gutter_error_icon")))
   488 
   485 
   489   private val gutter_elements = Set(Markup.WRITELN, Markup.WARNING, Markup.ERROR)
   486   private val gutter_elements =
       
   487     Set(Markup.WRITELN, Markup.WARNING, Markup.ERROR)
   490 
   488 
   491   def gutter_message(range: Text.Range): Option[Icon] =
   489   def gutter_message(range: Text.Range): Option[Icon] =
   492   {
   490   {
   493     val results =
   491     val results =
   494       snapshot.cumulate_markup[Int](range, 0, Some(gutter_elements), _ =>
   492       snapshot.cumulate_markup[Int](range, 0, gutter_elements, _ =>
   495         {
   493         {
   496           case (pri, Text.Info(_, XML.Elem(Markup(Markup.WRITELN, _),
   494           case (pri, Text.Info(_, XML.Elem(Markup(Markup.WRITELN, _),
   497               List(XML.Elem(Markup(Markup.INFORMATION, _), _))))) =>
   495               List(XML.Elem(Markup(Markup.INFORMATION, _), _))))) =>
   498             Some(pri max Rendering.information_pri)
   496             Some(pri max Rendering.information_pri)
   499           case (pri, Text.Info(_, XML.Elem(Markup(Markup.WARNING, _), body))) =>
   497           case (pri, Text.Info(_, XML.Elem(Markup(Markup.WARNING, _), body))) =>
   521   private val squiggly_elements = Set(Markup.WRITELN, Markup.WARNING, Markup.ERROR)
   519   private val squiggly_elements = Set(Markup.WRITELN, Markup.WARNING, Markup.ERROR)
   522 
   520 
   523   def squiggly_underline(range: Text.Range): List[Text.Info[Color]] =
   521   def squiggly_underline(range: Text.Range): List[Text.Info[Color]] =
   524   {
   522   {
   525     val results =
   523     val results =
   526       snapshot.cumulate_markup[Int](range, 0, Some(squiggly_elements), _ =>
   524       snapshot.cumulate_markup[Int](range, 0, squiggly_elements, _ =>
   527         {
   525         {
   528           case (pri, Text.Info(_, elem)) =>
   526           case (pri, Text.Info(_, elem)) =>
   529             if (Protocol.is_information(elem))
   527             if (Protocol.is_information(elem))
   530               Some(pri max Rendering.information_pri)
   528               Some(pri max Rendering.information_pri)
   531             else if (squiggly_elements(elem.name))
   529             else
   532               Some(pri max Rendering.message_pri(elem.name))
   530               Some(pri max Rendering.message_pri(elem.name))
   533             else None
       
   534         })
   531         })
   535     for {
   532     for {
   536       Text.Info(r, pri) <- results
   533       Text.Info(r, pri) <- results
   537       color <- squiggly_colors.get(pri)
   534       color <- squiggly_colors.get(pri)
   538     } yield Text.Info(r, color)
   535     } yield Text.Info(r, color)
   551       Markup.ERROR_MESSAGE, Markup.INFORMATION)
   548       Markup.ERROR_MESSAGE, Markup.INFORMATION)
   552 
   549 
   553   def line_background(range: Text.Range): Option[(Color, Boolean)] =
   550   def line_background(range: Text.Range): Option[(Color, Boolean)] =
   554   {
   551   {
   555     val results =
   552     val results =
   556       snapshot.cumulate_markup[Int](range, 0, Some(line_background_elements), _ =>
   553       snapshot.cumulate_markup[Int](range, 0, line_background_elements, _ =>
   557         {
   554         {
   558           case (pri, Text.Info(_, elem)) =>
   555           case (pri, Text.Info(_, elem)) =>
   559             val name = elem.name
   556             val name = elem.name
   560             if (name == Markup.INFORMATION)
   557             if (name == Markup.INFORMATION)
   561               Some(pri max Rendering.information_pri)
   558               Some(pri max Rendering.information_pri)
   565             else None
   562             else None
   566         })
   563         })
   567     val pri = (0 /: results) { case (p1, Text.Info(_, p2)) => p1 max p2 }
   564     val pri = (0 /: results) { case (p1, Text.Info(_, p2)) => p1 max p2 }
   568 
   565 
   569     val is_separator = pri > 0 &&
   566     val is_separator = pri > 0 &&
   570       snapshot.cumulate_markup[Boolean](range, false, Some(Set(Markup.SEPARATOR)), _ =>
   567       snapshot.cumulate_markup[Boolean](range, false, Set(Markup.SEPARATOR), _ =>
   571         {
   568         {
   572           case (_, Text.Info(_, elem)) =>
   569           case (_, Text.Info(_, elem)) =>
   573             if (elem.name == Markup.SEPARATOR) Some(true) else None
   570             if (elem.name == Markup.SEPARATOR) Some(true) else None
   574         }).exists(_.info)
   571         }).exists(_.info)
   575 
   572 
   591     if (snapshot.is_outdated) List(Text.Info(range, outdated_color))
   588     if (snapshot.is_outdated) List(Text.Info(range, outdated_color))
   592     else
   589     else
   593       for {
   590       for {
   594         Text.Info(r, result) <-
   591         Text.Info(r, result) <-
   595           snapshot.cumulate_markup[(Option[Protocol.Status], Option[Color])](
   592           snapshot.cumulate_markup[(Option[Protocol.Status], Option[Color])](
   596             range, (Some(Protocol.Status.init), None), Some(background1_elements), command_state =>
   593             range, (Some(Protocol.Status.init), None), background1_elements, command_state =>
   597             {
   594             {
   598               case (((Some(status), color), Text.Info(_, XML.Elem(markup, _))))
   595               case (((Some(status), color), Text.Info(_, XML.Elem(markup, _))))
   599               if (Protocol.command_status_markup(markup.name)) =>
   596               if (Protocol.command_status_markup(markup.name)) =>
   600                 Some((Some(Protocol.command_status(status, markup)), color))
   597                 Some((Some(Protocol.command_status(status, markup)), color))
   601               case (_, Text.Info(_, XML.Elem(Markup(Markup.BAD, _), _))) =>
   598               case (_, Text.Info(_, XML.Elem(Markup(Markup.BAD, _), _))) =>
   624       } yield Text.Info(r, color)
   621       } yield Text.Info(r, color)
   625   }
   622   }
   626 
   623 
   627 
   624 
   628   def background2(range: Text.Range): List[Text.Info[Color]] =
   625   def background2(range: Text.Range): List[Text.Info[Color]] =
   629     snapshot.select_markup(range, Some(Set(Markup.TOKEN_RANGE)), _ =>
   626     snapshot.select_markup(range, Set(Markup.TOKEN_RANGE), _ =>
   630       {
   627       {
   631         case Text.Info(_, elem) =>
   628         case Text.Info(_, elem) =>
   632           if (elem.name == Markup.TOKEN_RANGE) Some(light_color) else None
   629           if (elem.name == Markup.TOKEN_RANGE) Some(light_color) else None
   633       })
   630       })
   634 
   631 
   635 
   632 
   636   def bullet(range: Text.Range): List[Text.Info[Color]] =
   633   def bullet(range: Text.Range): List[Text.Info[Color]] =
   637     snapshot.select_markup(range, Some(Set(Markup.BULLET)), _ =>
   634     snapshot.select_markup(range, Set(Markup.BULLET), _ =>
   638       {
   635       {
   639         case Text.Info(_, elem) =>
   636         case Text.Info(_, elem) =>
   640           if (elem.name == Markup.BULLET) Some(bullet_color) else None
   637           if (elem.name == Markup.BULLET) Some(bullet_color) else None
   641       })
   638       })
   642 
   639 
   643 
   640 
   644   private val foreground_elements =
   641   private val foreground_elements =
   645     Set(Markup.STRING, Markup.ALTSTRING, Markup.VERBATIM, Markup.CARTOUCHE, Markup.ANTIQUOTED)
   642     Set(Markup.STRING, Markup.ALTSTRING, Markup.VERBATIM, Markup.CARTOUCHE, Markup.ANTIQUOTED)
   646 
   643 
   647   def foreground(range: Text.Range): List[Text.Info[Color]] =
   644   def foreground(range: Text.Range): List[Text.Info[Color]] =
   648     snapshot.select_markup(range, Some(foreground_elements), _ =>
   645     snapshot.select_markup(range, foreground_elements, _ =>
   649       {
   646       {
   650         case Text.Info(_, elem) =>
   647         case Text.Info(_, elem) =>
   651           if (elem.name == Markup.ANTIQUOTED) Some(antiquoted_color)
   648           if (elem.name == Markup.ANTIQUOTED) Some(antiquoted_color) else Some(quoted_color)
   652           else if (foreground_elements(elem.name)) Some(quoted_color)
       
   653           else None
       
   654       })
   649       })
   655 
   650 
   656 
   651 
   657   private val text_colors: Map[String, Color] = Map(
   652   private val text_colors: Map[String, Color] = Map(
   658       Markup.KEYWORD1 -> keyword1_color,
   653       Markup.KEYWORD1 -> keyword1_color,
   687 
   682 
   688   def text_color(range: Text.Range, color: Color): List[Text.Info[Color]] =
   683   def text_color(range: Text.Range, color: Color): List[Text.Info[Color]] =
   689   {
   684   {
   690     if (color == Token_Markup.hidden_color) List(Text.Info(range, color))
   685     if (color == Token_Markup.hidden_color) List(Text.Info(range, color))
   691     else
   686     else
   692       snapshot.cumulate_markup(range, color, Some(text_color_elements), _ =>
   687       snapshot.cumulate_markup(range, color, text_color_elements, _ =>
   693         {
   688         {
   694           case (_, Text.Info(_, elem)) => text_colors.get(elem.name)
   689           case (_, Text.Info(_, elem)) => text_colors.get(elem.name)
   695         })
   690         })
   696   }
   691   }
   697 
   692 
   698 
   693 
   699   /* nested text structure -- folds */
   694   /* nested text structure -- folds */
   700 
   695 
   701   private val fold_depth_elements = Set(Markup.TEXT_FOLD, Markup.GOAL, Markup.SUBGOAL)
   696   private val fold_depth_elements =
       
   697     Set(Markup.TEXT_FOLD, Markup.GOAL, Markup.SUBGOAL)
   702 
   698 
   703   def fold_depth(range: Text.Range): List[Text.Info[Int]] =
   699   def fold_depth(range: Text.Range): List[Text.Info[Int]] =
   704     snapshot.cumulate_markup[Int](range, 0, Some(fold_depth_elements), _ =>
   700     snapshot.cumulate_markup[Int](range, 0, fold_depth_elements, _ =>
   705       {
   701       {
   706         case (depth, Text.Info(_, elem)) =>
   702         case (depth, _) => Some(depth + 1)
   707           if (fold_depth_elements(elem.name)) Some(depth + 1) else None
       
   708       })
   703       })
   709 }
   704 }