src/Tools/jEdit/src/token_markup.scala
author wenzelm
Mon, 01 Mar 2021 23:17:47 +0100
changeset 73344 f5c147654661
parent 73340 0ffcad1f6130
child 73353 279e45248e9d
permissions -rw-r--r--
tuned --- fewer warnings;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43414
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
     1
/*  Title:      Tools/jEdit/src/token_markup.scala
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
     3
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
     4
Outer syntax token markup.
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
     5
*/
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
     6
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
     7
package isabelle.jedit
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
     8
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
     9
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    10
import isabelle._
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    11
63421
3bf02e7fa8a3 basic setup for indentation;
wenzelm
parents: 62104
diff changeset
    12
import javax.swing.text.Segment
3bf02e7fa8a3 basic setup for indentation;
wenzelm
parents: 62104
diff changeset
    13
71783
73dee865d567 avoid deprecated operations;
wenzelm
parents: 67126
diff changeset
    14
import scala.collection.JavaConverters
43482
ebb90ff55b79 added SyntaxUtilities.StyleExtender hook, with actual functionality in Isabelle/Scala;
wenzelm
parents: 43464
diff changeset
    15
65259
41d12227d5dc clarified modules;
wenzelm
parents: 65258
diff changeset
    16
import org.gjt.sp.jedit.{Mode, Buffer}
58701
cc83453fac15 make double-sure that line context is present, e.g. relevant for last line after visible text;
wenzelm
parents: 58699
diff changeset
    17
import org.gjt.sp.jedit.syntax.{Token => JEditToken, TokenMarker, TokenHandler, DummyTokenHandler,
65259
41d12227d5dc clarified modules;
wenzelm
parents: 65258
diff changeset
    18
  ParserRuleSet, ModeProvider, XModeHandler}
63422
5cf8dd98a717 clarified modules;
wenzelm
parents: 63421
diff changeset
    19
import org.gjt.sp.jedit.indent.IndentRule
61192
98eba31c51f8 tuned signature;
wenzelm
parents: 60238
diff changeset
    20
import org.gjt.sp.jedit.buffer.JEditBuffer
43452
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
    21
