src/Pure/General/pretty.ML
author wenzelm
Sat, 26 Apr 2025 20:52:46 +0200
changeset 82591 ae1e6ff06b03
parent 82587 7415414bd9d8
permissions -rw-r--r--
more robust output: no markup as last resort;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6118
caa439435666 fixed titles;
wenzelm
parents: 6116
diff changeset
     1
(*  Title:      Pure/General/pretty.ML
8806
wenzelm
parents: 8456
diff changeset
     2
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
80892
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
     3
    Author:     Makarius
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
     4
80892
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
     5
Generic pretty printing.
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
     6
80892
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
     7
The object to be printed is given as a tree with blocks and breaks. A block
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
     8
causes alignment and may specify additional indentation and markup. A break
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
     9
inserts a newline if the text until the next break is too long to fit on the
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    10
current line. After the newline, text is indented to the level of the
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    11
enclosing block. Normally, if a block is broken then all enclosing blocks will
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    12
also be broken.
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    13
80892
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    14
References:
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    15
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    16
  * L. C. Paulson, "ML for the Working Programmer" (1996),
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    17
    2nd edition, Cambridge University Press.
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    18
    Section 8.10 "A pretty printer"
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    19
    https://www.cl.cam.ac.uk/~lp15/MLbook/PDF/chapter8.pdf
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    20
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    21
  * D. C. Oppen, "Pretty Printing",
59c91b238034 tuned comments;
wenzelm
parents: 80878
diff changeset
    22
    ACM Transactions on Programming Languages and Systems (1980), 465-483.
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    23
*)
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    24
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    25
signature PRETTY =
14832
6589a58f57cb pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
wenzelm
parents: 12421
diff changeset
    26
sig
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    27
  type T
80810
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
    28
  val to_ML: T -> ML_Pretty.pretty
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
    29
  val from_ML: ML_Pretty.pretty -> T
80878
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
    30
  val blk: int * T list -> T
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
    31
  val block0: T list -> T
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
    32
  val block1: T list -> T
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
    33
  val block: T list -> T
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
    34
  type 'a block = {markup: 'a, open_block: bool, consistent: bool, indent: int}
80938
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
    35
  val make_block: Markup.output block -> T list -> T
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
    36
  val markup_block: Markup.T block -> T list -> T
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
    37
  val markup: Markup.T -> T list -> T
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
    38
  val markup_open: Markup.T -> T list -> T
80938
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
    39
  val mark: Markup.T -> T -> T
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
    40
  val mark_open: Markup.T -> T -> T
80938
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
    41
  val markup_blocks: Markup.T list block -> T list -> T
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    42
  val str: string -> T
80813
9dd4dcb08d37 clarified signature, following 1f718be3608b: Pretty.str is now value-oriented;
wenzelm
parents: 80812
diff changeset
    43
  val dots: T
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    44
  val brk: int -> T
61862
e2a9e46ac0fb support pretty break indent, like underlying ML systems;
wenzelm
parents: 56334
diff changeset
    45
  val brk_indent: int -> int -> T
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    46
  val fbrk: T
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    47
  val breaks: T list -> T list
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    48
  val fbreaks: T list -> T list
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
    49
  val strs: string list -> T
42266
f87e0be80a3f clarified Pretty.mark;
wenzelm
parents: 40131
diff changeset
    50
  val mark_str: Markup.T * string -> T
f87e0be80a3f clarified Pretty.mark;
wenzelm
parents: 40131
diff changeset
    51
  val marks_str: Markup.T list * string -> T
80873
e71cb37c7395 clarified signature: more explicit operations;
wenzelm
parents: 80867
diff changeset
    52
  val mark_position: Position.T -> T -> T
e71cb37c7395 clarified signature: more explicit operations;
wenzelm
parents: 80867
diff changeset
    53
  val mark_str_position: Position.T * string -> T
51570
3633828d80fc basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
wenzelm
parents: 51511
diff changeset
    54
  val item: T list -> T
52693
6651abced106 tuned signature;
wenzelm
parents: 51570
diff changeset
    55
  val text_fold: T list -> T
55763
4b3907cb5654 tuned signature;
wenzelm
parents: 55033
diff changeset
    56
  val keyword1: string -> T
4b3907cb5654 tuned signature;
wenzelm
parents: 55033
diff changeset
    57
  val keyword2: string -> T
50162
e06eabc421e7 some support for breakable text and paragraphs;
wenzelm
parents: 49656
diff changeset
    58
  val text: string -> T list
e06eabc421e7 some support for breakable text and paragraphs;
wenzelm
parents: 49656
diff changeset
    59
  val paragraph: T list -> T
e06eabc421e7 some support for breakable text and paragraphs;
wenzelm
parents: 49656
diff changeset
    60
  val para: string -> T
18802
f449d516f36b renamed gen_list to enum;
wenzelm
parents: 18603
diff changeset
    61
  val quote: T -> T
55033
8e8243975860 support for nested text cartouches;
wenzelm
parents: 52693
diff changeset
    62
  val cartouche: T -> T
18802
f449d516f36b renamed gen_list to enum;
wenzelm
parents: 18603
diff changeset
    63
  val separate: string -> T list -> T list
f449d516f36b renamed gen_list to enum;
wenzelm
parents: 18603
diff changeset
    64
  val commas: T list -> T list
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    65
  val enclose: string -> string -> T list -> T
18802
f449d516f36b renamed gen_list to enum;
wenzelm
parents: 18603
diff changeset
    66
  val enum: string -> string -> string -> T list -> T
30620
16b7ecc183e5 added position;
wenzelm
parents: 29606
diff changeset
    67
  val position: Position.T -> T
71465
910a081cca74 more position information for oracles (e.g. "skip_proof" for 'sorry'), requires Proofterm.proofs := 1;
wenzelm
parents: 69345
diff changeset
    68
  val here: Position.T -> T list
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    69
  val list: string -> string -> T list -> T
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    70
  val str_list: string -> string -> string list -> T
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    71
  val big_list: string -> T list -> T
