src/Pure/PIDE/command_span.ML
changeset 82931 fa8067dc6787
parent 82679 1dd29afaddda
child 83291 f033ff36d9c8
--- a/src/Pure/PIDE/command_span.ML	Tue Jul 29 16:43:49 2025 +0200
+++ b/src/Pure/PIDE/command_span.ML	Tue Jul 29 17:01:57 2025 +0200
@@ -11,12 +11,14 @@
   datatype span = Span of kind * Token.T list
   val kind: span -> kind
   val content: span -> Token.T list
+  val range: span -> Position.range
   val symbol_length: span -> int option
   val eof: span
   val is_eof: span -> bool
   val stopper: span Scan.stopper
   val adjust_offsets_kind: (int -> int option) -> kind -> kind
   val adjust_offsets: (int -> int option) -> span -> span
+  val command_ranges: span list -> Position.range list
 end;
 
 structure Command_Span: COMMAND_SPAN =
@@ -34,7 +36,8 @@
 
 fun kind (Span (k, _)) = k;
 fun content (Span (_, toks)) = toks;
-val symbol_length = Position.distance_of o Token.range_of o content;
+val range = Token.range_of o content;
+val symbol_length = Position.distance_of o range;
 
 
 (* stopper *)
@@ -57,4 +60,24 @@
 fun adjust_offsets adjust (Span (k, toks)) =
   Span (adjust_offsets_kind adjust k, map (Token.adjust_offsets adjust) toks);
 
+
+(* command ranges, including trailing non-commands (whitespace etc.) *)
+
+fun command_ranges spans =
+  let
+    fun ranges NONE [] result = rev result
+      | ranges (SOME pos) [] result =
+          let val end_pos = #2 (range (List.last spans))
+          in rev (Position.range (pos, end_pos) :: result) end
+      | ranges start_pos (span :: rest) result =
+          (case (start_pos, kind span) of
+            (NONE, Command_Span _) => ranges (SOME (#1 (range span))) rest result
+          | (SOME pos, Command_Span _) =>
+              let
+                val pos' = #1 (range span);
+                val result' = Position.range (pos, pos') :: result;
+              in ranges (SOME pos') rest result' end
+          | _ => ranges start_pos rest result);
+  in ranges NONE spans [] end;
+
 end;