255 } |
255 } |
256 case None => Nil |
256 case None => Nil |
257 } |
257 } |
258 |
258 |
259 def resolve_files( |
259 def resolve_files( |
260 thy_load: Thy_Load, |
260 resources: Resources, |
261 syntax: Outer_Syntax, |
261 syntax: Outer_Syntax, |
262 node_name: Document.Node.Name, |
262 node_name: Document.Node.Name, |
263 span: List[Token], |
263 span: List[Token], |
264 doc_blobs: Document.Blobs) |
264 doc_blobs: Document.Blobs) |
265 : List[Command.Blob] = |
265 : List[Command.Blob] = |
266 { |
266 { |
267 span_files(syntax, span).map(file_name => |
267 span_files(syntax, span).map(file_name => |
268 Exn.capture { |
268 Exn.capture { |
269 val name = |
269 val name = |
270 Document.Node.Name(thy_load.append(node_name.master_dir, Path.explode(file_name))) |
270 Document.Node.Name(resources.append(node_name.master_dir, Path.explode(file_name))) |
271 val blob = doc_blobs.get(name).map(blob => ((blob.bytes.sha1_digest, blob.file))) |
271 val blob = doc_blobs.get(name).map(blob => ((blob.bytes.sha1_digest, blob.file))) |
272 (name, blob) |
272 (name, blob) |
273 }) |
273 }) |
274 } |
274 } |
275 |
275 |
287 case _ => (cmds, blobs_spans) |
287 case _ => (cmds, blobs_spans) |
288 } |
288 } |
289 } |
289 } |
290 |
290 |
291 private def reparse_spans( |
291 private def reparse_spans( |
292 thy_load: Thy_Load, |
292 resources: Resources, |
293 syntax: Outer_Syntax, |
293 syntax: Outer_Syntax, |
294 doc_blobs: Document.Blobs, |
294 doc_blobs: Document.Blobs, |
295 name: Document.Node.Name, |
295 name: Document.Node.Name, |
296 commands: Linear_Set[Command], |
296 commands: Linear_Set[Command], |
297 first: Command, last: Command): Linear_Set[Command] = |
297 first: Command, last: Command): Linear_Set[Command] = |
298 { |
298 { |
299 val cmds0 = commands.iterator(first, last).toList |
299 val cmds0 = commands.iterator(first, last).toList |
300 val blobs_spans0 = |
300 val blobs_spans0 = |
301 parse_spans(syntax.scan(cmds0.iterator.map(_.source).mkString)). |
301 parse_spans(syntax.scan(cmds0.iterator.map(_.source).mkString)). |
302 map(span => (resolve_files(thy_load, syntax, name, span, doc_blobs), span)) |
302 map(span => (resolve_files(resources, syntax, name, span, doc_blobs), span)) |
303 |
303 |
304 val (cmds1, blobs_spans1) = chop_common(cmds0, blobs_spans0) |
304 val (cmds1, blobs_spans1) = chop_common(cmds0, blobs_spans0) |
305 |
305 |
306 val (rev_cmds2, rev_blobs_spans2) = chop_common(cmds1.reverse, blobs_spans1.reverse) |
306 val (rev_cmds2, rev_blobs_spans2) = chop_common(cmds1.reverse, blobs_spans1.reverse) |
307 val cmds2 = rev_cmds2.reverse |
307 val cmds2 = rev_cmds2.reverse |
322 |
322 |
323 /* recover command spans after edits */ |
323 /* recover command spans after edits */ |
324 |
324 |
325 // FIXME somewhat slow |
325 // FIXME somewhat slow |
326 private def recover_spans( |
326 private def recover_spans( |
327 thy_load: Thy_Load, |
327 resources: Resources, |
328 syntax: Outer_Syntax, |
328 syntax: Outer_Syntax, |
329 doc_blobs: Document.Blobs, |
329 doc_blobs: Document.Blobs, |
330 name: Document.Node.Name, |
330 name: Document.Node.Name, |
331 perspective: Command.Perspective, |
331 perspective: Command.Perspective, |
332 commands: Linear_Set[Command]): Linear_Set[Command] = |
332 commands: Linear_Set[Command]): Linear_Set[Command] = |
340 @tailrec def recover(cmds: Linear_Set[Command]): Linear_Set[Command] = |
340 @tailrec def recover(cmds: Linear_Set[Command]): Linear_Set[Command] = |
341 cmds.find(_.is_unparsed) match { |
341 cmds.find(_.is_unparsed) match { |
342 case Some(first_unparsed) => |
342 case Some(first_unparsed) => |
343 val first = next_invisible_command(cmds.reverse, first_unparsed) |
343 val first = next_invisible_command(cmds.reverse, first_unparsed) |
344 val last = next_invisible_command(cmds, first_unparsed) |
344 val last = next_invisible_command(cmds, first_unparsed) |
345 recover(reparse_spans(thy_load, syntax, doc_blobs, name, cmds, first, last)) |
345 recover(reparse_spans(resources, syntax, doc_blobs, name, cmds, first, last)) |
346 case None => cmds |
346 case None => cmds |
347 } |
347 } |
348 recover(commands) |
348 recover(commands) |
349 } |
349 } |
350 |
350 |
351 |
351 |
352 /* consolidate unfinished spans */ |
352 /* consolidate unfinished spans */ |
353 |
353 |
354 private def consolidate_spans( |
354 private def consolidate_spans( |
355 thy_load: Thy_Load, |
355 resources: Resources, |
356 syntax: Outer_Syntax, |
356 syntax: Outer_Syntax, |
357 doc_blobs: Document.Blobs, |
357 doc_blobs: Document.Blobs, |
358 reparse_limit: Int, |
358 reparse_limit: Int, |
359 name: Document.Node.Name, |
359 name: Document.Node.Name, |
360 perspective: Command.Perspective, |
360 perspective: Command.Perspective, |
372 var i = 0 |
372 var i = 0 |
373 while (i < reparse_limit && it.hasNext) { |
373 while (i < reparse_limit && it.hasNext) { |
374 last = it.next |
374 last = it.next |
375 i += last.length |
375 i += last.length |
376 } |
376 } |
377 reparse_spans(thy_load, syntax, doc_blobs, name, commands, first_unfinished, last) |
377 reparse_spans(resources, syntax, doc_blobs, name, commands, first_unfinished, last) |
378 case None => commands |
378 case None => commands |
379 } |
379 } |
380 case None => commands |
380 case None => commands |
381 } |
381 } |
382 } |
382 } |
394 removed.reverse.map(cmd => (old_cmds.prev(cmd), None)) ::: |
394 removed.reverse.map(cmd => (old_cmds.prev(cmd), None)) ::: |
395 inserted.map(cmd => (new_cmds.prev(cmd), Some(cmd))) |
395 inserted.map(cmd => (new_cmds.prev(cmd), Some(cmd))) |
396 } |
396 } |
397 |
397 |
398 private def text_edit( |
398 private def text_edit( |
399 thy_load: Thy_Load, |
399 resources: Resources, |
400 syntax: Outer_Syntax, |
400 syntax: Outer_Syntax, |
401 doc_blobs: Document.Blobs, |
401 doc_blobs: Document.Blobs, |
402 reparse_limit: Int, |
402 reparse_limit: Int, |
403 node: Document.Node, edit: Document.Edit_Text): Document.Node = |
403 node: Document.Node, edit: Document.Edit_Text): Document.Node = |
404 { |
404 { |
411 if (node.is_blob) node |
411 if (node.is_blob) node |
412 else { |
412 else { |
413 val commands0 = node.commands |
413 val commands0 = node.commands |
414 val commands1 = edit_text(text_edits, commands0) |
414 val commands1 = edit_text(text_edits, commands0) |
415 val commands2 = |
415 val commands2 = |
416 recover_spans(thy_load, syntax, doc_blobs, name, node.perspective.visible, commands1) |
416 recover_spans(resources, syntax, doc_blobs, name, node.perspective.visible, commands1) |
417 node.update_commands(commands2) |
417 node.update_commands(commands2) |
418 } |
418 } |
419 |
419 |
420 case (_, Document.Node.Deps(_)) => node |
420 case (_, Document.Node.Deps(_)) => node |
421 |
421 |
424 val perspective: Document.Node.Perspective_Command = |
424 val perspective: Document.Node.Perspective_Command = |
425 Document.Node.Perspective(required, visible_overlay, overlays) |
425 Document.Node.Perspective(required, visible_overlay, overlays) |
426 if (node.same_perspective(perspective)) node |
426 if (node.same_perspective(perspective)) node |
427 else |
427 else |
428 node.update_perspective(perspective).update_commands( |
428 node.update_perspective(perspective).update_commands( |
429 consolidate_spans(thy_load, syntax, doc_blobs, reparse_limit, |
429 consolidate_spans(resources, syntax, doc_blobs, reparse_limit, |
430 name, visible, node.commands)) |
430 name, visible, node.commands)) |
431 } |
431 } |
432 } |
432 } |
433 |
433 |
434 def text_edits( |
434 def text_edits( |
435 thy_load: Thy_Load, |
435 resources: Resources, |
436 reparse_limit: Int, |
436 reparse_limit: Int, |
437 previous: Document.Version, |
437 previous: Document.Version, |
438 doc_blobs: Document.Blobs, |
438 doc_blobs: Document.Blobs, |
439 edits: List[Document.Edit_Text]) |
439 edits: List[Document.Edit_Text]) |
440 : (Boolean, List[Document.Edit_Command], Document.Version) = |
440 : (Boolean, List[Document.Edit_Command], Document.Version) = |
441 { |
441 { |
442 val ((syntax, syntax_changed), reparse0, nodes0, doc_edits0) = |
442 val ((syntax, syntax_changed), reparse0, nodes0, doc_edits0) = |
443 header_edits(thy_load.base_syntax, previous, edits) |
443 header_edits(resources.base_syntax, previous, edits) |
444 |
444 |
445 if (edits.isEmpty) |
445 if (edits.isEmpty) |
446 (false, Nil, Document.Version.make(syntax, previous.nodes)) |
446 (false, Nil, Document.Version.make(syntax, previous.nodes)) |
447 else { |
447 else { |
448 val reparse = |
448 val reparse = |
467 val commands = node.commands |
467 val commands = node.commands |
468 |
468 |
469 val node1 = |
469 val node1 = |
470 if (reparse_set(name) && !commands.isEmpty) |
470 if (reparse_set(name) && !commands.isEmpty) |
471 node.update_commands( |
471 node.update_commands( |
472 reparse_spans(thy_load, syntax, doc_blobs, |
472 reparse_spans(resources, syntax, doc_blobs, |
473 name, commands, commands.head, commands.last)) |
473 name, commands, commands.head, commands.last)) |
474 else node |
474 else node |
475 val node2 = (node1 /: edits)(text_edit(thy_load, syntax, doc_blobs, reparse_limit, _, _)) |
475 val node2 = (node1 /: edits)(text_edit(resources, syntax, doc_blobs, reparse_limit, _, _)) |
476 |
476 |
477 if (!(node.same_perspective(node2.perspective))) |
477 if (!(node.same_perspective(node2.perspective))) |
478 doc_edits += (name -> node2.perspective) |
478 doc_edits += (name -> node2.perspective) |
479 |
479 |
480 doc_edits += (name -> Document.Node.Edits(diff_commands(commands, node2.commands))) |
480 doc_edits += (name -> Document.Node.Edits(diff_commands(commands, node2.commands))) |