From 0eded2a33c27df1f3efd7839b7797a737442a73e Mon Sep 17 00:00:00 2001 From: Joao Azevedo Date: Wed, 26 Jun 2024 13:46:57 +0000 Subject: [PATCH 1/5] Refactor: rename line length variables --- src/prettier_ada-documents-implementation.adb | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/prettier_ada-documents-implementation.adb b/src/prettier_ada-documents-implementation.adb index b221310..f7786b6 100644 --- a/src/prettier_ada-documents-implementation.adb +++ b/src/prettier_ada-documents-implementation.adb @@ -596,7 +596,7 @@ package body Prettier_Ada.Documents.Implementation is Group_Mode_Map : Symbol_To_Mode_Map; - Pos : Natural := + Current_Line_Length : Natural := Options.Indentation.Offset.Spaces + Options.Indentation.Offset.Tabs * Options.Indentation.Width; @@ -676,9 +676,9 @@ package body Prettier_Ada.Documents.Implementation is .Bare_Document .Command .Group_Contents); - Remainder : constant Integer := - Options.Width - Pos; - Has_Line_Suffix : constant Boolean := + Remaining_Line_Length : constant Integer := + Options.Width - Current_Line_Length; + Has_Line_Suffix : constant Boolean := Line_Suffix.Length > 0; begin @@ -689,7 +689,7 @@ package body Prettier_Ada.Documents.Implementation is Fits (Next, Print_Commands, - Remainder, + Remaining_Line_Length, Has_Line_Suffix, Group_Mode_Map) then @@ -774,7 +774,7 @@ package body Prettier_Ada.Documents.Implementation is if Fits (Print_Command, Print_Commands, - Remainder, + Remaining_Line_Length, Has_Line_Suffix, Group_Mode_Map) then @@ -868,7 +868,8 @@ package body Prettier_Ada.Documents.Implementation is ----------------------------------- procedure Process_Document_Command_Fill is - Remainder : constant Integer := Options.Width - Pos; + Remaining_Line_Length : constant Integer := + Options.Width - Current_Line_Length; Parts : constant Document_Vector := Document .Bare_Document @@ -888,7 +889,7 @@ package body Prettier_Ada.Documents.Implementation is Fits (Content_Flat_Command, [], - Remainder, + Remaining_Line_Length, Line_Suffix.Length > 0, Group_Mode_Map, True); @@ -919,7 +920,7 @@ package body Prettier_Ada.Documents.Implementation is Fits (Content_Flat_Command, [], - Remainder, + Remaining_Line_Length, Line_Suffix.Length > 0, Group_Mode_Map, True); @@ -958,7 +959,7 @@ package body Prettier_Ada.Documents.Implementation is Fits (Content_Flat_Command, [], - Remainder, + Remaining_Line_Length, Line_Suffix.Length > 0, Group_Mode_Map, True); @@ -988,7 +989,7 @@ package body Prettier_Ada.Documents.Implementation is Fits (First_And_Second_Content_Flat_Command, [], - Remainder, + Remaining_Line_Length, Line_Suffix.Length > 0, Group_Mode_Map, True); @@ -1050,13 +1051,13 @@ package body Prettier_Ada.Documents.Implementation is Gnatfmt_Trace.Trace ("131211"); Append (Result, End_Of_Line); Append (Result, Indentation.Root.Value); - Pos := + Current_Line_Length := Natural (Indentation.Root.Value.Display_Width); else Gnatfmt_Trace.Trace ("131212"); Append (Result, End_Of_Line); - Pos := + Current_Line_Length := Options.Indentation.Offset.Spaces + Options.Indentation.Offset.Tabs * Options.Indentation.Width; @@ -1064,10 +1065,11 @@ package body Prettier_Ada.Documents.Implementation is else Gnatfmt_Trace.Trace ("13122"); - Pos := @ - Trim (Result); + Current_Line_Length := @ - Trim (Result); Append (Result, End_Of_Line); Append (Result, Indentation.Value); - Pos := Natural (Indentation.Value.Display_Width); + Current_Line_Length := + Natural (Indentation.Value.Display_Width); end if; end if; end Process_Mode_Break; @@ -1088,7 +1090,7 @@ package body Prettier_Ada.Documents.Implementation is then Gnatfmt_Trace.Trace ("13211"); Append (Result, (" ", 1)); - Pos := @ + Natural (1); + Current_Line_Length := @ + Natural (1); end if; else @@ -1122,7 +1124,8 @@ package body Prettier_Ada.Documents.Implementation is Append (Result, Document.Bare_Document.Text); if Print_Commands.Length > 0 then - Pos := @ + Document.Bare_Document.Text.Display_Width; + Current_Line_Length := + @ + Document.Bare_Document.Text.Display_Width; end if; end Process_Document_Text; @@ -1192,13 +1195,13 @@ package body Prettier_Ada.Documents.Implementation is (Indentation, Document.Bare_Document.Command.Align_Data, Options, - Pos), + Current_Line_Length), Mode, Document.Bare_Document.Command.Align_Contents)); when Command_Trim => Gnatfmt_Trace.Trace ("6"); - Pos := @ - Trim (Result); + Current_Line_Length := @ - Trim (Result); when Command_Group => Gnatfmt_Trace.Trace ("7"); From 6b5d09b55885074cd8ffdc1b74211b6d54a844ac Mon Sep 17 00:00:00 2001 From: Joao Azevedo Date: Wed, 26 Jun 2024 13:47:05 +0000 Subject: [PATCH 2/5] Overload Format function to return the last line length --- src/prettier_ada-documents-implementation.adb | 24 +++++++++++++++---- src/prettier_ada-documents-implementation.ads | 13 ++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/prettier_ada-documents-implementation.adb b/src/prettier_ada-documents-implementation.adb index f7786b6..5f522aa 100644 --- a/src/prettier_ada-documents-implementation.adb +++ b/src/prettier_ada-documents-implementation.adb @@ -574,6 +574,20 @@ package body Prettier_Ada.Documents.Implementation is (Document : Document_Type; Options : Format_Options_Type := Default_Format_Options) return Ada.Strings.Unbounded.Unbounded_String + is (VSS.Strings.Conversions.To_Unbounded_UTF_8_String + (Format (Document, Options).Formatted_Document)); + + ------------ + -- Format -- + ------------ + + function Format + (Document : Document_Type; + Options : Format_Options_Type := Default_Format_Options; + Initial_Line_Length : Natural := + Options.Indentation.Offset.Spaces + + Options.Indentation.Offset.Tabs * Options.Indentation.Width) + return Format_Result_Type is use type Ada.Containers.Count_Type; use type VSS.Strings.Virtual_String; @@ -596,9 +610,7 @@ package body Prettier_Ada.Documents.Implementation is Group_Mode_Map : Symbol_To_Mode_Map; - Current_Line_Length : Natural := - Options.Indentation.Offset.Spaces - + Options.Indentation.Offset.Tabs * Options.Indentation.Width; + Current_Line_Length : Natural := Initial_Line_Length; Should_Remeasure : Boolean := False; @@ -1439,12 +1451,14 @@ package body Prettier_Ada.Documents.Implementation is Prettier_Ada.Documents.Builders.Reset_Document_Id; - return VSS.Strings.Conversions.To_Unbounded_UTF_8_String (Result.Text); + return + (Result.Text, + Current_Line_Length); exception when others => Prettier_Ada.Documents.Builders.Reset_Document_Id; - return Ada.Strings.Unbounded.Null_Unbounded_String; + return (VSS.Strings.Empty_Virtual_String, 0); end Format; ---------- diff --git a/src/prettier_ada-documents-implementation.ads b/src/prettier_ada-documents-implementation.ads index a2a6549..31f9158 100644 --- a/src/prettier_ada-documents-implementation.ads +++ b/src/prettier_ada-documents-implementation.ads @@ -32,6 +32,19 @@ private package Prettier_Ada.Documents.Implementation is return Ada.Strings.Unbounded.Unbounded_String; -- Formats Document with the given Options + type Format_Result_Type is + record + Formatted_Document : VSS.Strings.Virtual_String; + Last_Line_Length : Natural; + end record; + + function Format + (Document : Document_Type; + Options : Format_Options_Type := Default_Format_Options; + Initial_Line_Length : Natural := 0) + return Format_Result_Type; + -- Formats Document with the given Options + function New_Symbol return Symbol_Type; -- Returns a new Symbol_Type, used to uniquely identify parent -- Command_Group documents. From b7c0cf531ef0b143cd123cb253403eb44eb9f9c5 Mon Sep 17 00:00:00 2001 From: Joao Azevedo Date: Wed, 26 Jun 2024 13:47:08 +0000 Subject: [PATCH 3/5] Add Alignment_Table_Command without any handlers --- src/prettier_ada-document_vector_vectors.ads | 13 +++++++++++++ src/prettier_ada-documents-implementation.adb | 8 ++++++++ src/prettier_ada-documents-implementation.ads | 7 ++++++- src/prettier_ada-documents-json.adb | 3 +++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/prettier_ada-document_vector_vectors.ads diff --git a/src/prettier_ada-document_vector_vectors.ads b/src/prettier_ada-document_vector_vectors.ads new file mode 100644 index 0000000..0f4c7da --- /dev/null +++ b/src/prettier_ada-document_vector_vectors.ads @@ -0,0 +1,13 @@ +-- +-- Copyright (C) 2024, AdaCore +-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +-- + +with Ada.Containers.Vectors; +with Prettier_Ada.Document_Vectors; + +package Prettier_Ada.Document_Vector_Vectors is new + Ada.Containers.Vectors + (Positive, + Prettier_Ada.Document_Vectors.Vector, + Prettier_Ada.Document_Vectors."="); diff --git a/src/prettier_ada-documents-implementation.adb b/src/prettier_ada-documents-implementation.adb index 5f522aa..d0ec363 100644 --- a/src/prettier_ada-documents-implementation.adb +++ b/src/prettier_ada-documents-implementation.adb @@ -557,6 +557,9 @@ package body Prettier_Ada.Documents.Implementation is | Command_Cursor => null; + when Command_Alignment_Table => + raise Program_Error with "TODO"; + end case; end case; end; @@ -1437,6 +1440,9 @@ package body Prettier_Ada.Documents.Implementation is when Command_Break_Parent => Gnatfmt_Trace.Trace ("15"); null; + + when Command_Alignment_Table => + raise Program_Error with "TODO"; end case; end case; @@ -2195,6 +2201,8 @@ package body Prettier_Ada.Documents.Implementation is Gnatfmt_Trace.Trace ("T10"); null; + when Command_Alignment_Table => + raise Program_Error with "TODO"; end case; end case; diff --git a/src/prettier_ada-documents-implementation.ads b/src/prettier_ada-documents-implementation.ads index 31f9158..73b3abb 100644 --- a/src/prettier_ada-documents-implementation.ads +++ b/src/prettier_ada-documents-implementation.ads @@ -7,6 +7,7 @@ with Ada.Containers; with Ada.Strings.Unbounded; with Prettier_Ada.Document_Vectors; +with Prettier_Ada.Document_Vector_Vectors; with VSS.Strings; @@ -95,7 +96,8 @@ private package Prettier_Ada.Documents.Implementation is Command_Line, Command_Line_Suffix, Command_Line_Suffix_Boundary, - Command_Trim); + Command_Trim, + Command_Alignment_Table); type Command_Type (Kind : Command_Kind) is record case Kind is @@ -148,6 +150,9 @@ private package Prettier_Ada.Documents.Implementation is when Command_Trim => null; + + when Command_Alignment_Table => + Rows : Prettier_Ada.Document_Vector_Vectors.Vector; end case; end record; diff --git a/src/prettier_ada-documents-json.adb b/src/prettier_ada-documents-json.adb index 7be5edb..57a2791 100644 --- a/src/prettier_ada-documents-json.adb +++ b/src/prettier_ada-documents-json.adb @@ -215,6 +215,9 @@ package body Prettier_Ada.Documents.Json is when Command_Trim => Result.Set_Field ("command", "trim"); + + when Command_Alignment_Table => + raise Program_Error with "TODO"; end case; return Result; From 4968573ddfc3481974357936bfe960af13284eac Mon Sep 17 00:00:00 2001 From: Joao Azevedo Date: Wed, 26 Jun 2024 13:47:10 +0000 Subject: [PATCH 4/5] Add Alignment_Command_Table builder --- src/prettier_ada-documents-builders.adb | 14 ++++++++++++++ src/prettier_ada-documents-builders.ads | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/src/prettier_ada-documents-builders.adb b/src/prettier_ada-documents-builders.adb index 40bd6a7..0259615 100644 --- a/src/prettier_ada-documents-builders.adb +++ b/src/prettier_ada-documents-builders.adb @@ -435,4 +435,18 @@ package body Prettier_Ada.Documents.Builders is procedure Reset_Document_Id renames Prettier_Ada.Documents.Implementation.Reset_Document_Id; + --------------------- + -- Alignment_Table -- + --------------------- + + function Alignment_Table + (Rows : Prettier_Ada.Document_Vector_Vectors.Vector) + return Document_Type + is + begin + return + Wrap_Command + (new Command_Type'(Kind => Command_Alignment_Table, Rows => Rows)); + end Alignment_Table; + end Prettier_Ada.Documents.Builders; diff --git a/src/prettier_ada-documents-builders.ads b/src/prettier_ada-documents-builders.ads index a9bfe41..0c6383d 100644 --- a/src/prettier_ada-documents-builders.ads +++ b/src/prettier_ada-documents-builders.ads @@ -4,6 +4,7 @@ -- with Prettier_Ada.Document_Vectors; +with Prettier_Ada.Document_Vector_Vectors; -- This package provides functions to build a Document_Type. -- The API mimics the original Prettier builders API with the following @@ -171,6 +172,11 @@ package Prettier_Ada.Documents.Builders is return Document_Type; -- Join an array of Documents with a Separator + function Alignment_Table + (Rows : Prettier_Ada.Document_Vector_Vectors.Vector) + return Document_Type; + -- Create a new Aligment_Table Document Command + private No_Document : constant Document_Type := Prettier_Ada.Documents.No_Document; From 395f1806e6b0609d568c4288a4cd46bdc4bbf033 Mon Sep 17 00:00:00 2001 From: Joao Azevedo Date: Wed, 26 Jun 2024 13:47:16 +0000 Subject: [PATCH 5/5] Implement Table_Alignment algorithm --- src/prettier_ada-documents-builders.adb | 146 +- src/prettier_ada-documents-builders.ads | 8 +- src/prettier_ada-documents-implementation.adb | 1266 +++++++++++---- src/prettier_ada-documents-implementation.ads | 27 +- src/prettier_ada-documents-json.adb | 167 +- src/prettier_ada.ads | 4 +- .../test_programs/src/builders_tester.adb | 139 ++ testsuite/tests/builders/test.out | 1390 ++++++++++++++++- 8 files changed, 2839 insertions(+), 308 deletions(-) diff --git a/src/prettier_ada-documents-builders.adb b/src/prettier_ada-documents-builders.adb index 0259615..4be701f 100644 --- a/src/prettier_ada-documents-builders.adb +++ b/src/prettier_ada-documents-builders.adb @@ -440,13 +440,153 @@ package body Prettier_Ada.Documents.Builders is --------------------- function Alignment_Table - (Rows : Prettier_Ada.Document_Vector_Vectors.Vector) + (Rows : Document_Table; Must_Break : Boolean := True) return Document_Type + is + Elements : Prettier_Ada.Document_Vector_Vectors.Vector; + Separators : Prettier_Ada.Document_Vector_Vectors.Vector; + + procedure Normalize_Table; + -- Splits Rows into Elements and Separators. + -- Separators are placed between elements so this ensures that for each + -- row: + -- Elements (row).Length = Separators (row).Length - 1 + -- + -- Example: + -- + -- Rows: [[E11, S11, E12, S12, E13], [E21, S21, E22, S22, E23]] + -- + -- Results in: + -- + -- Elements: [[E11, E12, E13], [E21, E22, E23]] + -- Separators: [[S11, S12], [S21, S22]] + + --------------------- + -- Normalize_Table -- + --------------------- + + procedure Normalize_Table is + begin + -- Iterate through all rows + + for Row_Index in Rows.First_Index .. Rows.Last_Index loop + declare + use Prettier_Ada.Document_Vector_Vectors; + + use type Ada.Containers.Count_Type; + + Row : constant Constant_Reference_Type := + Rows.Constant_Reference (Row_Index); + -- This is the current row + + -- For each row, we will have a list of elements and a list + -- of separators. + + Row_Elements : Prettier_Ada.Document_Vectors.Vector; + Row_Separators : Prettier_Ada.Document_Vectors.Vector; + + Elements_Aggregate : Prettier_Ada.Document_Vectors.Vector; + -- Elements that follow another element are aggregated + -- together. + + begin + -- Iterate through all columns + + for Column_Index in Row.First_Index .. Row.Last_Index loop + declare + use Prettier_Ada.Document_Vectors; + + Table_Element : + constant Prettier_Ada + .Document_Vectors + .Constant_Reference_Type := + Row.Constant_Reference (Column_Index); + + Is_Separator : constant Boolean := + Table_Element.Bare_Document.Kind in Document_Command + and then Table_Element.Bare_Document.Command.Kind + in Command_Alignment_Table_Separator; + -- A table element can either be an element or a + -- separator. + begin + if Is_Separator then + -- Start by adding Elements_Aggregate to Row_Elements + + if Elements_Aggregate.Is_Empty then + -- No elements before the separator. Simply add an + -- empty string. + + Row_Elements.Append + (Text + (Ada.Strings.Unbounded.Null_Unbounded_String)); + + elsif Elements_Aggregate.Length = 1 then + Row_Elements.Append + (Elements_Aggregate.First_Element); + + else + Row_Elements.Append (Group (Elements_Aggregate)); + end if; + + Elements_Aggregate.Clear; + + -- Then add the separator to Row_Separators + + Row_Separators.Append (Table_Element); + + else + Elements_Aggregate.Append (Table_Element); + end if; + end; + end loop; + + -- If the last element of this row is not a separator, then + -- Elements_Aggregate won't be empty. If so, add it to + -- Row_Elements. + + if not Elements_Aggregate.Is_Empty then + if Elements_Aggregate.Length = 1 then + Row_Elements.Append (Elements_Aggregate.First_Element); + + else + Row_Elements.Append (Group (Elements_Aggregate)); + end if; + end if; + + -- Flush this row's elements and separators + Elements.Append (Row_Elements); + Separators.Append (Row_Separators); + end; + end loop; + end Normalize_Table; + + begin + Normalize_Table; + + return + Wrap_Command + (new Command_Type' + (Kind => Command_Alignment_Table, + Alignment_Table_Elements => Elements, + Alignment_Table_Separators => Separators, + Alignment_Table_Must_Break => Must_Break)); + end Alignment_Table; + + ------------------------------- + -- Alignment_Table_Separator -- + ------------------------------- + + function Alignment_Table_Separator + (Aligner_Text : Ada.Strings.Unbounded.Unbounded_String) return Document_Type is begin return Wrap_Command - (new Command_Type'(Kind => Command_Alignment_Table, Rows => Rows)); - end Alignment_Table; + (new Command_Type' + (Kind => + Command_Alignment_Table_Separator, + Alignment_Table_Separator_Text => + To_Prettier_String (Aligner_Text))); + end Alignment_Table_Separator; end Prettier_Ada.Documents.Builders; diff --git a/src/prettier_ada-documents-builders.ads b/src/prettier_ada-documents-builders.ads index 0c6383d..5f39827 100644 --- a/src/prettier_ada-documents-builders.ads +++ b/src/prettier_ada-documents-builders.ads @@ -18,6 +18,7 @@ with Prettier_Ada.Document_Vector_Vectors; package Prettier_Ada.Documents.Builders is subtype Document_Vector is Prettier_Ada.Document_Vectors.Vector; + subtype Document_Table is Prettier_Ada.Document_Vector_Vectors.Vector; No_Document : constant Document_Type; @@ -173,10 +174,15 @@ package Prettier_Ada.Documents.Builders is -- Join an array of Documents with a Separator function Alignment_Table - (Rows : Prettier_Ada.Document_Vector_Vectors.Vector) + (Rows : Document_Table; Must_Break : Boolean := True) return Document_Type; -- Create a new Aligment_Table Document Command + function Alignment_Table_Separator + (Aligner_Text : Ada.Strings.Unbounded.Unbounded_String) + return Document_Type; + -- Create a new Aligment_Table_Separator Document Command + private No_Document : constant Document_Type := Prettier_Ada.Documents.No_Document; diff --git a/src/prettier_ada-documents-implementation.adb b/src/prettier_ada-documents-implementation.adb index d0ec363..fb62eed 100644 --- a/src/prettier_ada-documents-implementation.adb +++ b/src/prettier_ada-documents-implementation.adb @@ -30,8 +30,6 @@ package body Prettier_Ada.Documents.Implementation is subtype Optional_Boolean is Optional_Booleans.Generic_Optional_Type; - subtype Document_Vector is Prettier_Ada.Document_Vectors.Vector; - package Document_Hashed_Sets is new Ada.Containers.Hashed_Sets (Element_Type => Document_Type, @@ -90,6 +88,28 @@ package body Prettier_Ada.Documents.Implementation is subtype Symbol_To_Mode_Map is Symbol_To_Mode_Maps.Map; + type Format_State_Record is record + Current_Line_Length : Natural; + Group_Mode_Map : Symbol_To_Mode_Map; + Line_Suffix : Print_Command_Type_Vector; + Print_Commands : Print_Command_Type_Vector; + Printed_Cursor_Count : Natural; + Result : Prettier_String; + Should_Remeasure : Boolean; + Last_Was_Hardline : Boolean; + -- Flag indicating if the last text added to Result was a hardline + end record; + + Default_Format_State : constant Format_State_Record := + (Current_Line_Length => 0, + Group_Mode_Map => Symbol_To_Mode_Maps.Empty_Map, + Line_Suffix => [], + Print_Commands => [], + Printed_Cursor_Count => 0, + Result => Empty_Prettier_String, + Should_Remeasure => False, + Last_Was_Hardline => False); + procedure Append (To : in out Prettier_String; Source : Prettier_String); -- Append Source to the end of To @@ -107,6 +127,12 @@ package body Prettier_Ada.Documents.Implementation is return Boolean; -- TODO: Description + procedure Format + (Format_State : in out Format_State_Record; + Format_Options : Format_Options_Type); + -- Resume the formatting operations on Format_State. + -- Formats according to Format_Options. + function Generate_Indentation (From : Indentation_Queue_Type; Data : Indentation_Data_Type; @@ -237,7 +263,6 @@ package body Prettier_Ada.Documents.Implementation is and not Group_Command.Break then -- TODO: Why should this be "propagated"? - Gnatfmt_Trace.Trace ("BPG"); Group_Command.all.Break := True; end if; end; @@ -294,18 +319,13 @@ package body Prettier_Ada.Documents.Implementation is Current_Has_Line_Suffix : Boolean := Has_Line_Suffix; begin - Gnatfmt_Trace.Trace ("F1"); if Remaining_Width = Integer'Last then - Gnatfmt_Trace.Trace ("F2"); return True; end if; while Remaining_Width >= 0 loop - Gnatfmt_Trace.Trace ("F3"); if Fit_Commands.Is_Empty then - Gnatfmt_Trace.Trace ("F4"); if Rest_Idx < Rest_Commands.First_Index then - Gnatfmt_Trace.Trace ("F5"); return True; end if; @@ -313,7 +333,6 @@ package body Prettier_Ada.Documents.Implementation is Rest_Idx := @ - Natural (1); else - Gnatfmt_Trace.Trace ("F6"); declare Current_Fit_Command : constant Fit_Command_Type := Fit_Commands.Last_Element; @@ -322,24 +341,22 @@ package body Prettier_Ada.Documents.Implementation is Document : Document_Type renames Current_Fit_Command.Document; + use type Ada.Containers.Count_Type; + begin - Gnatfmt_Trace.Trace ("F7"); Fit_Commands.Delete_Last; case Document.Bare_Document.Kind is when Document_Text => - Gnatfmt_Trace.Trace ("F8"); Append (Current_Line, Document.Bare_Document.Text); Remaining_Width := @ - Document.Bare_Document.Text.Display_Width; when Document_List => - Gnatfmt_Trace.Trace ("F9"); for Child_Document of reverse Get_Document_Parts (Document) loop - Gnatfmt_Trace.Trace ("F10"); Fit_Commands.Append (Fit_Command_Type'(Mode, Child_Document)); end loop; @@ -347,17 +364,14 @@ package body Prettier_Ada.Documents.Implementation is when Document_Command => case Document.Bare_Document.Command.Kind is when Command_Fill => - Gnatfmt_Trace.Trace ("F9"); for Child_Document of reverse Get_Document_Parts (Document) loop - Gnatfmt_Trace.Trace ("F10"); Fit_Commands.Append (Fit_Command_Type'(Mode, Child_Document)); end loop; when Command_Indent => - Gnatfmt_Trace.Trace ("F11"); Ada.Assertions.Assert (Document .Bare_Document @@ -373,7 +387,6 @@ package body Prettier_Ada.Documents.Implementation is .Indent_Contents)); when Command_Align => - Gnatfmt_Trace.Trace ("F11"); Ada.Assertions.Assert (Document .Bare_Document @@ -389,7 +402,6 @@ package body Prettier_Ada.Documents.Implementation is .Align_Contents)); when Command_Indent_If_Break => - Gnatfmt_Trace.Trace ("F11"); Ada.Assertions.Assert (Document .Bare_Document @@ -405,7 +417,6 @@ package body Prettier_Ada.Documents.Implementation is .Indent_If_Break_Contents)); when Command_Label => - Gnatfmt_Trace.Trace ("F11"); Ada.Assertions.Assert (Document .Bare_Document @@ -421,21 +432,16 @@ package body Prettier_Ada.Documents.Implementation is .Label_Contents)); when Command_Trim => - Gnatfmt_Trace.Trace ("F12"); Remaining_Width := @ + Trim (Current_Line); when Command_Group => - Gnatfmt_Trace.Trace ("F13"); if Must_Be_Flat and Document.Bare_Document.Command.Break then - Gnatfmt_Trace.Trace ("F14"); return False; end if; declare - use type Ada.Containers.Count_Type; - Group_Mode : constant Mode_Kind := (if Document.Bare_Document.Command.Break then Mode_Break @@ -468,7 +474,6 @@ package body Prettier_Ada.Documents.Implementation is .Group_Contents); begin - Gnatfmt_Trace.Trace ("F15"); Fit_Commands.Append (Fit_Command_Type'(Group_Mode, Contents)); end; @@ -510,7 +515,6 @@ package body Prettier_Ada.Documents.Implementation is .Flat_Contents); begin - Gnatfmt_Trace.Trace ("F16"); if Contents /= No_Document and then (if Contents.Bare_Document.Kind in Document_Text @@ -521,35 +525,28 @@ package body Prettier_Ada.Documents.Implementation is .Text .Is_Empty) then - Gnatfmt_Trace.Trace ("F17"); Fit_Commands.Append (Fit_Command_Type'(Mode, Contents)); end if; end; when Command_Line => - Gnatfmt_Trace.Trace ("F18"); if Mode = Mode_Break or Document.Bare_Document.Command.Hard then - Gnatfmt_Trace.Trace ("F19"); return True; end if; if not Document.Bare_Document.Command.Soft then - Gnatfmt_Trace.Trace ("F20"); Append (Current_Line, (" ", 1)); Remaining_Width := @ - Natural (1); end if; when Command_Line_Suffix => - Gnatfmt_Trace.Trace ("F21"); Current_Has_Line_Suffix := True; when Command_Line_Suffix_Boundary => - Gnatfmt_Trace.Trace ("F22"); if Current_Has_Line_Suffix then - Gnatfmt_Trace.Trace ("F23"); return False; end if; @@ -558,7 +555,157 @@ package body Prettier_Ada.Documents.Implementation is null; when Command_Alignment_Table => - raise Program_Error with "TODO"; + -- First check if the table has more than 1 row and + -- must break. In such case, no calculations are + -- needed. + + if Document + .Bare_Document + .Command + .Alignment_Table_Elements + .Length > 1 + and then Document + .Bare_Document + .Command + .Alignment_Table_Must_Break + then + return False; + end if; + + declare + Alignment_Table_Elements : Document_Table + renames Document + .Bare_Document + .Command + .Alignment_Table_Elements; + Alignment_Table_Separators : Document_Table + renames Document + .Bare_Document + .Command + .Alignment_Table_Separators; + + -- The algorithm relies on not only checking the + -- previous elements/separators of the row but + -- also of other rows. The easist way to do this + -- is with indices. Start by finding the longest + -- column and row. + + First_Row_Index : constant Positive := + Alignment_Table_Elements.First_Index; + Last_Row_Index : constant Positive := + Alignment_Table_Elements.Last_Index; + First_Column_Index : constant Positive := + Alignment_Table_Elements + .Constant_Reference (First_Row_Index) + .First_Index; + Last_Column_Index : constant Positive := + [for Row_Elements of Alignment_Table_Elements + => Row_Elements.Last_Index]'Reduce + (Positive'Max, + 1); + + begin + -- Append to Fit_Comands every element/separator + -- in reverse order (starting from the last + -- column of the last row). + + for Column_Index + in reverse First_Column_Index + .. Last_Column_Index + loop + if Alignment_Table_Separators + .Constant_Reference (Last_Row_Index) + .Last_Index + >= Column_Index + then + Fit_Commands.Append + (Fit_Command_Type' + (Mode_Flat, + Alignment_Table_Separators + .Constant_Reference + (Last_Row_Index) + .Constant_Reference + (Column_Index))); + end if; + + if Alignment_Table_Elements + .Constant_Reference (Last_Row_Index) + .Last_Index + >= Column_Index + then + Fit_Commands.Append + (Fit_Command_Type' + (Mode_Flat, + Alignment_Table_Elements + .Constant_Reference + (Last_Row_Index) + .Constant_Reference + (Column_Index))); + end if; + end loop; + + for Row_Index + in reverse First_Row_Index + .. Standard."-" (Last_Row_Index, 1) + loop + -- At a Line between rows + + Fit_Commands.Append + (Fit_Command_Type' + (Mode_Flat, + Prettier_Ada.Documents.Builders.Line)); + + for Column_Index + in reverse First_Column_Index + .. Last_Column_Index + loop + if Alignment_Table_Separators + .Constant_Reference (Row_Index) + .Last_Index + >= Column_Index + then + Fit_Commands.Append + (Fit_Command_Type' + (Mode_Flat, + Alignment_Table_Separators + .Constant_Reference + (Row_Index) + .Constant_Reference + (Column_Index))); + end if; + + if Alignment_Table_Elements + .Constant_Reference (Row_Index) + .Last_Index + >= Column_Index + then + Fit_Commands.Append + (Fit_Command_Type' + (Mode_Flat, + Alignment_Table_Elements + .Constant_Reference + (Row_Index) + .Constant_Reference + (Column_Index))); + end if; + end loop; + end loop; + end; + + when Command_Alignment_Table_Separator => + Append + (Current_Line, + Document + .Bare_Document + .Command + .Alignment_Table_Separator_Text); + Remaining_Width := + @ + - Document + .Bare_Document + .Command + .Alignment_Table_Separator_Text + .Display_Width; end case; end case; @@ -577,26 +724,56 @@ package body Prettier_Ada.Documents.Implementation is (Document : Document_Type; Options : Format_Options_Type := Default_Format_Options) return Ada.Strings.Unbounded.Unbounded_String - is (VSS.Strings.Conversions.To_Unbounded_UTF_8_String - (Format (Document, Options).Formatted_Document)); + is + State : Format_State_Record := Default_Format_State; + + begin + -- Adapt State, which at this point is a Default_Format_state, based + -- on Document (to be formatted) and Options. + + State.Current_Line_Length := + Options.Indentation.Offset.Spaces + + Options.Indentation.Offset.Tabs * Options.Indentation.Width; + + State.Result := + (VSS.Strings."&" + (VSS.Strings."*" + (VSS.Strings.Character_Count (Options.Indentation.Offset.Tabs), + VSS.Characters.Latin.Character_Tabulation), + VSS.Strings."*" + (VSS.Strings.Character_Count (Options.Indentation.Offset.Spaces), + VSS.Characters.Latin.Space)), + VSS.Strings.Display_Cell_Count + (Options.Indentation.Offset.Spaces + + Options.Indentation.Offset.Tabs * Options.Indentation.Width)); + + State.Print_Commands := + [Print_Command_Type' + (Root_Indent (Options.Indentation), + Mode_Break, + Document)]; + + Propagate_Breaks (Document); + + Format (State, Options); + + return + VSS.Strings.Conversions.To_Unbounded_UTF_8_String (State.Result.Text); + end Format; ------------ -- Format -- ------------ - function Format - (Document : Document_Type; - Options : Format_Options_Type := Default_Format_Options; - Initial_Line_Length : Natural := - Options.Indentation.Offset.Spaces - + Options.Indentation.Offset.Tabs * Options.Indentation.Width) - return Format_Result_Type + procedure Format + (Format_State : in out Format_State_Record; + Format_Options : Format_Options_Type) is use type Ada.Containers.Count_Type; use type VSS.Strings.Virtual_String; End_Of_Line : constant Prettier_String := - (case Options.End_Of_Line is + (case Format_Options.End_Of_Line is when LF => (VSS.Strings.Empty_Virtual_String & VSS.Characters.Latin.Line_Feed, @@ -611,42 +788,11 @@ package body Prettier_Ada.Documents.Implementation is & VSS.Characters.Latin.Line_Feed, 0)); - Group_Mode_Map : Symbol_To_Mode_Map; - - Current_Line_Length : Natural := Initial_Line_Length; - - Should_Remeasure : Boolean := False; - - Line_Suffix : Print_Command_Type_Vector := []; - - Print_Commands : Print_Command_Type_Vector := - [Print_Command_Type' - (Root_Indent (Options.Indentation), - Mode_Break, - Document)]; - - Printed_Cursor_Count : Natural := 0; - - Result : Prettier_String := - (VSS.Strings."&" - (VSS.Strings."*" - (VSS.Strings.Character_Count (Options.Indentation.Offset.Tabs), - VSS.Characters.Latin.Character_Tabulation), - VSS.Strings."*" - (VSS.Strings.Character_Count (Options.Indentation.Offset.Spaces), - VSS.Characters.Latin.Space)), - VSS.Strings.Display_Cell_Count - (Options.Indentation.Offset.Spaces - + Options.Indentation.Offset.Tabs * Options.Indentation.Width)); - begin - - Propagate_Breaks (Document); - - while Print_Commands.Length > 0 loop + while Format_State.Print_Commands.Length > 0 loop declare Print_Command : constant Print_Command_Type := - Print_Commands.Last_Element; + Format_State.Print_Commands.Last_Element; Indentation : Indentation_Queue_Type renames Print_Command.Indentation; Mode : Mode_Kind renames Print_Command.Mode; @@ -667,6 +813,29 @@ package body Prettier_Ada.Documents.Implementation is procedure Process_Document_Text; -- TODO: Description + procedure Process_Document_Command_Alignment_Table; + -- Processes Print_Command as an Alignment_Table. + -- An Alignment_Table can be processed in two modes: + -- - Break + -- - Flat + -- + -- To process an Alignment Table in Break mode, each column is + -- handled sequentially. For each column, the required alignment + -- is calculated and applied. Once a column is processed, its + -- separators are appended. This process is repeated for each + -- column until the entire table is processed. + -- + -- To process an Alignment_Table in Flat mode, each row is handled + -- sequentually as list. + + procedure Process_Document_Command_Alignment_Table_Separator; + -- Processes Print_Command as an Alignment_Table_Separator + -- command. An Alignment_Table_Separator command is only processed + -- this way if it's not a child document of an Alignment_Table or + -- if the Alignment_Table was handled in Flat mode. In this case, + -- the separators' text is simply appended to + -- Format_State.Result. + ------------------------------------ -- Process_Document_Command_Group -- ------------------------------------ @@ -692,31 +861,24 @@ package body Prettier_Ada.Documents.Implementation is .Command .Group_Contents); Remaining_Line_Length : constant Integer := - Options.Width - Current_Line_Length; + Format_Options.Width - Format_State.Current_Line_Length; Has_Line_Suffix : constant Boolean := - Line_Suffix.Length > 0; + Format_State.Line_Suffix.Length > 0; begin - Gnatfmt_Trace.Trace ("72"); - Should_Remeasure := False; + Format_State.Should_Remeasure := False; if not Document.Bare_Document.Command.Break and then Fits (Next, - Print_Commands, + Format_State.Print_Commands, Remaining_Line_Length, Has_Line_Suffix, - Group_Mode_Map) + Format_State.Group_Mode_Map) then - Gnatfmt_Trace.Trace ("721"); - Gnatfmt_Trace.Trace - ((if Next.Mode = Mode_Flat - then "flat" - else "break")); - Print_Commands.Append (Next); + Format_State.Print_Commands.Append (Next); else - Gnatfmt_Trace.Trace ("722"); if Document .Bare_Document .Command @@ -729,7 +891,6 @@ package body Prettier_Ada.Documents.Implementation is .Bare_Document .List.Length /= 0 then - Gnatfmt_Trace.Trace ("7221"); declare Expanded_States : constant Document_Vector := @@ -749,16 +910,13 @@ package body Prettier_Ada.Documents.Implementation is .Command .Break then - Gnatfmt_Trace.Trace ("72211"); - Gnatfmt_Trace.Trace ("break"); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Indentation, Mode_Break, Most_Expanded)); else - Gnatfmt_Trace.Trace ("72212"); for J in Expanded_States.First_Index + Natural (1) .. Expanded_States.Last_Index + Natural (1) @@ -766,15 +924,12 @@ package body Prettier_Ada.Documents.Implementation is if J >= Expanded_States.Last_Index + Natural (1) then - Gnatfmt_Trace.Trace ("722121"); - Gnatfmt_Trace.Trace ("break"); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Indentation, Mode_Break, Most_Expanded)); else - Gnatfmt_Trace.Trace ("722122"); declare State : constant Document_Type := @@ -788,18 +943,12 @@ package body Prettier_Ada.Documents.Implementation is begin if Fits (Print_Command, - Print_Commands, + Format_State.Print_Commands, Remaining_Line_Length, Has_Line_Suffix, - Group_Mode_Map) + Format_State.Group_Mode_Map) then - Gnatfmt_Trace.Trace ("7221221"); - Gnatfmt_Trace.Trace - ((if Print_Command.Mode - = Mode_Flat - then "flat" - else "break")); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command); exit; end if; @@ -810,9 +959,7 @@ package body Prettier_Ada.Documents.Implementation is end; else - Gnatfmt_Trace.Trace ("7222"); - Gnatfmt_Trace.Trace ("break"); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Indentation, Mode_Break, @@ -831,28 +978,21 @@ package body Prettier_Ada.Documents.Implementation is procedure Process_Mode_Flat is Print_Command : constant Print_Command_Type := Print_Command_Type' - (Indentation, - (if Document - .Bare_Document - .Command - .Break - then Mode_Break - else Mode_Flat), - Document - .Bare_Document - .Command - .Group_Contents); + (Indentation, + (if Document + .Bare_Document + .Command + .Break + then Mode_Break + else Mode_Flat), + Document + .Bare_Document + .Command + .Group_Contents); begin - Gnatfmt_Trace.Trace ("71"); - if not Should_Remeasure then - Gnatfmt_Trace.Trace ("711"); - Gnatfmt_Trace.Trace - ((if Print_Command.Mode = Mode_Flat - then "flat" - else "break")); - Print_Commands.Append (Print_Command); + if not Format_State.Should_Remeasure then + Format_State.Print_Commands.Append (Print_Command); else - Gnatfmt_Trace.Trace ("712"); Process_Mode_Break; end if; end Process_Mode_Flat; @@ -872,9 +1012,9 @@ package body Prettier_Ada.Documents.Implementation is if Document.Bare_Document.Command.Id /= No_Symbol then - Group_Mode_Map.Include + Format_State.Group_Mode_Map.Include (Document.Bare_Document.Command.Id, - Print_Commands.Last_Element.Mode); + Format_State.Print_Commands.Last_Element.Mode); end if; end Process_Document_Command_Group; @@ -884,7 +1024,7 @@ package body Prettier_Ada.Documents.Implementation is procedure Process_Document_Command_Fill is Remaining_Line_Length : constant Integer := - Options.Width - Current_Line_Length; + Format_Options.Width - Format_State.Current_Line_Length; Parts : constant Document_Vector := Document .Bare_Document @@ -905,15 +1045,20 @@ package body Prettier_Ada.Documents.Implementation is (Content_Flat_Command, [], Remaining_Line_Length, - Line_Suffix.Length > 0, - Group_Mode_Map, + Format_State.Line_Suffix.Length > 0, + Format_State.Group_Mode_Map, True); begin if Content_Fits then - Print_Commands.Append (Content_Flat_Command); + Format_State + .Print_Commands + .Append (Content_Flat_Command); + else - Print_Commands.Append (Content_Break_Command); + Format_State + .Print_Commands + .Append (Content_Break_Command); end if; end; @@ -936,18 +1081,26 @@ package body Prettier_Ada.Documents.Implementation is (Content_Flat_Command, [], Remaining_Line_Length, - Line_Suffix.Length > 0, - Group_Mode_Map, + Format_State.Line_Suffix.Length > 0, + Format_State.Group_Mode_Map, True); begin if Content_Fits then - Print_Commands.Append (White_Flat_Command); - Print_Commands.Append (Content_Flat_Command); + Format_State + .Print_Commands + .Append (White_Flat_Command); + Format_State + .Print_Commands + .Append (Content_Flat_Command); else - Print_Commands.Append (White_Break_Command); - Print_Commands.Append (Content_Break_Command); + Format_State + .Print_Commands + .Append (White_Break_Command); + Format_State + .Print_Commands + .Append (Content_Break_Command); end if; end; @@ -975,8 +1128,8 @@ package body Prettier_Ada.Documents.Implementation is (Content_Flat_Command, [], Remaining_Line_Length, - Line_Suffix.Length > 0, - Group_Mode_Map, + Format_State.Line_Suffix.Length > 0, + Format_State.Group_Mode_Map, True); Remaining_Parts : constant Document_Vector := @@ -1005,25 +1158,43 @@ package body Prettier_Ada.Documents.Implementation is (First_And_Second_Content_Flat_Command, [], Remaining_Line_Length, - Line_Suffix.Length > 0, - Group_Mode_Map, + Format_State.Line_Suffix.Length > 0, + Format_State.Group_Mode_Map, True); begin if First_And_Second_Content_Fits then - Print_Commands.Append (Remaining_Print_Command); - Print_Commands.Append (White_Flat_Command); - Print_Commands.Append (Content_Flat_Command); + Format_State + .Print_Commands + .Append (Remaining_Print_Command); + Format_State + .Print_Commands + .Append (White_Flat_Command); + Format_State + .Print_Commands + .Append (Content_Flat_Command); elsif Content_Fits then - Print_Commands.Append (Remaining_Print_Command); - Print_Commands.Append (White_Break_Command); - Print_Commands.Append (Content_Flat_Command); + Format_State + .Print_Commands + .Append (Remaining_Print_Command); + Format_State + .Print_Commands + .Append (White_Break_Command); + Format_State + .Print_Commands + .Append (Content_Flat_Command); else - Print_Commands.Append (Remaining_Print_Command); - Print_Commands.Append (White_Break_Command); - Print_Commands.Append (Content_Break_Command); + Format_State + .Print_Commands + .Append (Remaining_Print_Command); + Format_State + .Print_Commands + .Append (White_Break_Command); + Format_State + .Print_Commands + .Append (Content_Break_Command); end if; end; end if; @@ -1046,45 +1217,41 @@ package body Prettier_Ada.Documents.Implementation is procedure Process_Mode_Break is begin - Gnatfmt_Trace.Trace ("131"); - if not Line_Suffix.Is_Empty then - Gnatfmt_Trace.Trace ("1311"); - Print_Commands.Append + if not Format_State.Line_Suffix.Is_Empty then + Format_State.Print_Commands.Append (Print_Command_Type'(Indentation, Mode, Document)); - Gnatfmt_Trace.Trace - ("1312 Length" & Line_Suffix.Length'Image); - for Suffix of reverse Line_Suffix loop - Print_Commands.Append (Suffix); + for Suffix of reverse Format_State.Line_Suffix loop + Format_State.Print_Commands.Append (Suffix); end loop; - Line_Suffix.Clear; + Format_State.Line_Suffix.Clear; + Format_State.Last_Was_Hardline := False; else - Gnatfmt_Trace.Trace ("1312"); if Document.Bare_Document.Command.Literal then - Gnatfmt_Trace.Trace ("13121"); if Indentation.Root /= null then - Gnatfmt_Trace.Trace ("131211"); - Append (Result, End_Of_Line); - Append (Result, Indentation.Root.Value); - Current_Line_Length := + Append (Format_State.Result, End_Of_Line); + Append + (Format_State.Result, Indentation.Root.Value); + Format_State.Current_Line_Length := Natural (Indentation.Root.Value.Display_Width); else - Gnatfmt_Trace.Trace ("131212"); - Append (Result, End_Of_Line); - Current_Line_Length := - Options.Indentation.Offset.Spaces - + Options.Indentation.Offset.Tabs - * Options.Indentation.Width; + Append (Format_State.Result, End_Of_Line); + Format_State.Current_Line_Length := + Format_Options.Indentation.Offset.Spaces + + Format_Options.Indentation.Offset.Tabs + * Format_Options.Indentation.Width; end if; + Format_State.Last_Was_Hardline := False; else - Gnatfmt_Trace.Trace ("13122"); - Current_Line_Length := @ - Trim (Result); - Append (Result, End_Of_Line); - Append (Result, Indentation.Value); - Current_Line_Length := + Format_State.Current_Line_Length := + @ - Trim (Format_State.Result); + Append (Format_State.Result, End_Of_Line); + Append (Format_State.Result, Indentation.Value); + Format_State.Current_Line_Length := Natural (Indentation.Value.Display_Width); + Format_State.Last_Was_Hardline := True; end if; end if; end Process_Mode_Break; @@ -1095,28 +1262,24 @@ package body Prettier_Ada.Documents.Implementation is procedure Process_Mode_Flat is begin - Gnatfmt_Trace.Trace ("132"); if not Document.Bare_Document.Command.Hard then - Gnatfmt_Trace.Trace ("1321"); if not Document .Bare_Document .Command .Soft then - Gnatfmt_Trace.Trace ("13211"); - Append (Result, (" ", 1)); - Current_Line_Length := @ + Natural (1); + Append (Format_State.Result, (" ", 1)); + Format_State.Current_Line_Length := @ + Natural (1); end if; + Format_State.Last_Was_Hardline := False; else - Gnatfmt_Trace.Trace ("1322"); - Should_Remeasure := True; + Format_State.Should_Remeasure := True; Process_Mode_Break; end if; end Process_Mode_Flat; begin - Gnatfmt_Trace.Trace ("13"); case Mode is when Mode_Flat => Process_Mode_Flat; @@ -1135,13 +1298,9 @@ package body Prettier_Ada.Documents.Implementation is procedure Process_Document_Text is begin - Gnatfmt_Trace.Trace ("1"); - Append - (Result, Document.Bare_Document.Text); - if Print_Commands.Length > 0 then - Current_Line_Length := - @ + Document.Bare_Document.Text.Display_Width; - end if; + Append (Format_State.Result, Document.Bare_Document.Text); + Format_State.Current_Line_Length := + @ + Document.Bare_Document.Text.Display_Width; end Process_Document_Text; --------------------------- @@ -1153,22 +1312,543 @@ package body Prettier_Ada.Documents.Implementation is Document.Bare_Document.List; begin - Gnatfmt_Trace.Trace ("2"); - Gnatfmt_Trace.Trace ("2 Length" & Documents.Length'Image); for Child_Document of reverse Documents loop Ada.Assertions.Assert (Child_Document /= No_Document); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type'(Indentation, Mode, Child_Document)); end loop; end Process_Document_List; + ---------------------------------------------- + -- Process_Document_Command_Alignment_Table -- + ---------------------------------------------- + + procedure Process_Document_Command_Alignment_Table + is + procedure Process_Mode_Break; + -- Processes the Alignment_Table comamnd in Break mode + + procedure Process_Mode_Flat; + -- Processes the Alignment_Table comamnd in Flat mode + + ------------------------ + -- Process_Mode_Break -- + ------------------------ + + procedure Process_Mode_Break is + use VSS.Strings; + + type Format_State_Array is + array (Positive range <>) of Format_State_Record; + + Alignment_Table_Elements : Document_Table + renames Document + .Bare_Document + .Command + .Alignment_Table_Elements; + Alignment_Table_Separators : Document_Table + renames Document + .Bare_Document + .Command + .Alignment_Table_Separators; + + States : + Format_State_Array + (Alignment_Table_Elements.First_Index + .. Alignment_Table_Elements.Last_Index) := + [others => Format_State]; + -- The state for each row + + First_Row_Index : constant Positive := + Alignment_Table_Elements.First_Index; + Last_Row_Index : constant Positive := + Alignment_Table_Elements.Last_Index; + First_Column_Index : constant Positive := 1; + Last_Column_Index : constant Positive := + [for Row_Elements of Alignment_Table_Elements + => Row_Elements.Last_Index]'Reduce (Positive'Max, 1); + + Max_Line_Length : Natural := 0; + + begin + Prettier_Ada_Trace.Trace + ("On Process_Document_Command_Alignment_Table." + & "Process_Mode_Break"); + + for State of States loop + State.Result := Empty_Prettier_String; + end loop; + + if Format_State.Last_Was_Hardline then + -- If the last document appended to Format_State.Result + -- was a hardline, then we need to move any indentation + -- from Format_State.Result into + -- States (First_Row_Index).Result. Otherwise, if the + -- first document of the first row is a line break, + -- previously added identation is not removed, resulting + -- in trailing whitespaces in the final + -- Format_State.Result. + + Trim (Format_State.Result, Right); + States (First_Row_Index) + .Result + .Text + .Append (Indentation.Value.Text); + end if; + + Prettier_Ada_Trace.Trace + ("On Column_Index " & First_Column_Index'Image); + + for Row_Index in First_Row_Index .. Last_Row_Index loop + Prettier_Ada_Trace.Trace + ("On Row_Index " & Row_Index'Image); + declare + Separator_Display_Width : + constant Display_Cell_Count := + (if not Alignment_Table_Separators + .Reference (Row_Index) + .Is_Empty + then + Alignment_Table_Separators + .Reference (Row_Index) + .Reference (First_Column_Index) + .Bare_Document + .Command + .Alignment_Table_Separator_Text + .Display_Width + else 0); + Next_Options : + constant Format_Options_Type := + Format_Options_Type' + (Width => + (if Natural (Separator_Display_Width) + > Format_Options.Width + then 0 + else + Format_Options.Width + - Natural (Separator_Display_Width)), + Indentation => Format_Options.Indentation, + End_Of_Line => Format_Options.End_Of_Line); + -- The formatting options for each element need + -- to have an offset on the maximum width to account + -- the separator's width. + + begin + States (Row_Index).Should_Remeasure := False; + States (Row_Index).Print_Commands := + [Print_Command_Type' + (Indentation, + Mode_Break, + Alignment_Table_Elements + .Reference (Row_Index) + .Reference (First_Column_Index))]; + + Format (States (Row_Index), Next_Options); + + Prettier_Ada_Trace.Trace + ("States.State.Current_Line_Length" + & States (Row_Index).Current_Line_Length'Image); + + -- Compute the Max_Line_Length seen so far. If there's + -- not separators on this row, then this row line + -- length should not affect the alignment of others. + + if not Alignment_Table_Separators (Row_Index).Is_Empty + then + Max_Line_Length := + Natural'Max + (@, States (Row_Index).Current_Line_Length); + end if; + end; + end loop; + + Prettier_Ada_Trace.Trace + ("Max_Line_Length" & Max_Line_Length'Image); + + for Column_Index + in Standard."+" (First_Column_Index, 1) + .. Last_Column_Index + loop + Prettier_Ada_Trace.Trace + ("On Column_Index " & Column_Index'Image); + + -- Add padding to the buffers + + Prettier_Ada_Trace.Trace + ("Adding padding to the buffers"); + + for Row_Index in First_Row_Index .. Last_Row_Index loop + Prettier_Ada_Trace.Trace + ("On Row_Index " & Row_Index'Image); + + if Column_Index + <= Alignment_Table_Elements + .Element (Row_Index) + .Last_Index + then + declare + Padding : constant Character_Count := + Character_Count + (Max_Line_Length + - States (Row_Index).Current_Line_Length); + + begin + Prettier_Ada_Trace.Trace + ("Padding " & Padding'Image); + + if Padding /= 0 then + States (Row_Index) + .Result + .Text + .Append (Padding * ' '); + States (Row_Index).Current_Line_Length := + Max_Line_Length; + end if; + end; + end if; + + end loop; + + Prettier_Ada_Trace.Trace + ("Adding separators to the buffers"); + + -- Add separators to the buffers + + for Row_Index in First_Row_Index .. Last_Row_Index loop + Prettier_Ada_Trace.Trace + ("On Row_Index " & Row_Index'Image); + + if Standard."-" (Column_Index, 1) + <= Alignment_Table_Separators + .Element (Row_Index) + .Last_Index + then + declare + Separator : constant Document_Type := + Alignment_Table_Separators + .Constant_Reference (Row_Index) + .Constant_Reference + (Standard."-" (Column_Index, 1)); + + Separator_Display_Width : constant Natural := + Natural + (Separator + .Bare_Document + .Command + .Alignment_Table_Separator_Text + .Display_Width); + + Row_Line_Length_After_Separator : + constant Natural := + Max_Line_Length + Separator_Display_Width; + + begin + Prettier_Ada_Trace.Trace + ("Row_Line_Length_After_Separator " + & Row_Line_Length_After_Separator'Image); + + States (Row_Index) + .Result + .Text + .Append + (Separator + .Bare_Document + .Command + .Alignment_Table_Separator_Text + .Text); + States (Row_Index).Current_Line_Length := + Row_Line_Length_After_Separator; + end; + end if; + end loop; + + -- Format current element and add it to the buffers + + Prettier_Ada_Trace.Trace + ("Format current element and add it to the buffers"); + + Max_Line_Length := 0; + + for Row_Index in First_Row_Index .. Last_Row_Index loop + Prettier_Ada_Trace.Trace + ("On Row_Index " & Row_Index'Image); + + if Column_Index + <= Alignment_Table_Elements + .Constant_Reference (Row_Index) + .Last_Index + then + declare + Separator_Display_Width : + constant Display_Cell_Count := + (if Alignment_Table_Separators + .Constant_Reference (Row_Index) + .Last_Index + >= Column_Index + then + Alignment_Table_Separators + .Constant_Reference (Row_Index) + .Constant_Reference (Column_Index) + .Bare_Document + .Command + .Alignment_Table_Separator_Text + .Display_Width + else 0); + Next_Options : + constant Format_Options_Type := + Format_Options_Type' + (Width => + (if Natural (Separator_Display_Width) + > Format_Options.Width + then + 0 + else + Format_Options.Width + - Natural + (Separator_Display_Width)), + Indentation => + Format_Options.Indentation, + End_Of_Line => + Format_Options.End_Of_Line); + + begin + States (Row_Index).Should_Remeasure := False; + States (Row_Index).Print_Commands := + [Print_Command_Type' + (Indentation, + Mode_Break, + Alignment_Table_Elements + .Reference (Row_Index) + .Reference (Column_Index))]; + + Format (States (Row_Index), Next_Options); + + Prettier_Ada_Trace.Trace + ("States.State.Current_Line_Length" + & States (Row_Index) + .Current_Line_Length'Image); + + if not (Alignment_Table_Separators (Row_Index) + .Last_Index + < Column_Index) + then + Max_Line_Length := + Natural'Max + (@, + States (Row_Index).Current_Line_Length); + end if; + end; + end if; + end loop; + end loop; + + -- Finally, concatenate all buffers and add them to Result + + Format_State.Result + .Text + .Append (States (First_Row_Index).Result.Text); + for Row_Index + in Standard."+" (First_Row_Index, 1) .. Last_Row_Index + loop + Format_State.Result.Text.Append (End_Of_Line.Text); + Format_State.Result.Text.Append (Indentation.Value.Text); + Format_State.Result.Text.Append + (States (Row_Index).Result.Text); + end loop; + + -- Also update the Format_State.Current_Line_Length based on + -- the last table row. + + Format_State.Current_Line_Length := + States (Last_Row_Index).Current_Line_Length; + + end Process_Mode_Break; + + ----------------------- + -- Process_Mode_Flat -- + ----------------------- + + procedure Process_Mode_Flat is + Remaining_Line_Length : constant Integer := + Format_Options.Width - Format_State.Current_Line_Length; + Has_Line_Suffix : constant Boolean := + Format_State.Line_Suffix.Length > 0; + + begin + Prettier_Ada_Trace.Trace + ("On Process_Document_Command_Alignment_Table." + & "Process_Mode_Flat"); + + Prettier_Ada_Trace.Trace ("Checking if table fits"); + Prettier_Ada_Trace.Trace + ("Remaining_Line_Length: " & Remaining_Line_Length'Image); + + if not Fits + (Print_Command, + [], + Remaining_Line_Length, + Has_Line_Suffix, + Format_State.Group_Mode_Map) + then + Prettier_Ada_Trace.Trace ("Table does not fit"); + Process_Mode_Break; + + return; + end if; + + Prettier_Ada_Trace.Trace ("Table fits"); + + declare + Alignment_Table_Elements : Document_Table + renames Document + .Bare_Document + .Command + .Alignment_Table_Elements; + Alignment_Table_Separators : Document_Table + renames Document + .Bare_Document + .Command + .Alignment_Table_Separators; + + First_Row_Index : constant Positive := + Alignment_Table_Elements.First_Index; + Last_Row_Index : constant Positive := + Alignment_Table_Elements.Last_Index; + First_Column_Index : constant Positive := 1; + Last_Column_Index : constant Positive := + [for Row_Elements of Alignment_Table_Elements + => Row_Elements.Last_Index]'Reduce (Positive'Max, 1); + + begin + -- Add the last row + + for Column_Index + in reverse First_Column_Index .. Last_Column_Index + loop + if Alignment_Table_Separators + .Constant_Reference (Last_Row_Index) + .Last_Index + >= Column_Index + then + Format_State.Print_Commands.Append + (Print_Command_Type' + (Indentation, + Mode_Flat, + Alignment_Table_Separators + .Constant_Reference (Last_Row_Index) + .Constant_Reference (Column_Index))); + end if; + + if Alignment_Table_Elements + .Constant_Reference (Last_Row_Index) + .Last_Index + >= Column_Index + then + Format_State.Print_Commands.Append + (Print_Command_Type' + (Indentation, + Mode_Flat, + Alignment_Table_Elements + .Constant_Reference (Last_Row_Index) + .Constant_Reference (Column_Index))); + end if; + end loop; + + -- Add the remaining rows (in reverse order) with a Line + -- in between. + + for Row_Index + in reverse First_Row_Index + .. Standard."-" (Last_Row_Index, 1) + loop + Format_State.Print_Commands.Append + (Print_Command_Type' + (Indentation, + Mode_Flat, + Prettier_Ada + .Documents + .Builders + .Line)); + + for Column_Index + in reverse First_Column_Index .. Last_Column_Index + loop + if Alignment_Table_Separators + .Constant_Reference (Row_Index) + .Last_Index + >= Column_Index + then + Format_State.Print_Commands.Append + (Print_Command_Type' + (Indentation, + Mode_Flat, + Alignment_Table_Separators + .Constant_Reference (Row_Index) + .Constant_Reference (Column_Index))); + end if; + + if Alignment_Table_Elements + .Constant_Reference (Row_Index) + .Last_Index + >= Column_Index + then + Format_State.Print_Commands.Append + (Print_Command_Type' + (Indentation, + Mode_Flat, + Alignment_Table_Elements + .Constant_Reference (Row_Index) + .Constant_Reference (Column_Index))); + end if; + end loop; + end loop; + end; + end Process_Mode_Flat; + + begin + Prettier_Ada_Trace.Trace + ("On Process_Document_Command_Alignment_Table"); + + if Document.Bare_Document.Command.Alignment_Table_Must_Break + or Mode in Mode_Break + then + Prettier_Ada_Trace.Trace ("Table must break"); + Process_Mode_Break; + + else + Process_Mode_Flat; + end if; + end Process_Document_Command_Alignment_Table; + + -------------------------------------------------- + -- Process_Document_Command_Alignment_Separator -- + -------------------------------------------------- + + procedure Process_Document_Command_Alignment_Table_Separator + is + begin + Append + (Format_State.Result, + Document + .Bare_Document + .Command + .Alignment_Table_Separator_Text); + Format_State.Current_Line_Length := + @ + + Document + .Bare_Document + .Command + .Alignment_Table_Separator_Text + .Display_Width; + end Process_Document_Command_Alignment_Table_Separator; + begin - -- Ada.Text_IO.New_Line; - Print_Commands.Delete_Last; + Format_State.Print_Commands.Delete_Last; case Document.Bare_Document.Kind is when Document_Text => Process_Document_Text; + Format_State.Last_Was_Hardline := False; when Document_List => Process_Document_List; @@ -1176,8 +1856,7 @@ package body Prettier_Ada.Documents.Implementation is when Document_Command => case Document.Bare_Document.Command.Kind is when Command_Cursor => - Gnatfmt_Trace.Trace ("3"); - if Printed_Cursor_Count >= 2 then + if Format_State.Printed_Cursor_Count >= 2 then -- TODO: Replace this by a GNATfmt defined -- exception raise Program_Error; @@ -1185,49 +1864,45 @@ package body Prettier_Ada.Documents.Implementation is -- TODO: How to add this command to Result? -- Should Result be instead a Document_Type_Vector -- with only Document_Text and Command_Cursor? - Printed_Cursor_Count := @ + Natural (1); + Format_State.Printed_Cursor_Count := @ + Natural (1); when Command_Indent => - Gnatfmt_Trace.Trace ("4"); Ada.Assertions.Assert (Document.Bare_Document.Command.Indent_Contents /= No_Document); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Make_Indentation - (Indentation, Options.Indentation), + (Indentation, Format_Options.Indentation), Mode, Document.Bare_Document.Command.Indent_Contents)); when Command_Align => - Gnatfmt_Trace.Trace ("5"); Ada.Assertions.Assert (Document.Bare_Document.Command.Align_Contents /= No_Document); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Make_Align (Indentation, Document.Bare_Document.Command.Align_Data, - Options, - Current_Line_Length), + Format_Options, + Format_State.Current_Line_Length), Mode, Document.Bare_Document.Command.Align_Contents)); when Command_Trim => - Gnatfmt_Trace.Trace ("6"); - Current_Line_Length := @ - Trim (Result); + Format_State.Current_Line_Length := + @ - Trim (Format_State.Result); + Format_State.Last_Was_Hardline := False; when Command_Group => - Gnatfmt_Trace.Trace ("7"); Process_Document_Command_Group; when Command_Fill => - Gnatfmt_Trace.Trace ("8"); Process_Document_Command_Fill; when Command_If_Break => - Gnatfmt_Trace.Trace ("9"); declare Group_Mode : constant Mode_Kind := (if Document @@ -1236,13 +1911,13 @@ package body Prettier_Ada.Documents.Implementation is .If_Break_Group_Id /= No_Symbol then - (if Group_Mode_Map.Contains + (if Format_State.Group_Mode_Map.Contains (Document .Bare_Document .Command .If_Break_Group_Id) then - Group_Mode_Map.Element + Format_State.Group_Mode_Map.Element (Document .Bare_Document .Command @@ -1263,7 +1938,6 @@ package body Prettier_Ada.Documents.Implementation is .Break_Contents; begin - Gnatfmt_Trace.Trace ("91"); if Break_Contents /= No_Document and then not (Break_Contents.Bare_Document.Kind @@ -1274,8 +1948,7 @@ package body Prettier_Ada.Documents.Implementation is .Text .Is_Empty) then - Gnatfmt_Trace.Trace ("911"); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Indentation, Mode, @@ -1292,7 +1965,6 @@ package body Prettier_Ada.Documents.Implementation is .Flat_Contents; begin - Gnatfmt_Trace.Trace ("92"); if Flat_Contents /= No_Document and then not (Flat_Contents.Bare_Document.Kind @@ -1304,8 +1976,7 @@ package body Prettier_Ada.Documents.Implementation is .Is_Empty) then - Gnatfmt_Trace.Trace ("921"); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Indentation, Mode, @@ -1319,7 +1990,6 @@ package body Prettier_Ada.Documents.Implementation is end; when Command_Indent_If_Break => - Gnatfmt_Trace.Trace ("10"); declare Group_Mode : constant Mode_Kind := (if Document @@ -1327,13 +1997,13 @@ package body Prettier_Ada.Documents.Implementation is .Command .Indent_If_Break_Group_Id /= No_Symbol - and then Group_Mode_Map.Contains + and then Format_State.Group_Mode_Map.Contains (Document .Bare_Document .Command .Indent_If_Break_Group_Id) then - Group_Mode_Map.Element + Format_State.Group_Mode_Map.Element (Document .Bare_Document .Command @@ -1362,9 +2032,7 @@ package body Prettier_Ada.Documents.Implementation is .Indent_If_Break_Contents)); begin - Gnatfmt_Trace.Trace ("101"); - Gnatfmt_Trace.Trace ("1011"); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Indentation, Mode, @@ -1387,9 +2055,7 @@ package body Prettier_Ada.Documents.Implementation is .Indent_If_Break_Contents); begin - Gnatfmt_Trace.Trace ("102"); - Gnatfmt_Trace.Trace ("1021"); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Indentation, Mode, @@ -1402,8 +2068,7 @@ package body Prettier_Ada.Documents.Implementation is end; when Command_Line_Suffix => - Gnatfmt_Trace.Trace ("11"); - Line_Suffix.Append + Format_State.Line_Suffix.Append (Print_Command_Type' (Indentation, Mode, @@ -1413,10 +2078,8 @@ package body Prettier_Ada.Documents.Implementation is .Line_Suffix_Contents)); when Command_Line_Suffix_Boundary => - Gnatfmt_Trace.Trace ("12"); - if not Line_Suffix.Is_Empty then - Gnatfmt_Trace.Trace ("121"); - Print_Commands.Append + if not Format_State.Line_Suffix.Is_Empty then + Format_State.Print_Commands.Append (Print_Command_Type' (Indentation, Mode, @@ -1430,41 +2093,40 @@ package body Prettier_Ada.Documents.Implementation is Process_Document_Command_Line; when Command_Label => - Gnatfmt_Trace.Trace ("14"); - Print_Commands.Append + Format_State.Print_Commands.Append (Print_Command_Type' (Indentation, Mode, Document.Bare_Document.Command.Label_Contents)); when Command_Break_Parent => - Gnatfmt_Trace.Trace ("15"); null; when Command_Alignment_Table => - raise Program_Error with "TODO"; + Process_Document_Command_Alignment_Table; + + when Command_Alignment_Table_Separator => + Process_Document_Command_Alignment_Table_Separator; end case; end case; - if Print_Commands.Length = 0 and Line_Suffix.Length > 0 then - for Suffix of reverse Line_Suffix loop - Print_Commands.Append (Suffix); + if Format_State.Print_Commands.Length = 0 + and Format_State.Line_Suffix.Length > 0 + then + for Suffix of reverse Format_State.Line_Suffix loop + Format_State.Print_Commands.Append (Suffix); end loop; - Line_Suffix.Clear; + Format_State.Line_Suffix.Clear; end if; end; end loop; Prettier_Ada.Documents.Builders.Reset_Document_Id; - return - (Result.Text, - Current_Line_Length); - exception when others => Prettier_Ada.Documents.Builders.Reset_Document_Id; - return (VSS.Strings.Empty_Virtual_String, 0); + raise; end Format; ---------- @@ -1783,8 +2445,6 @@ package body Prettier_Ada.Documents.Implementation is is begin - Gnatfmt_Trace.Trace ("PonEnter"); - Gnatfmt_Trace.Trace (Already_Visited.Length'Image); if Document = No_Document then return Optional_Boolean'(Is_Set => False); end if; @@ -1793,19 +2453,15 @@ package body Prettier_Ada.Documents.Implementation is when Document_Command => case Document.Bare_Document.Command.Kind is when Command_Break_Parent => - Gnatfmt_Trace.Trace ("PonEnter2"); Break_Parent_Group (Group_Stack); when Command_Group => - Gnatfmt_Trace.Trace ("PonEnter3"); Group_Stack.Append (Document); if Already_Visited.Contains (Document) then - Gnatfmt_Trace.Trace ("PonEnter4"); return Optional_Boolean' (Is_Set => True, Value => False); end if; - Gnatfmt_Trace.Trace ("PInsert"); Already_Visited.Insert (Document); when others => @@ -1828,7 +2484,6 @@ package body Prettier_Ada.Documents.Implementation is return Optional_Boolean is begin - Gnatfmt_Trace.Trace ("PonExit"); if Document = No_Document then return Optional_Boolean'(Is_Set => False); end if; @@ -1836,7 +2491,6 @@ package body Prettier_Ada.Documents.Implementation is case Document.Bare_Document.Kind is when Document_Command => if Document.Bare_Document.Command.Kind in Command_Group then - Gnatfmt_Trace.Trace ("PonExit1"); declare Group : constant Document_Type := Group_Stack.Last_Element; @@ -1844,7 +2498,6 @@ package body Prettier_Ada.Documents.Implementation is begin Group_Stack.Delete_Last; if Group.Bare_Document.Command.Break then - Gnatfmt_Trace.Trace ("PonExit2"); Break_Parent_Group (Group_Stack); end if; end; @@ -2007,7 +2660,6 @@ package body Prettier_Ada.Documents.Implementation is begin while Doc_Stack.Length > 0 loop - Gnatfmt_Trace.Trace ("TLen" & Doc_Stack.Length'Image); declare Doc : constant Document_Type := Doc_Stack.Last_Element; @@ -2015,7 +2667,6 @@ package body Prettier_Ada.Documents.Implementation is Doc_Stack.Delete_Last; if Doc = Traverse_Doc_On_Exit_Stack_Marker then - Gnatfmt_Trace.Trace ("T1"); declare Doc : constant Document_Type := Doc_Stack.Last_Element; Ignore : constant Optional_Boolean := On_Exit (Doc); @@ -2028,7 +2679,6 @@ package body Prettier_Ada.Documents.Implementation is end if; if On_Exit /= null then - Gnatfmt_Trace.Trace ("T2"); Doc_Stack.Append (Doc); Doc_Stack.Append (Traverse_Doc_On_Exit_Stack_Marker); end if; @@ -2042,7 +2692,6 @@ package body Prettier_Ada.Documents.Implementation is if On_Enter_Result.Is_Set and then not On_Enter_Result.Value then - Gnatfmt_Trace.Trace ("T4"); goto Continue; end if; end; @@ -2050,11 +2699,9 @@ package body Prettier_Ada.Documents.Implementation is case Doc.Bare_Document.Kind is when Document_Text => - Gnatfmt_Trace.Trace ("T10"); null; when Document_List => - Gnatfmt_Trace.Trace ("T5"); declare Documents : constant Document_Vector := Doc.Bare_Document.List; @@ -2069,7 +2716,6 @@ package body Prettier_Ada.Documents.Implementation is when Document_Command => case Doc.Bare_Document.Command.Kind is when Command_Align => - Gnatfmt_Trace.Trace ("T9"); Ada.Assertions.Assert (Doc.Bare_Document.Command.Align_Contents /= No_Document); @@ -2077,7 +2723,6 @@ package body Prettier_Ada.Documents.Implementation is (Doc.Bare_Document.Command.Align_Contents); when Command_Indent => - Gnatfmt_Trace.Trace ("T9"); Ada.Assertions.Assert (Doc.Bare_Document.Command.Indent_Contents /= No_Document); @@ -2085,7 +2730,6 @@ package body Prettier_Ada.Documents.Implementation is (Doc.Bare_Document.Command.Indent_Contents); when Command_Indent_If_Break => - Gnatfmt_Trace.Trace ("T9"); Ada.Assertions.Assert (Doc.Bare_Document.Command.Indent_If_Break_Contents /= No_Document); @@ -2096,7 +2740,6 @@ package body Prettier_Ada.Documents.Implementation is .Indent_If_Break_Contents); when Command_Label => - Gnatfmt_Trace.Trace ("T9"); Ada.Assertions.Assert (Doc.Bare_Document.Command.Label_Contents /= No_Document); @@ -2104,7 +2747,6 @@ package body Prettier_Ada.Documents.Implementation is (Doc.Bare_Document.Command.Label_Contents); when Command_Line_Suffix => - Gnatfmt_Trace.Trace ("T9"); Ada.Assertions.Assert (Doc.Bare_Document.Command.Line_Suffix_Contents /= No_Document); @@ -2112,7 +2754,6 @@ package body Prettier_Ada.Documents.Implementation is (Doc.Bare_Document.Command.Line_Suffix_Contents); when Command_Fill => - Gnatfmt_Trace.Trace ("T5"); Ada.Assertions.Assert (Doc.Bare_Document.Command.Parts.Bare_Document /= null @@ -2137,7 +2778,6 @@ package body Prettier_Ada.Documents.Implementation is end; when Command_Group => - Gnatfmt_Trace.Trace ("T8"); if Should_Traverse_Conditional_Groups and Doc .Bare_Document @@ -2145,7 +2785,6 @@ package body Prettier_Ada.Documents.Implementation is .Expanded_States /= No_Document then - Gnatfmt_Trace.Trace ("T11"); Ada.Assertions.Assert (Doc .Bare_Document @@ -2165,14 +2804,12 @@ package body Prettier_Ada.Documents.Implementation is begin for State of reverse Expanded_States loop - Gnatfmt_Trace.Trace ("T13"); Ada.Assertions.Assert (State /= No_Document); Doc_Stack.Append (State); end loop; end; else - Gnatfmt_Trace.Trace ("T14"); Ada.Assertions.Assert (Doc.Bare_Document.Command.Group_Contents /= No_Document); @@ -2181,7 +2818,6 @@ package body Prettier_Ada.Documents.Implementation is end if; when Command_If_Break => - Gnatfmt_Trace.Trace ("T7"); Ada.Assertions.Assert (Doc.Bare_Document.Command.Flat_Contents /= No_Document); @@ -2198,11 +2834,77 @@ package body Prettier_Ada.Documents.Implementation is | Command_Line | Command_Line_Suffix_Boundary | Command_Trim => - Gnatfmt_Trace.Trace ("T10"); null; when Command_Alignment_Table => - raise Program_Error with "TODO"; + for Row_Index + in Doc + .Bare_Document + .Command + .Alignment_Table_Elements + .First_Index + .. Doc + .Bare_Document + .Command + .Alignment_Table_Elements + .Last_Index + loop + declare + First_Column_Index : constant Positive := + Doc + .Bare_Document + .Command + .Alignment_Table_Elements + .Constant_Reference (Row_Index) + .Last_Index; + Last_Column_Index : constant Positive := + Doc + .Bare_Document + .Command + .Alignment_Table_Elements + .Constant_Reference (Row_Index) + .Last_Index; + + begin + Doc_Stack.Append + (Doc + .Bare_Document + .Command + .Alignment_Table_Elements + .Constant_Reference + (Row_Index) + .Constant_Reference + (Last_Column_Index)); + + for Column_Index + in reverse First_Column_Index + .. Standard."-" + (Last_Column_Index, 1) + loop + Doc_Stack.Append + (Doc + .Bare_Document + .Command + .Alignment_Table_Separators + .Constant_Reference + (Row_Index) + .Constant_Reference + (Column_Index)); + Doc_Stack.Append + (Doc + .Bare_Document + .Command + .Alignment_Table_Elements + .Constant_Reference + (Row_Index) + .Constant_Reference + (Column_Index)); + end loop; + end; + end loop; + + when Command_Alignment_Table_Separator => + null; end case; end case; diff --git a/src/prettier_ada-documents-implementation.ads b/src/prettier_ada-documents-implementation.ads index 73b3abb..bc4e257 100644 --- a/src/prettier_ada-documents-implementation.ads +++ b/src/prettier_ada-documents-implementation.ads @@ -33,19 +33,6 @@ private package Prettier_Ada.Documents.Implementation is return Ada.Strings.Unbounded.Unbounded_String; -- Formats Document with the given Options - type Format_Result_Type is - record - Formatted_Document : VSS.Strings.Virtual_String; - Last_Line_Length : Natural; - end record; - - function Format - (Document : Document_Type; - Options : Format_Options_Type := Default_Format_Options; - Initial_Line_Length : Natural := 0) - return Format_Result_Type; - -- Formats Document with the given Options - function New_Symbol return Symbol_Type; -- Returns a new Symbol_Type, used to uniquely identify parent -- Command_Group documents. @@ -83,6 +70,10 @@ private package Prettier_Ada.Documents.Implementation is (Text : Ada.Strings.Unbounded.Unbounded_String) return Prettier_String; -- Converts an Unbounded_String into a Prettier_String + subtype Document_Vector is Prettier_Ada.Document_Vectors.Vector; + + subtype Document_Table is Prettier_Ada.Document_Vector_Vectors.Vector; + type Command_Kind is (Command_Align, Command_Break_Parent, @@ -97,7 +88,8 @@ private package Prettier_Ada.Documents.Implementation is Command_Line_Suffix, Command_Line_Suffix_Boundary, Command_Trim, - Command_Alignment_Table); + Command_Alignment_Table, + Command_Alignment_Table_Separator); type Command_Type (Kind : Command_Kind) is record case Kind is @@ -152,7 +144,12 @@ private package Prettier_Ada.Documents.Implementation is null; when Command_Alignment_Table => - Rows : Prettier_Ada.Document_Vector_Vectors.Vector; + Alignment_Table_Elements : Document_Table; + Alignment_Table_Separators : Document_Table; + Alignment_Table_Must_Break : Boolean; + + when Command_Alignment_Table_Separator => + Alignment_Table_Separator_Text : Prettier_String; end case; end record; diff --git a/src/prettier_ada-documents-json.adb b/src/prettier_ada-documents-json.adb index 57a2791..a65c978 100644 --- a/src/prettier_ada-documents-json.adb +++ b/src/prettier_ada-documents-json.adb @@ -3,6 +3,7 @@ -- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -- +with Ada.Assertions; with Ada.Containers; with Ada.Containers.Hashed_Maps; @@ -14,9 +15,32 @@ with GNATCOLL.JSON; with Prettier_Ada.Documents.Implementation; use Prettier_Ada.Documents.Implementation; with Prettier_Ada.Document_Vectors; +with Prettier_Ada.Document_Vector_Vectors; package body Prettier_Ada.Documents.Json is subtype Document_Vector is Prettier_Ada.Document_Vectors.Vector; + subtype Document_Table is Prettier_Ada.Document_Vector_Vectors.Vector; + + function Assert_Equal (Actual, Expected : Command_Kind) return Boolean; + -- Returns True is Actual = Expected, else raises an Assertion_Error. + + ------------------- + -- Assert_Equal -- + ------------------- + + function Assert_Equal (Actual, Expected : Command_Kind) return Boolean + is + begin + Ada.Assertions.Assert + (Actual = Expected, + "Unexpected Command_Type. Actual: """ + & Actual'Image + & """. Expected: """ + & Expected'Image + & """."); + + return True; + end Assert_Equal; function Wrap_Command (Command : Command_Access; Id : Natural) return Document_Type @@ -44,6 +68,9 @@ package body Prettier_Ada.Documents.Json is function From_Document_List (List : Document_Vector) return JSON_Value; -- Serialize a document list + function From_Document_Table (Table : Document_Table) return JSON_Value; + -- Serialize a document table + function From_Command (Command : Command_Type) return JSON_Value; -- Serialize a command @@ -92,6 +119,20 @@ package body Prettier_Ada.Documents.Json is return Create (Elements); end From_Document_List; + ------------------------- + -- From_Document_Table -- + ------------------------- + + function From_Document_Table (Table : Document_Table) return JSON_Value + is + Elements : JSON_Array; + begin + for Row of Table loop + Append (Elements, From_Document_List (Row)); + end loop; + return Create (Elements); + end From_Document_Table; + ------------------ -- From_Command -- ------------------ @@ -217,7 +258,22 @@ package body Prettier_Ada.Documents.Json is Result.Set_Field ("command", "trim"); when Command_Alignment_Table => - raise Program_Error with "TODO"; + Result.Set_Field ("kind", "alignmentTable"); + Result.Set_Field + ("elements", + From_Document_Table (Command.Alignment_Table_Elements)); + Result.Set_Field + ("separators", + From_Document_Table (Command.Alignment_Table_Separators)); + Result.Set_Field + ("mustBreak", Command.Alignment_Table_Must_Break); + + when Command_Alignment_Table_Separator => + Result.Set_Field ("kind", "alignmentTableSeparator"); + Result.Set_Field + ("text", + VSS.Strings.Conversions.To_UTF_8_String + (Command.Alignment_Table_Separator_Text.Text)); end case; return Result; @@ -371,6 +427,22 @@ package body Prettier_Ada.Documents.Json is -- TODO: Add description -- TODO: Add Pre and Post contracts + function To_Command_Alignment_Table + (Json : GNATCOLL.JSON.JSON_Value) + return Command_Type + with Post => Assert_Equal + (To_Command_Alignment_Table'Result.Kind, + Command_Alignment_Table); + -- Decodes Json as a Alignment_Table command + + function To_Command_Alignment_Table_Separator + (Json : GNATCOLL.JSON.JSON_Value) + return Command_Type + with Post => Assert_Equal + (To_Command_Alignment_Table_Separator'Result.Kind, + Command_Alignment_Table_Separator); + -- Decodes Json as a Alignment_Table_Separator command + ---------------------- -- To_Document_Text -- ---------------------- @@ -497,6 +569,18 @@ package body Prettier_Ada.Documents.Json is return Wrap_Command (new Command_Type'(To_Command_Trim (Json)), Id); + elsif Command_Text = "alignmentTable" then + return + Wrap_Command + (new Command_Type'(To_Command_Alignment_Table (Json)), Id); + + elsif Command_Text = "alignmentTableSeparator" then + return + Wrap_Command + (new Command_Type' + (To_Command_Alignment_Table_Separator (Json)), + Id); + else -- TODO: Raise a better exception raise Program_Error; @@ -782,6 +866,87 @@ package body Prettier_Ada.Documents.Json is return (Kind => Command_Trim); end To_Command_Trim; + -------------------------------- + -- To_Command_Alignment_Table -- + -------------------------------- + + function To_Command_Alignment_Table + (Json : GNATCOLL.JSON.JSON_Value) + return Command_Type + is + function To_Document_Table + (Json_Table : GNATCOLL.JSON.JSON_Value) + return Document_Table; + -- TODO: Add description + -- TODO: Add Pre and Post contracts + + ----------------------- + -- To_Document_Table -- + ----------------------- + + function To_Document_Table + (Json_Table : GNATCOLL.JSON.JSON_Value) + return Document_Table + is + Table : Document_Table; + + Rows : constant JSON_Array := Get (Json_Table); + Total_Rows : constant Natural := GNATCOLL.JSON.Length (Rows); + + begin + for Row_Index in 1 .. Total_Rows loop + declare + Current_Row : constant JSON_Array := + Get (Get (Rows, Row_Index)); + Total_Columns : constant Natural := + GNATCOLL.JSON.Length (Current_Row); + + Row : Document_Vector; + + begin + for Column_Index in 1 .. Total_Columns loop + Row.Append + (To_Document_Type (Get (Current_Row, Column_Index))); + end loop; + + Table.Append (Row); + end; + end loop; + + return Table; + end To_Document_Table; + + begin + return + Command_Type' + (Kind => Command_Alignment_Table, + Alignment_Table_Elements => + To_Document_Table (Get (Json, "elements")), + Alignment_Table_Separators => + To_Document_Table (Get (Json, "separators")), + Alignment_Table_Must_Break => Get (Json, "mustBreak")); + end To_Command_Alignment_Table; + + -------------------------------- + -- To_Command_Alignment_Table -- + -------------------------------- + + function To_Command_Alignment_Table_Separator + (Json : GNATCOLL.JSON.JSON_Value) + return Command_Type + is + Text : constant VSS.Strings.Virtual_String := + VSS.Strings.Conversions.To_Virtual_String + (UTF8_String'(Get (Json, "text"))); + Display_Width : constant VSS.Strings.Display_Cell_Count := + VSS.Strings.Utilities.Display_Width (Text); + begin + return + Command_Type' + (Kind => Command_Alignment_Table_Separator, + Alignment_Table_Separator_Text => (Text, Display_Width)); + end To_Command_Alignment_Table_Separator; + begin case Kind (Json) is when JSON_Boolean_Type diff --git a/src/prettier_ada.ads b/src/prettier_ada.ads index 8144662..5a87b2e 100644 --- a/src/prettier_ada.ads +++ b/src/prettier_ada.ads @@ -1,5 +1,5 @@ -- --- Copyright (C) 2023, AdaCore +-- Copyright (C) 2023-2024, AdaCore -- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -- @@ -9,7 +9,7 @@ with GNATCOLL.Traces; package Prettier_Ada is - Gnatfmt_Trace : GNATCOLL.Traces.Trace_Handle := + Prettier_Ada_Trace : GNATCOLL.Traces.Trace_Handle := GNATCOLL.Traces.Create ("PRETTIER_ADA", GNATCOLL.Traces.Off); Version : constant String := "debug"; diff --git a/testsuite/test_programs/src/builders_tester.adb b/testsuite/test_programs/src/builders_tester.adb index 610c469..4b925f6 100644 --- a/testsuite/test_programs/src/builders_tester.adb +++ b/testsuite/test_programs/src/builders_tester.adb @@ -22,6 +22,13 @@ procedure Builders_Tester is procedure Test_Align; -- Builds a Document_Type using the Align builder + procedure Test_Alignment_Table; + -- Builds multiple Document_Type objects using the Alignment_Table builder + + procedure Test_Alignment_Table_Separator; + -- Builds multiple Document_Type objects using the + -- Alignment_Table_Separator builder + procedure Test_Break_Parent; -- Builds a Document_Type using the Break_Parent builder @@ -134,6 +141,136 @@ procedure Builders_Tester is New_Line; end Test_Align; + -------------------------- + -- Test_Alignment_Table -- + -------------------------- + + procedure Test_Alignment_Table + is + function "+" (Source : String) return Document_Type + is (Alignment_Table_Separator (To_Unbounded_String (Source))); + -- Converts Source into a Table_Separator command + + function Build_Table return Document_Type; + -- Creates a compex testing table + + ------------------ + -- Build_Table -- + ------------------ + + function Build_Table return Document_Type + is + Group_1 : constant Symbol_Type := New_Symbol; + Group_2 : constant Symbol_Type := New_Symbol; + Group_3 : constant Symbol_Type := New_Symbol; + Group_4 : constant Symbol_Type := New_Symbol; + + Table : constant Document_Type := + Alignment_Table + ([[Hard_Line_Without_Break_Parent, + -- This line break tests that trailing spaces before a table + -- are removed + "A ", + +":", + Group (Indent (List ([Line, "B "])), Group_1), + +":=", + If_Break + (Indent (Indent (Group ([Line, "C", ";"]))), + Indent (Group ([Line, "C", ";"])), + (Group_Id => Group_1))], + ["AA ", + +":", + Group (Indent (List ([Line, "BB "])), Group_2), + +":=", + If_Break + (Indent (Indent (Group ([Line, "CC", ";"]))), + Indent (Group ([Line, "CC", ";"])), + (Group_Id => Group_2))], + ["AAA ", + +":", + Group (Indent (List ([Line, "BBBBBBBBB;"])), Group_3)], + -- BBBBBBBBB tests that it does not affect other separators + ["AAAA ", + +":", + Group (Indent (List ([Line, "BBBB "])), Group_4), + +":=", + If_Break + (Indent (Indent (Group ([Line, "CCCC", ";"]))), + Indent (Group ([Line, "CCCC", ";"])), + (Group_Id => Group_4))]]); + + Table_Wrapper : constant Document_Type := + Group + (["record", + Indent + (List + ([Hard_Line_Without_Break_Parent, + Table])), + Hard_Line_Without_Break_Parent, + "end record"]); + + begin + return Table_Wrapper; + end Build_Table; + + Alignment_Table_1 : constant Document_Type := Build_Table; + Alignment_Table_2 : constant Document_Type := Build_Table; + + begin + Put_Line ("=== Alignment_Table ==="); + + -- Test table alignment without line breaks + + Put_Line ("> Alignment_Table_1 Document JSON:"); + Put_Line (Serialize (Alignment_Table_1)); + Put_Line ("> Alignment_Table_1 Document Formatted:"); + Put_Line (Format (Alignment_Table_1)); + + -- Test table alignment with all line breaks + + Put_Line ("> Alignment_Table_2 Document JSON:"); + Put_Line (Serialize (Alignment_Table_2)); + Put_Line ("> Alignment_Table_2 Document Formatted:"); + Put_Line + (Format + (Alignment_Table_2, + (Width => 1, + Indentation => + (Kind => Spaces, + Width => 2, + Offset => (Spaces => 0, Tabs => 0)), + End_Of_Line => LF))); + New_Line; + end Test_Alignment_Table; + + ------------------------------------ + -- Test_Alignment_Table_Separator -- + ------------------------------------ + + procedure Test_Alignment_Table_Separator + is + Document : constant Document_Type := + List + (["A", + " ", + Alignment_Table_Separator (To_Unbounded_String (":")), + " ", + "B", + " ", + Alignment_Table_Separator (To_Unbounded_String (":=")), + " ", + "C", + ";"]); + + begin + Put_Line ("=== Alignment_Table_Separator ==="); + Put_Line ("> Alignment_Table_Separator Document JSON:"); + Put_Line (Serialize (Document)); + Put_Line ("> Alignment_Table_Separator Document Formatted:"); + Put_Line (Format (Document)); + New_Line; + end Test_Alignment_Table_Separator; + ------------------------ -- Test_Break_Parent -- ------------------------ @@ -594,6 +731,8 @@ begin -- Run all the test procedures Test_Align; + Test_Alignment_Table; + Test_Alignment_Table_Separator; Test_Break_Parent; Test_Cursor; Test_Fill; diff --git a/testsuite/tests/builders/test.out b/testsuite/tests/builders/test.out index 344113a..9c5e0c7 100644 --- a/testsuite/tests/builders/test.out +++ b/testsuite/tests/builders/test.out @@ -202,6 +202,1388 @@ begin AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(BBBBBBBBBBBBBBBBBBBB, CCCCCCCCCCCCCCCCCCCC) +=== Alignment_Table === +> Alignment_Table_1 Document JSON: +{ + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 83, + "kind": "list", + "list": [ + { + "id": 77, + "kind": "text", + "text": "record" + }, + { + "command": { + "command": "indent", + "indentContents": { + "id": 79, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": true, + "literal": false, + "soft": false + }, + "id": 78, + "kind": "command" + }, + { + "command": { + "elements": [ + [ + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 74, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": true, + "literal": false, + "soft": false + }, + "id": 0, + "kind": "command" + }, + { + "id": 1, + "kind": "text", + "text": "A " + } + ] + }, + "id": 0 + }, + "id": 75, + "kind": "command" + }, + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "command": { + "command": "indent", + "indentContents": { + "id": 5, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 3, + "kind": "command" + }, + { + "id": 4, + "kind": "text", + "text": "B " + } + ] + } + }, + "id": 6, + "kind": "command" + }, + "id": 1 + }, + "id": 7, + "kind": "command" + }, + { + "command": { + "breakContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 12, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 9, + "kind": "command" + }, + { + "id": 10, + "kind": "text", + "text": "C" + }, + { + "id": 11, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 13, + "kind": "command" + } + }, + "id": 14, + "kind": "command" + } + }, + "id": 15, + "kind": "command" + }, + "command": "ifBreak", + "flatContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 19, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 16, + "kind": "command" + }, + { + "id": 17, + "kind": "text", + "text": "C" + }, + { + "id": 18, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 20, + "kind": "command" + } + }, + "id": 21, + "kind": "command" + }, + "ifBreakGroupId": 1 + }, + "id": 22, + "kind": "command" + } + ], + [ + { + "id": 23, + "kind": "text", + "text": "AA " + }, + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "command": { + "command": "indent", + "indentContents": { + "id": 27, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 25, + "kind": "command" + }, + { + "id": 26, + "kind": "text", + "text": "BB " + } + ] + } + }, + "id": 28, + "kind": "command" + }, + "id": 2 + }, + "id": 29, + "kind": "command" + }, + { + "command": { + "breakContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 34, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 31, + "kind": "command" + }, + { + "id": 32, + "kind": "text", + "text": "CC" + }, + { + "id": 33, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 35, + "kind": "command" + } + }, + "id": 36, + "kind": "command" + } + }, + "id": 37, + "kind": "command" + }, + "command": "ifBreak", + "flatContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 41, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 38, + "kind": "command" + }, + { + "id": 39, + "kind": "text", + "text": "CC" + }, + { + "id": 40, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 42, + "kind": "command" + } + }, + "id": 43, + "kind": "command" + }, + "ifBreakGroupId": 2 + }, + "id": 44, + "kind": "command" + } + ], + [ + { + "id": 45, + "kind": "text", + "text": "AAA " + }, + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "command": { + "command": "indent", + "indentContents": { + "id": 49, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 47, + "kind": "command" + }, + { + "id": 48, + "kind": "text", + "text": "BBBBBBBBB;" + } + ] + } + }, + "id": 50, + "kind": "command" + }, + "id": 3 + }, + "id": 51, + "kind": "command" + } + ], + [ + { + "id": 52, + "kind": "text", + "text": "AAAA " + }, + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "command": { + "command": "indent", + "indentContents": { + "id": 56, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 54, + "kind": "command" + }, + { + "id": 55, + "kind": "text", + "text": "BBBB " + } + ] + } + }, + "id": 57, + "kind": "command" + }, + "id": 4 + }, + "id": 58, + "kind": "command" + }, + { + "command": { + "breakContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 63, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 60, + "kind": "command" + }, + { + "id": 61, + "kind": "text", + "text": "CCCC" + }, + { + "id": 62, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 64, + "kind": "command" + } + }, + "id": 65, + "kind": "command" + } + }, + "id": 66, + "kind": "command" + }, + "command": "ifBreak", + "flatContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 70, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 67, + "kind": "command" + }, + { + "id": 68, + "kind": "text", + "text": "CCCC" + }, + { + "id": 69, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 71, + "kind": "command" + } + }, + "id": 72, + "kind": "command" + }, + "ifBreakGroupId": 4 + }, + "id": 73, + "kind": "command" + } + ] + ], + "kind": "alignmentTable", + "mustBreak": true, + "separators": [ + [ + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":" + }, + "id": 2, + "kind": "command" + }, + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":=" + }, + "id": 8, + "kind": "command" + } + ], + [ + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":" + }, + "id": 24, + "kind": "command" + }, + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":=" + }, + "id": 30, + "kind": "command" + } + ], + [ + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":" + }, + "id": 46, + "kind": "command" + } + ], + [ + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":" + }, + "id": 53, + "kind": "command" + }, + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":=" + }, + "id": 59, + "kind": "command" + } + ] + ] + }, + "id": 76, + "kind": "command" + } + ] + } + }, + "id": 80, + "kind": "command" + }, + { + "command": { + "command": "line", + "hard": true, + "literal": false, + "soft": false + }, + "id": 81, + "kind": "command" + }, + { + "id": 82, + "kind": "text", + "text": "end record" + } + ] + }, + "id": 0 + }, + "id": 84, + "kind": "command" +} +> Alignment_Table_1 Document Formatted: +record + + A : B := C; + AA : BB := CC; + AAA : BBBBBBBBB; + AAAA : BBBB := CCCC; +end record +> Alignment_Table_2 Document JSON: +{ + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 168, + "kind": "list", + "list": [ + { + "id": 162, + "kind": "text", + "text": "record" + }, + { + "command": { + "command": "indent", + "indentContents": { + "id": 164, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": true, + "literal": false, + "soft": false + }, + "id": 163, + "kind": "command" + }, + { + "command": { + "elements": [ + [ + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 159, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": true, + "literal": false, + "soft": false + }, + "id": 85, + "kind": "command" + }, + { + "id": 86, + "kind": "text", + "text": "A " + } + ] + }, + "id": 0 + }, + "id": 160, + "kind": "command" + }, + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "command": { + "command": "indent", + "indentContents": { + "id": 90, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 88, + "kind": "command" + }, + { + "id": 89, + "kind": "text", + "text": "B " + } + ] + } + }, + "id": 91, + "kind": "command" + }, + "id": 5 + }, + "id": 92, + "kind": "command" + }, + { + "command": { + "breakContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 97, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 94, + "kind": "command" + }, + { + "id": 95, + "kind": "text", + "text": "C" + }, + { + "id": 96, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 98, + "kind": "command" + } + }, + "id": 99, + "kind": "command" + } + }, + "id": 100, + "kind": "command" + }, + "command": "ifBreak", + "flatContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 104, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 101, + "kind": "command" + }, + { + "id": 102, + "kind": "text", + "text": "C" + }, + { + "id": 103, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 105, + "kind": "command" + } + }, + "id": 106, + "kind": "command" + }, + "ifBreakGroupId": 5 + }, + "id": 107, + "kind": "command" + } + ], + [ + { + "id": 108, + "kind": "text", + "text": "AA " + }, + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "command": { + "command": "indent", + "indentContents": { + "id": 112, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 110, + "kind": "command" + }, + { + "id": 111, + "kind": "text", + "text": "BB " + } + ] + } + }, + "id": 113, + "kind": "command" + }, + "id": 6 + }, + "id": 114, + "kind": "command" + }, + { + "command": { + "breakContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 119, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 116, + "kind": "command" + }, + { + "id": 117, + "kind": "text", + "text": "CC" + }, + { + "id": 118, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 120, + "kind": "command" + } + }, + "id": 121, + "kind": "command" + } + }, + "id": 122, + "kind": "command" + }, + "command": "ifBreak", + "flatContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 126, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 123, + "kind": "command" + }, + { + "id": 124, + "kind": "text", + "text": "CC" + }, + { + "id": 125, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 127, + "kind": "command" + } + }, + "id": 128, + "kind": "command" + }, + "ifBreakGroupId": 6 + }, + "id": 129, + "kind": "command" + } + ], + [ + { + "id": 130, + "kind": "text", + "text": "AAA " + }, + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "command": { + "command": "indent", + "indentContents": { + "id": 134, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 132, + "kind": "command" + }, + { + "id": 133, + "kind": "text", + "text": "BBBBBBBBB;" + } + ] + } + }, + "id": 135, + "kind": "command" + }, + "id": 7 + }, + "id": 136, + "kind": "command" + } + ], + [ + { + "id": 137, + "kind": "text", + "text": "AAAA " + }, + { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "command": { + "command": "indent", + "indentContents": { + "id": 141, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 139, + "kind": "command" + }, + { + "id": 140, + "kind": "text", + "text": "BBBB " + } + ] + } + }, + "id": 142, + "kind": "command" + }, + "id": 8 + }, + "id": 143, + "kind": "command" + }, + { + "command": { + "breakContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 148, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 145, + "kind": "command" + }, + { + "id": 146, + "kind": "text", + "text": "CCCC" + }, + { + "id": 147, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 149, + "kind": "command" + } + }, + "id": 150, + "kind": "command" + } + }, + "id": 151, + "kind": "command" + }, + "command": "ifBreak", + "flatContents": { + "command": { + "command": "indent", + "indentContents": { + "command": { + "break": false, + "command": "group", + "expandedStates": null, + "groupContents": { + "id": 155, + "kind": "list", + "list": [ + { + "command": { + "command": "line", + "hard": false, + "literal": false, + "soft": false + }, + "id": 152, + "kind": "command" + }, + { + "id": 153, + "kind": "text", + "text": "CCCC" + }, + { + "id": 154, + "kind": "text", + "text": ";" + } + ] + }, + "id": 0 + }, + "id": 156, + "kind": "command" + } + }, + "id": 157, + "kind": "command" + }, + "ifBreakGroupId": 8 + }, + "id": 158, + "kind": "command" + } + ] + ], + "kind": "alignmentTable", + "mustBreak": true, + "separators": [ + [ + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":" + }, + "id": 87, + "kind": "command" + }, + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":=" + }, + "id": 93, + "kind": "command" + } + ], + [ + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":" + }, + "id": 109, + "kind": "command" + }, + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":=" + }, + "id": 115, + "kind": "command" + } + ], + [ + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":" + }, + "id": 131, + "kind": "command" + } + ], + [ + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":" + }, + "id": 138, + "kind": "command" + }, + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":=" + }, + "id": 144, + "kind": "command" + } + ] + ] + }, + "id": 161, + "kind": "command" + } + ] + } + }, + "id": 165, + "kind": "command" + }, + { + "command": { + "command": "line", + "hard": true, + "literal": false, + "soft": false + }, + "id": 166, + "kind": "command" + }, + { + "id": 167, + "kind": "text", + "text": "end record" + } + ] + }, + "id": 0 + }, + "id": 169, + "kind": "command" +} +> Alignment_Table_2 Document Formatted: +record + + A : + B := + C; + AA : + BB := + CC; + AAA : + BBBBBBBBB; + AAAA : + BBBB := + CCCC; +end record + +=== Alignment_Table_Separator === +> Alignment_Table_Separator Document JSON: +{ + "id": 10, + "kind": "list", + "list": [ + { + "id": 0, + "kind": "text", + "text": "A" + }, + { + "id": 1, + "kind": "text", + "text": " " + }, + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":" + }, + "id": 2, + "kind": "command" + }, + { + "id": 3, + "kind": "text", + "text": " " + }, + { + "id": 4, + "kind": "text", + "text": "B" + }, + { + "id": 5, + "kind": "text", + "text": " " + }, + { + "command": { + "kind": "alignmentTableSeparator", + "text": ":=" + }, + "id": 6, + "kind": "command" + }, + { + "id": 7, + "kind": "text", + "text": " " + }, + { + "id": 8, + "kind": "text", + "text": "C" + }, + { + "id": 9, + "kind": "text", + "text": ";" + } + ] +} +> Alignment_Table_Separator Document Formatted: +A : B := C; + === Break_Parent === > Break_Parent Document JSON: { @@ -270,7 +1652,7 @@ B { "command": { "command": "cursor", - "placeHolder": 1 + "placeHolder": 9 }, "id": 1, "kind": "command" @@ -512,7 +1894,7 @@ C } ] }, - "id": 2 + "id": 10 }, "id": 13, "kind": "command" @@ -624,7 +2006,7 @@ C } ] }, - "id": 3 + "id": 11 }, "id": 27, "kind": "command" @@ -715,7 +2097,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "kind": "text", "text": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" }, - "id": 4 + "id": 12 }, "id": 10, "kind": "command"