From 226e9b68d4924c342280dc8c32dc7ea6c41dda3e Mon Sep 17 00:00:00 2001 From: Fabien Chouteau Date: Thu, 5 Nov 2020 18:55:43 +0100 Subject: [PATCH] Alr.Commands.Edit: add support for custom editor (#611) * Alr.Commands.Edit: add support for custom editor The editor can be changed with: $ alr config --set --global editor.cmd "emacs ${GPR_FILE} * Update user-changes.md * Typo * Typo --- doc/user-changes.md | 18 ++++++ src/alire/alire-config.ads | 9 +++ src/alr/alr-commands-edit.adb | 83 +++++++++++++++++++++----- testsuite/tests/workflows/edit/test.py | 11 ++++ 4 files changed, 105 insertions(+), 16 deletions(-) diff --git a/doc/user-changes.md b/doc/user-changes.md index f7bb1c2d..dbae8326 100644 --- a/doc/user-changes.md +++ b/doc/user-changes.md @@ -4,6 +4,24 @@ This document is a development diary summarizing changes in `alr` that notably affect the user experience. It is intended as a one-stop point for users to stay on top of `alr` new features. +### Custom editor command for `alr edit` + +PR [#611](https://github.com/alire-project/alire/pull/611). + +The code editor launched by `alr edit` can now be configured instead of using +the hard-coded GNATstudio. Use `alr config --set --global editor.cmd " +"` for custom editor and command line arguments. The token ${GPR_FILE} is +replaced by a path to the project file to open. + +For instance: +```shell +$ alr config --set --global editor.cmd "emacs ${GPR_FILE}" +``` + +The default editor is still GNATstudio. + + + ### Assistance to generate and publish as tarball PR [#529](https://github.com/alire-project/alire/pull/529). diff --git a/src/alire/alire-config.ads b/src/alire/alire-config.ads index a14ea27b..461eb731 100644 --- a/src/alire/alire-config.ads +++ b/src/alire/alire-config.ads @@ -123,6 +123,8 @@ package Alire.Config is User_Name : constant Config_Key := "user.name"; User_Github_Login : constant Config_Key := "user.github_login"; + Editor_Cmd : constant Config_Key := "editor.cmd"; + end Keys; private @@ -194,6 +196,13 @@ private +("User GitHub login/username. Used to for the maintainers-logins " & "field of a new crate.")), + (+Keys.Editor_Cmd, + Cfg_String, + +("Editor command and arguments for editing crate code (alr edit)." & + " The executables and arguments are separated by a single space" & + " character. The token ${GPR_FILE} is replaced by" & + " a path to the project file to open.")), + (+"msys2.do_not_install", Cfg_Bool, +("If true, Alire will not try to automatically" & diff --git a/src/alr/alr-commands-edit.adb b/src/alr/alr-commands-edit.adb index ee9ba86c..07668c15 100644 --- a/src/alr/alr-commands-edit.adb +++ b/src/alr/alr-commands-edit.adb @@ -3,21 +3,51 @@ with Ada.Containers; with Alire; use Alire; with Alire.Utils; use Alire.Utils; with Alire.OS_Lib.Subprocess; +with Alire.Config; with Alr.Platform; with Alr.Root; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package body Alr.Commands.Edit is - ---------------------- - -- Start_GNATstudio -- - ---------------------- + ------------------ + -- Start_Editor -- + ------------------ + + procedure Start_Editor (Args : in out String_Vector; Prj : Relative_Path) is + Pattern : constant String := "${GPR_FILE}"; - procedure Start_GNATstudio (Prj : Relative_Path) is + Cmd : constant String := Args.First_Element; + + Replaced_Args : String_Vector; begin - Alire.OS_Lib.Subprocess.Checked_Spawn - ("gnatstudio", Empty_Vector & "-P" & Prj); - end Start_GNATstudio; + + Args.Delete_First; + + 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; + end loop; + + Trace.Info ("Editing crate with: ['" & Cmd & "' '" & + Flatten (Replaced_Args, "', '") & "']"); + Alire.OS_Lib.Subprocess.Checked_Spawn (Cmd, Replaced_Args); + end Start_Editor; ------------- -- Execute -- @@ -26,20 +56,41 @@ package body Alr.Commands.Edit is overriding procedure Execute (Cmd : in out Command) is use Ada.Containers; use GNAT.Strings; + use Alire.Config; + + Editor_Cmd : constant String := + Get (Keys.Editor_Cmd, "gnatstudio -P ${GPR_FILE}"); + + Args : String_Vector := Split (Editor_Cmd, ' '); begin + if Args.Is_Empty then + Reportaise_Command_Failed + ("No editor defined in config key '" & Keys.Editor_Cmd & "'."); + end if; + Requires_Full_Index; Requires_Valid_Session; Alr.Root.Current.Export_Build_Environment; - if Alire.OS_Lib.Subprocess.Locate_In_Path ("gnatstudio") = "" then - Reportaise_Command_Failed - ("GNATstudio not available or not in PATH. " & ASCII.LF & - "You can download the Community edition at: " & ASCII.LF & - "https://www.adacore.com/download"); - return; - end if; + declare + Exec : constant String := Args.First_Element; + begin + if Alire.OS_Lib.Subprocess.Locate_In_Path (Exec) = "" then + if Exec = "gnatstudio" or else Exec = "gnatstudio.exe" then + + Reportaise_Command_Failed + ("GNATstudio not available or not in PATH. " & ASCII.LF & + "You can download the Community edition at: " & ASCII.LF & + "https://www.adacore.com/download"); + else + Reportaise_Command_Failed + ("'" & Exec & "' not available or not in PATH."); + end if; + return; + end if; + end; declare Project_Files : constant Alire.Utils.String_Vector := @@ -51,7 +102,7 @@ package body Alr.Commands.Edit is ("No project file to open for this crate."); elsif Project_Files.Length = 1 then - Start_GNATstudio (Project_Files.First_Element); + Start_Editor (Args, Project_Files.First_Element); elsif Cmd.Prj = null or else @@ -66,7 +117,7 @@ package body Alr.Commands.Edit is ("Please specify a project file with --project=."); else - Start_GNATstudio (Cmd.Prj.all); + Start_Editor (Args, Cmd.Prj.all); end if; end; end Execute; diff --git a/testsuite/tests/workflows/edit/test.py b/testsuite/tests/workflows/edit/test.py index df8fc9fc..9419b12b 100644 --- a/testsuite/tests/workflows/edit/test.py +++ b/testsuite/tests/workflows/edit/test.py @@ -26,4 +26,15 @@ else: p = run_alr('edit', complain_on_error=False) assert_match(".*Please specify a project file with --project=.*", p.out) +# Set an editor that doesn't exist (different than GNATstudio) +run_alr('config', '--set', 'editor.cmd', 'doesnt_exist arg1 ab${GPR_FILE}ab arg3') +p = run_alr('edit', '--project=project1.gpr', complain_on_error=False) +assert_match("ERROR: 'doesnt_exist' not available or not in PATH.*", p.out) +print(p.out) + +# Use echo as an editor to check command line args +run_alr('config', '--set', 'editor.cmd', 'echo arg1 ab${GPR_FILE}ab arg3') +p = run_alr('edit', '--project=project1.gpr') +assert_match("arg1 abproject1.gprab arg3", p.out) + print('SUCCESS') -- 2.39.5