100 /** text edits **/ |
100 /** text edits **/ |
101 |
101 |
102 def text_edits( |
102 def text_edits( |
103 syntax: Outer_Syntax, |
103 syntax: Outer_Syntax, |
104 previous: Document.Version, |
104 previous: Document.Version, |
105 edits: List[Document.Edit_Text], |
105 edits: List[Document.Edit_Text]) |
106 headers: List[(String, Document.Node.Header)]) |
106 : (List[Document.Edit_Command], Document.Version) = |
107 : (List[Document.Edit_Command], List[(String, Thy_Header.Header)], Document.Version) = |
|
108 { |
107 { |
109 /* phase 1: edit individual command source */ |
108 /* phase 1: edit individual command source */ |
110 |
109 |
111 @tailrec def edit_text(eds: List[Text.Edit], commands: Linear_Set[Command]) |
110 @tailrec def edit_text(eds: List[Text.Edit], commands: Linear_Set[Command]) |
112 : Linear_Set[Command] = |
111 : Linear_Set[Command] = |
171 case None => commands |
170 case None => commands |
172 } |
171 } |
173 } |
172 } |
174 |
173 |
175 |
174 |
176 /* node header */ |
|
177 |
|
178 def node_header(name: String, node: Document.Node) |
|
179 : (List[(String, Thy_Header.Header)], Document.Node.Header) = |
|
180 (node.header.thy_header, headers.find(p => p._1 == name).map(_._2)) match { |
|
181 case (Exn.Res(thy_header0), Some(header @ Document.Node.Header(_, Exn.Res(thy_header)))) |
|
182 if thy_header0 != thy_header => |
|
183 (List((name, thy_header)), header) |
|
184 case (Exn.Exn(_), Some(header @ Document.Node.Header(_, Exn.Res(thy_header)))) => |
|
185 (List((name, thy_header)), header) |
|
186 case _ => (Nil, node.header) |
|
187 } |
|
188 |
|
189 |
|
190 /* resulting document edits */ |
175 /* resulting document edits */ |
191 |
176 |
192 { |
177 { |
193 val doc_edits = new mutable.ListBuffer[Document.Edit_Command] |
178 val doc_edits = new mutable.ListBuffer[Document.Edit_Command] |
194 val header_edits = new mutable.ListBuffer[(String, Thy_Header.Header)] |
|
195 var nodes = previous.nodes |
179 var nodes = previous.nodes |
196 |
180 |
197 edits foreach { |
181 edits foreach { |
198 case (name, Document.Node.Remove()) => |
182 case (name, Document.Node.Remove()) => |
199 doc_edits += (name -> Document.Node.Remove()) |
183 doc_edits += (name -> Document.Node.Remove()) |
211 val cmd_edits = |
195 val cmd_edits = |
212 removed_commands.reverse.map(cmd => (commands0.prev(cmd), None)) ::: |
196 removed_commands.reverse.map(cmd => (commands0.prev(cmd), None)) ::: |
213 inserted_commands.map(cmd => (commands2.prev(cmd), Some(cmd))) |
197 inserted_commands.map(cmd => (commands2.prev(cmd), Some(cmd))) |
214 |
198 |
215 doc_edits += (name -> Document.Node.Edits(cmd_edits)) |
199 doc_edits += (name -> Document.Node.Edits(cmd_edits)) |
216 |
200 nodes += (name -> node.copy(commands = commands2)) |
217 val (new_headers, new_header) = node_header(name, node) |
201 |
218 header_edits ++= new_headers |
202 case (name, Document.Node.Update_Header(header)) => |
219 |
203 val node = nodes(name) |
220 nodes += (name -> Document.Node(new_header, node.blobs, commands2)) |
204 val update_header = |
221 } |
205 (node.header.thy_header, header) match { |
222 (doc_edits.toList, header_edits.toList, Document.Version(Document.new_id(), nodes)) |
206 case (Exn.Res(thy_header0), Document.Node.Header(_, Exn.Res(thy_header))) |
|
207 if thy_header0 != thy_header => true |
|
208 case (Exn.Exn(_), Document.Node.Header(_, Exn.Res(thy_header))) => true |
|
209 } |
|
210 if (update_header) doc_edits += (name -> Document.Node.Update_Header(header)) |
|
211 } |
|
212 (doc_edits.toList, Document.Version(Document.new_id(), nodes)) |
223 } |
213 } |
224 } |
214 } |
225 } |
215 } |