src/Tools/VSCode/src/pretty_text_panel.scala
author Thomas Lindae <thomas.lindae@in.tum.de>
Fri, 14 Jun 2024 10:21:03 +0200
changeset 81054 4bfcb14547c6
child 81059 fb1183184e68
permissions -rw-r--r--
lsp: added Pretty_Text_Panel module;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
81054
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
     1
/*  Title:      Tools/VSCode/src/pretty_text_panel.scala
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
     2
    Author:     Thomas Lindae, TU Muenchen
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
     3
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
     4
Pretty-printed text or HTML with decorations.
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
     5
*/
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
     6
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
     7
package isabelle.vscode
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
     8
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
     9
import isabelle._
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    10
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    11
object Pretty_Text_Panel {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    12
  def apply(
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    13
    resources: VSCode_Resources,
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    14
    channel: Channel,
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    15
    output: (String, Option[LSP.Decoration_List]) => Unit
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    16
  ): Pretty_Text_Panel = new Pretty_Text_Panel(resources, channel, output)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    17
}
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    18
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    19
class Pretty_Text_Panel private(
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    20
  resources: VSCode_Resources,
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    21
  channel: Channel,
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    22
  output: (String, Option[LSP.Decoration_List]) => Unit
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    23
) {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    24
  private var current_body: XML.Body = Nil
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    25
  private var current_formatted: XML.Body = Nil
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    26
  private var margin: Double = resources.message_margin
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    27
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    28
  private val delay_margin = Delay.last(resources.output_delay, channel.Error_Logger) {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    29
    refresh(current_body)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    30
  }
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    31
  
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    32
  def update_margin(new_margin: Double): Unit = {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    33
    margin = new_margin
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    34
    delay_margin.invoke()
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    35
  }
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    36
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    37
  def refresh(body: XML.Body): Unit = {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    38
    val formatted = Pretty.formatted(Pretty.separate(body), margin = margin, metric = Symbol.Metric)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    39
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    40
    if (formatted == current_formatted) return
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    41
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    42
    current_body = body
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    43
    current_formatted = formatted
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    44
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    45
    if (resources.html_output) {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    46
      val node_context =
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    47
        new Browser_Info.Node_Context {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    48
          override def make_ref(props: Properties.T, body: XML.Body): Option[XML.Elem] =
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    49
            for {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    50
              thy_file <- Position.Def_File.unapply(props)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    51
              def_line <- Position.Def_Line.unapply(props)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    52
              source <- resources.source_file(thy_file)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    53
              uri = File.uri(Path.explode(source).absolute_file)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    54
            } yield HTML.link(uri.toString + "#" + def_line, body)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    55
        }
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    56
      val elements = Browser_Info.extra_elements.copy(entity = Markup.Elements.full)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    57
      val html = node_context.make_html(elements, formatted)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    58
      output(HTML.source(html).toString, None)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    59
    } else {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    60
      def convert_symbols(body: XML.Body): XML.Body = {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    61
        body.map {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    62
          case XML.Elem(markup, body) => XML.Elem(markup, convert_symbols(body))
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    63
          case XML.Text(content) => XML.Text(Symbol.output(resources.unicode_symbols, content))
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    64
        }
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    65
      }
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    66
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    67
      val tree = Markup_Tree.from_XML(convert_symbols(formatted))
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    68
      val text = resources.output_text(XML.content(formatted))
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    69
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    70
      val document = Line.Document(text)
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    71
      val decorations = tree
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    72
        .cumulate(Text.Range.full, None: Option[String], Rendering.text_color_elements, (_, m) => {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    73
          Some(Some(m.info.name))
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    74
        })
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    75
        .flatMap(e => e._2 match {
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    76
          case None => None
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    77
          case Some(i) => Some((document.range(e._1), "text_" ++ Rendering.text_color(i).toString))
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    78
        })
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    79
        .groupMap(_._2)(e => LSP.Decoration_Options(e._1, List())).toList
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    80
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    81
      output(text, Some(decorations))
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    82
    }
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    83
  }
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    84
}
4bfcb14547c6 lsp: added Pretty_Text_Panel module;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
diff changeset
    85