src/Tools/jEdit/src/document_model.scala
author wenzelm
Mon, 05 Jun 2017 23:55:58 +0200
changeset 66019 69b5ef78fb07
parent 65469 78ace4a14975
child 66036 b6396880b644
permissions -rw-r--r--
HTML preview via builtin HTTP server;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43282
5d294220ca43 moved sources -- eliminated Netbeans artifact of jedit package directory;
wenzelm
parents: 40851
diff changeset
     1
/*  Title:      Tools/jEdit/src/document_model.scala
36760
b82a698ef6c9 tuned headers;
wenzelm
parents: 36015
diff changeset
     2
    Author:     Fabian Immler, TU Munich
b82a698ef6c9 tuned headers;
wenzelm
parents: 36015
diff changeset
     3
    Author:     Makarius
b82a698ef6c9 tuned headers;
wenzelm
parents: 36015
diff changeset
     4
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
     5
Document model connected to jEdit buffer or external file: content of theory
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
     6
node or auxiliary file (blob).
36760
b82a698ef6c9 tuned headers;
wenzelm
parents: 36015
diff changeset
     7
*/
34407
aad6834ba380 added some headers and comments;
wenzelm
parents: 34406
diff changeset
     8
34784
02959dcea756 split Theory_View into Document_Model (connected to Buffer) and Document_View (connected to JEditTextArea);
wenzelm
parents: 34783
diff changeset
     9
package isabelle.jedit
34760
dc7f5e0d9d27 misc modernization of names;
wenzelm
parents: 34759
diff changeset
    10
34318
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
    11
36015
6111de7c916a adapted to Scala 2.8.0 Beta 1;
wenzelm
parents: 34871
diff changeset
    12
import isabelle._
6111de7c916a adapted to Scala 2.8.0 Beta 1;
wenzelm
parents: 34871
diff changeset
    13
64858
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    14
import java.io.{File => JFile}
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    15
34693
3e995f100ad2 sealed Edit;
wenzelm
parents: 34685
diff changeset
    16
import scala.collection.mutable
66019
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
    17
import scala.annotation.tailrec
34446
5c79f97ec1d1 superficial tuning;
wenzelm
parents: 34445
diff changeset
    18
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    19
import org.gjt.sp.jedit.{jEdit, View}
34784
02959dcea756 split Theory_View into Document_Model (connected to Buffer) and Document_View (connected to JEditTextArea);
wenzelm
parents: 34783
diff changeset
    20
import org.gjt.sp.jedit.Buffer
61192
98eba31c51f8 tuned signature;
wenzelm
parents: 60933
diff changeset
    21
import org.gjt.sp.jedit.buffer.{BufferAdapter, BufferListener, JEditBuffer}
34318
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
    22
34760
dc7f5e0d9d27 misc modernization of names;
wenzelm
parents: 34759
diff changeset
    23
34784
02959dcea756 split Theory_View into Document_Model (connected to Buffer) and Document_View (connected to JEditTextArea);
wenzelm
parents: 34783
diff changeset
    24