9730
11d137b25555 added indent;
wenzelm
parents: 9121
diff changeset
    72
  val indent: int -> T -> T
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
    73
  val unbreakable: T -> T
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
    74
  type output_ops =
80855
301612847ea3 further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
wenzelm
parents: 80854
diff changeset
    75
   {symbolic: bool,
301612847ea3 further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
wenzelm
parents: 80854
diff changeset
    76
    output: string -> Output.output * int,
80829
bdae6195a287 clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
wenzelm
parents: 80825
diff changeset
    77
    markup: Markup.output -> Markup.output,
81683
b31d09029b94 clarified signature: more direct indent_markup;
wenzelm
parents: 81270
diff changeset
    78
    indent_markup: Markup.output,
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
    79
    margin: int}
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
    80
  val output_ops: int option -> output_ops
80854
95da048f47d9 misc tuning and clarification;
wenzelm
parents: 80849
diff changeset
    81
  val pure_output_ops: int option -> output_ops
80830
28f069b85eea tuned signature: more options;
wenzelm
parents: 80829
diff changeset
    82
  val markup_output_ops: int option -> output_ops
80855
301612847ea3 further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
wenzelm
parents: 80854
diff changeset
    83
  val symbolic_output_ops: output_ops
80848
df85df6315af clarified signature: prefer explicit type Bytes.T;
wenzelm
parents: 80846
diff changeset
    84
  val symbolic_output: T -> Bytes.T
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
    85
  val symbolic_string_of: T -> string
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
    86
  val unformatted_string_of: T -> string
80848
df85df6315af clarified signature: prefer explicit type Bytes.T;
wenzelm
parents: 80846
diff changeset
    87
  val output: output_ops -> T -> Bytes.T
80841
1beb2dc3bf14 clarified signature;
wenzelm
parents: 80840
diff changeset
    88
  val string_of_ops: output_ops -> T -> string
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
    89
  val string_of: T -> string
82583
abd3885a3fcf more scalable;
wenzelm
parents: 82316
diff changeset
    90
  val strings_of: T -> string list
80863
af34fcf7215d tuned signature: more operations;
wenzelm
parents: 80861
diff changeset
    91
  val pure_string_of: T -> string
49656
7ff712de5747 treat wrapped markup elements as raw markup delimiters;
wenzelm
parents: 49565
diff changeset
    92
  val writeln: T -> unit
82316
83584916b6d7 support for writeln_urgent, which is shown in Output before state messages (reminiscent of old Output.urgent_message before 521cea5fa777);
wenzelm
parents: 81718
diff changeset
    93
  val writeln_urgent: T -> unit
56334
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
    94
  val markup_chunks: Markup.T -> T list -> T
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
    95
  val chunks: T list -> T
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
    96
  val chunks2: T list -> T
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
    97
  val block_enclose: T * T -> T list -> T
14832
6589a58f57cb pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
wenzelm
parents: 12421
diff changeset
    98
end;
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
    99
23617
840904fc1eb1 added print_mode setup: indent and markup;
wenzelm
parents: 22019
diff changeset
   100
structure Pretty: PRETTY =
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   101
struct
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   102
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   103
(** Pretty.T **)
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   104
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   105
(* abstype: ML_Pretty.pretty without (op =) *)
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   106
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   107
abstype T = T of ML_Pretty.pretty
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   108
with
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   109
  fun to_ML (T prt) = prt;
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   110
  val from_ML = T;
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   111
end;
10952
b520e4f1313b support general indentation (e.g. for non-tt latex output);
wenzelm
parents: 9730
diff changeset
   112
62785
70b9c7d4ed7f more robust pretty printing: permissive treatment of bad values;
wenzelm
parents: 62784
diff changeset
   113
val force_nat = Integer.max 0;
80810
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   114
val short_nat = FixedInt.fromInt o force_nat;
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   115
val long_nat = force_nat o FixedInt.toInt;
62785
70b9c7d4ed7f more robust pretty printing: permissive treatment of bad values;
wenzelm
parents: 62784
diff changeset
   116
80810
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   117
80878
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   118
(* blocks *)
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   119
80938
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   120
fun blk (indent, body) =
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   121
  from_ML (ML_Pretty.PrettyBlock (short_nat indent, false, [], map to_ML body));
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   122
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   123
fun block0 body = blk (0, body);
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   124
fun block1 body = blk (1, body);
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   125
fun block body = blk (2, body);
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   126
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   127
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   128
(* blocks with markup *)
a119154a5f27 minor performance tuning: more direct blocks without markup;
wenzelm
parents: 80937
diff changeset
   129
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   130
type 'a block = {markup: 'a, open_block: bool, consistent: bool, indent: int}
80878
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   131
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   132
fun make_block ({markup, open_block, consistent, indent}: Markup.output block) body =
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   133
  let
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   134
    val context =
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   135
      ML_Pretty.markup_context markup @
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   136
      ML_Pretty.open_block_context open_block;
80937
wenzelm
parents: 80936
diff changeset
   137
  in from_ML (ML_Pretty.PrettyBlock (short_nat indent, consistent, context, map to_ML body)) end;
61864
3a5992c3410c support for blocks with consistent breaks;
wenzelm
parents: 61863
diff changeset
   138
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   139
fun markup_block ({markup, open_block, consistent, indent}: Markup.T block) body =
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   140
  make_block
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   141
   {markup = YXML.output_markup markup,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   142
    open_block = open_block,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   143
    consistent = consistent,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   144
    indent = indent} body;
61864
3a5992c3410c support for blocks with consistent breaks;
wenzelm
parents: 61863
diff changeset
   145
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   146
fun markup m = markup_block {markup = m, open_block = false, consistent = false, indent = 0};
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   147
fun markup_open m = markup_block {markup = m, open_block = true, consistent = false, indent = 0};
80936
30c7922ec862 tuned signature;
wenzelm
parents: 80903
diff changeset
   148
30c7922ec862 tuned signature;
wenzelm
parents: 80903
diff changeset
   149
