| author | wenzelm | 
| Sat, 08 Jul 2023 19:28:26 +0200 | |
| changeset 78271 | c0dc000d2a40 | 
| parent 78021 | ce6e3bc34343 | 
| 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 | ||
| 75393 | 10 | object Position {
 | 
| 43780 | 11 | type T = Properties.T | 
| 27968 | 12 | |
| 55490 | 13 | val none: T = Nil | 
| 14 | ||
| 50201 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 15 | 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 | 16 | 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 | 17 | val End_Offset = new Properties.Int(Markup.END_OFFSET) | 
| 78021 | 18 | val Label = new Properties.String(Markup.LABEL) | 
| 50201 
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) | 
| 78021 | 26 | val Def_Label = new Properties.String(Markup.DEF_LABEL) | 
| 50201 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
49419diff
changeset | 27 | 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 | 28 | val Def_Id = new Properties.Long(Markup.DEF_ID) | 
| 49419 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 29 | |
| 75393 | 30 |   object Line_File {
 | 
| 56464 | 31 | def apply(line: Int, file: String): T = | 
| 32 | (if (line > 0) Line(line) else Nil) ::: | |
| 33 | (if (file != "") File(file) else Nil) | |
| 34 | ||
| 48920 | 35 | def unapply(pos: T): Option[(Int, String)] = | 
| 36 |       (pos, pos) match {
 | |
| 37 | case (Line(i), File(name)) => Some((i, name)) | |
| 38 | case (_, File(name)) => Some((1, name)) | |
| 39 | case _ => None | |
| 40 | } | |
| 41 | } | |
| 42 | ||
| 75393 | 43 |   object Def_Line_File {
 | 
| 49419 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 44 | def unapply(pos: T): Option[(Int, String)] = | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 45 |       (pos, pos) match {
 | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 46 | case (Def_Line(i), Def_File(name)) => Some((i, name)) | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 47 | case (_, Def_File(name)) => Some((1, name)) | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 48 | case _ => None | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 49 | } | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 50 | } | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 51 | |
| 75393 | 52 |   object Range {
 | 
| 57910 | 53 | 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 | 54 | def unapply(pos: T): Option[Symbol.Range] = | 
| 48920 | 55 |       (pos, pos) match {
 | 
| 56 | case (Offset(start), End_Offset(stop)) if start <= stop => Some(Text.Range(start, stop)) | |
| 57 | case (Offset(start), _) => Some(Text.Range(start, start + 1)) | |
| 58 | case _ => None | |
| 59 | } | |
| 60 | } | |
| 61 | ||
| 75393 | 62 |   object Def_Range {
 | 
| 74714 | 63 | def apply(range: Symbol.Range): T = Def_Offset(range.start) ::: Def_End_Offset(range.stop) | 
| 64 | def unapply(pos: T): Option[Symbol.Range] = | |
| 65 |       (pos, pos) match {
 | |
| 66 | case (Def_Offset(start), Def_End_Offset(stop)) if start <= stop => Some(Text.Range(start, stop)) | |
| 67 | case (Def_Offset(start), _) => Some(Text.Range(start, start + 1)) | |
| 68 | case _ => None | |
| 69 | } | |
| 70 | } | |
| 71 | ||
| 75393 | 72 |   object Item_Id {
 | 
| 64667 | 73 | def unapply(pos: T): Option[(Long, Symbol.Range)] = | 
| 57931 | 74 |       pos match {
 | 
| 64667 | 75 | case Id(id) => | 
| 76 | val offset = Offset.unapply(pos) getOrElse 0 | |
| 77 | val end_offset = End_Offset.unapply(pos) getOrElse (offset + 1) | |
| 78 | Some((id, Text.Range(offset, end_offset))) | |
| 38722 
ba31936497c2
organized markup properties via apply/unapply patterns;
 wenzelm parents: 
38568diff
changeset | 79 | case _ => None | 
| 
ba31936497c2
organized markup properties via apply/unapply patterns;
 wenzelm parents: 
38568diff
changeset | 80 | } | 
| 
ba31936497c2
organized markup properties via apply/unapply patterns;
 wenzelm parents: 
38568diff
changeset | 81 | } | 
| 38872 | 82 | |
| 75393 | 83 |   object Item_Def_Id {
 | 
| 64667 | 84 | def unapply(pos: T): Option[(Long, Symbol.Range)] = | 
| 57931 | 85 |       pos match {
 | 
| 64667 | 86 | case Def_Id(id) => | 
| 87 | val offset = Def_Offset.unapply(pos) getOrElse 0 | |
| 88 | val end_offset = Def_End_Offset.unapply(pos) getOrElse (offset + 1) | |
| 89 | Some((id, Text.Range(offset, end_offset))) | |
| 49419 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 90 | case _ => None | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 91 | } | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 92 | } | 
| 
e2726211f834
pass base_snapshot to enable hyperlinks into other nodes;
 wenzelm parents: 