object Document_Model
34588
e8ac8794971f superficial tuning;
wenzelm
parents: 34583
diff changeset
    25
{
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    26
  /* document models */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    27
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    28
  sealed case class State(
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    29
    models: Map[Document.Node.Name, Document_Model] = Map.empty,
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    30
    buffer_models: Map[JEditBuffer, Buffer_Model] = Map.empty)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    31
  {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
    32
    def file_models_iterator: Iterator[(Document.Node.Name, File_Model)] =
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    33
      for {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
    34
        (node_name, model) <- models.iterator
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    35
        if model.isInstanceOf[File_Model]
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
    36
      } yield (node_name, model.asInstanceOf[File_Model])
64813
7283f41d05ab manage buffer models as explicit global state;
wenzelm
parents: 64799
diff changeset
    37
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    38
    def open_buffer(session: Session, node_name: Document.Node.Name, buffer: Buffer)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    39
      : (Buffer_Model, State) =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    40
    {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    41
      val old_model =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    42
        models.get(node_name) match {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    43
          case Some(file_model: File_Model) => Some(file_model)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    44
          case Some(buffer_model: Buffer_Model) => Some(buffer_model.exit())
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    45
          case _ => None
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    46
        }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    47
      val buffer_model = Buffer_Model(session, node_name, buffer).init(old_model)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    48
      (buffer_model,
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    49
        copy(models = models + (node_name -> buffer_model),
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    50
          buffer_models = buffer_models + (buffer -> buffer_model)))
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    51
    }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    52
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    53
    def close_buffer(buffer: JEditBuffer): State =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    54
    {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    55
      buffer_models.get(buffer) match {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    56
        case None => this
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    57
        case Some(buffer_model) =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    58
          val file_model = buffer_model.exit()
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    59
          copy(models = models + (file_model.node_name -> file_model),
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    60
            buffer_models = buffer_models - buffer)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    61
      }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    62
    }
64835
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    63
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    64
    def provide_file(session: Session, node_name: Document.Node.Name, text: String): State =
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    65
      if (models.isDefinedAt(node_name)) this
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    66
      else {
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    67
        val edit = Text.Edit.insert(0, text)
64863
wenzelm
parents: 64858
diff changeset
    68
        val model = File_Model.init(session, node_name, text, pending_edits = List(edit))
64835
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    69
        copy(models = models + (node_name -> model))
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    70
      }
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    71
  }
34784
02959dcea756 split Theory_View into Document_Model (connected to Buffer) and Document_View (connected to JEditTextArea);
wenzelm
parents: 34783
diff changeset
    72
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    73
  private val state = Synchronized(State())  // owned by GUI thread
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    74
64835
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    75
  def get_models(): Map[Document.Node.Name, Document_Model] = state.value.models
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    76
  def get(name: Document.Node.Name): Option[Document_Model] = get_models.get(name)
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
    77
  def get(buffer: JEditBuffer): Option[Buffer_Model] = state.value.buffer_models.get(buffer)
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    78
64831
4792ee012e94 tuned signature;
wenzelm
parents: 64829
diff changeset
    79
  def bibtex_entries_iterator(): Iterator[Text.Info[(String, Document_Model)]] =
64829
07f209e957bc refer to bibtex entries via general Document_Model, instead of editor buffers;
wenzelm
parents: 64828
diff changeset
    80
    for {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
    81
      (_, model) <- state.value.models.iterator
65132
wenzelm
parents: 64885
diff changeset
    82
      info <- model.bibtex_entries.iterator
wenzelm
parents: 64885
diff changeset
    83
    } yield info.map((_, model))
64829
07f209e957bc refer to bibtex entries via general Document_Model, instead of editor buffers;
wenzelm
parents: 64828
diff changeset
    84
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
    85
64858
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    86
  /* sync external files */
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    87
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    88
  def sync_files(changed_files: Set[JFile]): Boolean =
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    89
  {
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    90
    state.change_result(st =>
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    91
      {
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    92
        val changed_models =
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    93
          (for {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
    94
            (node_name, model) <- st.file_models_iterator
64864
eec7ffef0be6 accomodate very big file_models and changed_files;
wenzelm
parents: 64863
diff changeset
    95
            file <- model.file if changed_files(file)
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
    96
            text <- PIDE.resources.read_file_content(node_name)
64858
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    97
            if model.content.text != text
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    98
          } yield {
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
    99
            val content = Document_Model.File_Content(text)
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
   100
            val edits = Text.Edit.replace(0, model.content.text, text)
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   101
            (node_name, model.copy(content = content, pending_edits = model.pending_edits ::: edits))
64858
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
   102
          }).toList
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
   103
        if (changed_models.isEmpty) (false, st)
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
   104
        else (true, st.copy(models = (st.models /: changed_models)(_ + _)))
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
   105
      })
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
   106
  }
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
   107
e31cf6eaecb8 update File_Model based on file-system events;
wenzelm
parents: 64836
diff changeset
   108
64836
wenzelm
parents: 64835
diff changeset
   109
  /* syntax */
wenzelm
parents: 64835
diff changeset
   110
wenzelm
parents: 64835
diff changeset
   111
  def syntax_changed(names: List[Document.Node.Name])
wenzelm
parents: 64835
diff changeset
   112
  {
wenzelm
parents: 64835
diff changeset
   113
    GUI_Thread.require {}
wenzelm
parents: 64835
diff changeset
   114
wenzelm
parents: 64835
diff changeset
   115
    val models = state.value.models
wenzelm
parents: 64835
diff changeset
   116
    for (name <- names.iterator; model <- models.get(name)) {
wenzelm
parents: 64835
diff changeset
   117
      model match { case buffer_model: Buffer_Model => buffer_model.syntax_changed() case _ => }
wenzelm
parents: 64835
diff changeset
   118
    }
wenzelm
parents: 64835
diff changeset
   119
  }
wenzelm
parents: 64835
diff changeset
   120
wenzelm
parents: 64835
diff changeset
   121
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   122
  /* init and exit */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   123
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   124
  def init(session: Session, node_name: Document.Node.Name, buffer: Buffer): Buffer_Model =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   125
  {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   126
    GUI_Thread.require {}
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   127
    state.change_result(st =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   128
      st.buffer_models.get(buffer) match {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   129
        case Some(buffer_model) if buffer_model.node_name == node_name =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   130
          buffer_model.init_token_marker
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   131
          (buffer_model, st)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   132
        case _ =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   133
          val res = st.close_buffer(buffer).open_buffer(session, node_name, buffer)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   134
          buffer.propertiesChanged
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   135
          res
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   136
      })
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   137
  }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   138
34784
02959dcea756 split Theory_View into Document_Model (connected to Buffer) and Document_View (connected to JEditTextArea);
wenzelm
parents: 34783
diff changeset
   139
  def exit(buffer: Buffer)
02959dcea756 split Theory_View into Document_Model (connected to Buffer) and Document_View (connected to JEditTextArea);
wenzelm
parents: 34783
diff changeset
   140
  {
57612
990ffb84489b clarified module name: facilitate alternative GUI frameworks;
wenzelm
parents: 57610
diff changeset
   141
    GUI_Thread.require {}
64813
7283f41d05ab manage buffer models as explicit global state;
wenzelm
parents: 64799
diff changeset
   142
    state.change(st =>
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   143
      if (st.buffer_models.isDefinedAt(buffer)) {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   144
        val res = st.close_buffer(buffer)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   145
        buffer.propertiesChanged
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   146
        res
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   147
      }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   148
      else st)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   149
  }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   150
64835
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   151
  def provide_files(session: Session, files: List[(Document.Node.Name, String)])
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   152
  {
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   153
    GUI_Thread.require {}
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   154
    state.change(st =>
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   155
      (st /: files) { case (st1, (node_name, text)) => st1.provide_file(session, node_name, text) })
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   156
  }
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   157
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   158
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   159
  /* required nodes */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   160
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   161
  def required_nodes(): Set[Document.Node.Name] =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   162
    (for {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   163
      (node_name, model) <- state.value.models.iterator
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   164
      if model.node_required
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   165
    } yield node_name).toSet
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   166
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   167
  def node_required(name: Document.Node.Name, toggle: Boolean = false, set: Boolean = false)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   168
  {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   169
    GUI_Thread.require {}
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   170
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   171
    val changed =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   172
      state.change_result(st =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   173
        st.models.get(name) match {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   174
          case None => (false, st)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   175
          case Some(model) =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   176
            val required = if (toggle) !model.node_required else set
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   177
            model match {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   178
              case model1: File_Model if required != model1.node_required =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   179
                (true, st.copy(models = st.models + (name -> model1.copy(node_required = required))))
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   180
              case model1: Buffer_Model if required != model1.node_required =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   181
                model1.set_node_required(required); (true, st)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   182
              case _ => (false, st)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   183
            }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   184
        })
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   185
    if (changed) {
65243
ba5ce07e06a7 proper plugin access;
wenzelm
parents: 65196
diff changeset
   186
      PIDE.plugin.options_changed()
65246
848965b5befc clarified singleton module;
wenzelm
parents: 65245
diff changeset
   187
      JEdit_Editor.flush()
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   188
    }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   189
  }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   190
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   191
  def view_node_required(view: View, toggle: Boolean = false, set: Boolean = false): Unit =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   192
    Document_Model.get(view.getBuffer).foreach(model =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   193
      node_required(model.node_name, toggle = toggle, set = set))
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   194
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   195
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   196
  /* flushed edits */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   197
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   198
  def flush_edits(hidden: Boolean, purge: Boolean): (Document.Blobs, List[Document.Edit_Text]) =
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   199
  {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   200
    GUI_Thread.require {}
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   201
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   202
    state.change_result(st =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   203
      {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   204
        val doc_blobs =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   205
          Document.Blobs(
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   206
            (for {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   207
              (node_name, model) <- st.models.iterator
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   208
              blob <- model.get_blob
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   209
            } yield (node_name -> blob)).toMap)
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   210
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   211
        val buffer_edits =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   212
          (for {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   213
            (_, model) <- st.buffer_models.iterator
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   214
            edit <- model.flush_edits(doc_blobs, hidden).iterator
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   215
          } yield edit).toList
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   216
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   217
        val file_edits =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   218
          (for {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   219
            (node_name, model) <- st.file_models_iterator
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   220
            (edits, model1) <- model.flush_edits(doc_blobs, hidden)
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   221
          } yield (edits, node_name -> model1)).toList
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   222
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   223
        val model_edits = buffer_edits ::: file_edits.flatMap(_._1)
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   224
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   225
        val purge_edits =
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   226
          if (purge) {
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   227
            val purged =
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   228
              (for ((node_name, model) <- st.file_models_iterator)
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   229
               yield (node_name -> model.purge_edits(doc_blobs))).toList
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   230
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   231
            val imports =
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   232
            {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   233
              val open_nodes =
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   234
                (for ((_, model) <- st.buffer_models.iterator) yield model.node_name).toList
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   235
              val touched_nodes = model_edits.map(_._1)
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   236
              val pending_nodes = for ((node_name, None) <- purged) yield node_name
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   237
              (open_nodes ::: touched_nodes ::: pending_nodes).map((_, Position.none))
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   238
            }
65359
9ca34f0407a9 provide session qualifier via resources;
wenzelm
parents: 65246
diff changeset
   239
            val retain = PIDE.resources.thy_info.dependencies(imports).deps.map(_.name).toSet
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   240
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   241
            for ((node_name, Some(edits)) <- purged; if !retain(node_name); edit <- edits)
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   242
              yield edit
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   243
          }
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   244
          else Nil
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   245
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   246
        val st1 = st.copy(models = st.models ++ file_edits.map(_._2) -- purge_edits.map(_._1))
65245
e955b33f432c proper plugin access;
wenzelm
parents: 65243
diff changeset
   247
        PIDE.plugin.file_watcher.purge(
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   248
          (for {
64868
6212d3c396b0 tuned signature;
wenzelm
parents: 64867
diff changeset
   249
            (_, model) <- st1.file_models_iterator
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   250
            file <- model.file
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   251
          } yield file.getParentFile).toSet)
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   252
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   253
        ((doc_blobs, model_edits ::: purge_edits), st1)
64813
7283f41d05ab manage buffer models as explicit global state;
wenzelm
parents: 64799
diff changeset
   254
      })
34318
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
   255
  }
43397
dba359c0ae3b more robust init;
wenzelm
parents: 43394
diff changeset
   256
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   257
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   258
  /* file content */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   259
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   260
  sealed case class File_Content(text: String)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   261
  {
64835
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   262
    lazy val bytes: Bytes = Bytes(Symbol.encode(text))
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   263
    lazy val chunk: Symbol.Text_Chunk = Symbol.Text_Chunk(text)
64831
4792ee012e94 tuned signature;
wenzelm
parents: 64829
diff changeset
   264
    lazy val bibtex_entries: List[Text.Info[String]] =
4792ee012e94 tuned signature;
wenzelm
parents: 64829
diff changeset
   265
      try { Bibtex.document_entries(text) }
64828
e837f6bf653c clarified modules;
wenzelm
parents: 64827
diff changeset
   266
      catch { case ERROR(msg) => Output.warning(msg); Nil }
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   267
  }
66019
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   268
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   269
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   270
  /* HTTP preview */
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   271
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   272
  def open_preview(view: View)
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   273
  {
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   274
    Document_Model.get(view.getBuffer) match {
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   275
      case Some(model) =>
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   276
        JEdit_Editor.hyperlink_url(
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   277
          PIDE.plugin.http_server.url.toString + PIDE.plugin.http_root + "/preview/" +
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   278
            model.node_name.theory).follow(view)
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   279
      case None =>
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   280
    }
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   281
  }
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   282
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   283
  def http_handlers(http_root: String): List[HTTP.Handler] =
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   284
  {
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   285
    val preview_root = http_root + "/preview"
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   286
    val preview =
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   287
      HTTP.get(preview_root, uri =>
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   288
        for {
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   289
          theory <- Library.try_unprefix(preview_root + "/", uri.toString)
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   290
          model <-
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   291
            get_models().iterator.collectFirst(
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   292
              { case (node_name, model) if node_name.theory == theory => model })
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   293
        }
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   294
        yield HTTP.Response.html(model.preview("../fonts")))
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   295
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   296
    List(HTTP.fonts(http_root + "/fonts"), preview)
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   297
  }
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   298
}
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   299
64829
07f209e957bc refer to bibtex entries via general Document_Model, instead of editor buffers;
wenzelm
parents: 64828
diff changeset
   300
