2023-03-20 04:05:22 +00:00
|
|
|
use crate::util::eval_source;
|
2022-03-16 18:17:06 +00:00
|
|
|
#[cfg(feature = "plugin")]
|
2022-07-17 18:29:19 +00:00
|
|
|
use nu_path::canonicalize_with;
|
Add `command_prelude` module (#12291)
# Description
When implementing a `Command`, one must also import all the types
present in the function signatures for `Command`. This makes it so that
we often import the same set of types in each command implementation
file. E.g., something like this:
```rust
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
record, Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
ShellError, Signature, Span, Type, Value,
};
```
This PR adds the `nu_engine::command_prelude` module which contains the
necessary and commonly used types to implement a `Command`:
```rust
// command_prelude.rs
pub use crate::CallExt;
pub use nu_protocol::{
ast::{Call, CellPath},
engine::{Command, EngineState, Stack},
record, Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, IntoSpanned,
PipelineData, Record, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value,
};
```
This should reduce the boilerplate needed to implement a command and
also gives us a place to track the breadth of the `Command` API. I tried
to be conservative with what went into the prelude modules, since it
might be hard/annoying to remove items from the prelude in the future.
Let me know if something should be included or excluded.
2024-03-26 21:17:30 +00:00
|
|
|
use nu_protocol::{
|
|
|
|
engine::{EngineState, Stack, StateWorkingSet},
|
|
|
|
report_error, HistoryFileFormat, PipelineData,
|
|
|
|
};
|
2023-01-24 20:28:59 +00:00
|
|
|
#[cfg(feature = "plugin")]
|
2023-04-07 00:35:45 +00:00
|
|
|
use nu_protocol::{ParseError, Spanned};
|
|
|
|
#[cfg(feature = "plugin")]
|
2023-01-24 20:28:59 +00:00
|
|
|
use nu_utils::utils::perf;
|
2022-03-16 18:17:06 +00:00
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
#[cfg(feature = "plugin")]
|
|
|
|
const PLUGIN_FILE: &str = "plugin.nu";
|
|
|
|
|
2022-06-14 20:53:33 +00:00
|
|
|
const HISTORY_FILE_TXT: &str = "history.txt";
|
|
|
|
const HISTORY_FILE_SQLITE: &str = "history.sqlite3";
|
|
|
|
|
2022-03-16 18:17:06 +00:00
|
|
|
#[cfg(feature = "plugin")]
|
|
|
|
pub fn read_plugin_file(
|
|
|
|
engine_state: &mut EngineState,
|
|
|
|
stack: &mut Stack,
|
2022-07-17 18:29:19 +00:00
|
|
|
plugin_file: Option<Spanned<String>>,
|
2022-03-16 18:17:06 +00:00
|
|
|
storage_path: &str,
|
|
|
|
) {
|
2023-01-24 20:28:59 +00:00
|
|
|
let start_time = std::time::Instant::now();
|
|
|
|
let mut plug_path = String::new();
|
2022-03-16 18:17:06 +00:00
|
|
|
// Reading signatures from signature file
|
|
|
|
// The plugin.nu file stores the parsed signature collected from each registered plugin
|
2022-07-17 18:29:19 +00:00
|
|
|
add_plugin_file(engine_state, plugin_file, storage_path);
|
2022-03-16 18:17:06 +00:00
|
|
|
|
|
|
|
let plugin_path = engine_state.plugin_signatures.clone();
|
|
|
|
if let Some(plugin_path) = plugin_path {
|
2022-11-04 20:11:17 +00:00
|
|
|
let plugin_filename = plugin_path.to_string_lossy();
|
2023-01-24 20:28:59 +00:00
|
|
|
plug_path = plugin_filename.to_string();
|
2022-03-16 18:17:06 +00:00
|
|
|
if let Ok(contents) = std::fs::read(&plugin_path) {
|
|
|
|
eval_source(
|
|
|
|
engine_state,
|
|
|
|
stack,
|
|
|
|
&contents,
|
|
|
|
&plugin_filename,
|
2022-12-07 18:31:57 +00:00
|
|
|
PipelineData::empty(),
|
2023-02-01 23:02:27 +00:00
|
|
|
false,
|
2022-03-16 18:17:06 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-24 20:28:59 +00:00
|
|
|
perf(
|
|
|
|
&format!("read_plugin_file {}", &plug_path),
|
|
|
|
start_time,
|
|
|
|
file!(),
|
|
|
|
line!(),
|
|
|
|
column!(),
|
2023-02-01 23:03:05 +00:00
|
|
|
engine_state.get_config().use_ansi_coloring,
|
2023-01-24 20:28:59 +00:00
|
|
|
);
|
2022-03-16 18:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "plugin")]
|
2022-07-17 18:29:19 +00:00
|
|
|
pub fn add_plugin_file(
|
|
|
|
engine_state: &mut EngineState,
|
|
|
|
plugin_file: Option<Spanned<String>>,
|
|
|
|
storage_path: &str,
|
|
|
|
) {
|
Canonicalize default-config-dir and plugin-path (#11999)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx
you can also mention related issues, PRs or discussions!
-->
# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.
Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
This PR makes sure `$nu.default-config-dir` and `$nu.plugin-path` are
canonicalized.
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
`$nu.default-config-dir` (and `$nu.plugin-path`) will now give canonical
paths, with symlinks and whatnot resolved.
# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library
> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->
I've added a couple of tests to check that even if the config folder
and/or any of the config files within are symlinks, the `$nu.*`
variables are properly canonicalized. These tests unfortunately only run
on Linux and MacOS, because I couldn't figure out how to change the
config directory on Windows. Also, given that they involve creating
files, I'm not sure if they're excessive, so I could remove one or two
of them.
# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
2024-03-02 17:15:31 +00:00
|
|
|
let working_set = StateWorkingSet::new(engine_state);
|
|
|
|
let cwd = working_set.get_cwd();
|
2022-07-17 18:29:19 +00:00
|
|
|
|
Canonicalize default-config-dir and plugin-path (#11999)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx
you can also mention related issues, PRs or discussions!
-->
# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.
Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
This PR makes sure `$nu.default-config-dir` and `$nu.plugin-path` are
canonicalized.
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
`$nu.default-config-dir` (and `$nu.plugin-path`) will now give canonical
paths, with symlinks and whatnot resolved.
# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library
> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->
I've added a couple of tests to check that even if the config folder
and/or any of the config files within are symlinks, the `$nu.*`
variables are properly canonicalized. These tests unfortunately only run
on Linux and MacOS, because I couldn't figure out how to change the
config directory on Windows. Also, given that they involve creating
files, I'm not sure if they're excessive, so I could remove one or two
of them.
# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
2024-03-02 17:15:31 +00:00
|
|
|
if let Some(plugin_file) = plugin_file {
|
2023-01-24 11:23:42 +00:00
|
|
|
if let Ok(path) = canonicalize_with(&plugin_file.item, cwd) {
|
|
|
|
engine_state.plugin_signatures = Some(path)
|
|
|
|
} else {
|
|
|
|
let e = ParseError::FileNotFound(plugin_file.item, plugin_file.span);
|
|
|
|
report_error(&working_set, &e);
|
2022-07-17 18:29:19 +00:00
|
|
|
}
|
2024-03-10 10:07:31 +00:00
|
|
|
} else if let Some(mut plugin_path) = nu_path::config_dir() {
|
2022-03-16 18:17:06 +00:00
|
|
|
// Path to store plugins signatures
|
|
|
|
plugin_path.push(storage_path);
|
Canonicalize each component of config files (#12167)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx
you can also mention related issues, PRs or discussions!
-->
# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.
Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
Because `std::fs::canonicalize` requires the path to exist, this PR
makes it so that when canonicalizing any config file, the
`$nu.default-config-dir/nushell` part is canonicalized first, then
`$nu.default-config-dir/nushell/foo.nu` is canonicalized.
This should also fix the issue @devyn pointed out
[here](https://github.com/nushell/nushell/pull/12118#issuecomment-1989546708)
where a couple of the tests failed if one's `~/.config/nushell` folder
was actually a symlink to a different folder. The tests previously
didn't canonicalize the expected paths.
I was going to make a PR that caches the config directory on startup (as
suggested by fdncred and Ian in Discord), but I can make that part of
this PR if we want to avoid creating unnecessary PRs. I think it
probably makes more sense to separate them though.
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library
> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->
# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
2024-03-13 11:26:06 +00:00
|
|
|
let mut plugin_path = canonicalize_with(&plugin_path, &cwd).unwrap_or(plugin_path);
|
2022-03-16 18:17:06 +00:00
|
|
|
plugin_path.push(PLUGIN_FILE);
|
Canonicalize each component of config files (#12167)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx
you can also mention related issues, PRs or discussions!
-->
# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.
Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
Because `std::fs::canonicalize` requires the path to exist, this PR
makes it so that when canonicalizing any config file, the
`$nu.default-config-dir/nushell` part is canonicalized first, then
`$nu.default-config-dir/nushell/foo.nu` is canonicalized.
This should also fix the issue @devyn pointed out
[here](https://github.com/nushell/nushell/pull/12118#issuecomment-1989546708)
where a couple of the tests failed if one's `~/.config/nushell` folder
was actually a symlink to a different folder. The tests previously
didn't canonicalize the expected paths.
I was going to make a PR that caches the config directory on startup (as
suggested by fdncred and Ian in Discord), but I can make that part of
this PR if we want to avoid creating unnecessary PRs. I think it
probably makes more sense to separate them though.
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library
> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->
# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
2024-03-13 11:26:06 +00:00
|
|
|
let plugin_path = canonicalize_with(&plugin_path, &cwd).unwrap_or(plugin_path);
|
|
|
|
engine_state.plugin_signatures = Some(plugin_path);
|
2022-03-16 18:17:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn eval_config_contents(
|
|
|
|
config_path: PathBuf,
|
|
|
|
engine_state: &mut EngineState,
|
|
|
|
stack: &mut Stack,
|
|
|
|
) {
|
|
|
|
if config_path.exists() & config_path.is_file() {
|
2022-11-04 20:11:17 +00:00
|
|
|
let config_filename = config_path.to_string_lossy();
|
2022-03-16 18:17:06 +00:00
|
|
|
|
|
|
|
if let Ok(contents) = std::fs::read(&config_path) {
|
2024-04-09 14:06:41 +00:00
|
|
|
// Change currently parsed directory
|
|
|
|
let prev_currently_parsed_cwd = engine_state.currently_parsed_cwd.clone();
|
|
|
|
engine_state.start_in_file(Some(&config_filename));
|
|
|
|
|
2022-03-16 18:17:06 +00:00
|
|
|
eval_source(
|
|
|
|
engine_state,
|
|
|
|
stack,
|
|
|
|
&contents,
|
|
|
|
&config_filename,
|
2022-12-07 18:31:57 +00:00
|
|
|
PipelineData::empty(),
|
2023-02-01 23:02:27 +00:00
|
|
|
false,
|
2022-03-16 18:17:06 +00:00
|
|
|
);
|
|
|
|
|
2024-04-09 14:06:41 +00:00
|
|
|
// Restore the currently parsed directory back
|
|
|
|
engine_state.currently_parsed_cwd = prev_currently_parsed_cwd;
|
|
|
|
|
2022-07-14 14:09:27 +00:00
|
|
|
// Merge the environment in case env vars changed in the config
|
2022-03-16 18:17:06 +00:00
|
|
|
match nu_engine::env::current_dir(engine_state, stack) {
|
|
|
|
Ok(cwd) => {
|
2023-06-04 19:04:28 +00:00
|
|
|
if let Err(e) = engine_state.merge_env(stack, cwd) {
|
2022-03-16 18:17:06 +00:00
|
|
|
let working_set = StateWorkingSet::new(engine_state);
|
|
|
|
report_error(&working_set, &e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
let working_set = StateWorkingSet::new(engine_state);
|
|
|
|
report_error(&working_set, &e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-06-14 20:53:33 +00:00
|
|
|
|
|
|
|
pub(crate) fn get_history_path(storage_path: &str, mode: HistoryFileFormat) -> Option<PathBuf> {
|
|
|
|
nu_path::config_dir().map(|mut history_path| {
|
|
|
|
history_path.push(storage_path);
|
|
|
|
history_path.push(match mode {
|
|
|
|
HistoryFileFormat::PlainText => HISTORY_FILE_TXT,
|
|
|
|
HistoryFileFormat::Sqlite => HISTORY_FILE_SQLITE,
|
|
|
|
});
|
|
|
|
history_path
|
|
|
|
})
|
|
|
|
}
|