src/Pure/PIDE/document.scala
changeset 44672 07dad1433cd7
parent 44642 446fe2abe252
child 44676 7de87f1ae965
equal deleted inserted replaced
44671:7f0b4515588a 44672:07dad1433cd7
   166 
   166 
   167   /* changes of plain text, eventually resulting in document edits */
   167   /* changes of plain text, eventually resulting in document edits */
   168 
   168 
   169   object Change
   169   object Change
   170   {
   170   {
   171     val init: Change = Change(Future.value(Version.init), Nil, Future.value(Version.init))
   171     val init: Change = Change(Some(Future.value(Version.init)), Nil, Future.value(Version.init))
   172   }
   172   }
   173 
   173 
   174   sealed case class Change(
   174   sealed case class Change(
   175     val previous: Future[Version],
   175     val previous: Option[Future[Version]],
   176     val edits: List[Edit_Text],
   176     val edits: List[Edit_Text],
   177     val version: Future[Version])
   177     val version: Future[Version])
   178   {
   178   {
   179     def is_finished: Boolean = previous.is_finished && version.is_finished
   179     def is_finished: Boolean =
       
   180       (previous match { case None => true case Some(future) => future.is_finished }) &&
       
   181       version.is_finished
       
   182 
       
   183     def truncate: Change = copy(previous = None, edits = Nil)
   180   }
   184   }
   181 
   185 
   182 
   186 
   183   /* history navigation */
   187   /* history navigation */
   184 
   188 
   185   object History
   189   object History
   186   {
   190   {
   187     val init: History = new History(List(Change.init))
   191     val init: History = History(List(Change.init))
   188   }
   192   }
   189 
   193 
   190   // FIXME pruning, purging of state
   194   // FIXME pruning, purging of state
   191   class History(val undo_list: List[Change])
   195   sealed case class History(val undo_list: List[Change])
   192   {
   196   {
   193     require(!undo_list.isEmpty)
   197     require(!undo_list.isEmpty)
   194 
   198 
   195     def tip: Change = undo_list.head
   199     def tip: Change = undo_list.head
   196     def +(change: Change): History = new History(change :: undo_list)
   200     def +(change: Change): History = copy(undo_list = change :: undo_list)
   197   }
   201   }
   198 
   202 
   199 
   203 
   200 
   204 
   201   /** global state -- document structure, execution process, editing history **/
   205   /** global state -- document structure, execution process, editing history **/
   340       }
   344       }
   341 
   345 
   342     def is_stable(change: Change): Boolean =
   346     def is_stable(change: Change): Boolean =
   343       change.is_finished && is_assigned(change.version.get_finished)
   347       change.is_finished && is_assigned(change.version.get_finished)
   344 
   348 
   345     def recent_stable: Option[Change] = history.undo_list.find(is_stable)
   349     def recent_stable: Change = history.undo_list.find(is_stable) getOrElse fail
   346     def tip_stable: Boolean = is_stable(history.tip)
   350     def tip_stable: Boolean = is_stable(history.tip)
   347     def tip_version: Version = history.tip.version.get_finished
   351     def tip_version: Version = history.tip.version.get_finished
   348 
   352 
   349     def last_exec_offset(name: Node.Name): Text.Offset =
   353     def last_exec_offset(name: Node.Name): Text.Offset =
   350     {
   354     {
   364     def continue_history(
   368     def continue_history(
   365         previous: Future[Version],
   369         previous: Future[Version],
   366         edits: List[Edit_Text],
   370         edits: List[Edit_Text],
   367         version: Future[Version]): (Change, State) =
   371         version: Future[Version]): (Change, State) =
   368     {
   372     {
   369       val change = Change(previous, edits, version)
   373       val change = Change(Some(previous), edits, version)
   370       (change, copy(history = history + change))
   374       (change, copy(history = history + change))
       
   375     }
       
   376 
       
   377     def prune_history(retain: Int = 0): (List[Version], State) =
       
   378     {
       
   379       val undo_list = history.undo_list
       
   380       val n = undo_list.iterator.zipWithIndex.find(p => is_stable(p._1)).get._2 + 1
       
   381       val (retained, dropped) = undo_list.splitAt(n max retain)
       
   382 
       
   383       retained.splitAt(retained.length - 1) match {
       
   384         case (prefix, List(last)) =>
       
   385           val dropped_versions = dropped.map(change => change.version.get_finished)
       
   386           val state1 = copy(history = History(prefix ::: List(last.truncate)))
       
   387           (dropped_versions, state1)
       
   388         case _ => fail
       
   389       }
   371     }
   390     }
   372 
   391 
   373     def command_state(version: Version, command: Command): Command.State =
   392     def command_state(version: Version, command: Command): Command.State =
   374     {
   393     {
   375       require(is_assigned(version))
   394       require(is_assigned(version))
   382 
   401 
   383 
   402 
   384     // persistent user-view
   403     // persistent user-view
   385     def snapshot(name: Node.Name, pending_edits: List[Text.Edit]): Snapshot =
   404     def snapshot(name: Node.Name, pending_edits: List[Text.Edit]): Snapshot =
   386     {
   405     {
   387       val stable = recent_stable.get
   406       val stable = recent_stable
   388       val latest = history.tip
   407       val latest = history.tip
   389 
   408 
   390       // FIXME proper treatment of removed nodes
   409       // FIXME proper treatment of removed nodes
   391       val edits =
   410       val edits =
   392         (pending_edits /: history.undo_list.takeWhile(_ != stable))((edits, change) =>
   411         (pending_edits /: history.undo_list.takeWhile(_ != stable))((edits, change) =>