sealed abstract class Document_Model extends Document.Model
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   301
{
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   302
  /* content */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   303
64831
4792ee012e94 tuned signature;
wenzelm
parents: 64829
diff changeset
   304
  def bibtex_entries: List[Text.Info[String]]
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   305
66019
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   306
  def preview(fonts_dir: String): String =
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   307
  {
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   308
    val snapshot = await_stable_snapshot()
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   309
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   310
    HTML.output_document(
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   311
      List(HTML.style(HTML.fonts_css(HTML.fonts_dir(fonts_dir)) + File.read(HTML.isabelle_css))),
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   312
      List(
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   313
        HTML.chapter("Theory " + quote(node_name.theory_base_name)),
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   314
        HTML.source(snapshot.node.commands.iterator.map(_.source).mkString)),
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   315
      css = "")
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   316
  }
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   317
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   318
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   319
  /* perspective */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   320
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   321
  def document_view_ranges(snapshot: Document.Snapshot): List[Text.Range] = Nil
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   322
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   323
  def node_perspective(
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   324
    doc_blobs: Document.Blobs, hidden: Boolean): (Boolean, Document.Node.Perspective_Text) =
43397
dba359c0ae3b more robust init;
wenzelm
parents: 43394
diff changeset
   325
  {
57612
990ffb84489b clarified module name: facilitate alternative GUI frameworks;
wenzelm
parents: 57610
diff changeset
   326
    GUI_Thread.require {}
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   327
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   328
    if (Isabelle.continuous_checking && is_theory) {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   329
      val snapshot = this.snapshot()
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   330
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   331
      val reparse = snapshot.node.load_commands_changed(doc_blobs)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   332
      val perspective =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   333
        if (hidden) Text.Perspective.empty
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   334
        else {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   335
          val view_ranges = document_view_ranges(snapshot)
65246
848965b5befc clarified singleton module;
wenzelm
parents: 65245
diff changeset
   336
          val load_ranges = snapshot.commands_loading_ranges(JEdit_Editor.visible_node(_))
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   337
          Text.Perspective(view_ranges ::: load_ranges)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   338
        }
65246
848965b5befc clarified singleton module;
wenzelm
parents: 65245
diff changeset
   339
      val overlays = JEdit_Editor.node_overlays(node_name)
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   340
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   341
      (reparse, Document.Node.Perspective(node_required, perspective, overlays))
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   342
    }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   343
    else (false, Document.Node.no_perspective_text)
43397
dba359c0ae3b more robust init;
wenzelm
parents: 43394
diff changeset
   344
  }
66019
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   345
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   346
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   347
  /* snapshot */
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   348
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   349
  @tailrec final def await_stable_snapshot(): Document.Snapshot =
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   350
  {
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   351
    val snapshot = this.snapshot()
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   352
    if (snapshot.is_outdated) {
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   353
      Thread.sleep(PIDE.options.seconds("editor_output_delay").ms)
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   354
      await_stable_snapshot()
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   355
    }
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   356
    else snapshot
69b5ef78fb07 HTML preview via builtin HTTP server;
wenzelm
parents: 65469
diff changeset
   357
  }
34318
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
   358
}
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
   359
