src/Tools/jEdit/src/proofdocument/proof_document.scala
changeset 34818 7df68a8f0e3e
parent 34815 6bae73cd8e33
child 34819 86cb7f8e5a0d
equal deleted inserted replaced
34817:b4efd0ef2f3e 34818:7df68a8f0e3e
     7  */
     7  */
     8 
     8 
     9 package isabelle.proofdocument
     9 package isabelle.proofdocument
    10 
    10 
    11 
    11 
       
    12 import scala.actors.Actor._
       
    13 
    12 import java.util.regex.Pattern
    14 import java.util.regex.Pattern
    13 
    15 
    14 
    16 
    15 object Proof_Document
    17 object Proof_Document
    16 {
    18 {
    17   // Be careful when changing this regex. Not only must it handle the
    19   // Be careful when changing this regex. Not only must it handle the
    18   // spurious end of a token but also:  
    20   // spurious end of a token but also:
    19   // Bug ID: 5050507 Pattern.matches throws StackOverflow Error
    21   // Bug ID: 5050507 Pattern.matches throws StackOverflow Error
    20   // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5050507
    22   // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5050507
    21   
    23 
    22   val token_pattern = 
    24   val token_pattern =
    23     Pattern.compile(
    25     Pattern.compile(
    24       "\\{\\*([^*]|\\*[^}]|\\*\\z)*(\\z|\\*\\})|" +
    26       "\\{\\*([^*]|\\*[^}]|\\*\\z)*(\\z|\\*\\})|" +
    25       "\\(\\*([^*]|\\*[^)]|\\*\\z)*(\\z|\\*\\))|" +
    27       "\\(\\*([^*]|\\*[^)]|\\*\\z)*(\\z|\\*\\))|" +
    26       "(\\?'?|')[A-Za-z_0-9.]*|" + 
    28       "(\\?'?|')[A-Za-z_0-9.]*|" +
    27       "[A-Za-z_0-9.]+|" + 
    29       "[A-Za-z_0-9.]+|" +
    28       "[!#$%&*+-/<=>?@^_|~]+|" +
    30       "[!#$%&*+-/<=>?@^_|~]+|" +
    29       "\"([^\\\\\"]?(\\\\(.|\\z))?)*+(\"|\\z)|" +
    31       "\"([^\\\\\"]?(\\\\(.|\\z))?)*+(\"|\\z)|" +
    30       "`([^\\\\`]?(\\\\(.|\\z))?)*+(`|\\z)|" +
    32       "`([^\\\\`]?(\\\\(.|\\z))?)*+(`|\\z)|" +
    31       "[()\\[\\]{}:;]", Pattern.MULTILINE)
    33       "[()\\[\\]{}:;]", Pattern.MULTILINE)
    32 
    34 
    36   type StructureChange = List[(Option[Command], Option[Command])]
    38   type StructureChange = List[(Option[Command], Option[Command])]
    37 }
    39 }
    38 
    40 
    39 
    41 
    40 class Proof_Document(
    42 class Proof_Document(
    41   val id: Isar_Document.Document_ID,
    43     val id: Isar_Document.Document_ID,
    42   val tokens: Linear_Set[Token],   // FIXME plain List, inside Command
    44     val tokens: Linear_Set[Token],   // FIXME plain List, inside Command
    43   val token_start: Map[Token, Int],  // FIXME eliminate
    45     val token_start: Map[Token, Int],  // FIXME eliminate
    44   val commands: Linear_Set[Command],
    46     val commands: Linear_Set[Command],
    45   var states: Map[Command, Command])   // FIXME immutable, eliminate!?
    47     var states: Map[Command, Command])   // FIXME immutable, eliminate!?
       
    48   extends Session.Entity
    46 {
    49 {
    47   import Proof_Document.StructureChange
    50   import Proof_Document.StructureChange
    48 
    51 
    49   def content = Token.string_from_tokens(Nil ++ tokens, token_start)
    52   def content = Token.string_from_tokens(Nil ++ tokens, token_start)
    50 
    53 
    51 
    54 
    52   
    55   /* accumulated messages */
       
    56 
       
    57   private val accumulator = actor {
       
    58     loop {
       
    59       react {
       
    60         case (session: Session, message: XML.Tree) =>
       
    61           message match {
       
    62             case XML.Elem(Markup.MESSAGE, (Markup.CLASS, Markup.STATUS) :: _, elems) =>
       
    63               for {
       
    64                 XML.Elem(Markup.EDIT, (Markup.ID, cmd_id) :: (Markup.STATE, state_id) :: _, _)
       
    65                   <- elems
       
    66               } {
       
    67                 session.lookup_entity(cmd_id) match {
       
    68                   case Some(cmd: Command) =>
       
    69                     val state = cmd.finish_static(state_id)
       
    70                     session.register_entity(state)
       
    71                     states += (cmd -> state)  // FIXME !?
       
    72                     session.command_change.event(cmd)   // FIXME really!?
       
    73                   case _ =>
       
    74                 }
       
    75               }
       
    76             case _ =>
       
    77           }
       
    78 
       
    79         case bad => System.err.println("document accumulator: ignoring bad message " + bad)
       
    80       }
       
    81     }
       
    82   }
       
    83 
       
    84   def consume(session: Session, message: XML.Tree) { accumulator ! (session, message) }
       
    85 
       
    86 
       
    87 
    53   /** token view **/
    88   /** token view **/
    54 
    89 
    55   def text_changed(session: Session, change: Change): (Proof_Document, StructureChange) =
    90   def text_changed(session: Session, change: Change): (Proof_Document, StructureChange) =
    56   {
    91   {
    57     def edit_doc(doc_chgs: (Proof_Document, StructureChange), edit: Edit) = {
    92     def edit_doc(doc_chgs: (Proof_Document, StructureChange), edit: Edit) = {
    99     start = split_end.foldLeft (start) ((s, t) =>
   134     start = split_end.foldLeft (start) ((s, t) =>
   100     s + (t -> (change.start + change.added.length)))
   135     s + (t -> (change.start + change.added.length)))
   101 
   136 
   102     val ins = new Token(change.added, Token.Kind.OTHER)
   137     val ins = new Token(change.added, Token.Kind.OTHER)
   103     start += (ins -> change.start)
   138     start += (ins -> change.start)
   104     
   139 
   105     var invalid_tokens = split_begin ::: ins :: split_end ::: end
   140     var invalid_tokens = split_begin ::: ins :: split_end ::: end
   106     var new_tokens: List[Token] = Nil
   141     var new_tokens: List[Token] = Nil
   107     var old_suffix: List[Token] = Nil
   142     var old_suffix: List[Token] = Nil
   108 
   143 
   109     val match_start = invalid_tokens.firstOption.map(start(_)).getOrElse(0)
   144     val match_start = invalid_tokens.firstOption.map(start(_)).getOrElse(0)
   138     val new_token_list = begin ::: insert ::: old_suffix
   173     val new_token_list = begin ::: insert ::: old_suffix
   139     token_changed(session, id, begin.lastOption, insert,
   174     token_changed(session, id, begin.lastOption, insert,
   140       old_suffix.firstOption, new_token_list, start)
   175       old_suffix.firstOption, new_token_list, start)
   141   }
   176   }
   142 
   177 
   143   
   178 
   144   /** command view **/
   179   /** command view **/
   145 
   180 
   146   private def token_changed(
   181   private def token_changed(
   147     session: Session,
   182     session: Session,
   148     new_id: String,
   183     new_id: String,