fun mark m prt = if m = Markup.empty then prt else markup m [prt];
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   150
fun mark_open m prt = if m = Markup.empty then prt else markup_open m [prt];
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   151
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   152
fun markup_blocks ({markup, open_block, consistent, indent}: Markup.T list block) body =
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   153
  if forall Markup.is_empty markup andalso not open_block andalso not consistent
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   154
  then blk (indent, body)
80942
501ebf1fc308 minor performance tuning for blocks without markup;
wenzelm
parents: 80938
diff changeset
   155
  else
501ebf1fc308 minor performance tuning for blocks without markup;
wenzelm
parents: 80938
diff changeset
   156
    let
501ebf1fc308 minor performance tuning for blocks without markup;
wenzelm
parents: 80938
diff changeset
   157
      val markups = filter_out Markup.is_empty markup;
501ebf1fc308 minor performance tuning for blocks without markup;
wenzelm
parents: 80938
diff changeset
   158
      val (ms, m) = if null markups then ([], Markup.empty) else split_last markups;
501ebf1fc308 minor performance tuning for blocks without markup;
wenzelm
parents: 80938
diff changeset
   159
    in
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   160
      fold_rev mark_open ms
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   161
        (markup_block
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   162
          {markup = m, open_block = open_block, consistent = consistent, indent = indent} body)
80942
501ebf1fc308 minor performance tuning for blocks without markup;
wenzelm
parents: 80938
diff changeset
   163
    end;
80937
wenzelm
parents: 80936
diff changeset
   164
80878
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   165
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   166
(* breaks *)
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   167
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   168
fun brk_indent wd ind = from_ML (ML_Pretty.PrettyBreak (short_nat wd, short_nat ind));
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   169
fun brk wd = brk_indent wd 0;
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   170
val fbrk = from_ML ML_Pretty.PrettyLineBreak;
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   171
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   172
fun breaks prts = Library.separate (brk 1) prts;
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   173
fun fbreaks prts = Library.separate fbrk prts;
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   174
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   175
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   176
(* derived operations to create formatting expressions *)
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   177
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   178
val str = from_ML o ML_Pretty.str;
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   179
val dots = from_ML ML_Pretty.dots;
cddd64134b49 tuned signature and module structure;
wenzelm
parents: 80875
diff changeset
   180
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   181
val strs = block o breaks o map str;
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   182
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   183
fun mark_str (m, s) = mark_open m (str s);
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   184
fun marks_str (ms, s) = fold_rev mark_open ms (str s);
42266
f87e0be80a3f clarified Pretty.mark;
wenzelm
parents: 40131
diff changeset
   185
80875
2e33897071b6 clarified signature;
wenzelm
parents: 80873
diff changeset
   186
val mark_position = mark o Position.markup;
2e33897071b6 clarified signature;
wenzelm
parents: 80873
diff changeset
   187
fun mark_str_position (pos, s) = mark_str (Position.markup pos, s);
80873
e71cb37c7395 clarified signature: more explicit operations;
wenzelm
parents: 80867
diff changeset
   188
51570
3633828d80fc basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
wenzelm
parents: 51511
diff changeset
   189
val item = markup Markup.item;
52693
6651abced106 tuned signature;
wenzelm
parents: 51570
diff changeset
   190
val text_fold = markup Markup.text_fold;
51570
3633828d80fc basic support for Pretty.item, which is considered as logical markup and interpreted in Isabelle/Scala, but ignored elsewhere (TTY, latex etc.);
wenzelm
parents: 51511
diff changeset
   191
55763
4b3907cb5654 tuned signature;
wenzelm
parents: 55033
diff changeset
   192
fun keyword1 name = mark_str (Markup.keyword1, name);
4b3907cb5654 tuned signature;
wenzelm
parents: 55033
diff changeset
   193
fun keyword2 name = mark_str (Markup.keyword2, name);
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   194
50162
e06eabc421e7 some support for breakable text and paragraphs;
wenzelm
parents: 49656
diff changeset
   195
val text = breaks o map str o Symbol.explode_words;
50201
c26369c9eda6 Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
wenzelm
parents: 50162
diff changeset
   196
val paragraph = markup Markup.paragraph;
50162
e06eabc421e7 some support for breakable text and paragraphs;
wenzelm
parents: 49656
diff changeset
   197
val para = paragraph o text;
e06eabc421e7 some support for breakable text and paragraphs;
wenzelm
parents: 49656
diff changeset
   198
80328
559909bd7715 clarified signature: more operations;
wenzelm
parents: 74231
diff changeset
   199
fun quote prt = block1 [str "\"", prt, str "\""];
559909bd7715 clarified signature: more operations;
wenzelm
parents: 74231
diff changeset
   200
fun cartouche prt = block1 [str Symbol.open_, prt, str Symbol.close];
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   201
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   202
fun separate sep prts =
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   203
  flat (Library.separate [str sep, brk 1] (map single prts));
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   204
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   205
val commas = separate ",";
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   206
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   207
fun enclose lpar rpar prts =
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   208
  block (str lpar :: (prts @ [str rpar]));
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   209
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   210
fun enum sep lpar rpar prts = enclose lpar rpar (separate sep prts);
10952
b520e4f1313b support general indentation (e.g. for non-tt latex output);
wenzelm
parents: 9730
diff changeset
   211
30620
16b7ecc183e5 added position;
wenzelm
parents: 29606
diff changeset
   212
val position =
80504
7ea69c26524b tuned signature: more operations;
wenzelm
parents: 80328
diff changeset
   213
  enum "," "{" "}" o map (str o Properties.print_eq) o Position.properties_of;
30620
16b7ecc183e5 added position;
wenzelm
parents: 29606
diff changeset
   214
71465
910a081cca74 more position information for oracles (e.g. "skip_proof" for 'sorry'), requires Proofterm.proofs := 1;
wenzelm
parents: 69345
diff changeset
   215
fun here pos =
80873
e71cb37c7395 clarified signature: more explicit operations;
wenzelm
parents: 80867
diff changeset
   216
  let val (s1, s2) = Position.here_strs pos