64863
wenzelm
parents: 64858
diff changeset
   360
object File_Model
wenzelm
parents: 64858
diff changeset
   361
{
wenzelm
parents: 64858
diff changeset
   362
  def init(session: Session,
wenzelm
parents: 64858
diff changeset
   363
    node_name: Document.Node.Name,
wenzelm
parents: 64858
diff changeset
   364
    text: String,
wenzelm
parents: 64858
diff changeset
   365
    node_required: Boolean = false,
wenzelm
parents: 64858
diff changeset
   366
    last_perspective: Document.Node.Perspective_Text = Document.Node.no_perspective_text,
wenzelm
parents: 64858
diff changeset
   367
    pending_edits: List[Text.Edit] = Nil): File_Model =
wenzelm
parents: 64858
diff changeset
   368
  {
65469
78ace4a14975 more explicit jEdit file operations;
wenzelm
parents: 65359
diff changeset
   369
    val file = JEdit_Lib.check_file(node_name.node)
65245
e955b33f432c proper plugin access;
wenzelm
parents: 65243
diff changeset
   370
    file.foreach(PIDE.plugin.file_watcher.register_parent(_))
64863
wenzelm
parents: 64858
diff changeset
   371
64864
eec7ffef0be6 accomodate very big file_models and changed_files;
wenzelm
parents: 64863
diff changeset
   372
    val content = Document_Model.File_Content(text)
eec7ffef0be6 accomodate very big file_models and changed_files;
wenzelm
parents: 64863
diff changeset
   373
    File_Model(session, node_name, file, content, node_required, last_perspective, pending_edits)
64863
wenzelm
parents: 64858
diff changeset
   374
  }
wenzelm
parents: 64858
diff changeset
   375
}
wenzelm
parents: 64858
diff changeset
   376
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   377
case class File_Model(
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   378
  session: Session,
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   379
  node_name: Document.Node.Name,
64864
eec7ffef0be6 accomodate very big file_models and changed_files;
wenzelm
parents: 64863
diff changeset
   380
  file: Option[JFile],
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   381
  content: Document_Model.File_Content,
64863
wenzelm
parents: 64858
diff changeset
   382
  node_required: Boolean,
wenzelm
parents: 64858
diff changeset
   383
  last_perspective: Document.Node.Perspective_Text,
wenzelm
parents: 64858
diff changeset
   384
  pending_edits: List[Text.Edit]) extends Document_Model
