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, |