Skip to content

Commit

Permalink
added "en" command (#1697)
Browse files Browse the repository at this point in the history
Fixes #1655
  • Loading branch information
jdx authored Nov 28, 2024
1 parent 8c0b694 commit 23ee779
Show file tree
Hide file tree
Showing 18 changed files with 311 additions and 57 deletions.
3 changes: 3 additions & 0 deletions docs/.vitepress/cli_commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ export const commands: { [key: string]: Command } = {
doctor: {
hide: false,
},
en: {
hide: false,
},
env: {
hide: false,
},
Expand Down
38 changes: 38 additions & 0 deletions docs/cli/en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# `mise en`

- **Usage**: `mise en [-s --shell <SHELL>] [DIR]`
- **Source code**: [`src/cli/en.rs`](https://github.com/jdx/mise/blob/main/src/cli/en.rs)

[experimental] starts a new shell with the mise environment built from the current configuration

This is an alternative to `mise activate` that allows you to explicitly start a mise session.
It will have the tools and environment variables in the configs loaded.
Note that changing directories will not update the mise environment.

## Arguments

### `[DIR]`

Directory to start the shell in

**Default:** `.`

## Flags

### `-s --shell <SHELL>`

Shell to start

Defaults to $SHELL

Examples:

$ mise en .
$ node -v
v20.0.0

Skip loading bashrc:
$ mise en -s "bash --norc"

Skip loading zshrc:
$ mise en -s "zsh -f"
1 change: 1 addition & 0 deletions docs/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Answer yes to all confirmation prompts
- [`mise direnv <SUBCOMMAND>`](/cli/direnv.md)
- [`mise direnv activate`](/cli/direnv/activate.md)
- [`mise doctor`](/cli/doctor.md)
- [`mise en [-s --shell <SHELL>] [DIR]`](/cli/en.md)
- [`mise env [FLAGS] [TOOL@VERSION]...`](/cli/env.md)
- [`mise exec [FLAGS] [TOOL@VERSION]... [COMMAND]...`](/cli/exec.md)
- [`mise generate <SUBCOMMAND>`](/cli/generate.md)
Expand Down
8 changes: 8 additions & 0 deletions docs/cli/run.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ Print directly to stdout/stderr instead of by line
Defaults to true if --jobs == 1
Configure with `task_output` config or `MISE_TASK_OUTPUT` env var

### `-s --shell <SHELL>`

Shell to use to run toml tasks

Defaults to `sh -c -o errexit -o pipefail` on unix, and `cmd /c` on Windows
Can also be set with the setting `MISE_UNIX_DEFAULT_INLINE_SHELL_ARGS` or `MISE_WINDOWS_DEFAULT_INLINE_SHELL_ARGS`
Or it can be overridden with the `shell` property on a task.

### `-t --tool... <TOOL@VERSION>`

Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 [email protected]
Expand Down
8 changes: 8 additions & 0 deletions docs/cli/tasks/run.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ Print directly to stdout/stderr instead of by line
Defaults to true if --jobs == 1
Configure with `task_output` config or `MISE_TASK_OUTPUT` env var

### `-s --shell <SHELL>`

Shell to use to run toml tasks

Defaults to `sh -c -o errexit -o pipefail` on unix, and `cmd /c` on Windows
Can also be set with the setting `MISE_UNIX_DEFAULT_INLINE_SHELL_ARGS` or `MISE_WINDOWS_DEFAULT_INLINE_SHELL_ARGS`
Or it can be overridden with the `shell` property on a task.

### `-t --tool... <TOOL@VERSION>`

Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 [email protected]
Expand Down
3 changes: 3 additions & 0 deletions man/man1/mise.1
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ Output direnv function to use mise inside direnv
mise\-doctor(1)
Check mise installation for possible problems
.TP
mise\-en(1)
[experimental] starts a new shell with the mise environment built from the current configuration
.TP
mise\-env(1)
Exports env vars to activate mise a single time
.TP
Expand Down
35 changes: 35 additions & 0 deletions mise.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ flag "-p --prefix" hide=true
flag "-P --profile" help="Set the profile (environment)" hide=true global=true {
arg "<PROFILE>"
}
flag "-s --shell" hide=true {
arg "<SHELL>"
}
flag "-t --tool" help="Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 [email protected]" var=true hide=true {
arg "<TOOL@VERSION>"
}
Expand Down Expand Up @@ -343,6 +346,30 @@ cmd "doctor" help="Check mise installation for possible problems" {
[WARN] plugin node is not installed
"
}
cmd "en" help="[experimental] starts a new shell with the mise environment built from the current configuration" {
long_help r"[experimental] starts a new shell with the mise environment built from the current configuration

This is an alternative to `mise activate` that allows you to explicitly start a mise session.
It will have the tools and environment variables in the configs loaded.
Note that changing directories will not update the mise environment."
after_long_help r#"Examples:

$ mise en .
$ node -v
v20.0.0

Skip loading bashrc:
$ mise en -s "bash --norc"

Skip loading zshrc:
$ mise en -s "zsh -f"
"#
flag "-s --shell" help="Shell to start" {
long_help "Shell to start\n\nDefaults to $SHELL"
arg "<SHELL>"
}
arg "[DIR]" help="Directory to start the shell in" default="."
}
cmd "env" help="Exports env vars to activate mise a single time" {
alias "e"
long_help r"Exports env vars to activate mise a single time
Expand Down Expand Up @@ -958,6 +985,10 @@ The name of the script will be the name of the tasks.
flag "-f --force" help="Force the tasks to run even if outputs are up to date"
flag "-p --prefix" help="Print stdout/stderr by line, prefixed with the tasks's label\nDefaults to true if --jobs > 1\nConfigure with `task_output` config or `MISE_TASK_OUTPUT` env var"
flag "-i --interleave" help="Print directly to stdout/stderr instead of by line\nDefaults to true if --jobs == 1\nConfigure with `task_output` config or `MISE_TASK_OUTPUT` env var"
flag "-s --shell" help="Shell to use to run toml tasks" {
long_help "Shell to use to run toml tasks\n\nDefaults to `sh -c -o errexit -o pipefail` on unix, and `cmd /c` on Windows\nCan also be set with the setting `MISE_UNIX_DEFAULT_INLINE_SHELL_ARGS` or `MISE_WINDOWS_DEFAULT_INLINE_SHELL_ARGS`\nOr it can be overridden with the `shell` property on a task."
arg "<SHELL>"
}
flag "-t --tool" help="Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 [email protected]" var=true {
arg "<TOOL@VERSION>"
}
Expand Down Expand Up @@ -1321,6 +1352,10 @@ The name of the script will be the name of the tasks.
flag "-f --force" help="Force the tasks to run even if outputs are up to date"
flag "-p --prefix" help="Print stdout/stderr by line, prefixed with the tasks's label\nDefaults to true if --jobs > 1\nConfigure with `task_output` config or `MISE_TASK_OUTPUT` env var"
flag "-i --interleave" help="Print directly to stdout/stderr instead of by line\nDefaults to true if --jobs == 1\nConfigure with `task_output` config or `MISE_TASK_OUTPUT` env var"
flag "-s --shell" help="Shell to use to run toml tasks" {
long_help "Shell to use to run toml tasks\n\nDefaults to `sh -c -o errexit -o pipefail` on unix, and `cmd /c` on Windows\nCan also be set with the setting `MISE_UNIX_DEFAULT_INLINE_SHELL_ARGS` or `MISE_WINDOWS_DEFAULT_INLINE_SHELL_ARGS`\nOr it can be overridden with the `shell` property on a task."
arg "<SHELL>"
}
flag "-t --tool" help="Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 [email protected]" var=true {
arg "<TOOL@VERSION>"
}
Expand Down
2 changes: 1 addition & 1 deletion schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@
}
},
"unix_default_inline_shell_args": {
"default": ["sh", "-c"],
"default": ["sh", "-c", "-o", "errexit"],
"description": "List of default shell arguments for unix to be used with inline commands. For example, `sh`, `-c` for sh.",
"type": "array",
"items": {
Expand Down
2 changes: 1 addition & 1 deletion settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ description = "List of default shell arguments for unix to be used with `file`.
env = "MISE_UNIX_DEFAULT_INLINE_SHELL_ARGS"
type = "ListString"
rust_type = "Vec<String>"
default = ["sh", "-c"]
default = ["sh", "-c", "-o", "errexit"]
parse_env = "list_by_comma"
description = "List of default shell arguments for unix to be used with inline commands. For example, `sh`, `-c` for sh."

Expand Down
59 changes: 59 additions & 0 deletions src/cli/en.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use crate::cli::exec::Exec;
use crate::config::Settings;
use std::path::PathBuf;

use crate::env;

/// [experimental] starts a new shell with the mise environment built from the current configuration
///
/// This is an alternative to `mise activate` that allows you to explicitly start a mise session.
/// It will have the tools and environment variables in the configs loaded.
/// Note that changing directories will not update the mise environment.
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
pub struct En {
/// Directory to start the shell in
#[clap(default_value = ".", verbatim_doc_comment, value_hint = clap::ValueHint::DirPath)]
pub dir: PathBuf,

/// Shell to start
///
/// Defaults to $SHELL
#[clap(verbatim_doc_comment, long, short = 's', env = "MISE_SHELL")]
pub shell: Option<String>,
}

impl En {
pub fn run(self) -> eyre::Result<()> {
let settings = Settings::get();
settings.ensure_experimental("en")?;

env::set_current_dir(&self.dir)?;
let shell = self.shell.unwrap_or((*env::SHELL).clone());
let command = shell_words::split(&shell).map_err(|e| eyre::eyre!(e))?;

Exec {
tool: vec![],
raw: false,
jobs: None,
c: None,
command: Some(command),
}
.run()
}
}

static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise en .</bold>
$ <bold>node -v</bold>
v20.0.0
Skip loading bashrc:
$ <bold>mise en -s "bash --norc"</bold>
Skip loading zshrc:
$ <bold>mise en -s "zsh -f"</bold>
"#
);
31 changes: 25 additions & 6 deletions src/cli/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ pub struct Exec {

/// Command string to execute (same as --command)
#[clap(conflicts_with = "c", required_unless_present = "c", last = true)]
pub command: Option<Vec<OsString>>,
pub command: Option<Vec<String>>,

/// Command string to execute
#[clap(short, long = "command", value_hint = ValueHint::CommandString, conflicts_with = "command")]
pub c: Option<OsString>,
pub c: Option<String>,

/// Number of jobs to run in parallel
/// [default: 4]
Expand Down Expand Up @@ -74,9 +74,28 @@ impl Exec {
ts.notify_if_versions_missing()
});

let (program, args) = parse_command(&env::SHELL, &self.command, &self.c);
let (program, mut args) = parse_command(&env::SHELL, &self.command, &self.c);
let env = measure!("env_with_path", { ts.env_with_path(&CONFIG)? });

if program.rsplit('/').next() == Some("fish") {
let mut cmd = vec![];
for (k, v) in env.iter().filter(|(k, _)| *k != "PATH") {
cmd.push(format!(
"set -gx {} {}",
shell_escape::escape(k.into()),
shell_escape::escape(v.into())
));
}
for p in ts.list_final_paths()? {
cmd.push(format!(
"fish_add_path -gm {}",
shell_escape::escape(p.to_string_lossy())
));
}
args.insert(0, cmd.join("\n"));
args.insert(0, "-C".into());
}

time!("exec");
self.exec(program, args, env)
}
Expand Down Expand Up @@ -142,9 +161,9 @@ impl Exec {

fn parse_command(
shell: &str,
command: &Option<Vec<OsString>>,
c: &Option<OsString>,
) -> (OsString, Vec<OsString>) {
command: &Option<Vec<String>>,
c: &Option<String>,
) -> (String, Vec<String>) {
match (&command, &c) {
(Some(command), _) => {
let (program, args) = command.split_first().unwrap();
Expand Down
6 changes: 6 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod current;
mod deactivate;
mod direnv;
mod doctor;
mod en;
mod env;
pub mod exec;
mod external;
Expand Down Expand Up @@ -112,6 +113,8 @@ pub struct Cli {
/// Set the profile (environment)
#[clap(short = 'P', long, global = true, hide = true)]
pub profile: Option<String>,
#[clap(long, short, hide = true)]
pub shell: Option<String>,
/// Tool(s) to run in addition to what is in mise.toml files
/// e.g.: node@20 [email protected]
#[clap(short, long, hide = true, value_name = "TOOL@VERSION")]
Expand Down Expand Up @@ -159,6 +162,7 @@ pub enum Commands {
Deactivate(deactivate::Deactivate),
Direnv(direnv::Direnv),
Doctor(doctor::Doctor),
En(en::En),
Env(env::Env),
Exec(exec::Exec),
Generate(generate::Generate),
Expand Down Expand Up @@ -219,6 +223,7 @@ impl Commands {
Self::Deactivate(cmd) => cmd.run(),
Self::Direnv(cmd) => cmd.run(),
Self::Doctor(cmd) => cmd.run(),
Self::En(cmd) => cmd.run(),
Self::Env(cmd) => cmd.run(),
Self::Exec(cmd) => cmd.run(),
Self::Generate(cmd) => cmd.run(),
Expand Down Expand Up @@ -325,6 +330,7 @@ impl Cli {
no_timings: self.no_timings,
output: run::TaskOutput::Prefix,
prefix: self.prefix,
shell: self.shell,
quiet: self.quiet,
raw: self.raw,
timings: self.timings,
Expand Down
Loading

0 comments on commit 23ee779

Please sign in to comment.