Skip to content

Commit f20c1a4

Browse files
Show hint instead failing if --source-file is not passed to es set
1 parent 33c7c63 commit f20c1a4

File tree

9 files changed

+82
-78
lines changed

9 files changed

+82
-78
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## [Unreleased] - ReleaseDate
4+
5+
### Changed
6+
7+
- `es set` subcommand no longer requires `--source-file` arg
8+
- The intention is to make the command useful even without the wrapping function (and to provide helpful hint output)
9+
- Rename binary from `env-select` to `es`
10+
- I'm _not_ considering this a breaking change, because running the binary directly was not considered a supported use case.
11+
312
## [1.1.0] - 2024-02-09
413

514
### Added

docs/src/SUMMARY.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
- [Load Values from Kubernetes](./user_guide/env/kubernetes.md)
1515
- [Inheritance & Cascading Configs](./user_guide/inheritance.md)
1616
- [Side Effects](./user_guide/side_effects.md)
17-
- [Troubleshooting](./user_guide/troubleshooting.md)
1817

1918
# API Reference
2019

docs/src/install.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,33 @@
11
# Install
22

3-
See [installation instructions](/artifacts)
3+
See [the artifacts page](/artifacts) to download and install the `es` binary using your preferred method.
4+
5+
## Install Shell Function
6+
7+
While not strictly required, it's highly recommended to install the `es` shell function. This wraps the `es` binary command, allowing it to automatically modify your current shell environment with the `es set` subcommand. Otherwise, you'll have to manually pipe the output of `es set` to `source`.
8+
9+
> If you only plan to use the `es run` command, this is **not relevant**.
10+
11+
This is necessary because a child process is not allowed to modify its parent's environment. That means the `es` process cannot modify the environment of the invoking shell. The wrapping shell function takes the output of `es` and runs it in that shell session to update the environment.
12+
13+
Here's how you install it:
14+
15+
**Restart your shell afterward to apply changes.**
16+
17+
### Bash
18+
19+
```sh
20+
echo "source <(es init --shell bash)" >> ~/.bashrc
21+
```
22+
23+
### Zsh
24+
25+
```sh
26+
echo "source <(es init --shell zsh)" >> ~/.zshrc
27+
```
28+
29+
### Fish
30+
31+
```sh
32+
echo "es init --shell fish | source" >> ~/.config/fish/config.fish
33+
```

docs/src/user_guide/troubleshooting.md

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/commands/init.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::{
2-
commands::{CommandContext, SubcommandTrait},
3-
console,
4-
};
1+
use crate::commands::{CommandContext, SubcommandTrait};
52
use anyhow::Context;
63
use clap::Parser;
74

@@ -17,6 +14,6 @@ impl SubcommandTrait for InitCommand {
1714
.init_script()
1815
.context("Error generating shell init script")?;
1916
println!("{script}");
20-
console::print_installation_hint()
17+
Ok(())
2118
}
2219
}

src/commands/set.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
use crate::commands::{CommandContext, Selection, SubcommandTrait};
2-
use anyhow::{anyhow, Context};
1+
use crate::{
2+
commands::{CommandContext, Selection, SubcommandTrait},
3+
console::print_hint,
4+
};
5+
use anyhow::Context;
36
use clap::Parser;
47
use std::fs;
58

