Skip to content

Commit 1116657

Browse files
committed
new: Add proto shell command. (#879)
1 parent bc4e8f7 commit 1116657

File tree

7 files changed

+89
-7
lines changed

7 files changed

+89
-7
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
- Pre-builts will now use a much smaller archive when downloading.
2424
- Fixed a UTF-8 unpacking error.
2525

26+
#### 🚀 Updates
27+
28+
- Added a new command, `proto shell`, that will initialize a list of tools into the environment and start an interactive shell session.
29+
- By default, it will use the current shell, but you can override this with the `--shell` option.
30+
- Example: `proto shell node@20 npm@10`
31+
2632
#### ⚙️ Internal
2733

2834
- Updated dependencies.

crates/cli/src/app.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::commands::{
22
ActivateArgs, AliasArgs, BinArgs, CleanArgs, CompletionsArgs, DiagnoseArgs, ExecArgs,
3-
InstallArgs, MigrateArgs, OutdatedArgs, PinArgs, RegenArgs, RunArgs, SetupArgs, StatusArgs,
4-
UnaliasArgs, UninstallArgs, UnpinArgs, UpgradeArgs, VersionsArgs,
3+
InstallArgs, MigrateArgs, OutdatedArgs, PinArgs, RegenArgs, RunArgs, SetupArgs, ShellArgs,
4+
StatusArgs, UnaliasArgs, UninstallArgs, UnpinArgs, UpgradeArgs, VersionsArgs,
55
debug::{DebugConfigArgs, DebugEnvArgs},
66
plugin::{AddPluginArgs, InfoPluginArgs, ListPluginsArgs, RemovePluginArgs, SearchPluginArgs},
77
};
@@ -293,6 +293,13 @@ pub enum Commands {
293293
)]
294294
Setup(SetupArgs),
295295

296+
#[command(
297+
aliases = ["sh", "session"],
298+
name = "shell",
299+
about = "Initialize a list of tools into the environment and start an interactive shell session."
300+
)]
301+
Shell(ShellArgs),
302+
296303
#[command(
297304
name = "status",
298305
about = "List all configured tools and their current installation status."

crates/cli/src/commands/exec.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,20 @@ use starbase_shell::ShellType;
1212
#[derive(Args, Clone, Debug)]
1313
pub struct ExecArgs {
1414
#[arg(help = "Tools to initialize")]
15-
tools: Vec<String>,
15+
pub tools: Vec<String>,
1616

1717
#[arg(long, help = "Inherit tools to initialize from .prototools configs")]
18-
tools_from_config: bool,
18+
pub tools_from_config: bool,
1919

2020
#[arg(long, help = "Execute the command as-is without quoting or escaping")]
21-
raw: bool,
21+
pub raw: bool,
2222

2323
#[arg(long, help = "Shell to execute the command with")]
24-
shell: Option<ShellType>,
24+
pub shell: Option<ShellType>,
2525

2626
// Passthrough args (after --)
2727
#[arg(last = true, help = "The command to execute after initializing tools")]
28-
command: Vec<String>,
28+
pub command: Vec<String>,
2929
}
3030

3131
#[tracing::instrument(skip_all)]

crates/cli/src/commands/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub(crate) mod plugin;
1414
mod regen;
1515
mod run;
1616
mod setup;
17+
mod shell;
1718
mod status;
1819
mod unalias;
1920
mod uninstall;
@@ -35,6 +36,7 @@ pub use pin::*;
3536
pub use regen::*;
3637
pub use run::*;
3738
pub use setup::*;
39+
pub use shell::*;
3840
pub use status::*;
3941
pub use unalias::*;
4042
pub use uninstall::*;

crates/cli/src/commands/shell.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use super::exec::*;
2+
use crate::error::ProtoCliError;
3+
use crate::session::ProtoSession;
4+
use clap::Args;
5+
use starbase::AppResult;
6+
use starbase_shell::ShellType;
7+
8+
#[derive(Args, Clone, Debug)]
9+
pub struct ShellArgs {
10+
#[arg(help = "Tools to initialize")]
11+
tools: Vec<String>,
12+
13+
#[arg(long, help = "Shell to start a session for")]
14+
shell: Option<ShellType>,
15+
}
16+
17+
#[tracing::instrument(skip_all)]
18+
pub async fn shell(session: ProtoSession, args: ShellArgs) -> AppResult {
19+
// Detect the shell that we need to activate for
20+
let shell_type = match args.shell {
21+
Some(value) => value,
22+
None => ShellType::try_detect()?,
23+
};
24+
25+
// Define the interactive command to use
26+
let command = match shell_type {
27+
ShellType::Ash => "ash -i",
28+
ShellType::Bash => "bash -i",
29+
ShellType::Elvish => "elvish",
30+
ShellType::Fish => "fish --interactive",
31+
ShellType::Ion => "ion",
32+
ShellType::Murex => "murex",
33+
ShellType::Nu => "nu --interactive",
34+
ShellType::Pwsh => "pwsh -Interactive -NoLogo",
35+
ShellType::Sh => "sh",
36+
ShellType::Xonsh => "xonsh --interactive",
37+
ShellType::Zsh => "zsh --interactive",
38+
ShellType::PowerShell => {
39+
return Err(ProtoCliError::ShellPowerShellNotSupported.into());
40+
}
41+
};
42+
43+
// Passthrough to exec
44+
exec(
45+
session,
46+
ExecArgs {
47+
tools_from_config: args.tools.is_empty(),
48+
tools: args.tools,
49+
raw: false,
50+
shell: None,
51+
command: command
52+
.split_whitespace()
53+
.map(|arg| arg.to_owned())
54+
.collect(),
55+
},
56+
)
57+
.await
58+
}

crates/cli/src/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ pub enum ProtoCliError {
145145
)]
146146
RunNoSelfUpgrade { command: String, tool: String },
147147

148+
// SHELL
149+
#[diagnostic(code(proto::commands::shell::unsupported_powershell))]
150+
#[error(
151+
"PowerShell (powershell.exe) does not support interactive shells. Try using pwsh (pwsh.exe) instead by passing {}.",
152+
"--shell pwsh".style(Style::Shell)
153+
)]
154+
ShellPowerShellNotSupported,
155+
148156
// UPGRADE
149157
#[diagnostic(code(proto::commands::upgrade::failed))]
150158
#[error("Failed to upgrade proto, {} binary could not be located after download!", .bin.style(Style::Shell))]

crates/cli/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ async fn main() -> MainResult {
101101
Commands::Regen(args) => commands::regen(session, args).await,
102102
Commands::Run(args) => commands::run(session, args).await,
103103
Commands::Setup(args) => commands::setup(session, args).await,
104+
Commands::Shell(args) => commands::shell(session, args).await,
104105
Commands::Status(args) => commands::status(session, args).await,
105106
Commands::Unalias(args) => commands::unalias(session, args).await,
106107
Commands::Uninstall(args) => commands::uninstall(session, args).await,

0 commit comments

Comments
 (0)