34588
e8ac8794971f superficial tuning;
wenzelm
parents: 34583
diff changeset
   385
{
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   386
  /* header */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   387
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   388
  def node_header: Document.Node.Header =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   389
    PIDE.resources.special_header(node_name) getOrElse
65359
9ca34f0407a9 provide session qualifier via resources;
wenzelm
parents: 65246
diff changeset
   390
      PIDE.resources.check_thy_reader(node_name, Scan.char_reader(content.text), strict = false)
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   391
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   392
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   393
  /* content */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   394
64829
07f209e957bc refer to bibtex entries via general Document_Model, instead of editor buffers;
wenzelm
parents: 64828
diff changeset
   395
  def node_position(offset: Text.Offset): Line.Node_Position =
07f209e957bc refer to bibtex entries via general Document_Model, instead of editor buffers;
wenzelm
parents: 64828
diff changeset
   396
    Line.Node_Position(node_name.node,
65196
e8760a98db78 discontinued pointless Text.Length: Javascript and Java agree in old-fashioned UTF-16;
wenzelm
parents: 65132
diff changeset
   397
      Line.Position.zero.advance(content.text.substring(0, offset)))
64829
07f209e957bc refer to bibtex entries via general Document_Model, instead of editor buffers;
wenzelm
parents: 64828
diff changeset
   398
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   399
  def get_blob: Option[Document.Blob] =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   400
    if (is_theory) None
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   401
    else Some(Document.Blob(content.bytes, content.chunk, pending_edits.nonEmpty))
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   402
64831
4792ee012e94 tuned signature;
wenzelm
parents: 64829
diff changeset
   403
  def bibtex_entries: List[Text.Info[String]] =
64828
e837f6bf653c clarified modules;
wenzelm
parents: 64827
diff changeset
   404
    if (Bibtex.check_name(node_name)) content.bibtex_entries else Nil
64680
wenzelm
parents: 64673
diff changeset
   405
wenzelm
parents: 64673
diff changeset
   406
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   407
  /* edits */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   408
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   409
  def update_text(text: String): Option[File_Model] =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   410
    Text.Edit.replace(0, content.text, text) match {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   411
      case Nil => None
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   412
      case edits =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   413
        val content1 = Document_Model.File_Content(text)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   414
        val pending_edits1 = pending_edits ::: edits
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   415
        Some(copy(content = content1, pending_edits = pending_edits1))
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   416
    }
38222
dac5fa0ac971 replaced individual Document_Model history by all-inclusive one in Session;
wenzelm
parents: 38158
diff changeset
   417
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   418
  def flush_edits(doc_blobs: Document.Blobs, hidden: Boolean)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   419
    : Option[(List[Document.Edit_Text], File_Model)] =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   420
  {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   421
    val (reparse, perspective) = node_perspective(doc_blobs, hidden)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   422
    if (reparse || pending_edits.nonEmpty || last_perspective != perspective) {
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   423
      val edits = node_edits(node_header, pending_edits, perspective)
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   424
      Some((edits, copy(last_perspective = perspective, pending_edits = Nil)))
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   425
    }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   426
    else None
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   427
  }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   428
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   429
  def purge_edits(doc_blobs: Document.Blobs): Option[List[Document.Edit_Text]] =
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   430
    if (node_required || !Document.Node.is_no_perspective_text(last_perspective) ||
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   431
        pending_edits.nonEmpty) None
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   432
    else {
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   433
      val text_edits = List(Text.Edit.remove(0, content.text))
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   434
      Some(node_edits(Document.Node.no_header, text_edits, Document.Node.no_perspective_text))
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   435
    }
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   436
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   437
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   438
  /* snapshot */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   439
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   440
  def is_stable: Boolean = pending_edits.isEmpty
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   441
  def snapshot(): Document.Snapshot = session.snapshot(node_name, pending_edits)
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   442
}
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   443
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   444
case class Buffer_Model(session: Session, node_name: Document.Node.Name, buffer: Buffer)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   445
  extends Document_Model
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   446
{
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   447
  /* header */
54509
1f77110c94ef maintain document model for all files, with document view for theory only, and special blob for non-theory files;
wenzelm
parents: 54464
diff changeset
   448
48707
ba531af91148 simplified Document.Node.Header -- internalized errors;
wenzelm
parents: 47393
diff changeset
   449
  def node_header(): Document.Node.Header =
46920
5f44c8bea84e more explicit indication of swing thread context;
wenzelm
parents: 46750
diff changeset
   450
  {
57612
990ffb84489b clarified module name: facilitate alternative GUI frameworks;
wenzelm
parents: 57610
diff changeset
   451
    GUI_Thread.require {}
54509
1f77110c94ef maintain document model for all files, with document view for theory only, and special blob for non-theory files;
wenzelm
parents: 54464
diff changeset
   452
64673
b5965890e54d more uniform treatment of file name vs. theory name and special header;
wenzelm
parents: 63446
diff changeset
   453
    PIDE.resources.special_header(node_name) getOrElse
64826
c97296294f6d clarified check_thy_reader: check node_name here;
wenzelm
parents: 64825
diff changeset
   454
      JEdit_Lib.buffer_lock(buffer) {
65359
9ca34f0407a9 provide session qualifier via resources;
wenzelm
parents: 65246
diff changeset
   455
        PIDE.resources.check_thy_reader(node_name, JEdit_Lib.buffer_reader(buffer), strict = false)
46748
8f3ae4d04a2d refined node_header -- more direct buffer access (again);
wenzelm
parents: 46740
diff changeset
   456
      }
46920
5f44c8bea84e more explicit indication of swing thread context;
wenzelm
parents: 46750
diff changeset
   457
  }
44385
e7fdb008aa7d propagate editor perspective through document model;
wenzelm
parents: 44379
diff changeset
   458
e7fdb008aa7d propagate editor perspective through document model;
wenzelm
parents: 44379
diff changeset
   459
e7fdb008aa7d propagate editor perspective through document model;
wenzelm
parents: 44379
diff changeset
   460
  /* perspective */
e7fdb008aa7d propagate editor perspective through document model;
wenzelm
parents: 44379
diff changeset
   461
57612
990ffb84489b clarified module name: facilitate alternative GUI frameworks;
wenzelm
parents: 57610
diff changeset
   462
  // owned by GUI thread
52816
c608e0ade554 home-grown mouse handling to pretend that the painted checkbox is actually a Swing component;
wenzelm
parents: 52815
diff changeset
   463
  private var _node_required = false
c608e0ade554 home-grown mouse handling to pretend that the painted checkbox is actually a Swing component;
wenzelm
parents: 52815
diff changeset
   464
  def node_required: Boolean = _node_required
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   465
  def set_node_required(b: Boolean) { GUI_Thread.require { _node_required = b } }
52808
143f225e50f5 allow explicit indication of required node: full eval, no prints;
wenzelm
parents: 52807
diff changeset
   466
64883
e89f5ef32aa2 tuned signature;
wenzelm
parents: 64868
diff changeset
   467
  def document_view_iterator: Iterator[Document_View] =
e89f5ef32aa2 tuned signature;
wenzelm
parents: 64868
diff changeset
   468
    for {
e89f5ef32aa2 tuned signature;
wenzelm
parents: 64868
diff changeset
   469
      text_area <- JEdit_Lib.jedit_text_areas(buffer)
e89f5ef32aa2 tuned signature;
wenzelm
parents: 64868
diff changeset
   470
      doc_view <- Document_View.get(text_area)
e89f5ef32aa2 tuned signature;
wenzelm
parents: 64868
diff changeset
   471
    } yield doc_view
e89f5ef32aa2 tuned signature;
wenzelm
parents: 64868
diff changeset
   472
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   473
  override def document_view_ranges(snapshot: Document.Snapshot): List[Text.Range] =
44385
e7fdb008aa7d propagate editor perspective through document model;
wenzelm
parents: 44379
diff changeset
   474
  {
57612
990ffb84489b clarified module name: facilitate alternative GUI frameworks;
wenzelm
parents: 57610
diff changeset
   475
    GUI_Thread.require {}
52759
a20631db9c8a support declarative editor_execution_range, instead of old-style check/cancel buttons;
wenzelm
parents: 50565
diff changeset
   476
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   477
    (for {
64883
e89f5ef32aa2 tuned signature;
wenzelm
parents: 64868
diff changeset
   478
      doc_view <- document_view_iterator
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   479
      range <- doc_view.perspective(snapshot).ranges.iterator
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   480
    } yield range).toList
44385
e7fdb008aa7d propagate editor perspective through document model;
wenzelm
parents: 44379
diff changeset
   481
  }
e7fdb008aa7d propagate editor perspective through document model;
wenzelm
parents: 44379
diff changeset
   482
e7fdb008aa7d propagate editor perspective through document model;
wenzelm
parents: 44379
diff changeset
   483
54509
1f77110c94ef maintain document model for all files, with document view for theory only, and special blob for non-theory files;
wenzelm
parents: 54464
diff changeset
   484
  /* blob */
1f77110c94ef maintain document model for all files, with document view for theory only, and special blob for non-theory files;
wenzelm
parents: 54464
diff changeset
   485
64885
205274ca16ee tuned whitespace;
wenzelm
parents: 64883
diff changeset
   486
  // owned by GUI thread
205274ca16ee tuned whitespace;
wenzelm
parents: 64883
diff changeset
   487
  private var _blob: Option[(Bytes, Symbol.Text_Chunk)] = None
54511
1fd24c96ce9b caching of blob;
wenzelm
parents: 54509
diff changeset
   488
57612
990ffb84489b clarified module name: facilitate alternative GUI frameworks;
wenzelm
parents: 57610
diff changeset
   489
  private def reset_blob(): Unit = GUI_Thread.require { _blob = None }
54511
1fd24c96ce9b caching of blob;
wenzelm
parents: 54509
diff changeset
   490
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   491
  def get_blob: Option[Document.Blob] =
57612
990ffb84489b clarified module name: facilitate alternative GUI frameworks;
wenzelm
parents: 57610
diff changeset
   492
    GUI_Thread.require {
55783
da0513d95155 more formal Document.Blobs;
wenzelm
parents: 55781
diff changeset
   493
      if (is_theory) None
da0513d95155 more formal Document.Blobs;
wenzelm
parents: 55781
diff changeset
   494
      else {
56473
5b5c750e9763 simplified Text.Chunk -- eliminated ooddities;
wenzelm
parents: 56469
diff changeset
   495
        val (bytes, chunk) =
55783
da0513d95155 more formal Document.Blobs;
wenzelm
parents: 55781
diff changeset
   496
          _blob match {
da0513d95155 more formal Document.Blobs;
wenzelm
parents: 55781
diff changeset
   497
            case Some(x) => x
da0513d95155 more formal Document.Blobs;
wenzelm
parents: 55781
diff changeset
   498
            case None =>
64835
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   499
              val bytes = PIDE.resources.make_file_content(buffer)
56746
d37a5d09a277 tuned signature;
wenzelm
parents: 56662
diff changeset
   500
              val chunk = Symbol.Text_Chunk(buffer.getSegment(0, buffer.getLength))
56473
5b5c750e9763 simplified Text.Chunk -- eliminated ooddities;
wenzelm
parents: 56469
diff changeset
   501
              _blob = Some((bytes, chunk))
5b5c750e9763 simplified Text.Chunk -- eliminated ooddities;
wenzelm
parents: 56469
diff changeset
   502
              (bytes, chunk)
55783
da0513d95155 more formal Document.Blobs;
wenzelm
parents: 55781
diff changeset
   503
          }
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   504
        val changed = pending_edits.nonEmpty
56473
5b5c750e9763 simplified Text.Chunk -- eliminated ooddities;
wenzelm
parents: 56469
diff changeset
   505
        Some(Document.Blob(bytes, chunk, changed))
54511
1fd24c96ce9b caching of blob;
wenzelm
parents: 54509
diff changeset
   506
      }
1fd24c96ce9b caching of blob;
wenzelm
parents: 54509
diff changeset
   507
    }
54509
1f77110c94ef maintain document model for all files, with document view for theory only, and special blob for non-theory files;
wenzelm
parents: 54464
diff changeset
   508
1f77110c94ef maintain document model for all files, with document view for theory only, and special blob for non-theory files;
wenzelm
parents: 54464
diff changeset
   509
58543
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   510
  /* bibtex entries */
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   511
64885
205274ca16ee tuned whitespace;
wenzelm
parents: 64883
diff changeset
   512
  // owned by GUI thread
205274ca16ee tuned whitespace;
wenzelm
parents: 64883
diff changeset
   513
  private var _bibtex_entries: Option[List[Text.Info[String]]] = None
58543
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   514
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   515
  private def reset_bibtex_entries(): Unit = GUI_Thread.require { _bibtex_entries = None }
58543
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   516
64831
4792ee012e94 tuned signature;
wenzelm
parents: 64829
diff changeset
   517
  def bibtex_entries: List[Text.Info[String]] =
58543
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   518
    GUI_Thread.require {
64828
e837f6bf653c clarified modules;
wenzelm
parents: 64827
diff changeset
   519
      if (Bibtex.check_name(node_name)) {
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   520
        _bibtex_entries match {
58543
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   521
          case Some(entries) => entries
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   522
          case None =>
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   523
            val text = JEdit_Lib.buffer_text(buffer)
64828
e837f6bf653c clarified modules;
wenzelm
parents: 64827
diff changeset
   524
            val entries =
64831
4792ee012e94 tuned signature;
wenzelm
parents: 64829
diff changeset
   525
              try { Bibtex.document_entries(text) }
64828
e837f6bf653c clarified modules;
wenzelm
parents: 64827
diff changeset
   526
              catch { case ERROR(msg) => Output.warning(msg); Nil }
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   527
            _bibtex_entries = Some(entries)
58543
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   528
            entries
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   529
        }
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   530
      }
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   531
      else Nil
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   532
    }
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   533
9c1389befa56 maintain Document_Model.bibtex_entries;
wenzelm
parents: 57883
diff changeset
   534
50344
608265769ce0 emit bulk edits on initialization of multiple buffers, which greatly improves performance when starting big sessions (e.g. JinjaThreads);
wenzelm
parents: 50207
diff changeset
   535
  /* pending edits */
43648
e32de528b5ef more explicit edit_node vs. init_node;
wenzelm
parents: 43644
diff changeset
   536
60272
4f72b00d9952 no GUI_Thread for SideKick parsers (in contrast to 4c8205fe3644), to avoid danger of deadlock due to nested context switch;
wenzelm
parents: 59737
diff changeset
   537
  private object pending_edits
38224
809578d7f6af more explicit model of pending text edits;
wenzelm
parents: 38223
diff changeset
   538
  {
38425
e467db701d78 moved Text_Edit to Text.Edit;
wenzelm
parents: 38417
diff changeset
   539
    private val pending = new mutable.ListBuffer[Text.Edit]
57615
df1b3452d71c more explicit discrimination of empty nodes -- suppress from Theories panel;
wenzelm
parents: 57612
diff changeset
   540
    private var last_perspective = Document.Node.no_perspective_text
44438
0fc38897248a early filtering of unchanged perspective;
wenzelm
parents: 44436
diff changeset
   541
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   542
    def nonEmpty: Boolean = synchronized { pending.nonEmpty }
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   543
    def get_edits: List[Text.Edit] = synchronized { pending.toList }
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   544
    def get_last_perspective: Document.Node.Perspective_Text = synchronized { last_perspective }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   545
    def set_last_perspective(perspective: Document.Node.Perspective_Text): Unit =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   546
      synchronized { last_perspective = perspective }
38224
809578d7f6af more explicit model of pending text edits;
wenzelm
parents: 38223
diff changeset
   547
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   548
    def flush_edits(doc_blobs: Document.Blobs, hidden: Boolean): List[Document.Edit_Text] =
61728
5f5ff1eab407 double flush to ensure persistent "state" output is reset;
wenzelm
parents: 61538
diff changeset
   549
      synchronized {
5f5ff1eab407 double flush to ensure persistent "state" output is reset;
wenzelm
parents: 61538
diff changeset
   550
        GUI_Thread.require {}
60272
4f72b00d9952 no GUI_Thread for SideKick parsers (in contrast to 4c8205fe3644), to avoid danger of deadlock due to nested context switch;
wenzelm
parents: 59737
diff changeset
   551
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   552
        val edits = get_edits
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   553
        val (reparse, perspective) = node_perspective(doc_blobs, hidden)
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   554
        if (reparse || edits.nonEmpty || last_perspective != perspective) {
61728
5f5ff1eab407 double flush to ensure persistent "state" output is reset;
wenzelm
parents: 61538
diff changeset
   555
          pending.clear
5f5ff1eab407 double flush to ensure persistent "state" output is reset;
wenzelm
parents: 61538
diff changeset
   556
          last_perspective = perspective
64867
e7220f4de11f support "purge" operation on document model;
wenzelm
parents: 64864
diff changeset
   557
          node_edits(node_header, edits, perspective)
61728
5f5ff1eab407 double flush to ensure persistent "state" output is reset;
wenzelm
parents: 61538
diff changeset
   558
        }
5f5ff1eab407 double flush to ensure persistent "state" output is reset;
wenzelm
parents: 61538
diff changeset
   559
        else Nil
43648
e32de528b5ef more explicit edit_node vs. init_node;
wenzelm
parents: 43644
diff changeset
   560
      }
38224
809578d7f6af more explicit model of pending text edits;
wenzelm
parents: 38223
diff changeset
   561
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   562
    def edit(edits: List[Text.Edit]): Unit = synchronized
38224
809578d7f6af more explicit model of pending text edits;
wenzelm
parents: 38223
diff changeset
   563
    {
60272
4f72b00d9952 no GUI_Thread for SideKick parsers (in contrast to 4c8205fe3644), to avoid danger of deadlock due to nested context switch;
wenzelm
parents: 59737
diff changeset
   564
      GUI_Thread.require {}
4f72b00d9952 no GUI_Thread for SideKick parsers (in contrast to 4c8205fe3644), to avoid danger of deadlock due to nested context switch;
wenzelm
parents: 59737
diff changeset
   565
54511
1fd24c96ce9b caching of blob;
wenzelm
parents: 54509
diff changeset
   566
      reset_blob()
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   567
      reset_bibtex_entries()
54511
1fd24c96ce9b caching of blob;
wenzelm
parents: 54509
diff changeset
   568
64883
e89f5ef32aa2 tuned signature;
wenzelm
parents: 64868
diff changeset
   569
      for (doc_view <- document_view_iterator)
61538
bf4969660913 avoid highlighted area getting "stuck" after edit;
wenzelm
parents: 61192
diff changeset
   570
        doc_view.rich_text_area.active_reset()
bf4969660913 avoid highlighted area getting "stuck" after edit;
wenzelm
parents: 61192
diff changeset
   571
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   572
      pending ++= edits
65246
848965b5befc clarified singleton module;
wenzelm
parents: 65245
diff changeset
   573
      JEdit_Editor.invoke()
44436
546adfa8a6fc update_perspective without actual edits, bypassing the full state assignment protocol;
wenzelm
parents: 44385
diff changeset
   574
    }
546adfa8a6fc update_perspective without actual edits, bypassing the full state assignment protocol;
wenzelm
parents: 44385
diff changeset
   575
  }
546adfa8a6fc update_perspective without actual edits, bypassing the full state assignment protocol;
wenzelm
parents: 44385
diff changeset
   576
64835
fd1efd6dd385 resolve dependencies implicitly via File_Model, without jEdit Buffer_Model;
wenzelm
parents: 64832
diff changeset
   577
  def is_stable: Boolean = !pending_edits.nonEmpty
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   578
  def snapshot(): Document.Snapshot = session.snapshot(node_name, pending_edits.get_edits)
60933
6d03e05ef041 more robust access to stable tip version: take all pending edits into account, don't assume model for current buffer;
wenzelm
parents: 60274
diff changeset
   579
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   580
  def flush_edits(doc_blobs: Document.Blobs, hidden: Boolean): List[Document.Edit_Text] =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   581
    pending_edits.flush_edits(doc_blobs, hidden)
34828
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   582
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   583
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   584
  /* buffer listener */
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   585
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   586
  private val buffer_listener: BufferListener = new BufferAdapter
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   587
  {
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   588
    override def contentInserted(buffer: JEditBuffer,
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   589
      start_line: Int, offset: Int, num_lines: Int, length: Int)
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   590
    {
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   591
      pending_edits.edit(List(Text.Edit.insert(offset, buffer.getText(offset, length))))
34828
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   592
    }
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   593
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   594
    override def preContentRemoved(buffer: JEditBuffer,
38426
2858ec7b6dd8 specific types Text.Offset and Text.Range;
wenzelm
parents: 38425
diff changeset
   595
      start_line: Int, offset: Int, num_lines: Int, removed_length: Int)
34828
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   596
    {
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   597
      pending_edits.edit(List(Text.Edit.remove(offset, buffer.getText(offset, removed_length))))
34828
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   598
    }
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   599
  }
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   600
c2308b317244 misc tuning;
wenzelm
parents: 34827
diff changeset
   601
59078
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   602
  /* syntax */
37557
1ae272fd4082 refresh Isabelle token marker after buffer properties changed, e.g. when fold mode is switched;
wenzelm
parents: 37555
diff changeset
   603
59078
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   604
  def syntax_changed()
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   605
  {
61192
98eba31c51f8 tuned signature;
wenzelm
parents: 60933
diff changeset
   606
    JEdit_Lib.buffer_line_manager(buffer).setFirstInvalidLineContext(0)
59080
611914621edb added Untyped.method convenience (for *this* class only);
wenzelm
parents: 59079
diff changeset
   607
    for (text_area <- JEdit_Lib.jedit_text_areas(buffer))
611914621edb added Untyped.method convenience (for *this* class only);
wenzelm
parents: 59079
diff changeset
   608
      Untyped.method(Class.forName("org.gjt.sp.jedit.textarea.TextArea"), "foldStructureChanged").
611914621edb added Untyped.method convenience (for *this* class only);
wenzelm
parents: 59079
diff changeset
   609
        invoke(text_area)
62246
d9410066dbd5 more thorough syntax_changed: new commands need require new folds;
wenzelm
parents: 61728
diff changeset
   610
    buffer.invalidateCachedFoldLevels
59078
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   611
  }
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   612
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   613
  def init_token_marker()
59077
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   614
  {
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   615
    Isabelle.buffer_token_marker(buffer) match {
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   616
      case Some(marker) if marker != buffer.getTokenMarker =>
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   617
        buffer.setTokenMarker(marker)
59078
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   618
        syntax_changed()
59077
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   619
      case _ =>
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   620
    }
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   621
  }
7e0d3da6e6d8 node-specific syntax, with base_syntax as default;
wenzelm
parents: 59076
diff changeset
   622
59078
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   623
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   624
  /* init */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   625
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   626
  def init(old_model: Option[File_Model]): Buffer_Model =
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   627
  {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   628
    GUI_Thread.require {}
59078
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   629
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   630
    old_model match {
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   631
      case None =>
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   632
        pending_edits.edit(List(Text.Edit.insert(0, JEdit_Lib.buffer_text(buffer))))
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   633
      case Some(file_model) =>
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   634
        set_node_required(file_model.node_required)
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   635
        pending_edits.set_last_perspective(file_model.last_perspective)
64818
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   636
        pending_edits.edit(
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   637
          file_model.pending_edits :::
67a0a563d2b3 clarified buffer events: exit model while loading;
wenzelm
parents: 64817
diff changeset
   638
            Text.Edit.replace(0, file_model.content.text, JEdit_Lib.buffer_text(buffer)))
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   639
    }
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   640
34784
02959dcea756 split Theory_View into Document_Model (connected to Buffer) and Document_View (connected to JEditTextArea);
wenzelm
parents: 34783
diff changeset
   641
    buffer.addBufferListener(buffer_listener)
59078
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   642
    init_token_marker()
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   643
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   644
    this
34680
1f1f6c95de64 clarified structure of TheoryView
immler@in.tum.de
parents: 34679
diff changeset
   645
  }
1f1f6c95de64 clarified structure of TheoryView
immler@in.tum.de
parents: 34679
diff changeset
   646
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   647
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   648
  /* exit */
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   649
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   650
  def exit(): File_Model =
34680
1f1f6c95de64 clarified structure of TheoryView
immler@in.tum.de
parents: 34679
diff changeset
   651
  {
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   652
    GUI_Thread.require {}
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   653
34784
02959dcea756 split Theory_View into Document_Model (connected to Buffer) and Document_View (connected to JEditTextArea);
wenzelm
parents: 34783
diff changeset
   654
    buffer.removeBufferListener(buffer_listener)
59078
cf255dc2b48f more careful syntax_changed propagation -- avoid global jEdit.propertiesChanged;
wenzelm
parents: 59077
diff changeset
   655
    init_token_marker()
64817
0bb6b582bb4f separate Buffer_Model vs. File_Model;
wenzelm
parents: 64813
diff changeset
   656
64863
wenzelm
parents: 64858
diff changeset
   657
    File_Model.init(session, node_name, JEdit_Lib.buffer_text(buffer), node_required,
wenzelm
parents: 64858
diff changeset
   658
      pending_edits.get_last_perspective, pending_edits.get_edits)
34680
1f1f6c95de64 clarified structure of TheoryView
immler@in.tum.de
parents: 34679
diff changeset
   659
  }
34447
wenzelm
parents: 34446
diff changeset
   660
}