Accept filenames in other plugin management commands (#12639)

# Description

This allows the following commands to all accept a filename instead of a
plugin name:

- `plugin use`
- `plugin rm`
- `plugin stop`

Slightly complicated because of the need to also check against
`NU_PLUGIN_DIRS`, but I also fixed some issues with that at the same
time

Requested by @fdncred

# User-Facing Changes

The new commands are updated as described.

# Tests + Formatting

Tests for `NU_PLUGIN_DIRS` handling also made more robust.

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting

- [ ] Double check new docs to make sure they describe this capability
This commit is contained in:
Devyn Cairns
2024-04-24 04:28:45 -07:00
committed by GitHub
parent 1633004643
commit b576123b0a
11 changed files with 283 additions and 37 deletions

View File

@ -1,7 +1,10 @@
use std::fs::{self, File};
use std::{
fs::{self, File},
path::PathBuf,
};
use nu_engine::{command_prelude::*, current_dir};
use nu_protocol::PluginCacheFile;
use nu_protocol::{engine::StateWorkingSet, PluginCacheFile};
pub(crate) fn modify_plugin_file(
engine_state: &EngineState,
@ -48,3 +51,39 @@ pub(crate) fn modify_plugin_file(
Ok(())
}
pub(crate) fn canonicalize_possible_filename_arg(
engine_state: &EngineState,
stack: &Stack,
arg: &str,
) -> PathBuf {
// This results in the best possible chance of a match with the plugin item
if let Ok(cwd) = nu_engine::current_dir(engine_state, stack) {
let path = nu_path::expand_path_with(arg, &cwd, true);
// Try to canonicalize
nu_path::locate_in_dirs(&path, &cwd, || get_plugin_dirs(engine_state, stack))
// If we couldn't locate it, return the expanded path alone
.unwrap_or(path)
} else {
arg.into()
}
}
pub(crate) fn get_plugin_dirs(
engine_state: &EngineState,
stack: &Stack,
) -> impl Iterator<Item = String> {
// Get the NU_PLUGIN_DIRS constant or env var
let working_set = StateWorkingSet::new(engine_state);
let value = working_set
.find_variable(b"$NU_PLUGIN_DIRS")
.and_then(|var_id| working_set.get_constant(var_id).ok().cloned())
.or_else(|| stack.get_env_var(engine_state, "NU_PLUGIN_DIRS"));
// Get all of the strings in the list, if possible
value
.into_iter()
.flat_map(|value| value.into_list().ok())
.flatten()
.flat_map(|list_item| list_item.coerce_into_string().ok())
}