e71cb37c7395 clarified signature: more explicit operations;
wenzelm
parents: 80867
diff changeset
   217
  in if s2 = "" then [] else [str s1, mark_str_position (pos, s2)] end;
71465
910a081cca74 more position information for oracles (e.g. "skip_proof" for 'sorry'), requires Proofterm.proofs := 1;
wenzelm
parents: 69345
diff changeset
   218
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   219
val list = enum ",";
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   220
fun str_list lpar rpar strs = list lpar rpar (map str strs);
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   221
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   222
fun big_list name prts = block (fbreaks (str name :: prts));
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   223
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   224
fun indent 0 prt = prt
80328
559909bd7715 clarified signature: more operations;
wenzelm
parents: 74231
diff changeset
   225
  | indent n prt = block0 [str (Symbol.spaces n), prt];
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   226
80810
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   227
val unbreakable =
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   228
  let
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   229
    fun unbreak (ML_Pretty.PrettyBlock (ind, consistent, context, body)) =
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   230
          ML_Pretty.PrettyBlock (ind, consistent, context, map unbreak body)
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   231
      | unbreak (ML_Pretty.PrettyBreak (wd, _)) =
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   232
          ML_Pretty.str (Symbol.spaces (long_nat wd))
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   233
      | unbreak prt = prt;
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   234
  in to_ML #> unbreak #> from_ML end;
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   235
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   236
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   237
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   238
(** formatting **)
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   239
82591
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   240
(* robust string output, with potential data loss *)
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   241
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   242
fun robust_string_of out prt =
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   243
  let
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   244
    val bs = out prt;
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   245
    val bs' =
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   246
      if Bytes.size bs <= String.maxSize then bs
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   247
      else out (from_ML (ML_Pretty.no_markup (to_ML prt)));
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   248
  in Bytes.content bs' end;
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   249
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   250
80861
9de19e3a7231 dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
wenzelm
parents: 80856
diff changeset
   251
(* output operations *)
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   252
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   253
type output_ops =
80855
301612847ea3 further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
wenzelm
parents: 80854
diff changeset
   254
 {symbolic: bool,
301612847ea3 further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
wenzelm
parents: 80854
diff changeset
   255
  output: string -> Output.output * int,
80829
bdae6195a287 clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
wenzelm
parents: 80825
diff changeset
   256
  markup: Markup.output -> Markup.output,
81683
b31d09029b94 clarified signature: more direct indent_markup;
wenzelm
parents: 81270
diff changeset
   257
  indent_markup: Markup.output,
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   258
  margin: int};
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   259
80861
9de19e3a7231 dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
wenzelm
parents: 80856
diff changeset
   260
fun make_output_ops {symbolic, markup} opt_margin : output_ops =
80855
301612847ea3 further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
wenzelm
parents: 80854
diff changeset
   261
 {symbolic = symbolic,
301612847ea3 further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
wenzelm
parents: 80854
diff changeset
   262
  output = fn s => (s, size s),
80854
95da048f47d9 misc tuning and clarification;
wenzelm
parents: 80849
diff changeset
   263
  markup = markup,
81683
b31d09029b94 clarified signature: more direct indent_markup;
wenzelm
parents: 81270
diff changeset
   264
  indent_markup = Markup.no_output,
80854
95da048f47d9 misc tuning and clarification;
wenzelm
parents: 80849
diff changeset
   265
  margin = ML_Pretty.get_margin opt_margin};
80849
e3a419073736 drop pointless print_mode operations Output.output / Output.escape;
wenzelm
parents: 80848
diff changeset
   266
80861
9de19e3a7231 dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
wenzelm
parents: 80856
diff changeset
   267
val pure_output_ops = make_output_ops {symbolic = false, markup = K Markup.no_output};
9de19e3a7231 dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
wenzelm
parents: 80856
diff changeset
   268
val markup_output_ops = make_output_ops {symbolic = false, markup = I};
9de19e3a7231 dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
wenzelm
parents: 80856
diff changeset
   269
val symbolic_output_ops = make_output_ops {symbolic = true, markup = I} NONE;
9de19e3a7231 dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
wenzelm
parents: 80856
diff changeset
   270
9de19e3a7231 dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
wenzelm
parents: 80856
diff changeset
   271
fun output_ops opt_margin =
80867
32d0a41eea25 tuned signature;
wenzelm
parents: 80863
diff changeset
   272
  if Print_Mode.PIDE_enabled () then symbolic_output_ops
80861
9de19e3a7231 dismantle print_mode operations for Markup/Pretty: hardwired check of "print_mode_active Print_Mode.PIDE";
wenzelm
parents: 80856
diff changeset
   273
  else pure_output_ops opt_margin;
80829
bdae6195a287 clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
wenzelm
parents: 80825
diff changeset
   274
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   275
fun output_newline (ops: output_ops) = #1 (#output ops "\n");
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   276
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   277
fun output_spaces (ops: output_ops) = #output ops o Symbol.spaces;
80848
df85df6315af clarified signature: prefer explicit type Bytes.T;
wenzelm
parents: 80846
diff changeset
   278
fun output_spaces_bytes ops = Bytes.add o #1 o output_spaces ops;
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   279
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   280
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   281
(* output tree *)
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   282
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   283
datatype tree =
81696
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   284
    End  (*end of markup*)
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   285
  | Block of
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   286
     {markup: Markup.output,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   287
      open_block: bool,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   288
      consistent: bool,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   289
      indent: int,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   290
      body: tree list,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   291
      length: int}
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   292
  | Break of bool * int * int  (*mandatory flag, width if not taken, extra indentation if taken*)
81696
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   293
  | Str of Output.output * int;  (*string output, length*)
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   294
81696
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   295
fun tree_length End = 0
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   296
  | tree_length (Block {length = len, ...}) = len
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   297
  | tree_length (Break (_, wd, _)) = wd
81696
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   298
  | tree_length (Str (_, len)) = len;
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   299
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   300
local
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   301
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   302
fun block_length indent =
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   303
  let
80936
30c7922ec862 tuned signature;
wenzelm
parents: 80903
diff changeset
   304
    fun block_len len body =
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   305
      let