9+
const WEBSITE: &str = "https://env-select.lucaspickering.me";
10+
611
/// Modify shell environment via a configured variable/application
712
#[derive(Clone, Debug, Parser)]
813
pub struct SetCommand {
@@ -12,21 +17,32 @@ pub struct SetCommand {
1217

1318
impl SubcommandTrait for SetCommand {
1419
fn execute(self, context: CommandContext) -> anyhow::Result<()> {
15-
let source_file = context.source_file.as_ref().ok_or_else(|| {
16-
anyhow!("--source-file argument required for subcommand `set`")
17-
})?;
18-
1920
let profile = context.select_profile(&self.selection)?;
2021
let environment = context.load_environment(profile)?;
2122

2223
let source_output = context.shell.export(&environment);
23-
fs::write(source_file, source_output).with_context(|| {
24-
format!("Error writing sourceable output to file {source_file:?}")
25-
})?;
2624

27-
// Tell the user what we exported
28-
println!("The following variables will be set:");
29-
println!("{environment:#}");
25+
// If --source-file was passed, we were probably called from the shell
26+
// wrapper function. Write sourceable output to the given file.
27+
if let Some(source_file) = context.source_file.as_ref() {
28+
fs::write(source_file, source_output).with_context(|| {
29+
format!(
30+
"Error writing sourceable output to file {source_file:?}"
31+
)
32+
})?;
33+
// Tell the user what we exported
34+
println!("The following variables will be set:");
35+
println!("{environment:#}");
36+
} else {
37+
// We were *not* called from the shell wrapper here, so just print
38+
// the output and let the user know about a pro tip
39+
print!("{source_output}");
40+
// TODO update message/link
41+
print_hint(&format!(
42+
"Add `es` wrapping shell function to apply to env-select automatically on shell startup: \
43+
{WEBSITE}/book/install.html#install-shell-function",
44+
))?;
45+
}
3046

3147
Ok(())
3248
}

src/console.rs

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,9 @@ use crate::config::{Application, MapExt, Name, Profile};
22
use anyhow::bail;
33
use dialoguer::{theme::ColorfulTheme, Select};
44
use indexmap::IndexMap;
5-
use std::{
6-
fmt::Write,
7-
io::{self, IsTerminal},
8-
};
5+
use std::fmt::Write;
96
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
107

11-
const REPOSITORY: &str = env!("CARGO_PKG_REPOSITORY");
12-
const VERSION: &str = env!("CARGO_PKG_VERSION");
13-
148
/// Prompt the user to select one option from a list.
159
pub fn prompt_options<'a, T: Prompt>(
1610
options: &'a IndexMap<Name, T>,
@@ -47,28 +41,17 @@ pub fn prompt_options<'a, T: Prompt>(
4741
}
4842
}
4943

50-
/// Print the given message, but only if we're connected to a TTY. If not on a
51-
/// TTY, this hint isn't relevant so hide it.
44+
/// Print the given message to stderr, with warning styling
5245
pub fn print_hint(message: &str) -> anyhow::Result<()> {
53-
if io::stdout().is_terminal() {
54-
let mut stdout = StandardStream::stdout(ColorChoice::Always);
55-
stdout.set_color(
56-
ColorSpec::new().set_fg(Some(Color::Red)).set_bold(true),
57-
)?;
58-
println!("{message}");
59-
stdout.reset()?;
60-
}
46+
let mut stderr = StandardStream::stderr(ColorChoice::Always);
47+
stderr.set_color(
48+
ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true),
49+
)?;
50+
eprintln!("{message}");
51+
stderr.reset()?;
6152
Ok(())
6253
}
6354

64-
/// Print a friendly hint reminding the user to configure their shell
65-
pub fn print_installation_hint() -> anyhow::Result<()> {
66-
print_hint(&format!(
67-
"Initialize env-select automatically on shell startup: \
68-
{REPOSITORY}/tree/v{VERSION}#configure-your-shell",
69-
))
70-
}
71-
7255
/// Little helper to define how a type should be rendered in a TUI prompt
7356
pub trait Prompt: Sized {
7457
const SELF_NAME: &'static str;

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ fn main() -> ExitCode {
7171
// If the error includes an exit code, use it
7272
match error.downcast::<ExitCodeError>() {
7373
// If we're propagating the exit code, we don't want to print
74-
// the error. This is for `env-select run`, which means
74+
// the error. This is for `es run`, which means
7575
// stdout/stderr have been forwarded and we don't want to tack
7676
// on any more logging.
7777
Ok(error) => error.into(),

tests/common/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ pub fn shell_path(shell_kind: &str) -> PathBuf {
2424
)
2525
}
2626

27-
/// Run a script inside the given shell. This will use `env-select init` to
28-
/// load the correct shell function, then
27+
/// Run a script inside the given shell. This will use `es init` to load the
28+
/// correct shell function, then run the script.
2929
///
3030
/// `detect_shell` argument controls whether env-select will guess which shell
3131
/// it's running under (true) or we'll explicitly tell it with -s (false).
@@ -34,7 +34,7 @@ pub fn execute_script(
3434
shell_kind: &str,
3535
detect_shell: bool,
3636
) -> Command {
37-
// Get the function source from `env-select init`
37+
// Get the function source from `es init`
3838
let mut es = env_select();
3939
if detect_shell {
4040
es.env("SHELL", shell_path(shell_kind));

0 commit comments

Comments
 (0)