support for begin/end matching;
authorwenzelm
Tue, 21 Oct 2014 20:19:14 +0200
changeset 58752 2077bc9558cf
parent 58751 6de7dbaf3c44
child 58753 960bf499ca5d
support for begin/end matching;
src/Tools/jEdit/src/structure_matching.scala
--- a/src/Tools/jEdit/src/structure_matching.scala	Tue Oct 21 20:18:37 2014 +0200
+++ b/src/Tools/jEdit/src/structure_matching.scala	Tue Oct 21 20:19:14 2014 +0200
@@ -16,6 +16,23 @@
 {
   object Isabelle_Matcher extends StructureMatcher
   {
+    def scan_block(
+      open: Token => Boolean,
+      close: Token => Boolean,
+      reset: Token => Boolean,
+      init_range: Text.Range,
+      init_depth: Int,
+      it: Iterator[Text.Info[Token]]): Option[Text.Range] =
+    {
+      it.scanLeft((init_range, init_depth))(
+        { case ((r, d), Text.Info(range, tok)) =>
+            if (open(tok)) (range, d + 1)
+            else if (close(tok)) (range, d - 1)
+            else if (reset(tok)) (range, 0)
+            else (r, d) }
+      ).collectFirst({ case (r, 0) => r })
+    }
+
     def find_pair(text_area: TextArea): Option[(Text.Range, Text.Range)] =
     {
       val buffer = text_area.getBuffer
@@ -34,15 +51,34 @@
           def rev_iterator(line: Int, lim: Int = limit): Iterator[Text.Info[Token]] =
             Token_Markup.line_token_reverse_iterator(syntax, buffer, line, line - lim)
 
-          iterator(caret_line, 1).find(info => info.range.touches(caret)) match {
+          def caret_iterator(): Iterator[Text.Info[Token]] =
+            iterator(caret_line).dropWhile(info => !info.range.touches(caret))
+
+          def rev_caret_iterator(): Iterator[Text.Info[Token]] =
+            rev_iterator(caret_line).dropWhile(info => !info.range.touches(caret))
+
+          iterator(caret_line, 1).find(info => info.range.touches(caret)) match
+          {
             case Some(Text.Info(range1, tok)) if syntax.command_kind(tok, Keyword.qed_global) =>
-              rev_iterator(caret_line).dropWhile(info => caret <= info.range.stop).
-                find(info => syntax.command_kind(info.info, Keyword.theory))
+              rev_caret_iterator().find(info => syntax.command_kind(info.info, Keyword.theory))
               match {
                 case Some(Text.Info(range2, tok))
                 if syntax.command_kind(tok, Keyword.theory_goal) => Some((range1, range2))
                 case _ => None
               }
+
+            case Some(Text.Info(range1, tok)) if tok.is_begin =>
+              val it = caret_iterator()
+              it.next
+              scan_block(_.is_begin, _.is_end, _ => false, range1, 1, it).
+                map(range2 => (range1, range2))
+
+            case Some(Text.Info(range1, tok)) if tok.is_end =>
+              val it = rev_caret_iterator()
+              it.next
+              scan_block(_.is_end, _.is_begin, _ => false, range1, 1, it).
+                map(range2 => (range1, range2))
+
             case _ => None
           }
         case _ => None