| author | paulson | 
| Mon, 08 Nov 2021 09:31:26 +0000 | |
| changeset 74730 | 25f5f1fa31bb | 
| parent 74714 | 135787601438 | 
| child 75393 | 87ebf5a50283 | 
| permissions | -rw-r--r-- | 
| 27968 | 1 | /* Title: Pure/General/position.scala | 
| 2 | Author: Makarius | |
| 3 | ||
| 4 | Position properties. | |
| 5 | */ | |
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 9 | ||
| 32450 | 10 | object Position | 
| 11 | {
 | |
| 43780 | 12 | type T = Properties.T | 
| 27968 | 13 | |
| 55490 | 14 | val none: T = Nil | 
| 15 | ||
| 50201 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 16 | val Line = new Properties.Int(Markup.LINE) | 
| 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 17 | val Offset = new Properties.Int(Markup.OFFSET) | 
| 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 18 | val End_Offset = new Properties.Int(Markup.END_OFFSET) | 
| 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 19 | val File = new Properties.String(Markup.FILE) | 
| 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 20 | val Id = new Properties.Long(Markup.ID) | 
| 59706 
bf6ca55aae13
proper command id for inlined errors, which is important for Command.State.accumulate;
 wenzelm parents: 
59671diff
changeset | 21 | val Id_String = new Properties.String(Markup.ID) | 
| 31705 | 22 | |
| 50201 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 23 | val Def_Line = new Properties.Int(Markup.DEF_LINE) | 
| 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 24 | val Def_Offset = new Properties.Int(Markup.DEF_OFFSET) | 
| 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 25 | val Def_End_Offset = new Properties.Int(Markup.DEF_END_OFFSET) | 
| 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 26 | val Def_File = new Properties.String(Markup.DEF_FILE) | 
| 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 27 | val Def_Id = new Properties.Long(Markup.DEF_ID) | 
| 49419 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 28 | |
| 74675 | 29 | val Def_Theory = new Properties.String(Markup.DEF_THEORY) | 
| 74263 
be49c660ebbf
more markup, e.g. to locate defining theory node in formal document output;
 wenzelm parents: 
72708diff
changeset | 30 | |
| 48920 | 31 | object Line_File | 
| 32 |   {
 | |
| 56464 | 33 | def apply(line: Int, file: String): T = | 
| 34 | (if (line > 0) Line(line) else Nil) ::: | |
| 35 | (if (file != "") File(file) else Nil) | |
| 36 | ||
| 48920 | 37 | def unapply(pos: T): Option[(Int, String)] = | 
| 38 |       (pos, pos) match {
 | |
| 39 | case (Line(i), File(name)) => Some((i, name)) | |
| 40 | case (_, File(name)) => Some((1, name)) | |
| 41 | case _ => None | |
| 42 | } | |
| 43 | } | |
| 44 | ||
| 49419 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 45 | object Def_Line_File | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 46 |   {
 | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 47 | def unapply(pos: T): Option[(Int, String)] = | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 48 |       (pos, pos) match {
 | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 49 | case (Def_Line(i), Def_File(name)) => Some((i, name)) | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 50 | case (_, Def_File(name)) => Some((1, name)) | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 51 | case _ => None | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 52 | } | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 53 | } | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 54 | |
| 38722 
ba31936497c2
organized markup properties via apply/unapply patterns;
 wenzelm parents: 
38568diff
changeset | 55 | object Range | 
| 
ba31936497c2
organized markup properties via apply/unapply patterns;
 wenzelm parents: 
38568diff
changeset | 56 |   {
 | 
| 57910 | 57 | def apply(range: Symbol.Range): T = Offset(range.start) ::: End_Offset(range.stop) | 
| 55884 
f2c0eaedd579
tuned signature -- emphasize symbol positions (prover) vs. decoded text offsets (editor);
 wenzelm parents: 
55555diff
changeset | 58 | def unapply(pos: T): Option[Symbol.Range] = | 
| 48920 | 59 |       (pos, pos) match {
 | 
| 60 | case (Offset(start), End_Offset(stop)) if start <= stop => Some(Text.Range(start, stop)) | |
| 61 | case (Offset(start), _) => Some(Text.Range(start, start + 1)) | |
| 62 | case _ => None | |
| 63 | } | |
| 64 | } | |
| 65 | ||
| 74714 | 66 | object Def_Range | 
| 67 |   {
 | |
| 68 | def apply(range: Symbol.Range): T = Def_Offset(range.start) ::: Def_End_Offset(range.stop) | |
| 69 | def unapply(pos: T): Option[Symbol.Range] = | |
| 70 |       (pos, pos) match {
 | |
| 71 | case (Def_Offset(start), Def_End_Offset(stop)) if start <= stop => Some(Text.Range(start, stop)) | |
| 72 | case (Def_Offset(start), _) => Some(Text.Range(start, start + 1)) | |
| 73 | case _ => None | |
| 74 | } | |
| 75 | } | |
| 76 | ||
| 64662 | 77 | object Item_Id | 
| 48920 | 78 |   {
 | 
| 64667 | 79 | def unapply(pos: T): Option[(Long, Symbol.Range)] = | 
| 57931 | 80 |       pos match {
 | 
| 64667 | 81 | case Id(id) => | 
| 82 | val offset = Offset.unapply(pos) getOrElse 0 | |
| 83 | val end_offset = End_Offset.unapply(pos) getOrElse (offset + 1) | |
| 84 | Some((id, Text.Range(offset, end_offset))) | |
| 38722 
ba31936497c2
organized markup properties via apply/unapply patterns;
 wenzelm parents: 
38568diff
changeset | 85 | case _ => None | 
| 
ba31936497c2
organized markup properties via apply/unapply patterns;
 wenzelm parents: 
38568diff
changeset | 86 | } | 
| 
ba31936497c2
organized markup properties via apply/unapply patterns;
 wenzelm parents: 
38568diff
changeset | 87 | } | 
| 38872 | 88 | |
| 64662 | 89 | object Item_Def_Id | 
| 49419 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 90 |   {
 | 
| 64667 | 91 | def unapply(pos: T): Option[(Long, Symbol.Range)] = | 
| 57931 | 92 |       pos match {
 | 
| 64667 | 93 | case Def_Id(id) => | 
| 94 | val offset = Def_Offset.unapply(pos) getOrElse 0 | |
| 95 | val end_offset = Def_End_Offset.unapply(pos) getOrElse (offset + 1) | |
| 96 | Some((id, Text.Range(offset, end_offset))) | |
| 49419 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 97 | case _ => None | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 98 | } | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 99 | } | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 100 | |
| 64662 | 101 | object Item_File | 
| 102 |   {
 | |
| 64667 | 103 | def unapply(pos: T): Option[(String, Int, Symbol.Range)] = | 
| 64662 | 104 |       pos match {
 | 
| 105 | case Line_File(line, name) => | |
| 64667 | 106 | val offset = Offset.unapply(pos) getOrElse 0 | 
| 107 | val end_offset = End_Offset.unapply(pos) getOrElse (offset + 1) | |
| 108 | Some((name, line, Text.Range(offset, end_offset))) | |
| 64662 | 109 | case _ => None | 
| 110 | } | |
| 111 | } | |
| 112 | ||
| 113 | object Item_Def_File | |
| 114 |   {
 | |
| 64667 | 115 | def unapply(pos: T): Option[(String, Int, Symbol.Range)] = | 
| 64662 | 116 |       pos match {
 | 
| 117 | case Def_Line_File(line, name) => | |
| 64667 | 118 | val offset = Def_Offset.unapply(pos) getOrElse 0 | 
| 119 | val end_offset = Def_End_Offset.unapply(pos) getOrElse (offset + 1) | |
| 120 | Some((name, line, Text.Range(offset, end_offset))) | |
| 64662 | 121 | case _ => None | 
| 122 | } | |
| 123 | } | |
| 124 | ||
| 48370 | 125 | |
| 56532 
3da244bc02bd
tuned message, to accommodate extra brackets produced by Scala parsers;
 wenzelm parents: 
56473diff
changeset | 126 | /* here: user output */ | 
| 48992 | 127 | |
| 65402 | 128 | def here(props: T, delimited: Boolean = true): String = | 
| 64728 | 129 |   {
 | 
| 72708 | 130 | val pos = props.filter(Markup.position_property) | 
| 64728 | 131 | if (pos.isEmpty) "" | 
| 132 |     else {
 | |
| 133 | val s0 = | |
| 134 |         (Line.unapply(pos), File.unapply(pos)) match {
 | |
| 135 | case (Some(i), None) => "line " + i.toString | |
| 136 | case (Some(i), Some(name)) => "line " + i.toString + " of " + quote(name) | |
| 137 | case (None, Some(name)) => "file " + quote(name) | |
| 138 | case _ => "" | |
| 139 | } | |
| 68287 | 140 |       val s = if (s0 == "") s0 else if (delimited) " (" + s0 + ")" else s0
 | 
| 64728 | 141 | Markup(Markup.POSITION, pos).markup(s) | 
| 142 | } | |
| 143 | } | |
| 67882 | 144 | |
| 145 | ||
| 146 | /* JSON representation */ | |
| 147 | ||
| 148 | object JSON | |
| 149 |   {
 | |
| 150 | def apply(pos: T): isabelle.JSON.Object.T = | |
| 151 | isabelle.JSON.Object.empty ++ | |
| 152 | Line.unapply(pos).map(Line.name -> _) ++ | |
| 153 | Offset.unapply(pos).map(Offset.name -> _) ++ | |
| 154 | End_Offset.unapply(pos).map(End_Offset.name -> _) ++ | |
| 155 | File.unapply(pos).map(File.name -> _) ++ | |
| 156 | Id.unapply(pos).map(Id.name -> _) | |
| 157 | ||
| 158 | def unapply(json: isabelle.JSON.T): Option[T] = | |
| 159 |       for {
 | |
| 160 | line <- isabelle.JSON.int_default(json, Line.name) | |
| 161 | offset <- isabelle.JSON.int_default(json, Offset.name) | |
| 162 | end_offset <- isabelle.JSON.int_default(json, End_Offset.name) | |
| 163 | file <- isabelle.JSON.string_default(json, File.name) | |
| 164 | id <- isabelle.JSON.long_default(json, Id.name) | |
| 165 | } | |
| 166 |       yield {
 | |
| 167 | def defined(name: String): Boolean = isabelle.JSON.value(json, name).isDefined | |
| 168 | (if (defined(Line.name)) Line(line) else Nil) ::: | |
| 169 | (if (defined(Offset.name)) Offset(offset) else Nil) ::: | |
| 170 | (if (defined(End_Offset.name)) End_Offset(end_offset) else Nil) ::: | |
| 171 | (if (defined(File.name)) File(file) else Nil) ::: | |
| 172 | (if (defined(Id.name)) Id(id) else Nil) | |
| 173 | } | |
| 174 | } | |
| 27968 | 175 | } |