80936
30c7922ec862 tuned signature;
wenzelm
parents: 80903
diff changeset
   306
        val (line, rest) = chop_prefix (fn Break (true, _, _) => false | _ => true) body;
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   307
        val len' = Int.max (fold (Integer.add o tree_length) line 0, len);
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   308
      in
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   309
        (case rest of
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   310
          Break (true, _, ind) :: rest' =>
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   311
            block_len len' (Break (false, indent + ind, 0) :: rest')
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   312
        | [] => len')
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   313
      end;
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   314
  in block_len 0 end;
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   315
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   316
val fbreak = Break (true, 1, 0);
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   317
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   318
in
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   319
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   320
fun output_tree (ops: output_ops) make_length =
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   321
  let
81270
wenzelm
parents: 81269
diff changeset
   322
    fun tree (ML_Pretty.PrettyBlock (ind, consistent, context, body)) =
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   323
          let
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   324
            val indent = long_nat ind;
81270
wenzelm
parents: 81269
diff changeset
   325
            val body' = map tree body;
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   326
          in
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   327
            Block
81266
8300511f4c45 clarified signature;
wenzelm
parents: 81121
diff changeset
   328
             {markup = #markup ops (ML_Pretty.markup_get context),
8300511f4c45 clarified signature;
wenzelm
parents: 81121
diff changeset
   329
              open_block = ML_Pretty.open_block_detect context,
81121
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   330
              consistent = consistent,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   331
              indent = indent,
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   332
              body = body',
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   333
              length = if make_length then block_length indent body' else ~1}
7cacedbddba7 support for pretty blocks that are "open" and thus have no impact on formatting, only on markup;
wenzelm
parents: 81120
diff changeset
   334
          end
81270
wenzelm
parents: 81269
diff changeset
   335
      | tree (ML_Pretty.PrettyBreak (wd, ind)) = Break (false, long_nat wd, long_nat ind)
wenzelm
parents: 81269
diff changeset
   336
      | tree ML_Pretty.PrettyLineBreak = fbreak
wenzelm
parents: 81269
diff changeset
   337
      | tree (ML_Pretty.PrettyString s) = Str (#output ops s ||> force_nat)
wenzelm
parents: 81269
diff changeset
   338
      | tree (ML_Pretty.PrettyStringWithWidth (s, n)) = Str (s, long_nat n);
wenzelm
parents: 81269
diff changeset
   339
  in tree o to_ML end;
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   340
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   341
end;
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   342
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   343
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   344
(* formatted output *)
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   345
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   346
local
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   347
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   348
type context = Markup.output list;  (*stack of pending markup*)
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   349
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   350
abstype state = State of context * Bytes.T
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   351
with
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   352
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   353
fun state_output (State (_, output)) = output;
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   354
81718
289ded3c342f tuned names: more uniform;
wenzelm
parents: 81701
diff changeset
   355
val init_state = State ([], Bytes.empty);
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   356
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   357
fun add_state s (State (context, output)) =
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   358
  State (context, Bytes.add s output);
17756
d4a35f82fbb4 minor tweaks for Poplog/ML;
wenzelm
parents: 17542
diff changeset
   359
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   360
fun push_state (markup as (bg, _)) (State (context, output)) =
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   361
  State (markup :: context, Bytes.add bg output);
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   362
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   363
fun pop_state (State ((_, en) :: context, output)) =
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   364
  State (context, Bytes.add en output);
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   365
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   366
fun close_state (State (context, output)) =
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   367
  State ([], fold (Bytes.add o #2) context output);
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   368
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   369
fun reopen_state (State (old_context, _)) (State (context, output)) =
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   370
  State (old_context @ context, fold_rev (Bytes.add o #1) old_context output);
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   371
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   372
end;
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   373
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   374
type text = {main: state, line: state option, pos: int, nl: int};
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   375
81718
289ded3c342f tuned names: more uniform;
wenzelm
parents: 81701
diff changeset
   376
val init_no_line: text = {main = init_state, line = NONE, pos = 0, nl = 0};
289ded3c342f tuned names: more uniform;
wenzelm
parents: 81701
diff changeset
   377
val init_line: text = {main = init_state, line = SOME init_state, pos = 0, nl = 0};
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   378
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   379
fun string (s, len) {main, line, pos, nl} : text =
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   380
 {main = add_state s main,
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   381
  line = Option.map (add_state s) line,
10952
b520e4f1313b support general indentation (e.g. for non-tt latex output);
wenzelm
parents: 9730
diff changeset
   382
  pos = pos + len,
b520e4f1313b support general indentation (e.g. for non-tt latex output);
wenzelm
parents: 9730
diff changeset
   383
  nl = nl};
b520e4f1313b support general indentation (e.g. for non-tt latex output);
wenzelm
parents: 9730
diff changeset
   384
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   385
fun push m {main, line, pos, nl} : text =
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   386
 {main = push_state m main,
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   387
  line = Option.map (push_state m) line,
81696
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   388
  pos = pos,
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   389
  nl = nl};
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   390
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   391
fun pop {main, line, pos, nl} : text =
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   392
 {main = pop_state main,
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   393
  line = Option.map pop_state line,
81269
wenzelm
parents: 81268
diff changeset
   394
  pos = pos,
wenzelm
parents: 81268
diff changeset
   395
  nl = nl};
wenzelm
parents: 81268
diff changeset
   396
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   397
fun result ({main, ...}: text) = state_output main;
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   398
10952
b520e4f1313b support general indentation (e.g. for non-tt latex output);
wenzelm
parents: 9730
diff changeset
   399
(*Add the lengths of the expressions until the next Break; if no Break then
b520e4f1313b support general indentation (e.g. for non-tt latex output);
wenzelm
parents: 9730
diff changeset
   400
  include "after", to account for text following this block.*)
61864
3a5992c3410c support for blocks with consistent breaks;
wenzelm
parents: 61863
diff changeset
   401
fun break_dist (Break _ :: _, _) = 0
80936
30c7922ec862 tuned signature;
wenzelm
parents: 80903
diff changeset
   402
  | break_dist (prt :: prts, after) = tree_length prt + break_dist (prts, after)
61864
3a5992c3410c support for blocks with consistent breaks;
wenzelm
parents: 61863
diff changeset
   403
  | break_dist ([], after) = after;
3a5992c3410c support for blocks with consistent breaks;
wenzelm
parents: 61863
diff changeset
   404
80936
30c7922ec862 tuned signature;
wenzelm
parents: 80903
diff changeset
   405
val force_break = fn Break (false, wd, ind) => Break (true, wd, ind) | prt => prt;
10952
b520e4f1313b support general indentation (e.g. for non-tt latex output);
wenzelm
parents: 9730
diff changeset
   406
b520e4f1313b support general indentation (e.g. for non-tt latex output);
wenzelm
parents: 9730
diff changeset
   407
(*Search for the next break (at this or higher levels) and force it to occur.*)
61864
3a5992c3410c support for blocks with consistent breaks;
wenzelm
parents: 61863
diff changeset
   408
fun force_next [] = []
80936
30c7922ec862 tuned signature;
wenzelm
parents: 80903
diff changeset
   409
  | force_next ((prt as Break _) :: prts) = force_break prt :: prts
30c7922ec862 tuned signature;
wenzelm
parents: 80903
diff changeset
   410
  | force_next (prt :: prts) = prt :: force_next prts;
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   411
81697
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   412
nonfix before;
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   413
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   414
in
19266
2e8ad3f2cd66 added command, keyword;
wenzelm
parents: 18802
diff changeset
   415
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   416
fun format_tree (ops: output_ops) input =
36745
403585a89772 unified/simplified Pretty.margin_default;
wenzelm
parents: 36733
diff changeset
   417
  let
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   418
    val margin = #margin ops;
36745
403585a89772 unified/simplified Pretty.margin_default;
wenzelm
parents: 36733
diff changeset
   419
    val breakgain = margin div 20;     (*minimum added space required of a break*)
403585a89772 unified/simplified Pretty.margin_default;
wenzelm
parents: 36733
diff changeset
   420
    val emergencypos = margin div 2;   (*position too far to right*)
403585a89772 unified/simplified Pretty.margin_default;
wenzelm
parents: 36733
diff changeset
   421
81701
wenzelm
parents: 81700
diff changeset
   422
    fun blanks_state n state = add_state (#1 (output_spaces ops n)) state;
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   423
    val blanks = string o output_spaces ops;
81683
b31d09029b94 clarified signature: more direct indent_markup;
wenzelm
parents: 81270
diff changeset
   424
b31d09029b94 clarified signature: more direct indent_markup;
wenzelm
parents: 81270
diff changeset
   425
    val indent_markup = #indent_markup ops;
b31d09029b94 clarified signature: more direct indent_markup;
wenzelm
parents: 81270
diff changeset
   426
    val no_indent_markup = indent_markup = Markup.no_output;
b31d09029b94 clarified signature: more direct indent_markup;
wenzelm
parents: 81270
diff changeset
   427
81701
wenzelm
parents: 81700
diff changeset
   428
    val break_state = add_state (output_newline ops);
wenzelm
parents: 81700
diff changeset
   429
    fun break (state, pos) ({main, nl, ...}: text) : text =
81683
b31d09029b94 clarified signature: more direct indent_markup;
wenzelm
parents: 81270
diff changeset
   430
      let
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   431
        val (main', line') =
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   432
          if no_indent_markup then
81701
wenzelm
parents: 81700
diff changeset
   433
            (main |> break_state |> add_state (Symbol.spaces pos), NONE)
81699
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   434
          else
d407fbe2e5a2 misc tuning and clarification: more explicit types;
wenzelm
parents: 81697
diff changeset
   435
            let
81701
wenzelm
parents: 81700
diff changeset
   436
              val ss = Bytes.contents (state_output (the state));
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   437
              val main' =
81701
wenzelm
parents: 81700
diff changeset
   438
                if null ss then main |> break_state
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   439
                else
81701
wenzelm
parents: 81700
diff changeset
   440
                  main |> close_state |> break_state
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   441
                  |> push_state indent_markup |> fold add_state ss |> pop_state
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   442
                  |> reopen_state main;
81718
289ded3c342f tuned names: more uniform;
wenzelm
parents: 81701
diff changeset
   443
              val line' = init_state |> fold add_state ss |> reopen_state main;
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   444
            in (main', SOME line') end;
81701
wenzelm
parents: 81700
diff changeset
   445
      in {main = main', line = line', pos = pos, nl = nl + 1} end;
81697
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   446
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   447
    (*'before' is the indentation context of the current block*)
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   448
    (*'after' is the width of the input context until the next break*)
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   449
    fun format (trees, before, after) (text as {pos, ...}) =
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   450
      (case trees of
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   451
        [] => text
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   452
      | End :: ts => format (ts, before, after) (pop text)
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   453
      | Block {markup, open_block = true, body, ...} :: ts =>
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   454
          text |> push markup |> format (body @ End :: ts, before, after)
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   455
      | Block {markup, consistent, indent, body, length = blen, ...} :: ts =>
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   456
          let
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   457
            val pos' = pos + indent;
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   458
            val pos'' = pos' mod emergencypos;
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   459
            val before' =
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   460
              if pos' < emergencypos
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   461
              then (Option.map (close_state o blanks_state indent) (#line text), pos')
81718
289ded3c342f tuned names: more uniform;
wenzelm
parents: 81701
diff changeset
   462
              else (Option.map (fn _ => blanks_state pos'' init_state) (#line text), pos'');
81697
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   463
            val after' = break_dist (ts, after)
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   464
            val body' = body
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   465
              |> (consistent andalso pos + blen > margin - after') ? map force_break;
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   466
            val btext: text =
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   467
              text |> push markup |> format (body' @ [End], before', after');
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   468
            (*if this block was broken then force the next break*)
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   469
            val ts' = if #nl text < #nl btext then force_next ts else ts;
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   470
          in format (ts', before, after) btext end
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   471
      | Break (force, wd, ind) :: ts =>
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   472
          (*no break if text to next break fits on this line
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   473
            or if breaking would add only breakgain to space*)
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   474
          format (ts, before, after)
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   475
            (if not force andalso
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   476
                pos + wd <= Int.max (margin - break_dist (ts, after), #2 before + breakgain)
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   477
             then text |> blanks wd  (*just insert wd blanks*)
81701
wenzelm
parents: 81700
diff changeset
   478
             else text |> break before |> blanks ind)
81697
1629c2ff4880 misc tuning: more uniform;
wenzelm
parents: 81696
diff changeset
   479
      | Str str :: ts => format (ts, before, after) (string str text));
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   480
81718
289ded3c342f tuned names: more uniform;
wenzelm
parents: 81701
diff changeset
   481
    val init = if no_indent_markup then init_no_line else init_line;
36745
403585a89772 unified/simplified Pretty.margin_default;
wenzelm
parents: 36733
diff changeset
   482
  in
81700
5c90d1f3a44c proper treatment of markup within line indentation, notably for Latex.output_ops;
wenzelm
parents: 81699
diff changeset
   483
    result (format ([output_tree ops true input], (#line init, 0), 0) init)
36745
403585a89772 unified/simplified Pretty.margin_default;
wenzelm
parents: 36733
diff changeset
   484
  end;
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   485
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   486
end;
14832
6589a58f57cb pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
wenzelm
parents: 12421
diff changeset
   487
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   488
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   489
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   490
(** no formatting **)
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   491
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   492
(* symbolic output: XML markup for blocks/breaks + other markup *)
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   493
80848
df85df6315af clarified signature: prefer explicit type Bytes.T;
wenzelm
parents: 80846
diff changeset
   494
val symbolic_output =
80829
bdae6195a287 clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
wenzelm
parents: 80825
diff changeset
   495
  let
80855
301612847ea3 further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
wenzelm
parents: 80854
diff changeset
   496
    val ops = symbolic_output_ops;
18802
f449d516f36b renamed gen_list to enum;
wenzelm
parents: 18603
diff changeset
   497
81268
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   498
    fun markup_bytes m output_body =
80829
bdae6195a287 clarified Pretty.markup_block: use value-oriented YXML.output_markup, with final re-interpretation via print_mode in output_tree;
wenzelm
parents: 80825
diff changeset
   499
      let val (bg, en) = #markup ops (YXML.output_markup m)
81268
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   500
      in Bytes.add bg #> output_body #> Bytes.add en end;
80822
4f54a509bc89 clarified modules (see also ea7c2ee8a47a);
wenzelm
parents: 80821
diff changeset
   501
81696
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   502
    fun output End = I
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   503
      | output (Block {markup = (bg, en), body = [], ...}) = Bytes.add bg #> Bytes.add en
81268
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   504
      | output (Block {markup = (bg, en), open_block = true, body, ...}) =
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   505
          Bytes.add bg #> fold output body #> Bytes.add en
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   506
      | output (Block {markup = (bg, en), consistent, indent, body, ...}) =
81267
d5ad89fda714 clarified symbolic output: avoid redundant "block" element for open_block = true;
wenzelm
parents: 81266
diff changeset
   507
          let val block_markup = Markup.block {consistent = consistent, indent = indent}
81268
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   508
          in Bytes.add bg #> markup_bytes block_markup (fold output body) #> Bytes.add en end
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   509
      | output (Break (false, wd, ind)) =
81120
080beab27264 clarified signature;
wenzelm
parents: 80942
diff changeset
   510
          markup_bytes (Markup.break {width = wd, indent = ind}) (output_spaces_bytes ops wd)
81268
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   511
      | output (Break (true, _, _)) = Bytes.add (output_newline ops)
81696
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   512
      | output (Str (s, _)) = Bytes.add s;
81268
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   513
  in Bytes.build o output o output_tree ops false end;
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   514
82591
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   515
val symbolic_string_of = robust_string_of symbolic_output;
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   516
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   517
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   518
(* unformatted output: other markup only *)
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   519
80834
wenzelm
parents: 80830
diff changeset
   520
fun unformatted ops =
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   521
  let
81696
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   522
    fun output End = I
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   523
      | output (Block ({markup = (bg, en), body, ...})) =
81268
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   524
          Bytes.add bg #> fold output body #> Bytes.add en
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   525
      | output (Break (_, wd, _)) = output_spaces_bytes ops wd
81696
b540572e3fd2 clarified internal data representation, following push/pop model of Scala version;
wenzelm
parents: 81693
diff changeset
   526
      | output (Str (s, _)) = Bytes.add s;
81268
ff3dd5ba47d0 tuned signature;
wenzelm
parents: 81267
diff changeset
   527
  in Bytes.build o output o output_tree ops false end;
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   528
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   529
fun unformatted_string_of prt =
82591
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   530
  robust_string_of (unformatted (output_ops NONE)) prt;
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   531
30624
e755b8b76365 simplified datatype ML_Pretty.pretty: model Isabelle not Poly/ML;
wenzelm
parents: 30620
diff changeset
   532
36748
wenzelm
parents: 36747
diff changeset
   533
(* output interfaces *)
30620
16b7ecc183e5 added position;
wenzelm
parents: 29606
diff changeset
   534
80855
301612847ea3 further clarification of print_mode: PIDE markup depends on "isabelle_process" alone, Latex is stateless;
wenzelm
parents: 80854
diff changeset
   535
fun output ops = if #symbolic ops then symbolic_output else format_tree ops;
23645
d220d12bd45e export mode_markup;
wenzelm
parents: 23638
diff changeset
   536
82591
ae1e6ff06b03 more robust output: no markup as last resort;
wenzelm
parents: 82587
diff changeset
   537
fun string_of_ops ops = robust_string_of (output ops);
80841
1beb2dc3bf14 clarified signature;
wenzelm
parents: 80840
diff changeset
   538
fun string_of prt = string_of_ops (output_ops NONE) prt;
49656
7ff712de5747 treat wrapped markup elements as raw markup delimiters;
wenzelm
parents: 49565
diff changeset
   539
82583
abd3885a3fcf more scalable;
wenzelm
parents: 82316
diff changeset
   540
fun strings_of prt = Bytes.contents (output (output_ops NONE) prt);
abd3885a3fcf more scalable;
wenzelm
parents: 82316
diff changeset
   541
80863
af34fcf7215d tuned signature: more operations;
wenzelm
parents: 80861
diff changeset
   542
val pure_string_of = string_of_ops (pure_output_ops NONE);
af34fcf7215d tuned signature: more operations;
wenzelm
parents: 80861
diff changeset
   543
82316
83584916b6d7 support for writeln_urgent, which is shown in Output before state messages (reminiscent of old Output.urgent_message before 521cea5fa777);
wenzelm
parents: 81718
diff changeset
   544
fun gen_writeln urgent prt =
83584916b6d7 support for writeln_urgent, which is shown in Output before state messages (reminiscent of old Output.urgent_message before 521cea5fa777);
wenzelm
parents: 81718
diff changeset
   545
  (if urgent then Output.writelns_urgent else Output.writelns)
83584916b6d7 support for writeln_urgent, which is shown in Output before state messages (reminiscent of old Output.urgent_message before 521cea5fa777);
wenzelm
parents: 81718
diff changeset
   546
    (Bytes.contents (output (output_ops NONE) prt));
83584916b6d7 support for writeln_urgent, which is shown in Output before state messages (reminiscent of old Output.urgent_message before 521cea5fa777);
wenzelm
parents: 81718
diff changeset
   547
83584916b6d7 support for writeln_urgent, which is shown in Output before state messages (reminiscent of old Output.urgent_message before 521cea5fa777);
wenzelm
parents: 81718
diff changeset
   548
val writeln = gen_writeln false;
83584916b6d7 support for writeln_urgent, which is shown in Output before state messages (reminiscent of old Output.urgent_message before 521cea5fa777);
wenzelm
parents: 81718
diff changeset
   549
val writeln_urgent = gen_writeln true;
80825
b866d1510bd0 clarified signature: more explicit type output_ops: default via print_mode;
wenzelm
parents: 80824
diff changeset
   550
6116
8ba2f25610f7 files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
wenzelm
parents:
diff changeset
   551
56334
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   552
(* chunks *)
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   553
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   554
fun markup_chunks m prts = markup m (fbreaks (map (text_fold o single) prts));
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   555
val chunks = markup_chunks Markup.empty;
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   556
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   557
fun chunks2 prts =
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   558
  (case try split_last prts of
80328
559909bd7715 clarified signature: more operations;
wenzelm
parents: 74231
diff changeset
   559
    NONE => block0 []
56334
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   560
  | SOME (prefix, last) =>
80328
559909bd7715 clarified signature: more operations;
wenzelm
parents: 74231
diff changeset
   561
      block0 (maps (fn prt => [text_fold [prt, fbrk], fbrk]) prefix @ [text_fold [last]]));
56334
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   562
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   563
fun block_enclose (prt1, prt2) prts = chunks [block (fbreaks (prt1 :: prts)), prt2];
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   564
80810
1f718be3608b clarified Pretty.T vs. output tree (following Isabelle/Scala): Output.output_width (via print_mode) happens during formatting, instead of construction;
wenzelm
parents: 80809
diff changeset
   565
end;
56334
6b3739fee456 some shortcuts for chunks, which sometimes avoid bulky string output;
wenzelm
parents: 55918
diff changeset
   566
80844
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   567
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   568
b569fbe1c262 tuned module structure;
wenzelm
parents: 80843
diff changeset
   569
(** back-patching **)
62899
845ed4584e21 clarified bootstrap of @{make_string} -- avoid query on ML environment;
wenzelm
parents: 62823
diff changeset
   570
80809
4a64fc4d1cde clarified signature: type ML_Pretty.pretty coincides with PolyML.pretty;
wenzelm
parents: 80805
diff changeset
   571
structure ML_Pretty: ML_PRETTY =
62899
845ed4584e21 clarified bootstrap of @{make_string} -- avoid query on ML environment;
wenzelm
parents: 62823
diff changeset
   572
struct
845ed4584e21 clarified bootstrap of @{make_string} -- avoid query on ML environment;
wenzelm
parents: 62823
diff changeset
   573
  open ML_Pretty;
80809
4a64fc4d1cde clarified signature: type ML_Pretty.pretty coincides with PolyML.pretty;
wenzelm
parents: 80805
diff changeset
   574
  val string_of = Pretty.string_of o Pretty.from_ML;
62899
845ed4584e21 clarified bootstrap of @{make_string} -- avoid query on ML environment;
wenzelm
parents: 62823
diff changeset
   575
end;
80812
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   576
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   577
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   578
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   579
(** toplevel pretty printing **)
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   580
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   581
val _ = ML_system_pp (fn d => fn _ => ML_Pretty.prune (d + 1) o Pretty.to_ML o Pretty.quote);
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   582
val _ = ML_system_pp (fn _ => fn _ => Pretty.to_ML o Pretty.position);
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   583
val _ = ML_system_pp (fn _ => fn _ => Pretty.to_ML o Pretty.mark_str o Path.print_markup);
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   584
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   585
val _ =
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   586
  ML_system_pp (fn _ => fn _ => fn t =>
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   587
    ML_Pretty.str ("<thread " ^ quote (Isabelle_Thread.print t) ^
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   588
      (if Isabelle_Thread.is_active t then "" else " (inactive)") ^ ">"));
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   589
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   590
val _ =
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   591
  ML_system_pp (fn _ => fn _ => fn bytes =>
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   592
    ML_Pretty.str
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   593
     (if Bytes.is_empty bytes then "Bytes.empty"
0f820da558f9 clarified signature and modules;
wenzelm
parents: 80810
diff changeset
   594
      else "Bytes {size = " ^ string_of_int (Bytes.size bytes) ^ "}"));