From c864eeffdacf86739e83eba3a462b2ae6baad2c3 Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Sun, 23 Jun 2024 18:27:10 +0200 Subject: [PATCH] feat: improve VSCode launch command (#1703) * Improve VSCode launch command * Refactor replacement patterns to common package --- src/alire/alire-environment-formatting.adb | 72 ++++++++++++++++++---- src/alire/alire-environment-formatting.ads | 43 ++++++++++++- src/alire/alire-environment-loading.adb | 5 +- src/alr/alr-commands-edit.adb | 45 ++++++-------- 4 files changed, 124 insertions(+), 41 deletions(-) diff --git a/src/alire/alire-environment-formatting.adb b/src/alire/alire-environment-formatting.adb index 4f8029f7a..5d7105c4f 100644 --- a/src/alire/alire-environment-formatting.adb +++ b/src/alire/alire-environment-formatting.adb @@ -1,3 +1,5 @@ +with AAA.Enum_Tools; + with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Alire.OS_Lib; @@ -5,6 +7,50 @@ with Alire.Platforms.Current; package body Alire.Environment.Formatting is + -------------- + -- Contains -- + -------------- + + overriding + function Contains (This : Replacements; Pattern : Patterns) return Boolean + is (Pattern_String_Maps.Map (This).Contains (Pattern)); + + ----------- + -- Value -- + ----------- + + function Value (This : Replacements; Pattern : Patterns) return String + is (This (Pattern)); + + ------------------------------ + -- For_Manifest_Environment -- + ------------------------------ + + function For_Manifest_Environment (Crate_Root : Any_Path) + return Replacements + is + Result : Replacements; + begin + Result.Insert (Distrib_Root, Alire.Platforms.Current.Distribution_Root); + Result.Insert (Formatting.Crate_Root, Crate_Root); + + return Result; + end For_Manifest_Environment; + + ---------------- + -- For_Editor -- + ---------------- + + function For_Editor (Root : Alire.Roots.Root; + Prj_File : Relative_Path) + return Replacements + is + Result : Replacements := For_Manifest_Environment (Root.Path); + begin + Result.Insert (GPR_File, Prj_File); + return Result; + end For_Editor; + ---------------- -- Find_Start -- ---------------- @@ -52,8 +98,9 @@ package body Alire.Environment.Formatting is -- Format -- ------------ - function Format (Release_Dir : Any_Path; - Value : String) + function Format (Item : String; + Repl : Replacements; + Is_Path : Boolean) return String is ------------- @@ -63,20 +110,16 @@ package body Alire.Environment.Formatting is procedure Replace (Str : in out Unbounded_String; From, To : Positive) is + function Is_Known is new AAA.Enum_Tools.Is_Valid (Patterns); Id : constant String := Slice (Str, From + 2, To - 1); begin - - if Id = "DISTRIB_ROOT" then - Replace_Slice (Str, From, To, Platforms.Current.Distribution_Root); - - elsif Id = "CRATE_ROOT" then - Replace_Slice - (Str, From, To, - Release_Dir); + if Is_Known (Id) then + Replace_Slice (Str, From, To, Repl (Patterns'Value (Id))); elsif Id = "_ALIRE_TEST_" then -- This is used to test the env var formatting feature Replace_Slice (Str, From, To, "TEST"); + else raise Unknown_Formatting_Key; end if; @@ -99,7 +142,7 @@ package body Alire.Environment.Formatting is return AAA.Strings.Replace (S, "/", "" & OS_Lib.Dir_Separator); end To_Native; - Result : Unbounded_String := To_Unbounded_String (Value); + Result : Unbounded_String := To_Unbounded_String (Item); From : Natural := 1; To : Natural; begin @@ -126,7 +169,12 @@ package body Alire.Environment.Formatting is end loop; -- For final usage, we use the native separator - return To_Native (+Result); + + if Is_Path then + return To_Native (+Result); + else + return +Result; + end if; end Format; end Alire.Environment.Formatting; diff --git a/src/alire/alire-environment-formatting.ads b/src/alire/alire-environment-formatting.ads index 0a28f0027..24d3d4b9e 100644 --- a/src/alire/alire-environment-formatting.ads +++ b/src/alire/alire-environment-formatting.ads @@ -1,10 +1,47 @@ +with Alire.Roots; + +private with Ada.Containers.Indefinite_Ordered_Maps; + package Alire.Environment.Formatting is - function Format (Release_Dir : Any_Path; - Value : String) + type Patterns is (Crate_Root, + Distrib_Root, + GPR_File); + -- These correspond directly with ${PATTERNs} that can be replaced + + function Dollar_Image (Pattern : Patterns) return String + is ("${" & Pattern'Image & "}"); + + type Replacements (<>) is tagged private; + + function For_Manifest_Environment (Crate_Root : Any_Path) + return Replacements; + -- Crate_Root can't be an absolute path as this may be called with relative + -- paths during build hashing. + + function For_Editor (Root : Alire.Roots.Root; + Prj_File : Relative_Path) + return Replacements; + + function Contains (This : Replacements; Pattern : Patterns) return Boolean; + + function Value (This : Replacements; Pattern : Patterns) return String + with Pre => This.Contains (Pattern); + + function Format (Item : String; + Repl : Replacements; + Is_Path : Boolean) return String; - -- Format the environment variable value with ${} replacement patterns + -- If Is_Path, a final pass is done to use platform-specific dir separators + -- Format the item with ${} replacement patterns. Unknown_Formatting_Key : exception; +private + + package Pattern_String_Maps is new + Ada.Containers.Indefinite_Ordered_Maps (Patterns, String); + + type Replacements is new Pattern_String_Maps.Map with null record; + end Alire.Environment.Formatting; diff --git a/src/alire/alire-environment-loading.adb b/src/alire/alire-environment-loading.adb index 7c2a72071..16890a0ef 100644 --- a/src/alire/alire-environment-loading.adb +++ b/src/alire/alire-environment-loading.adb @@ -122,7 +122,10 @@ package body Alire.Environment.Loading is begin declare Value : constant String := - Formatting.Format (Release_Base, Act.Value); + Formatting.Format + (Act.Value, + Formatting.For_Manifest_Environment (Release_Base), + Is_Path => True); begin case Act.Action is diff --git a/src/alr/alr-commands-edit.adb b/src/alr/alr-commands-edit.adb index dbfc1a579..95bf41821 100644 --- a/src/alr/alr-commands-edit.adb +++ b/src/alr/alr-commands-edit.adb @@ -1,16 +1,17 @@ with Ada.Containers; with Alire; use Alire; +with Alire.Environment.Formatting; with Alire.Settings.Builtins; with Alire.OS_Lib.Subprocess; with Alire.Platforms.Current; with CLIC.User_Input; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; - package body Alr.Commands.Edit is + package Format renames Alire.Environment.Formatting; + Switch_Select : constant String := "--select-editor"; -------------------- @@ -79,8 +80,10 @@ package body Alr.Commands.Edit is function Cmd (E : Editor_With_Command) return String is (case E is - when VScode => "code ${GPR_FILE}", - when GNATstudio => "gnatstudio -P ${GPR_FILE}"); + when VScode => + "code " & Format.Dollar_Image (Format.Crate_Root), + when GNATstudio => + "gnatstudio -P " & Format.Dollar_Image (Format.GPR_File)); Choices : AAA.Strings.Vector; begin @@ -114,8 +117,10 @@ package body Alr.Commands.Edit is when Other => Trace.Always ("In your custom editor command, `alr` will replace " - & TTY.Emph ("${GPR_FILE}") - & " with the corresponding project file."); + & TTY.Emph (Format.Dollar_Image (Format.Crate_Root)) + & " and " & TTY.Emph (Format.Dollar_Image (Format.GPR_File)) + & " patterns with the workspace root or project file path, " + & "respectively."); declare Custom : constant String := Query_String ("Please enter a custom editor command", @@ -131,11 +136,10 @@ package body Alr.Commands.Edit is -- Start_Editor -- ------------------ - procedure Start_Editor (Args : in out AAA.Strings.Vector; + procedure Start_Editor (Root : in out Alire.Roots.Root; + Args : in out AAA.Strings.Vector; Prj : Relative_Path) is - Pattern : constant String := "${GPR_FILE}"; - Cmd : constant String := Args.First_Element; Replaced_Args : AAA.Strings.Vector; @@ -146,20 +150,11 @@ package body Alr.Commands.Edit is for Elt of Args loop -- Replace pattern in Elt, if any - declare - Us : Unbounded_String := +Elt; - Index : Natural; - begin - Index := Ada.Strings.Unbounded.Index (Us, Pattern); - if Index /= 0 then - Replace_Slice (Us, - Low => Index, - High => Index + Pattern'Length - 1, - By => Prj); - end if; - - Replaced_Args.Append (+Us); - end; + Replaced_Args.Append + (Format.Format + (Elt, + Format.For_Editor (Root, Prj), + Is_Path => True)); end loop; Trace.Info ("Editing crate with: ['" & Cmd & "' '" & @@ -230,7 +225,7 @@ package body Alr.Commands.Edit is ("No project file to open for this crate."); elsif Project_Files.Length = 1 then - Start_Editor (Edit_Args, Project_Files.First_Element); + Start_Editor (Cmd.Root, Edit_Args, Project_Files.First_Element); elsif Cmd.Prj = null or else @@ -245,7 +240,7 @@ package body Alr.Commands.Edit is ("Please specify a project file with --project=."); else - Start_Editor (Edit_Args, Cmd.Prj.all); + Start_Editor (Cmd.Root, Edit_Args, Cmd.Prj.all); end if; end; end Execute;