wenzelm@43414: /* Title: Tools/jEdit/src/token_markup.scala wenzelm@43414: Author: Makarius wenzelm@43414: wenzelm@43414: Outer syntax token markup. wenzelm@43414: */ wenzelm@43414: wenzelm@43414: package isabelle.jedit wenzelm@43414: wenzelm@43414: wenzelm@43414: import isabelle._ wenzelm@43414: wenzelm@43482: import java.awt.{Font, Color} wenzelm@43482: import java.awt.font.TextAttribute wenzelm@43482: wenzelm@43482: import org.gjt.sp.util.SyntaxUtilities wenzelm@43452: import org.gjt.sp.jedit.Mode wenzelm@43452: import org.gjt.sp.jedit.syntax.{Token => JEditToken, TokenMarker, TokenHandler, wenzelm@43482: ParserRuleSet, ModeProvider, XModeHandler, SyntaxStyle} wenzelm@43452: wenzelm@43414: import javax.swing.text.Segment wenzelm@43414: wenzelm@43414: wenzelm@43414: object Token_Markup wenzelm@43414: { wenzelm@43443: /* extended syntax styles */ wenzelm@43414: wenzelm@43440: private val plain_range: Int = JEditToken.ID_COUNT wenzelm@43482: private val full_range: Int = 4 * plain_range + 1 wenzelm@43414: private def check_range(i: Int) { require(0 <= i && i < plain_range) } wenzelm@43414: wenzelm@43414: def subscript(i: Byte): Byte = { check_range(i); (i + plain_range).toByte } wenzelm@43414: def superscript(i: Byte): Byte = { check_range(i); (i + 2 * plain_range).toByte } wenzelm@43460: def bold(i: Byte): Byte = { check_range(i); (i + 3 * plain_range).toByte } wenzelm@43460: val hidden: Byte = (4 * plain_range).toByte wenzelm@43414: wenzelm@43482: private def script_style(style: SyntaxStyle, i: Int): SyntaxStyle = wenzelm@43482: { wenzelm@43482: import scala.collection.JavaConversions._ wenzelm@43482: val font = style.getFont.deriveFont(Map(TextAttribute.SUPERSCRIPT -> new java.lang.Integer(i))) wenzelm@43482: new SyntaxStyle(style.getForegroundColor, style.getBackgroundColor, font) wenzelm@43482: } wenzelm@43482: wenzelm@43482: private def bold_style(style: SyntaxStyle): SyntaxStyle = wenzelm@43482: new SyntaxStyle(style.getForegroundColor, style.getBackgroundColor, wenzelm@43482: style.getFont.deriveFont(Font.BOLD)) wenzelm@43482: wenzelm@43482: class Style_Extender extends SyntaxUtilities.StyleExtender wenzelm@43482: { wenzelm@43482: override def extendStyles(styles: Array[SyntaxStyle]): Array[SyntaxStyle] = wenzelm@43482: { wenzelm@43482: val new_styles = new Array[SyntaxStyle](full_range) wenzelm@43482: for (i <- 0 until plain_range) { wenzelm@43482: val style = styles(i) wenzelm@43482: new_styles(i) = style wenzelm@43482: new_styles(subscript(i.toByte)) = script_style(style, -1) wenzelm@43482: new_styles(superscript(i.toByte)) = script_style(style, 1) wenzelm@43482: new_styles(bold(i.toByte)) = bold_style(style) wenzelm@43482: } wenzelm@43482: new_styles(hidden) = wenzelm@43482: new SyntaxStyle(Color.white, null, new Font(styles(0).getFont.getFamily, 0, 1)) wenzelm@43482: new_styles wenzelm@43482: } wenzelm@43482: } wenzelm@43482: wenzelm@43443: private def extended_styles(symbols: Symbol.Interpretation, text: CharSequence) wenzelm@43443: : Map[Text.Offset, Byte => Byte] = wenzelm@43443: { wenzelm@43482: // FIXME \\<^bsub> \\<^esub> \\<^bsup> \\<^esup> wenzelm@43482: def ctrl_style(sym: String): Option[Byte => Byte] = wenzelm@43482: if (symbols.is_subscript_decoded(sym)) Some(subscript(_)) wenzelm@43482: else if (symbols.is_superscript_decoded(sym)) Some(superscript(_)) wenzelm@43482: else if (symbols.is_bold_decoded(sym)) Some(bold(_)) wenzelm@43482: else None wenzelm@43455: wenzelm@43482: var result = Map[Text.Offset, Byte => Byte]() wenzelm@43482: def mark(start: Text.Offset, stop: Text.Offset, style: Byte => Byte) wenzelm@43482: { wenzelm@43482: for (i <- start until stop) result += (i -> style) wenzelm@43482: } wenzelm@43482: var offset = 0 wenzelm@43482: var ctrl = "" wenzelm@43482: for (sym <- Symbol.iterator(text).map(_.toString)) { wenzelm@43482: if (ctrl_style(sym).isDefined) ctrl = sym wenzelm@43482: else if (ctrl != "") { wenzelm@43482: if (symbols.is_controllable(sym) && sym != "\"") { wenzelm@43482: mark(offset - ctrl.length, offset, _ => hidden) wenzelm@43482: mark(offset, offset + sym.length, ctrl_style(ctrl).get) wenzelm@43482: } wenzelm@43482: ctrl = "" wenzelm@43443: } wenzelm@43482: offset += sym.length wenzelm@43443: } wenzelm@43482: result wenzelm@43443: } wenzelm@43443: wenzelm@43414: wenzelm@43414: /* token marker */ wenzelm@43414: wenzelm@43414: private val isabelle_rules = new ParserRuleSet("isabelle", "MAIN") wenzelm@43414: wenzelm@43429: private class Line_Context(val context: Scan.Context) wenzelm@43429: extends TokenMarker.LineContext(isabelle_rules, null) wenzelm@43414: { wenzelm@43414: override def hashCode: Int = context.hashCode wenzelm@43414: override def equals(that: Any): Boolean = wenzelm@43414: that match { wenzelm@43414: case other: Line_Context => context == other.context wenzelm@43414: case _ => false wenzelm@43414: } wenzelm@43414: } wenzelm@43414: wenzelm@43452: class Marker extends TokenMarker wenzelm@43452: { wenzelm@43452: override def markTokens(context: TokenMarker.LineContext, wenzelm@43452: handler: TokenHandler, line: Segment): TokenMarker.LineContext = wenzelm@43452: { wenzelm@43452: val symbols = Isabelle.system.symbols wenzelm@43452: val syntax = Isabelle.session.current_syntax() wenzelm@43414: wenzelm@43452: val ctxt = wenzelm@43452: context match { wenzelm@43452: case c: Line_Context => c.context wenzelm@43452: case _ => Scan.Finished wenzelm@43452: } wenzelm@43452: val (tokens, ctxt1) = syntax.scan_context(line, ctxt) wenzelm@43452: val context1 = new Line_Context(ctxt1) wenzelm@43452: wenzelm@43452: val extended = extended_styles(symbols, line) wenzelm@43443: wenzelm@43452: var offset = 0 wenzelm@43452: for (token <- tokens) { wenzelm@43452: val style = Isabelle_Markup.token_markup(syntax, token) wenzelm@43452: val length = token.source.length wenzelm@43452: val end_offset = offset + length wenzelm@43452: if ((offset until end_offset) exists extended.isDefinedAt) { wenzelm@43452: for (i <- offset until end_offset) { wenzelm@43452: val style1 = wenzelm@43452: extended.get(i) match { wenzelm@43452: case None => style wenzelm@43452: case Some(ext) => ext(style) wenzelm@43452: } wenzelm@43452: handler.handleToken(line, style1, i, 1, context1) wenzelm@43443: } wenzelm@43414: } wenzelm@43452: else handler.handleToken(line, style, offset, length, context1) wenzelm@43452: offset += length wenzelm@43452: } wenzelm@43452: handler.handleToken(line, JEditToken.END, line.count, 0, context1) wenzelm@43452: wenzelm@43452: val context2 = context1.intern wenzelm@43452: handler.setLineContext(context2) wenzelm@43452: context2 wenzelm@43452: } wenzelm@43452: } wenzelm@43452: wenzelm@43416: wenzelm@43452: /* mode provider */ wenzelm@43452: wenzelm@43452: class Mode_Provider(orig_provider: ModeProvider) extends ModeProvider wenzelm@43452: { wenzelm@43452: for (mode <- orig_provider.getModes) addMode(mode) wenzelm@43452: wenzelm@43452: val isabelle_token_marker = new Token_Markup.Marker wenzelm@43452: wenzelm@43452: override def loadMode(mode: Mode, xmh: XModeHandler) wenzelm@43452: { wenzelm@43452: super.loadMode(mode, xmh) wenzelm@43452: if (mode.getName == "isabelle") wenzelm@43452: mode.setTokenMarker(isabelle_token_marker) wenzelm@43414: } wenzelm@43452: } wenzelm@43414: } wenzelm@43414: