Repository: wezterm/wezterm (language: rust)

Issue:
Have `wezterm -e` start with `--always-new-process`
This is a follow up of https://github.com/wez/wezterm/issues/2782.

Most terminals will not attach to a running instance of a daemon and therefore are blocking when invoked with `-e`. Some tools rely on waiting for the spawned program to terminate.

In my case I had qutebrowsers external editor command set to `$TERMINAL -e vim {file}`. qutebrowser would create `file` and wait for `vim` to finish before reading and deleting it. With `TERMINAL=wezterm` this didn't work as the file got deleted immediately.

**Describe the solution you'd like**
`wezterm -e` should behave as if `wezterm start --always-new-process`.

**Describe alternatives you've considered**
I now handle `TERMINAL==wezterm` specially and start it as a new process, but I'd rather it just worked with `-e`.


Discussion / hints:
I agree, `-e` should start a blocking wezterm for compatibility reasons.

I think `wezterm start` should still **not** use `--always-new-process` by default, only the `-e` alias should start a new process by default. I can send in a patch later. I don't have a strong opinion though, so if @wez wants `start` and `-e` to be always consistent, then that's fine with me too.
> I think `wezterm start` should still **not** use `--always-new-process` by default.

I agree.

> I don't have a strong opinion though, so if @wez wants `start` and `-e` to be always consistent, then that's fine with me too.

Yeah, and if that means that `-e` continues to behave the way it does now, that's fine too.
I think this request makes sense, but I'm not sure whether the `clap` library can make it work that way. If you'd like to look into how to make that work, I'd be happy to review a PR for it!
> but I'm not sure whether the `clap` library can make it work that way