48992diff
changeset | 93 | |
| 75393 | 94 |   object Item_File {
 | 
| 64667 | 95 | def unapply(pos: T): Option[(String, Int, Symbol.Range)] = | 
| 64662 | 96 |       pos match {
 | 
| 97 | case Line_File(line, name) => | |
| 64667 | 98 | val offset = Offset.unapply(pos) getOrElse 0 | 
| 99 | val end_offset = End_Offset.unapply(pos) getOrElse (offset + 1) | |
| 100 | Some((name, line, Text.Range(offset, end_offset))) | |
| 64662 | 101 | case _ => None | 
| 102 | } | |
| 103 | } | |
| 104 | ||
| 75393 | 105 |   object Item_Def_File {
 | 
| 64667 | 106 | def unapply(pos: T): Option[(String, Int, Symbol.Range)] = | 
| 64662 | 107 |       pos match {
 | 
| 108 | case Def_Line_File(line, name) => | |
| 64667 | 109 | val offset = Def_Offset.unapply(pos) getOrElse 0 | 
| 110 | val end_offset = Def_End_Offset.unapply(pos) getOrElse (offset + 1) | |
| 111 | Some((name, line, Text.Range(offset, end_offset))) | |
| 64662 | 112 | case _ => None | 
| 113 | } | |
| 114 | } | |
| 115 | ||
| 48370 | 116 | |
| 56532 
3da244bc02bd
tuned message, to accommodate extra brackets produced by Scala parsers;
 wenzelm parents: 
56473diff
changeset | 117 | /* here: user output */ | 
| 48992 | 118 | |
| 75393 | 119 |   def here(props: T, delimited: Boolean = true): String = {
 | 
| 72708 | 120 | val pos = props.filter(Markup.position_property) | 
| 77368 | 121 | if_proper(pos, | 
| 122 |       {
 | |
| 123 | val s0 = | |
| 124 |           (Line.unapply(pos), File.unapply(pos)) match {
 | |
| 125 | case (Some(i), None) => "line " + i.toString | |
| 126 | case (Some(i), Some(name)) => "line " + i.toString + " of " + quote(name) | |
| 127 | case (None, Some(name)) => "file " + quote(name) | |
| 128 | case _ => "" | |
| 129 | } | |
| 130 |         val s = if (s0 == "") s0 else if (delimited) " (" + s0 + ")" else s0
 | |
| 131 | Markup(Markup.POSITION, pos).markup(s) | |
| 132 | }) | |
| 64728 | 133 | } | 
| 67882 | 134 | |
| 135 | ||
| 136 | /* JSON representation */ | |
| 137 | ||
| 75393 | 138 |   object JSON {
 | 
| 67882 | 139 | def apply(pos: T): isabelle.JSON.Object.T = | 
| 140 | isabelle.JSON.Object.empty ++ | |
| 141 | Line.unapply(pos).map(Line.name -> _) ++ | |
| 142 | Offset.unapply(pos).map(Offset.name -> _) ++ | |
| 143 | End_Offset.unapply(pos).map(End_Offset.name -> _) ++ | |
| 144 | File.unapply(pos).map(File.name -> _) ++ | |
| 145 | Id.unapply(pos).map(Id.name -> _) | |
| 146 | ||
| 147 | def unapply(json: isabelle.JSON.T): Option[T] = | |
| 148 |       for {
 | |
| 149 | line <- isabelle.JSON.int_default(json, Line.name) | |
| 150 | offset <- isabelle.JSON.int_default(json, Offset.name) | |
| 151 | end_offset <- isabelle.JSON.int_default(json, End_Offset.name) | |
| 152 | file <- isabelle.JSON.string_default(json, File.name) | |
| 153 | id <- isabelle.JSON.long_default(json, Id.name) | |
| 154 | } | |
| 155 |       yield {
 | |
| 156 | def defined(name: String): Boolean = isabelle.JSON.value(json, name).isDefined | |
| 157 | (if (defined(Line.name)) Line(line) else Nil) ::: | |
| 158 | (if (defined(Offset.name)) Offset(offset) else Nil) ::: | |
| 159 | (if (defined(End_Offset.name)) End_Offset(end_offset) else Nil) ::: | |
| 160 | (if (defined(File.name)) File(file) else Nil) ::: | |
| 161 | (if (defined(Id.name)) Id(id) else Nil) | |
| 162 | } | |
| 163 | } | |
| 27968 | 164 | } |