<!-- 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. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # 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 -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `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. -->
78 lines
2.1 KiB
Rust
78 lines
2.1 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::{span, ModuleId, Span, VarId};
|
|
use std::collections::HashSet;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub enum ImportPatternMember {
|
|
Glob { span: Span },
|
|
Name { name: Vec<u8>, span: Span },
|
|
List { names: Vec<(Vec<u8>, Span)> },
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct ImportPatternHead {
|
|
pub name: Vec<u8>,
|
|
pub id: Option<ModuleId>,
|
|
pub span: Span,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct ImportPattern {
|
|
pub head: ImportPatternHead,
|
|
pub members: Vec<ImportPatternMember>,
|
|
// communicate to eval which decls/aliases were hidden during `parse_hide()` so it does not
|
|
// interpret these as env var names:
|
|
pub hidden: HashSet<Vec<u8>>,
|
|
// information for the eval which const values to put into stack as variables
|
|
pub constants: Vec<VarId>,
|
|
}
|
|
|
|
impl ImportPattern {
|
|
pub fn new() -> Self {
|
|
ImportPattern {
|
|
head: ImportPatternHead {
|
|
name: vec![],
|
|
id: None,
|
|
span: Span::unknown(),
|
|
},
|
|
members: vec![],
|
|
hidden: HashSet::new(),
|
|
constants: vec![],
|
|
}
|
|
}
|
|
|
|
pub fn span(&self) -> Span {
|
|
let mut spans = vec![self.head.span];
|
|
|
|
for member in &self.members {
|
|
match member {
|
|
ImportPatternMember::Glob { span } => spans.push(*span),
|
|
ImportPatternMember::Name { name: _, span } => spans.push(*span),
|
|
ImportPatternMember::List { names } => {
|
|
for (_, span) in names {
|
|
spans.push(*span);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
span(&spans)
|
|
}
|
|
|
|
pub fn with_hidden(self, hidden: HashSet<Vec<u8>>) -> Self {
|
|
ImportPattern {
|
|
head: self.head,
|
|
members: self.members,
|
|
hidden,
|
|
constants: self.constants,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for ImportPattern {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|