There is no way to implement it while keeping it as a simple clap alias, because [clap uses a bijective mapping model](https://github.com/clap-rs/clap/issues/1820#issuecomment-615547678), so there is no way to have different behaviour between different aliases: All aliases are the same element to clap and you can't determine which alias was used.

However that's no problem, it is easy to fake this with only a few lines of code.

Fix patch:
diff --git a/assets/shell-completion/fish b/assets/shell-completion/fish
index d742beaa2af..616beb74342 100644
--- a/assets/shell-completion/fish
+++ b/assets/shell-completion/fish
@@ -3,7 +3,7 @@ complete -c wezterm -n "__fish_use_subcommand" -l config -d 'Override specific c
 complete -c wezterm -n "__fish_use_subcommand" -s n -l skip-config -d 'Skip loading wezterm.lua'
 complete -c wezterm -n "__fish_use_subcommand" -s h -l help -d 'Print help'
 complete -c wezterm -n "__fish_use_subcommand" -s V -l version -d 'Print version'
-complete -c wezterm -n "__fish_use_subcommand" -f -a "start" -d 'Start the GUI, optionally running an alternative program'
+complete -c wezterm -n "__fish_use_subcommand" -f -a "start" -d 'Start the GUI, optionally running an alternative program [aliases: -e]'
 complete -c wezterm -n "__fish_use_subcommand" -f -a "ssh" -d 'Establish an ssh session'
 complete -c wezterm -n "__fish_use_subcommand" -f -a "serial" -d 'Open a serial port'
 complete -c wezterm -n "__fish_use_subcommand" -f -a "connect" -d 'Connect to wezterm multiplexer'
@@ -189,7 +189,7 @@ complete -c wezterm -n "__fish_seen_subcommand_from replay" -l cat -d 'Just emit
 complete -c wezterm -n "__fish_seen_subcommand_from replay" -s h -l help -d 'Print help'
 complete -c wezterm -n "__fish_seen_subcommand_from shell-completion" -l shell -d 'Which shell to generate for' -r -f -a "{bash	'',elvish	'',fish	'',power-shell	'',zsh	'',fig	''}"
 complete -c wezterm -n "__fish_seen_subcommand_from shell-completion" -s h -l help -d 'Print help'
-complete -c wezterm -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from start; and not __fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from serial; and not __fish_seen_subcommand_from connect; and not __fish_seen_subcommand_from ls-fonts; and not __fish_seen_subcommand_from show-keys; and not __fish_seen_subcommand_from cli; and not __fish_seen_subcommand_from imgcat; and not __fish_seen_subcommand_from set-working-directory; and not __fish_seen_subcommand_from record; and not __fish_seen_subcommand_from replay; and not __fish_seen_subcommand_from shell-completion; and not __fish_seen_subcommand_from help" -f -a "start" -d 'Start the GUI, optionally running an alternative program'
+complete -c wezterm -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from start; and not __fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from serial; and not __fish_seen_subcommand_from connect; and not __fish_seen_subcommand_from ls-fonts; and not __fish_seen_subcommand_from show-keys; and not __fish_seen_subcommand_from cli; and not __fish_seen_subcommand_from imgcat; and not __fish_seen_subcommand_from set-working-directory; and not __fish_seen_subcommand_from record; and not __fish_seen_subcommand_from replay; and not __fish_seen_subcommand_from shell-completion; and not __fish_seen_subcommand_from help" -f -a "start" -d 'Start the GUI, optionally running an alternative program [aliases: -e]'
 complete -c wezterm -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from start; and not __fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from serial; and not __fish_seen_subcommand_from connect; and not __fish_seen_subcommand_from ls-fonts; and not __fish_seen_subcommand_from show-keys; and not __fish_seen_subcommand_from cli; and not __fish_seen_subcommand_from imgcat; and not __fish_seen_subcommand_from set-working-directory; and not __fish_seen_subcommand_from record; and not __fish_seen_subcommand_from replay; and not __fish_seen_subcommand_from shell-completion; and not __fish_seen_subcommand_from help" -f -a "ssh" -d 'Establish an ssh session'
 complete -c wezterm -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from start; and not __fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from serial; and not __fish_seen_subcommand_from connect; and not __fish_seen_subcommand_from ls-fonts; and not __fish_seen_subcommand_from show-keys; and not __fish_seen_subcommand_from cli; and not __fish_seen_subcommand_from imgcat; and not __fish_seen_subcommand_from set-working-directory; and not __fish_seen_subcommand_from record; and not __fish_seen_subcommand_from replay; and not __fish_seen_subcommand_from shell-completion; and not __fish_seen_subcommand_from help" -f -a "serial" -d 'Open a serial port'
 complete -c wezterm -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from start; and not __fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from serial; and not __fish_seen_subcommand_from connect; and not __fish_seen_subcommand_from ls-fonts; and not __fish_seen_subcommand_from show-keys; and not __fish_seen_subcommand_from cli; and not __fish_seen_subcommand_from imgcat; and not __fish_seen_subcommand_from set-working-directory; and not __fish_seen_subcommand_from record; and not __fish_seen_subcommand_from replay; and not __fish_seen_subcommand_from shell-completion; and not __fish_seen_subcommand_from help" -f -a "connect" -d 'Connect to wezterm multiplexer'
diff --git a/assets/shell-completion/zsh b/assets/shell-completion/zsh
index 71ea1beacf6..e8765f40b6d 100644
--- a/assets/shell-completion/zsh
+++ b/assets/shell-completion/zsh
@@ -45,7 +45,7 @@ _arguments "${_arguments_options[@]}" \
 '--attach[When used with --domain, if the domain already has running panes, wezterm will simply attach and will NOT spawn the specified PROG. If you omit --attach when using --domain, wezterm will attach AND then spawn PROG]' \
 '-h[Print help (see more with '\''--help'\'')]' \
 '--help[Print help (see more with '\''--help'\'')]' \
-'*::prog -- Instead of executing your shell, run PROG. For example\: `wezterm start -- bash -l` will spawn bash as if it were a login shell:_cmdambivalent' \
+'*::prog -- Instead of executing your shell, run PROG. For example\: `wezterm start -- bash -l` will spawn bash as if it were a login shell. \[aliases\: -e\]:_cmdambivalent' \
 && ret=0
 ;;
 (ssh)