43414
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    22
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    23
object Token_Markup
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    24
{
58529
cd4439d8799c support for bibtex token markup;
wenzelm
parents: 57612
diff changeset
    25
  /* line context */
43414
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    26
58748
8f92f17d8781 support for structure matching;
wenzelm
parents: 58701
diff changeset
    27
  object Line_Context
8f92f17d8781 support for structure matching;
wenzelm
parents: 58701
diff changeset
    28
  {
63444
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
    29
    def init(mode: String): Line_Context =
63603
9d9ea2c6bc38 clarified modules;
wenzelm
parents: 63454
diff changeset
    30
      new Line_Context(mode, Some(Scan.Finished), Line_Structure.init)
63454
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    31
66176
b51a40281016 tuned signature;
wenzelm
parents: 65259
diff changeset
    32
    def before(buffer: JEditBuffer, line: Int): Line_Context =
63454
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    33
      if (line == 0) init(JEdit_Lib.buffer_mode(buffer))
66176
b51a40281016 tuned signature;
wenzelm
parents: 65259
diff changeset
    34
      else after(buffer, line - 1)
63454
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    35
66176
b51a40281016 tuned signature;
wenzelm
parents: 65259
diff changeset
    36
    def after(buffer: JEditBuffer, line: Int): Line_Context =
63454
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    37
    {
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    38
      val line_mgr = JEdit_Lib.buffer_line_manager(buffer)
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    39
      def context =
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    40
        line_mgr.getLineContext(line) match {
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    41
          case c: Line_Context => Some(c)
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    42
          case _ => None
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    43
        }
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    44
      context getOrElse {
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    45
        buffer.markTokens(line, DummyTokenHandler.INSTANCE)
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    46
        context getOrElse init(JEdit_Lib.buffer_mode(buffer))
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    47
      }
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    48
    }
58748
8f92f17d8781 support for structure matching;
wenzelm
parents: 58701
diff changeset
    49
  }
8f92f17d8781 support for structure matching;
wenzelm
parents: 58701
diff changeset
    50
58699
e46afcceb781 tuned signature;
wenzelm
parents: 58698
diff changeset
    51
  class Line_Context(
63444
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
    52
      val mode: String,
58699
e46afcceb781 tuned signature;
wenzelm
parents: 58698
diff changeset
    53
      val context: Option[Scan.Line_Context],
63603
9d9ea2c6bc38 clarified modules;
wenzelm
parents: 63454
diff changeset
    54
      val structure: Line_Structure)
63444
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
    55
    extends TokenMarker.LineContext(new ParserRuleSet(mode, "MAIN"), null)
43414
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    56
  {
63454
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    57
    def get_context: Scan.Line_Context = context.getOrElse(Scan.Finished)
08a1f61a49a6 tuned signature;
wenzelm
parents: 63444
diff changeset
    58
63444
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
    59
    override def hashCode: Int = (mode, context, structure).hashCode
43414
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    60
    override def equals(that: Any): Boolean =
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    61
      that match {
63444
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
    62
        case other: Line_Context =>
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
    63
          mode == other.mode && context == other.context && structure == other.structure
43414
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    64
        case _ => false
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    65
      }
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    66
  }
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
    67
58749
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    68
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
    69
  /* tokens from line (inclusive) */
58749
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    70
58802
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
    71
  private def try_line_tokens(syntax: Outer_Syntax, buffer: JEditBuffer, line: Int)
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
    72
    : Option[List[Token]] =
58748
8f92f17d8781 support for structure matching;
wenzelm
parents: 58701
diff changeset
    73
  {
66176
b51a40281016 tuned signature;
wenzelm
parents: 65259
diff changeset
    74
    val line_context = Line_Context.before(buffer, line)
58748
8f92f17d8781 support for structure matching;
wenzelm
parents: 58701
diff changeset
    75
    for {
8f92f17d8781 support for structure matching;
wenzelm
parents: 58701
diff changeset
    76
      ctxt <- line_context.context
67014
e6a695d6a6b2 tuned signature;
wenzelm
parents: 66176
diff changeset
    77
      text <- JEdit_Lib.get_text(buffer, JEdit_Lib.line_range(buffer, line))
59083
88b0b1f28adc tuned signature;
wenzelm
parents: 59079
diff changeset
    78
    } yield Token.explode_line(syntax.keywords, text, ctxt)._1
58748
8f92f17d8781 support for structure matching;
wenzelm
parents: 58701
diff changeset
    79
  }
58699
e46afcceb781 tuned signature;
wenzelm
parents: 58698
diff changeset
    80
58749
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    81
  def line_token_iterator(
58750
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    82
      syntax: Outer_Syntax,
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    83
      buffer: JEditBuffer,
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    84
      start_line: Int,
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    85
      end_line: Int): Iterator[Text.Info[Token]] =
58749
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    86
    for {
58750
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    87
      line <- Range(start_line max 0, end_line min buffer.getLineCount).iterator
58749
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    88
      tokens <- try_line_tokens(syntax, buffer, line).iterator
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    89
      starts =
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    90
        tokens.iterator.scanLeft(buffer.getLineStartOffset(line))(
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    91
          (i, tok) => i + tok.source.length)
58750
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    92
      (i, tok) <- starts zip tokens.iterator
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    93
    } yield Text.Info(Text.Range(i, i + tok.source.length), tok)
58749
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    94
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
    95
  def line_token_reverse_iterator(
58750
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    96
      syntax: Outer_Syntax,
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    97
      buffer: JEditBuffer,
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    98
      start_line: Int,
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
    99
      end_line: Int): Iterator[Text.Info[Token]] =
58749
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
   100
    for {
58750
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
   101
      line <- Range(start_line min (buffer.getLineCount - 1), end_line max -1, -1).iterator
58749
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
   102
      tokens <- try_line_tokens(syntax, buffer, line).iterator
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
   103
      stops =
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
   104
        tokens.reverseIterator.scanLeft(buffer.getLineEndOffset(line) min buffer.getLength)(
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
   105
          (i, tok) => i - tok.source.length)
58750
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
   106
      (i, tok) <- stops zip tokens.reverseIterator
1b4b005d73c1 added option jedit_structure_limit;
wenzelm
parents: 58749
diff changeset
   107
    } yield Text.Info(Text.Range(i - tok.source.length, i), tok)
58749
83b0f633190e some structure matching, based on line token iterators;
wenzelm
parents: 58748
diff changeset
   108
58694
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   109
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   110
  /* tokens from offset (inclusive) */
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   111
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   112
  def token_iterator(syntax: Outer_Syntax, buffer: JEditBuffer, offset: Text.Offset):
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   113
      Iterator[Text.Info[Token]] =
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   114
    if (JEdit_Lib.buffer_range(buffer).contains(offset))
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   115
      line_token_iterator(syntax, buffer, buffer.getLineOfOffset(offset), buffer.getLineCount).
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   116
        dropWhile(info => !info.range.contains(offset))
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   117
    else Iterator.empty
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   118
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   119
  def token_reverse_iterator(syntax: Outer_Syntax, buffer: JEditBuffer, offset: Text.Offset):
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   120
      Iterator[Text.Info[Token]] =
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   121
    if (JEdit_Lib.buffer_range(buffer).contains(offset))
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   122
      line_token_reverse_iterator(syntax, buffer, buffer.getLineOfOffset(offset), -1).
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   123
        dropWhile(info => !info.range.contains(offset))
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   124
    else Iterator.empty
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   125
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   126
58809
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   127
  /* command spans */
58802
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   128
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   129
  def command_span(syntax: Outer_Syntax, buffer: JEditBuffer, offset: Text.Offset)
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   130
    : Option[Text.Info[Command_Span.Span]] =
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   131
  {
63441
4c3fa4dba79f explicit kind "before_command";
wenzelm
parents: 63422
diff changeset
   132
    val keywords = syntax.keywords
4c3fa4dba79f explicit kind "before_command";
wenzelm
parents: 63422
diff changeset
   133
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   134
    def maybe_command_start(i: Text.Offset): Option[Text.Info[Token]] =
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   135
      token_reverse_iterator(syntax, buffer, i).
63441
4c3fa4dba79f explicit kind "before_command";
wenzelm
parents: 63422
diff changeset
   136
        find(info => keywords.is_before_command(info.info) || info.info.is_command)
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   137
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   138
    def maybe_command_stop(i: Text.Offset): Option[Text.Info[Token]] =
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   139
      token_iterator(syntax, buffer, i).
63441
4c3fa4dba79f explicit kind "before_command";
wenzelm
parents: 63422
diff changeset
   140
        find(info => keywords.is_before_command(info.info) || info.info.is_command)
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   141
58802
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   142
    if (JEdit_Lib.buffer_range(buffer).contains(offset)) {
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   143
      val start_info =
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   144
      {
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   145
        val info1 = maybe_command_start(offset)
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   146
        info1 match {
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   147
          case Some(Text.Info(range1, tok1)) if tok1.is_command =>
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   148
            val info2 = maybe_command_start(range1.start - 1)
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   149
            info2 match {
63441
4c3fa4dba79f explicit kind "before_command";
wenzelm
parents: 63422
diff changeset
   150
              case Some(Text.Info(_, tok2)) if keywords.is_before_command(tok2) => info2
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   151
              case _ => info1
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   152
            }
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   153
          case _ => info1
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   154
        }
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   155
      }
63441
4c3fa4dba79f explicit kind "before_command";
wenzelm
parents: 63422
diff changeset
   156
      val (start_before_command, start, start_next) =
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   157
        start_info match {
63441
4c3fa4dba79f explicit kind "before_command";
wenzelm
parents: 63422
diff changeset
   158
          case Some(Text.Info(range, tok)) =>
4c3fa4dba79f explicit kind "before_command";
wenzelm
parents: 63422
diff changeset
   159
            (keywords.is_before_command(tok), range.start, range.stop)
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   160
          case None => (false, 0, 0)
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   161
        }
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   162
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   163
      val stop_info =
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   164
      {
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   165
        val info1 = maybe_command_stop(start_next)
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   166
        info1 match {
63441
4c3fa4dba79f explicit kind "before_command";
wenzelm
parents: 63422
diff changeset
   167
          case Some(Text.Info(range1, tok1)) if tok1.is_command && start_before_command =>
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   168
            maybe_command_stop(range1.stop)
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   169
          case _ => info1
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   170
        }
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   171
      }
58802
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   172
      val stop =
59924
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   173
        stop_info match {
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   174
          case Some(Text.Info(range, _)) => range.start
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   175
          case None => buffer.getLength
801b979ec0c2 more general notion of command span: command keyword not necessarily at start;
wenzelm
parents: 59286
diff changeset
   176
        }
58802
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   177
67014
e6a695d6a6b2 tuned signature;
wenzelm
parents: 66176
diff changeset
   178
      val text = JEdit_Lib.get_text(buffer, Text.Range(start, stop)).getOrElse("")
58802
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   179
      val spans = syntax.parse_spans(text)
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   180
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   181
      (spans.iterator.scanLeft(start)(_ + _.length) zip spans.iterator).
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   182
        map({ case (i, span) => Text.Info(Text.Range(i, i + span.length), span) }).
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   183
        find(_.range.contains(offset))
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   184
    }
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   185
    else None
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   186
  }
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   187
58809
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   188
  private def _command_span_iterator(
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   189
      syntax: Outer_Syntax,
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   190
      buffer: JEditBuffer,
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   191
      offset: Text.Offset,
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   192
      next_offset: Text.Range => Text.Offset): Iterator[Text.Info[Command_Span.Span]] =
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   193
    new Iterator[Text.Info[Command_Span.Span]]
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   194
    {
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   195
      private var next_span = command_span(syntax, buffer, offset)
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   196
      def hasNext: Boolean = next_span.isDefined
73337
0af9e7e4476f tuned --- fewer warnings;
wenzelm
parents: 71933
diff changeset
   197
      def next(): Text.Info[Command_Span.Span] =
58809
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   198
      {
73344
f5c147654661 tuned --- fewer warnings;
wenzelm
parents: 73340
diff changeset
   199
        val span = next_span.getOrElse(Iterator.empty.next())
58809
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   200
        next_span = command_span(syntax, buffer, next_offset(span.range))
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   201
        span
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   202
      }
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   203
    }
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   204
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   205
  def command_span_iterator(syntax: Outer_Syntax, buffer: JEditBuffer, offset: Text.Offset)
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   206
      : Iterator[Text.Info[Command_Span.Span]] =
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   207
    _command_span_iterator(syntax, buffer, offset max 0, range => range.stop)
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   208
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   209
  def command_span_reverse_iterator(syntax: Outer_Syntax, buffer: JEditBuffer, offset: Text.Offset)
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   210
      : Iterator[Text.Info[Command_Span.Span]] =
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   211
    _command_span_iterator(syntax, buffer,
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   212
      (offset min buffer.getLength) - 1, range => range.start - 1)
3c34490ccd4c more iterators;
wenzelm
parents: 58802
diff changeset
   213
58802
3cc68ec558b0 find command span in buffer;
wenzelm
parents: 58750
diff changeset
   214
58694
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   215
  /* token marker */
58683
c9b7a00d5a10 buffer_line_context via untyped access;
wenzelm
parents: 58529
diff changeset
   216
59077
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   217
  class Marker(
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   218
    protected val mode: String,
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   219
    protected val opt_buffer: Option[Buffer]) extends TokenMarker
43452
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   220
  {
59077
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   221
    override def hashCode: Int = (mode, opt_buffer).hashCode
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   222
    override def equals(that: Any): Boolean =
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   223
      that match {
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   224
        case other: Marker => mode == other.mode && opt_buffer == other.opt_buffer
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   225
        case _ => false
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   226
      }
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   227
59076
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   228
    override def toString: String =
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   229
      opt_buffer match {
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   230
        case None => "Marker(" + mode + ")"
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   231
        case Some(buffer) => "Marker(" + mode + "," + JEdit_Lib.buffer_name(buffer) + ")"
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   232
      }
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   233
43452
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   234
    override def markTokens(context: TokenMarker.LineContext,
46210
553ec602d337 paranoia null check -- prevent spurious crash of jedit token markup;
wenzelm
parents: 46178
diff changeset
   235
        handler: TokenHandler, raw_line: Segment): TokenMarker.LineContext =
43452
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   236
    {
46210
553ec602d337 paranoia null check -- prevent spurious crash of jedit token markup;
wenzelm
parents: 46178
diff changeset
   237
      val line = if (raw_line == null) new Segment else raw_line
63444
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
   238
      val line_context =
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
   239
        context match { case c: Line_Context => c case _ => Line_Context.init(mode) }
58748
8f92f17d8781 support for structure matching;
wenzelm
parents: 58701
diff changeset
   240
      val structure = line_context.structure
46210
553ec602d337 paranoia null check -- prevent spurious crash of jedit token markup;
wenzelm
parents: 46178
diff changeset
   241
43553
df80747342cb proper tokens only if session is ready;
wenzelm
parents: 43511
diff changeset
   242
      val context1 =
44702
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   243
      {
59076
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   244
        val opt_syntax =
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   245
          opt_buffer match {
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   246
            case Some(buffer) => Isabelle.buffer_syntax(buffer)
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   247
            case None => Isabelle.mode_syntax(mode)
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   248
          }
44702
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   249
        val (styled_tokens, context1) =
59076
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   250
          (line_context.context, opt_syntax) match {
58694
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   251
            case (Some(ctxt), _) if mode == "isabelle-ml" || mode == "sml" =>
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   252
              val (tokens, ctxt1) = ML_Lex.tokenize_line(mode == "sml", line, ctxt)
64621
7116f2634e32 clarified module name;
wenzelm
parents: 63603
diff changeset
   253
              val styled_tokens =
7116f2634e32 clarified module name;
wenzelm
parents: 63603
diff changeset
   254
                tokens.map(tok => (JEdit_Rendering.ml_token_markup(tok), tok.source))
63444
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
   255
              (styled_tokens, new Line_Context(line_context.mode, Some(ctxt1), structure))
58694
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   256
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   257
            case (Some(ctxt), Some(syntax)) if syntax.has_tokens =>
59083
88b0b1f28adc tuned signature;
wenzelm
parents: 59079
diff changeset
   258
              val (tokens, ctxt1) = Token.explode_line(syntax.keywords, line, ctxt)
63603
9d9ea2c6bc38 clarified modules;
wenzelm
parents: 63454
diff changeset
   259
              val structure1 = structure.update(syntax.keywords, tokens)
58694
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   260
              val styled_tokens =
64621
7116f2634e32 clarified module name;
wenzelm
parents: 63603
diff changeset
   261
                tokens.map(tok => (JEdit_Rendering.token_markup(syntax, tok), tok.source))
63444
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
   262
              (styled_tokens, new Line_Context(line_context.mode, Some(ctxt1), structure1))
58694
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   263
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   264
            case _ =>
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   265
              val styled_token = (JEditToken.NULL, line.subSequence(0, line.count).toString)
63444
8191c3e9f2d3 support more modes;
wenzelm
parents: 63441
diff changeset
   266
              (List(styled_token), new Line_Context(line_context.mode, None, structure))
44702
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   267
          }
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   268
65258
a0701669d159 clarified modules;
wenzelm
parents: 64621
diff changeset
   269
        val extended = Syntax_Style.extended(line)
71933
aec0f7b58cc6 proper rendering of complex codepoints, e.g. \<^url> code: 0x01F310;
wenzelm
parents: 71783
diff changeset
   270
        def special(i: Int): Boolean = extended.isDefinedAt(i) || line.charAt(i) == '\t'
44702
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   271
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   272
        var offset = 0
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   273
        for ((style, token) <- styled_tokens) {
55500
cdbbaa3074a8 isabelle-ml mode with separate token marker;
wenzelm
parents: 53785
diff changeset
   274
          val length = token.length
71933
aec0f7b58cc6 proper rendering of complex codepoints, e.g. \<^url> code: 0x01F310;
wenzelm
parents: 71783
diff changeset
   275
          if ((offset until (offset + length)).exists(special)) {
aec0f7b58cc6 proper rendering of complex codepoints, e.g. \<^url> code: 0x01F310;
wenzelm
parents: 71783
diff changeset
   276
            for ((c, i) <- Codepoint.iterator_offset(token)) {
44702
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   277
              val style1 =
71933
aec0f7b58cc6 proper rendering of complex codepoints, e.g. \<^url> code: 0x01F310;
wenzelm
parents: 71783
diff changeset
   278
                extended.get(offset + i) match {
44702
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   279
                  case None => style
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   280
                  case Some(ext) => ext(style)
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   281
                }
71933
aec0f7b58cc6 proper rendering of complex codepoints, e.g. \<^url> code: 0x01F310;
wenzelm
parents: 71783
diff changeset
   282
              handler.handleToken(line, style1, offset + i, Character.charCount(c), context1)
43553
df80747342cb proper tokens only if session is ready;
wenzelm
parents: 43511
diff changeset
   283
            }
df80747342cb proper tokens only if session is ready;
wenzelm
parents: 43511
diff changeset
   284
          }
44702
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   285
          else handler.handleToken(line, style, offset, length, context1)
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   286
          offset += length
43452
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   287
        }
44702
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   288
        handler.handleToken(line, JEditToken.END, line.count, 0, context1)
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   289
        context1
eb00752507c7 improved handling of extended styles and hard tabs when prover is inactive;
wenzelm
parents: 44701
diff changeset
   290
      }
58694
983e98da2a42 support line context with depth;
wenzelm
parents: 58693
diff changeset
   291
43452
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   292
      val context2 = context1.intern
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   293
      handler.setLineContext(context2)
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   294
      context2
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   295
    }
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   296
  }
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   297
43416
e730cdd97dcf more precise imitatation of original TokenMarker: no locking, interned context etc.;
wenzelm
parents: 43414
diff changeset
   298
43452
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   299
  /* mode provider */
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   300
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   301
  class Mode_Provider(orig_provider: ModeProvider) extends ModeProvider
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   302
  {
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   303
    for (mode <- orig_provider.getModes) addMode(mode)
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   304
73340
0ffcad1f6130 tuned --- fewer warnings;
wenzelm
parents: 73337
diff changeset
   305
    override def loadMode(mode: Mode, xmh: XModeHandler): Unit =
43452
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   306
    {
5cf548485529 avoid setTokenMarker fluctuation on buffer reload etc. via static isabelle_token_marker, which is installed by hijacking the jEdit ModeProvider;
wenzelm
parents: 43443
diff changeset
   307
      super.loadMode(mode, xmh)
59076
65babcd8b0e6 clarified token marker / syntax for mode vs. buffer;
wenzelm
parents: 59063
diff changeset
   308
      Isabelle.mode_token_marker(mode.getName).foreach(mode.setTokenMarker _)
63422
5cf8dd98a717 clarified modules;
wenzelm
parents: 63421
diff changeset
   309
      Isabelle.indent_rule(mode.getName).foreach(indent_rule =>
63421
3bf02e7fa8a3 basic setup for indentation;
wenzelm
parents: 62104
diff changeset
   310
        Untyped.set[java.util.List[IndentRule]](
71783
73dee865d567 avoid deprecated operations;
wenzelm
parents: 67126
diff changeset
   311
          mode, "indentRules", JavaConverters.seqAsJavaList(List(indent_rule))))
53277
6aa348237973 more uniform configuration of editor modes and token markers;
wenzelm
parents: 53274
diff changeset
   312
    }
44358
2a2df4de1bbe more robust initialization of token marker and line context wrt. session startup;
wenzelm
parents: 44356
diff changeset
   313
  }
43414
f0770743b7ec static token markup, based on outer syntax only;
wenzelm
parents:
diff changeset
   314
}