diff --git a/lib/helpview.gi b/lib/helpview.gi index cafa286ca0..0082cfc466 100644 --- a/lib/helpview.gi +++ b/lib/helpview.gi @@ -80,7 +80,7 @@ if ARCH_IS_WINDOWS() then winfilename:=MakeExternalFilename( SplitString( filename, "#" )[1] ); fi; Print( "Opening help page ", winfilename, " in default windows browser ... \c" ); - Exec( Concatenation("start ", winfilename ) ); + Exec2( "start", winfilename ); Print( "done! \n" ); end ); @@ -138,7 +138,7 @@ elif ARCH_IS_MAC_OS_X() then fi; file := file.file; fi; - Exec(Concatenation("open -a Preview ", file)); + Exec2("open", "-a", "Preview", file); Print("# see page ", page, " in the Preview window.\n"); end ); @@ -155,7 +155,7 @@ elif ARCH_IS_MAC_OS_X() then fi; file := file.file; fi; - Exec(Concatenation("open -a \"Adobe Reader\" ", file)); + Exec2("open", "-a", "Adobe Reader", file); Print("# see page ", page, " in the Adobe Reader window.\n"); end ); @@ -172,7 +172,7 @@ elif ARCH_IS_MAC_OS_X() then fi; file := file.file; fi; - Exec(Concatenation("open ", file)); + Exec2("open ", file); Print("# see page ", page, " in the pdf viewer window.\n"); end ); @@ -187,16 +187,15 @@ elif ARCH_IS_MAC_OS_X() then fi; file := file.file; fi; - Exec( Concatenation( - "osascript < ## DeclareGlobalFunction( "Exec" ); + +DeclareGlobalName( "Exec2" ); diff --git a/lib/process.gi b/lib/process.gi index 3c2d42a3b7..d937ddadf3 100644 --- a/lib/process.gi +++ b/lib/process.gi @@ -261,3 +261,77 @@ InstallGlobalFunction( Exec, function( arg ) Process( dir, shell, InputTextUser(), OutputTextUser(), [ cs, cmd ] ); end ); + +# TODO: document this, come up with a better name, write some tests... +BindGlobal( "Exec2", function( arg ) + local args, result, a, input, output, dir, cmd; + + args := []; + result := rec(); + + # parse the inputs + for a in arg do + if IsDirectory(a) then + if IsBound(dir) then + Error("must specify at most one working directory"); + fi; + dir := a; + elif IsInputStream(a) then + if IsBound(input) then + Error("must specify at most one input stream"); + fi; + input := a; + elif IsOutputStream(a) then + if IsBound(output) then + Error("must specify at most one output stream"); + fi; + output := a; + elif IsString(a) then + ConvertToStringRep(a); + if not IsBound(cmd) then + cmd := a; + else + Add(args, a); + fi; + else + Error("unsupported argument type"); + fi; + od; + + if not IsBound(cmd) then + Error("must specify a command to execute"); + fi; + + # determine full executable path if it is not already a path + if not '/' in cmd then + a := Filename( DirectoriesSystemPrograms(), cmd ); + if a = fail and ARCH_IS_WINDOWS() then + a := Filename( DirectoriesSystemPrograms(), Concatenation( cmd, ".exe" ) ); + fi; + if a = fail then + Error("could not locate executable for '", cmd, "'"); + fi; + cmd := a; + fi; + + # set default working directory if necessary + if not IsBound(dir) then + dir := DirectoryCurrent(); + fi; + + # if no input stream was specified, pass no input to the command + if not IsBound(input) then + input := InputTextNone(); + fi; + + # if no output stream was specified, put output into the returned record + if not IsBound(output) then + result.output := ""; + output := OutputTextString(result.output, false); + fi; + + # execute the command + result.status := Process( dir, cmd, input, output, args ); + + return result; +end ); diff --git a/lib/streams.gi b/lib/streams.gi index df426f85b2..7a7ca8fc9b 100644 --- a/lib/streams.gi +++ b/lib/streams.gi @@ -1311,19 +1311,20 @@ InstallGlobalFunction( InputFromUser, InstallGlobalFunction( OpenExternal, function(filename) local file; if ARCH_IS_MAC_OS_X() then - Exec(Concatenation("open \"",filename,"\"")); + Exec2("open", filename); elif ARCH_IS_WINDOWS() then - Exec(Concatenation("cmd /c start \"",filename,"\"")); + Exec2("cmd", "/c", "start", filename); elif ARCH_IS_WSL() then # If users pass a URL, make sure if does not get mangled. if ForAny(["https://", "http://"], {pre} -> StartsWith(filename, pre)) then file := filename; else - file := Concatenation("$(wslpath -a -w \"",filename,"\")"); + file := ""; + Exec2("wslpath", "-a", "-w", filename, OutputTextString(file, false)); fi; - Exec(Concatenation("explorer.exe \"", file, "\"")); + Exec2("explorer.exe", file); else - Exec(Concatenation("xdg-open \"",filename,"\"")); + Exec2("xdg-open", filename); fi; end );