@@ -609,7 +609,7 @@ esac
 (( $+functions[_wezterm_commands] )) ||
 _wezterm_commands() {
     local commands; commands=(
-'start:Start the GUI, optionally running an alternative program' \
+'start:Start the GUI, optionally running an alternative program \[aliases\: -e\]' \
 'ssh:Establish an ssh session' \
 'serial:Open a serial port' \
 'connect:Connect to wezterm multiplexer' \
@@ -816,7 +816,7 @@ _wezterm__cli__help__help_commands() {
 (( $+functions[_wezterm__help_commands] )) ||
 _wezterm__help_commands() {
     local commands; commands=(
-'start:Start the GUI, optionally running an alternative program' \
+'start:Start the GUI, optionally running an alternative program \[aliases\: -e\]' \
 'ssh:Establish an ssh session' \
 'serial:Open a serial port' \
 'connect:Connect to wezterm multiplexer' \
diff --git a/docs/examples/cmd-synopsis-wezterm-start--help.txt b/docs/examples/cmd-synopsis-wezterm-start--help.txt
index d1f17221780..55891910c87 100644
--- a/docs/examples/cmd-synopsis-wezterm-start--help.txt
+++ b/docs/examples/cmd-synopsis-wezterm-start--help.txt
@@ -1,11 +1,11 @@
-Start the GUI, optionally running an alternative program
+Start the GUI, optionally running an alternative program [aliases: -e]
 
 Usage: wezterm start [OPTIONS] [PROG]...
 
 Arguments:
   [PROG]...
           Instead of executing your shell, run PROG. For example: `wezterm start
-          -- bash -l` will spawn bash as if it were a login shell
+          -- bash -l` will spawn bash as if it were a login shell. [aliases: -e]
 
 Options:
       --no-auto-connect
diff --git a/wezterm-gui-subcommands/src/lib.rs b/wezterm-gui-subcommands/src/lib.rs
index a69f4b24195..abc3ff297c8 100644
--- a/wezterm-gui-subcommands/src/lib.rs
+++ b/wezterm-gui-subcommands/src/lib.rs
@@ -26,7 +26,6 @@ pub fn name_equals_value(arg: &str) -> Result<(String, String), String> {
 
 #[derive(Debug, Parser, Default, Clone)]
 #[command(trailing_var_arg = true)]
-#[command(visible_short_flag_alias = 'e')]
 pub struct StartCommand {
     /// If true, do not connect to domains marked as connect_automatically
     /// in your wezterm configuration file.
@@ -99,7 +98,7 @@ pub struct StartCommand {
 
     /// Instead of executing your shell, run PROG.
     /// For example: `wezterm start -- bash -l` will spawn bash
-    /// as if it were a login shell.
+    /// as if it were a login shell. [aliases: -e]
     #[arg(value_parser, value_hint=ValueHint::CommandWithArguments, num_args=1..)]
     pub prog: Vec<OsString>,
 }
diff --git a/wezterm-gui/src/main.rs b/wezterm-gui/src/main.rs
index fefea78ca03..986573fed9f 100644
--- a/wezterm-gui/src/main.rs
+++ b/wezterm-gui/src/main.rs
@@ -105,10 +105,13 @@ struct Opt {
 enum SubCommand {
     #[command(
         name = "start",
-        about = "Start the GUI, optionally running an alternative program"
+        about = "Start the GUI, optionally running an alternative program [aliases: -e]"
     )]
     Start(StartCommand),
 
+    #[command(short_flag_alias = 'e', hide = true)]
+    BlockingStart(StartCommand),
+
     #[command(name = "ssh", about = "Establish an ssh session")]
     Ssh(SshCommand),
 
@@ -1161,6 +1164,16 @@ fn run() -> anyhow::Result<()> {
     let config = config::configuration();
 
     let sub = match opts.cmd.as_ref().cloned() {
+        Some(SubCommand::BlockingStart(start)) => {
+            // Act as if the normal start subcommand was used,
+            // except that we always start a new instance.
+            // This is needed for compatibility, because many tools assume
+            // that "$TERMINAL -e $COMMAND" blocks until the command finished.
+            SubCommand::Start(StartCommand {
+                always_new_process: true,
+                ..start
+            })
+        }
         Some(sub) => sub,
         None => {
             // Need to fake an argv0
@@ -1184,6 +1197,7 @@ fn run() -> anyhow::Result<()> {
             wezterm_blob_leases::clear_storage();
             res
         }
+        SubCommand::BlockingStart(_) => unreachable!(),
         SubCommand::Ssh(ssh) => run_ssh(ssh),
         SubCommand::Serial(serial) => run_serial(config, serial),
         SubCommand::Connect(connect) => run_terminal_gui(
diff --git a/wezterm/src/main.rs b/wezterm/src/main.rs
index d5aabe45925..8b846bec041 100644
--- a/wezterm/src/main.rs
+++ b/wezterm/src/main.rs
@@ -91,7 +91,7 @@ impl CompletionGenerator for Shell {
 enum SubCommand {
     #[command(
         name = "start",
-        about = "Start the GUI, optionally running an alternative program"
+        about = "Start the GUI, optionally running an alternative program [aliases: -e]"
     )]
     Start(StartCommand),
 


Test patch: