2022-11-11 23:20:28 +01:00
|
|
|
use nu_protocol::{
|
2023-08-18 19:47:38 +02:00
|
|
|
ast::Expr,
|
2023-03-10 19:14:55 +01:00
|
|
|
engine::{Command, EngineState, Stack, Visibility},
|
2023-08-17 10:58:38 +02:00
|
|
|
ModuleId, Signature, Span, SyntaxShape, Type, Value,
|
2022-11-11 23:20:28 +01:00
|
|
|
};
|
|
|
|
use std::cmp::Ordering;
|
revert: move to ahash (#9464)
This PR reverts https://github.com/nushell/nushell/pull/9391
We try not to revert PRs like this, though after discussion with the
Nushell team, we decided to revert this one.
The main reason is that Nushell, as a codebase, isn't ready for these
kinds of optimisations. It's in the part of the development cycle where
our main focus should be on improving the algorithms inside of Nushell
itself. Once we have matured our algorithms, then we can look for
opportunities to switch out technologies we're using for alternate
forms.
Much of Nushell still has lots of opportunities for tuning the codebase,
paying down technical debt, and making the codebase generally cleaner
and more robust. This should be the focus. Performance improvements
should flow out of that work.
Said another, optimisation that isn't part of tuning the codebase is
premature at this stage. We need to focus on doing the hard work of
making the engine, parser, etc better.
# User-Facing Changes
Reverts the HashMap -> ahash change.
cc @FilipAndersson245
2023-06-18 05:27:57 +02:00
|
|
|
use std::collections::HashMap;
|
2022-11-11 23:20:28 +01:00
|
|
|
|
2022-12-30 16:44:37 +01:00
|
|
|
pub struct ScopeData<'e, 's> {
|
2022-11-11 23:20:28 +01:00
|
|
|
engine_state: &'e EngineState,
|
|
|
|
stack: &'s Stack,
|
|
|
|
vars_map: HashMap<&'e Vec<u8>, &'e usize>,
|
2023-07-13 21:05:03 +02:00
|
|
|
decls_map: HashMap<&'e Vec<u8>, &'e usize>,
|
2022-11-11 23:20:28 +01:00
|
|
|
modules_map: HashMap<&'e Vec<u8>, &'e usize>,
|
|
|
|
visibility: Visibility,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'e, 's> ScopeData<'e, 's> {
|
|
|
|
pub fn new(engine_state: &'e EngineState, stack: &'s Stack) -> Self {
|
|
|
|
Self {
|
|
|
|
engine_state,
|
|
|
|
stack,
|
|
|
|
vars_map: HashMap::new(),
|
2023-04-07 20:09:38 +02:00
|
|
|
decls_map: HashMap::new(),
|
2022-11-11 23:20:28 +01:00
|
|
|
modules_map: HashMap::new(),
|
|
|
|
visibility: Visibility::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-17 10:58:38 +02:00
|
|
|
pub fn populate_vars(&mut self) {
|
2022-11-11 23:20:28 +01:00
|
|
|
for overlay_frame in self.engine_state.active_overlays(&[]) {
|
|
|
|
self.vars_map.extend(&overlay_frame.vars);
|
2023-08-17 10:58:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// decls include all commands, i.e., normal commands, aliases, and externals
|
|
|
|
pub fn populate_decls(&mut self) {
|
|
|
|
for overlay_frame in self.engine_state.active_overlays(&[]) {
|
2023-04-07 20:09:38 +02:00
|
|
|
self.decls_map.extend(&overlay_frame.decls);
|
2022-11-11 23:20:28 +01:00
|
|
|
self.visibility.merge_with(overlay_frame.visibility.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-30 16:44:37 +01:00
|
|
|
pub fn populate_modules(&mut self) {
|
|
|
|
for overlay_frame in self.engine_state.active_overlays(&[]) {
|
|
|
|
self.modules_map.extend(&overlay_frame.modules);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn collect_vars(&self, span: Span) -> Vec<Value> {
|
2022-11-11 23:20:28 +01:00
|
|
|
let mut vars = vec![];
|
|
|
|
|
2023-08-17 10:58:38 +02:00
|
|
|
for (var_name, var_id) in &self.vars_map {
|
|
|
|
let var_name = Value::string(String::from_utf8_lossy(var_name).to_string(), span);
|
2022-11-11 23:20:28 +01:00
|
|
|
|
2023-08-18 19:47:38 +02:00
|
|
|
let var = self.engine_state.get_var(**var_id);
|
|
|
|
let var_type = Value::string(var.ty.to_string(), span);
|
|
|
|
let is_const = Value::bool(var.const_val.is_some(), span);
|
2023-08-17 10:58:38 +02:00
|
|
|
|
|
|
|
let var_value = if let Ok(val) = self.stack.get_var(**var_id, span) {
|
2022-11-11 23:20:28 +01:00
|
|
|
val
|
|
|
|
} else {
|
|
|
|
Value::nothing(span)
|
|
|
|
};
|
|
|
|
|
2023-08-17 10:58:38 +02:00
|
|
|
let var_id_val = Value::int(**var_id as i64, span);
|
|
|
|
|
2022-11-11 23:20:28 +01:00
|
|
|
vars.push(Value::Record {
|
2023-08-17 10:58:38 +02:00
|
|
|
cols: vec![
|
|
|
|
"name".to_string(),
|
|
|
|
"type".to_string(),
|
|
|
|
"value".to_string(),
|
2023-08-18 19:47:38 +02:00
|
|
|
"is_const".to_string(),
|
2023-08-17 10:58:38 +02:00
|
|
|
"var_id".to_string(),
|
|
|
|
],
|
2023-08-18 19:47:38 +02:00
|
|
|
vals: vec![var_name, var_type, var_value, is_const, var_id_val],
|
2022-11-11 23:20:28 +01:00
|
|
|
span,
|
|
|
|
})
|
|
|
|
}
|
2023-08-17 16:37:01 +02:00
|
|
|
|
|
|
|
sort_rows(&mut vars);
|
2022-11-11 23:20:28 +01:00
|
|
|
vars
|
|
|
|
}
|
|
|
|
|
2022-12-30 16:44:37 +01:00
|
|
|
pub fn collect_commands(&self, span: Span) -> Vec<Value> {
|
2022-11-11 23:20:28 +01:00
|
|
|
let mut commands = vec![];
|
2023-08-17 10:58:38 +02:00
|
|
|
|
2023-07-13 21:05:03 +02:00
|
|
|
for (command_name, decl_id) in &self.decls_map {
|
2023-04-07 20:09:38 +02:00
|
|
|
if self.visibility.is_decl_id_visible(decl_id)
|
|
|
|
&& !self.engine_state.get_decl(**decl_id).is_alias()
|
|
|
|
{
|
2022-11-11 23:20:28 +01:00
|
|
|
let mut cols = vec![];
|
|
|
|
let mut vals = vec![];
|
|
|
|
|
|
|
|
cols.push("name".into());
|
|
|
|
vals.push(Value::String {
|
|
|
|
val: String::from_utf8_lossy(command_name).to_string(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
let decl = self.engine_state.get_decl(**decl_id);
|
|
|
|
let signature = decl.signature();
|
|
|
|
|
|
|
|
cols.push("category".to_string());
|
|
|
|
vals.push(Value::String {
|
|
|
|
val: signature.category.to_string(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
2022-11-12 23:26:20 +01:00
|
|
|
cols.push("signatures".to_string());
|
|
|
|
vals.push(self.collect_signatures(&signature, span));
|
2022-11-11 23:20:28 +01:00
|
|
|
|
|
|
|
cols.push("usage".to_string());
|
|
|
|
vals.push(Value::String {
|
|
|
|
val: decl.usage().into(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("examples".to_string());
|
|
|
|
vals.push(Value::List {
|
|
|
|
vals: decl
|
|
|
|
.examples()
|
|
|
|
.into_iter()
|
|
|
|
.map(|x| Value::Record {
|
2023-03-05 10:56:06 +01:00
|
|
|
cols: vec!["description".into(), "example".into(), "result".into()],
|
2022-11-11 23:20:28 +01:00
|
|
|
vals: vec![
|
|
|
|
Value::String {
|
|
|
|
val: x.description.to_string(),
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
Value::String {
|
|
|
|
val: x.example.to_string(),
|
|
|
|
span,
|
|
|
|
},
|
2023-03-05 10:56:06 +01:00
|
|
|
if let Some(result) = x.result {
|
|
|
|
result
|
|
|
|
} else {
|
|
|
|
Value::Nothing { span }
|
|
|
|
},
|
2022-11-11 23:20:28 +01:00
|
|
|
],
|
|
|
|
span,
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("is_builtin".to_string());
|
|
|
|
// we can only be a is_builtin or is_custom, not both
|
|
|
|
vals.push(Value::Bool {
|
|
|
|
val: !decl.is_custom_command(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("is_sub".to_string());
|
|
|
|
vals.push(Value::Bool {
|
|
|
|
val: decl.is_sub(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("is_plugin".to_string());
|
|
|
|
vals.push(Value::Bool {
|
|
|
|
val: decl.is_plugin().is_some(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("is_custom".to_string());
|
|
|
|
vals.push(Value::Bool {
|
|
|
|
val: decl.is_custom_command(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("is_keyword".into());
|
|
|
|
vals.push(Value::Bool {
|
|
|
|
val: decl.is_parser_keyword(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("is_extern".to_string());
|
|
|
|
vals.push(Value::Bool {
|
|
|
|
val: decl.is_known_external(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("creates_scope".to_string());
|
|
|
|
vals.push(Value::Bool {
|
|
|
|
val: signature.creates_scope,
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("extra_usage".to_string());
|
|
|
|
vals.push(Value::String {
|
|
|
|
val: decl.extra_usage().into(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
let search_terms = decl.search_terms();
|
|
|
|
cols.push("search_terms".to_string());
|
2023-01-29 01:57:26 +01:00
|
|
|
vals.push(Value::String {
|
|
|
|
val: search_terms.join(", "),
|
|
|
|
span,
|
2022-11-11 23:20:28 +01:00
|
|
|
});
|
|
|
|
|
2023-08-17 10:58:38 +02:00
|
|
|
cols.push("decl_id".into());
|
|
|
|
vals.push(Value::int(**decl_id as i64, span));
|
|
|
|
|
2022-11-11 23:20:28 +01:00
|
|
|
commands.push(Value::Record { cols, vals, span })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-17 16:37:01 +02:00
|
|
|
sort_rows(&mut commands);
|
|
|
|
|
2022-11-11 23:20:28 +01:00
|
|
|
commands
|
|
|
|
}
|
|
|
|
|
2022-11-12 23:26:20 +01:00
|
|
|
fn collect_signatures(&self, signature: &Signature, span: Span) -> Value {
|
|
|
|
let mut sigs = signature
|
|
|
|
.input_output_types
|
|
|
|
.iter()
|
|
|
|
.map(|(input_type, output_type)| {
|
|
|
|
(
|
|
|
|
input_type.to_shape().to_string(),
|
|
|
|
Value::List {
|
|
|
|
vals: self.collect_signature_entries(
|
|
|
|
input_type,
|
|
|
|
output_type,
|
|
|
|
signature,
|
|
|
|
span,
|
|
|
|
),
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.collect::<Vec<(String, Value)>>();
|
2023-04-17 18:19:37 +02:00
|
|
|
|
|
|
|
// Until we allow custom commands to have input and output types, let's just
|
2023-06-20 23:33:01 +02:00
|
|
|
// make them Type::Any Type::Any so they can show up in our `scope commands`
|
2023-04-17 18:19:37 +02:00
|
|
|
// a little bit better. If sigs is empty, we're pretty sure that we're dealing
|
|
|
|
// with a custom command.
|
|
|
|
if sigs.is_empty() {
|
|
|
|
let any_type = &Type::Any;
|
|
|
|
sigs.push((
|
|
|
|
any_type.to_shape().to_string(),
|
|
|
|
Value::List {
|
|
|
|
vals: self.collect_signature_entries(any_type, any_type, signature, span),
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
));
|
|
|
|
}
|
2022-11-12 23:26:20 +01:00
|
|
|
sigs.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2));
|
|
|
|
// For most commands, input types are not repeated in
|
|
|
|
// `input_output_types`, i.e. each input type has only one associated
|
|
|
|
// output type. Furthermore, we want this to always be true. However,
|
|
|
|
// there are currently some exceptions, such as `hash sha256` which
|
|
|
|
// takes in string but may output string or binary depending on the
|
|
|
|
// presence of the --binary flag. In such cases, the "special case"
|
|
|
|
// signature usually comes later in the input_output_types, so this will
|
|
|
|
// remove them from the record.
|
|
|
|
sigs.dedup_by(|(k1, _), (k2, _)| k1 == k2);
|
|
|
|
let (cols, vals) = sigs.into_iter().unzip();
|
|
|
|
Value::Record { cols, vals, span }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn collect_signature_entries(
|
|
|
|
&self,
|
|
|
|
input_type: &Type,
|
|
|
|
output_type: &Type,
|
|
|
|
signature: &Signature,
|
|
|
|
span: Span,
|
|
|
|
) -> Vec<Value> {
|
2022-11-11 23:20:28 +01:00
|
|
|
let mut sig_records = vec![];
|
|
|
|
|
|
|
|
let sig_cols = vec![
|
|
|
|
"parameter_name".to_string(),
|
|
|
|
"parameter_type".to_string(),
|
|
|
|
"syntax_shape".to_string(),
|
|
|
|
"is_optional".to_string(),
|
|
|
|
"short_flag".to_string(),
|
|
|
|
"description".to_string(),
|
|
|
|
"custom_completion".to_string(),
|
Parameter defaults to $nu.scope.commands (#9152)
(*third* try at posting this PR, #9104, like #9084, got polluted with
unrelated commits. I'm never going to pull from the github feature
branch again!)
# 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.
-->
Show parameter defaults in scope command signature, where they're
available for display by help.
per https://github.com/nushell/nushell/issues/8928.
I found unexpected ramifications in one completer (NuHelpCompleter) and
plugins, which both use the flag-formatting routine from builtin help.
For the moment I made the minimum necessary changes to get the mainline
scenario to pass tests and run. But we should circle back on what to do
with plugins and help completer..
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
1. New `parameter_default` column to `signatures` table in
`$nu.scope.commands`
It is populated with whatever parameters can be defaulted: currently
positional args and named flags.
2. Built in help (both `help <command>` and `<command> --help` will
display the defaults
3. Help completer will display defaults for flags, but not for
positionals.
Example:
A custom command with some default parameters:
```
〉cat ~/work/dflts.nu
# sample function to show defaults in help
export def main [
arg1: string # mandatory positional
arg2:string=abc # optional positional
--switch # no default here
--named:int # named flag, no default
--other:string=def # flag
--hard:record<foo:int bar:string, bas:bool> # default can be compound type
= {foo:22, bar:"other worlds", bas:false}
] { {arg1: $arg1,
arg2: $arg2,
switch: $switch,
named: $named,
other: $other,
hard: $hard, }
}
〉use ~/work/dflts.nu
〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion
╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮
│ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │
├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤
│ 0 │ │ input │ any │ false │ │
│ 1 │ arg1 │ positional │ string │ false │ │
│ 2 │ arg2 │ positional │ string │ true │ abc │
│ 3 │ switch │ switch │ │ true │ │
│ 4 │ named │ named │ int │ true │ │
│ 5 │ other │ named │ string │ true │ def │
│ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │
│ │ │ │ │ │ │ foo │ 22 │ │
│ │ │ │ │ │ │ bar │ other worlds │ │
│ │ │ │ │ │ │ bas │ false │ │
│ │ │ │ │ │ ╰───────┴───────────────╯ │
│ 7 │ │ output │ any │ false │ │
╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯
〉help dflts
sample function to show defaults in help
Usage:
> dflts {flags} <arg1> (arg2)
Flags:
--switch - switch -- no default here
--named <Int> - named flag, typed, but no default
--other <String> - flag with default (default: 'def')
--hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false})
-h, --help - Display the help message for this command
Parameters:
arg1 <string>: mandatory positional
arg2 <string>: optional positional (optional, default: 'abc')
```
Compared to (relevant bits of) help output previously:
```
Flags:
-h, --help - Display the help message for this command
-, --switch - no default here
-, --named <int> - named flag, no default
-, --other <string> - flag
-, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type
Signatures:
<any> | dflts <string> <string> -> <any>
Parameters:
arg1 <string>: mandatory positional
(optional) arg2 <string>: optional positional
```
# 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 -- crates/nu-std/tests/run.nu` 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
> [x] 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.
-->
2023-05-11 20:59:56 +02:00
|
|
|
"parameter_default".to_string(),
|
2022-11-11 23:20:28 +01:00
|
|
|
];
|
|
|
|
|
2022-11-12 23:26:20 +01:00
|
|
|
// input
|
|
|
|
sig_records.push(Value::Record {
|
|
|
|
cols: sig_cols.clone(),
|
|
|
|
vals: vec![
|
|
|
|
Value::nothing(span),
|
|
|
|
Value::string("input", span),
|
|
|
|
Value::string(input_type.to_shape().to_string(), span),
|
2023-07-21 15:20:33 +02:00
|
|
|
Value::bool(false, span),
|
2022-11-12 23:26:20 +01:00
|
|
|
Value::nothing(span),
|
|
|
|
Value::nothing(span),
|
|
|
|
Value::nothing(span),
|
Parameter defaults to $nu.scope.commands (#9152)
(*third* try at posting this PR, #9104, like #9084, got polluted with
unrelated commits. I'm never going to pull from the github feature
branch again!)
# 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.
-->
Show parameter defaults in scope command signature, where they're
available for display by help.
per https://github.com/nushell/nushell/issues/8928.
I found unexpected ramifications in one completer (NuHelpCompleter) and
plugins, which both use the flag-formatting routine from builtin help.
For the moment I made the minimum necessary changes to get the mainline
scenario to pass tests and run. But we should circle back on what to do
with plugins and help completer..
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
1. New `parameter_default` column to `signatures` table in
`$nu.scope.commands`
It is populated with whatever parameters can be defaulted: currently
positional args and named flags.
2. Built in help (both `help <command>` and `<command> --help` will
display the defaults
3. Help completer will display defaults for flags, but not for
positionals.
Example:
A custom command with some default parameters:
```
〉cat ~/work/dflts.nu
# sample function to show defaults in help
export def main [
arg1: string # mandatory positional
arg2:string=abc # optional positional
--switch # no default here
--named:int # named flag, no default
--other:string=def # flag
--hard:record<foo:int bar:string, bas:bool> # default can be compound type
= {foo:22, bar:"other worlds", bas:false}
] { {arg1: $arg1,
arg2: $arg2,
switch: $switch,
named: $named,
other: $other,
hard: $hard, }
}
〉use ~/work/dflts.nu
〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion
╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮
│ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │
├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤
│ 0 │ │ input │ any │ false │ │
│ 1 │ arg1 │ positional │ string │ false │ │
│ 2 │ arg2 │ positional │ string │ true │ abc │
│ 3 │ switch │ switch │ │ true │ │
│ 4 │ named │ named │ int │ true │ │
│ 5 │ other │ named │ string │ true │ def │
│ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │
│ │ │ │ │ │ │ foo │ 22 │ │
│ │ │ │ │ │ │ bar │ other worlds │ │
│ │ │ │ │ │ │ bas │ false │ │
│ │ │ │ │ │ ╰───────┴───────────────╯ │
│ 7 │ │ output │ any │ false │ │
╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯
〉help dflts
sample function to show defaults in help
Usage:
> dflts {flags} <arg1> (arg2)
Flags:
--switch - switch -- no default here
--named <Int> - named flag, typed, but no default
--other <String> - flag with default (default: 'def')
--hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false})
-h, --help - Display the help message for this command
Parameters:
arg1 <string>: mandatory positional
arg2 <string>: optional positional (optional, default: 'abc')
```
Compared to (relevant bits of) help output previously:
```
Flags:
-h, --help - Display the help message for this command
-, --switch - no default here
-, --named <int> - named flag, no default
-, --other <string> - flag
-, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type
Signatures:
<any> | dflts <string> <string> -> <any>
Parameters:
arg1 <string>: mandatory positional
(optional) arg2 <string>: optional positional
```
# 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 -- crates/nu-std/tests/run.nu` 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
> [x] 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.
-->
2023-05-11 20:59:56 +02:00
|
|
|
Value::nothing(span),
|
2022-11-12 23:26:20 +01:00
|
|
|
],
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
2022-11-11 23:20:28 +01:00
|
|
|
// required_positional
|
|
|
|
for req in &signature.required_positional {
|
|
|
|
let sig_vals = vec![
|
|
|
|
Value::string(&req.name, span),
|
|
|
|
Value::string("positional", span),
|
|
|
|
Value::string(req.shape.to_string(), span),
|
2023-07-21 15:20:33 +02:00
|
|
|
Value::bool(false, span),
|
2022-11-11 23:20:28 +01:00
|
|
|
Value::nothing(span),
|
|
|
|
Value::string(&req.desc, span),
|
|
|
|
Value::string(
|
|
|
|
extract_custom_completion_from_arg(self.engine_state, &req.shape),
|
|
|
|
span,
|
|
|
|
),
|
Parameter defaults to $nu.scope.commands (#9152)
(*third* try at posting this PR, #9104, like #9084, got polluted with
unrelated commits. I'm never going to pull from the github feature
branch again!)
# 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.
-->
Show parameter defaults in scope command signature, where they're
available for display by help.
per https://github.com/nushell/nushell/issues/8928.
I found unexpected ramifications in one completer (NuHelpCompleter) and
plugins, which both use the flag-formatting routine from builtin help.
For the moment I made the minimum necessary changes to get the mainline
scenario to pass tests and run. But we should circle back on what to do
with plugins and help completer..
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
1. New `parameter_default` column to `signatures` table in
`$nu.scope.commands`
It is populated with whatever parameters can be defaulted: currently
positional args and named flags.
2. Built in help (both `help <command>` and `<command> --help` will
display the defaults
3. Help completer will display defaults for flags, but not for
positionals.
Example:
A custom command with some default parameters:
```
〉cat ~/work/dflts.nu
# sample function to show defaults in help
export def main [
arg1: string # mandatory positional
arg2:string=abc # optional positional
--switch # no default here
--named:int # named flag, no default
--other:string=def # flag
--hard:record<foo:int bar:string, bas:bool> # default can be compound type
= {foo:22, bar:"other worlds", bas:false}
] { {arg1: $arg1,
arg2: $arg2,
switch: $switch,
named: $named,
other: $other,
hard: $hard, }
}
〉use ~/work/dflts.nu
〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion
╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮
│ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │
├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤
│ 0 │ │ input │ any │ false │ │
│ 1 │ arg1 │ positional │ string │ false │ │
│ 2 │ arg2 │ positional │ string │ true │ abc │
│ 3 │ switch │ switch │ │ true │ │
│ 4 │ named │ named │ int │ true │ │
│ 5 │ other │ named │ string │ true │ def │
│ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │
│ │ │ │ │ │ │ foo │ 22 │ │
│ │ │ │ │ │ │ bar │ other worlds │ │
│ │ │ │ │ │ │ bas │ false │ │
│ │ │ │ │ │ ╰───────┴───────────────╯ │
│ 7 │ │ output │ any │ false │ │
╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯
〉help dflts
sample function to show defaults in help
Usage:
> dflts {flags} <arg1> (arg2)
Flags:
--switch - switch -- no default here
--named <Int> - named flag, typed, but no default
--other <String> - flag with default (default: 'def')
--hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false})
-h, --help - Display the help message for this command
Parameters:
arg1 <string>: mandatory positional
arg2 <string>: optional positional (optional, default: 'abc')
```
Compared to (relevant bits of) help output previously:
```
Flags:
-h, --help - Display the help message for this command
-, --switch - no default here
-, --named <int> - named flag, no default
-, --other <string> - flag
-, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type
Signatures:
<any> | dflts <string> <string> -> <any>
Parameters:
arg1 <string>: mandatory positional
(optional) arg2 <string>: optional positional
```
# 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 -- crates/nu-std/tests/run.nu` 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
> [x] 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.
-->
2023-05-11 20:59:56 +02:00
|
|
|
Value::nothing(span),
|
2022-11-11 23:20:28 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
sig_records.push(Value::Record {
|
|
|
|
cols: sig_cols.clone(),
|
|
|
|
vals: sig_vals,
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// optional_positional
|
|
|
|
for opt in &signature.optional_positional {
|
|
|
|
let sig_vals = vec![
|
|
|
|
Value::string(&opt.name, span),
|
|
|
|
Value::string("positional", span),
|
|
|
|
Value::string(opt.shape.to_string(), span),
|
2023-07-21 15:20:33 +02:00
|
|
|
Value::bool(true, span),
|
2022-11-11 23:20:28 +01:00
|
|
|
Value::nothing(span),
|
|
|
|
Value::string(&opt.desc, span),
|
|
|
|
Value::string(
|
|
|
|
extract_custom_completion_from_arg(self.engine_state, &opt.shape),
|
|
|
|
span,
|
|
|
|
),
|
Parameter defaults to $nu.scope.commands (#9152)
(*third* try at posting this PR, #9104, like #9084, got polluted with
unrelated commits. I'm never going to pull from the github feature
branch again!)
# 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.
-->
Show parameter defaults in scope command signature, where they're
available for display by help.
per https://github.com/nushell/nushell/issues/8928.
I found unexpected ramifications in one completer (NuHelpCompleter) and
plugins, which both use the flag-formatting routine from builtin help.
For the moment I made the minimum necessary changes to get the mainline
scenario to pass tests and run. But we should circle back on what to do
with plugins and help completer..
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
1. New `parameter_default` column to `signatures` table in
`$nu.scope.commands`
It is populated with whatever parameters can be defaulted: currently
positional args and named flags.
2. Built in help (both `help <command>` and `<command> --help` will
display the defaults
3. Help completer will display defaults for flags, but not for
positionals.
Example:
A custom command with some default parameters:
```
〉cat ~/work/dflts.nu
# sample function to show defaults in help
export def main [
arg1: string # mandatory positional
arg2:string=abc # optional positional
--switch # no default here
--named:int # named flag, no default
--other:string=def # flag
--hard:record<foo:int bar:string, bas:bool> # default can be compound type
= {foo:22, bar:"other worlds", bas:false}
] { {arg1: $arg1,
arg2: $arg2,
switch: $switch,
named: $named,
other: $other,
hard: $hard, }
}
〉use ~/work/dflts.nu
〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion
╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮
│ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │
├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤
│ 0 │ │ input │ any │ false │ │
│ 1 │ arg1 │ positional │ string │ false │ │
│ 2 │ arg2 │ positional │ string │ true │ abc │
│ 3 │ switch │ switch │ │ true │ │
│ 4 │ named │ named │ int │ true │ │
│ 5 │ other │ named │ string │ true │ def │
│ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │
│ │ │ │ │ │ │ foo │ 22 │ │
│ │ │ │ │ │ │ bar │ other worlds │ │
│ │ │ │ │ │ │ bas │ false │ │
│ │ │ │ │ │ ╰───────┴───────────────╯ │
│ 7 │ │ output │ any │ false │ │
╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯
〉help dflts
sample function to show defaults in help
Usage:
> dflts {flags} <arg1> (arg2)
Flags:
--switch - switch -- no default here
--named <Int> - named flag, typed, but no default
--other <String> - flag with default (default: 'def')
--hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false})
-h, --help - Display the help message for this command
Parameters:
arg1 <string>: mandatory positional
arg2 <string>: optional positional (optional, default: 'abc')
```
Compared to (relevant bits of) help output previously:
```
Flags:
-h, --help - Display the help message for this command
-, --switch - no default here
-, --named <int> - named flag, no default
-, --other <string> - flag
-, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type
Signatures:
<any> | dflts <string> <string> -> <any>
Parameters:
arg1 <string>: mandatory positional
(optional) arg2 <string>: optional positional
```
# 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 -- crates/nu-std/tests/run.nu` 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
> [x] 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.
-->
2023-05-11 20:59:56 +02:00
|
|
|
if let Some(val) = &opt.default_value {
|
|
|
|
val.clone()
|
|
|
|
} else {
|
|
|
|
Value::nothing(span)
|
|
|
|
},
|
2022-11-11 23:20:28 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
sig_records.push(Value::Record {
|
|
|
|
cols: sig_cols.clone(),
|
|
|
|
vals: sig_vals,
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// rest_positional
|
|
|
|
if let Some(rest) = &signature.rest_positional {
|
|
|
|
let sig_vals = vec![
|
2022-11-12 23:26:20 +01:00
|
|
|
Value::string(if rest.name == "rest" { "" } else { &rest.name }, span),
|
2022-11-11 23:20:28 +01:00
|
|
|
Value::string("rest", span),
|
|
|
|
Value::string(rest.shape.to_string(), span),
|
2023-07-21 15:20:33 +02:00
|
|
|
Value::bool(true, span),
|
2022-11-11 23:20:28 +01:00
|
|
|
Value::nothing(span),
|
|
|
|
Value::string(&rest.desc, span),
|
|
|
|
Value::string(
|
|
|
|
extract_custom_completion_from_arg(self.engine_state, &rest.shape),
|
|
|
|
span,
|
|
|
|
),
|
Parameter defaults to $nu.scope.commands (#9152)
(*third* try at posting this PR, #9104, like #9084, got polluted with
unrelated commits. I'm never going to pull from the github feature
branch again!)
# 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.
-->
Show parameter defaults in scope command signature, where they're
available for display by help.
per https://github.com/nushell/nushell/issues/8928.
I found unexpected ramifications in one completer (NuHelpCompleter) and
plugins, which both use the flag-formatting routine from builtin help.
For the moment I made the minimum necessary changes to get the mainline
scenario to pass tests and run. But we should circle back on what to do
with plugins and help completer..
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
1. New `parameter_default` column to `signatures` table in
`$nu.scope.commands`
It is populated with whatever parameters can be defaulted: currently
positional args and named flags.
2. Built in help (both `help <command>` and `<command> --help` will
display the defaults
3. Help completer will display defaults for flags, but not for
positionals.
Example:
A custom command with some default parameters:
```
〉cat ~/work/dflts.nu
# sample function to show defaults in help
export def main [
arg1: string # mandatory positional
arg2:string=abc # optional positional
--switch # no default here
--named:int # named flag, no default
--other:string=def # flag
--hard:record<foo:int bar:string, bas:bool> # default can be compound type
= {foo:22, bar:"other worlds", bas:false}
] { {arg1: $arg1,
arg2: $arg2,
switch: $switch,
named: $named,
other: $other,
hard: $hard, }
}
〉use ~/work/dflts.nu
〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion
╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮
│ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │
├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤
│ 0 │ │ input │ any │ false │ │
│ 1 │ arg1 │ positional │ string │ false │ │
│ 2 │ arg2 │ positional │ string │ true │ abc │
│ 3 │ switch │ switch │ │ true │ │
│ 4 │ named │ named │ int │ true │ │
│ 5 │ other │ named │ string │ true │ def │
│ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │
│ │ │ │ │ │ │ foo │ 22 │ │
│ │ │ │ │ │ │ bar │ other worlds │ │
│ │ │ │ │ │ │ bas │ false │ │
│ │ │ │ │ │ ╰───────┴───────────────╯ │
│ 7 │ │ output │ any │ false │ │
╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯
〉help dflts
sample function to show defaults in help
Usage:
> dflts {flags} <arg1> (arg2)
Flags:
--switch - switch -- no default here
--named <Int> - named flag, typed, but no default
--other <String> - flag with default (default: 'def')
--hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false})
-h, --help - Display the help message for this command
Parameters:
arg1 <string>: mandatory positional
arg2 <string>: optional positional (optional, default: 'abc')
```
Compared to (relevant bits of) help output previously:
```
Flags:
-h, --help - Display the help message for this command
-, --switch - no default here
-, --named <int> - named flag, no default
-, --other <string> - flag
-, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type
Signatures:
<any> | dflts <string> <string> -> <any>
Parameters:
arg1 <string>: mandatory positional
(optional) arg2 <string>: optional positional
```
# 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 -- crates/nu-std/tests/run.nu` 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
> [x] 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.
-->
2023-05-11 20:59:56 +02:00
|
|
|
Value::nothing(span), // rest_positional does have default, but parser prohibits specifying it?!
|
2022-11-11 23:20:28 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
sig_records.push(Value::Record {
|
|
|
|
cols: sig_cols.clone(),
|
|
|
|
vals: sig_vals,
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// named flags
|
|
|
|
for named in &signature.named {
|
|
|
|
let flag_type;
|
|
|
|
|
|
|
|
// Skip the help flag
|
|
|
|
if named.long == "help" {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut custom_completion_command_name: String = "".to_string();
|
|
|
|
let shape = if let Some(arg) = &named.arg {
|
|
|
|
flag_type = Value::string("named", span);
|
|
|
|
custom_completion_command_name =
|
|
|
|
extract_custom_completion_from_arg(self.engine_state, arg);
|
|
|
|
Value::string(arg.to_string(), span)
|
|
|
|
} else {
|
|
|
|
flag_type = Value::string("switch", span);
|
|
|
|
Value::nothing(span)
|
|
|
|
};
|
|
|
|
|
|
|
|
let short_flag = if let Some(c) = named.short {
|
|
|
|
Value::string(c, span)
|
|
|
|
} else {
|
|
|
|
Value::nothing(span)
|
|
|
|
};
|
|
|
|
|
|
|
|
let sig_vals = vec![
|
|
|
|
Value::string(&named.long, span),
|
|
|
|
flag_type,
|
|
|
|
shape,
|
2023-07-21 15:20:33 +02:00
|
|
|
Value::bool(!named.required, span),
|
2022-11-11 23:20:28 +01:00
|
|
|
short_flag,
|
|
|
|
Value::string(&named.desc, span),
|
|
|
|
Value::string(custom_completion_command_name, span),
|
Parameter defaults to $nu.scope.commands (#9152)
(*third* try at posting this PR, #9104, like #9084, got polluted with
unrelated commits. I'm never going to pull from the github feature
branch again!)
# 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.
-->
Show parameter defaults in scope command signature, where they're
available for display by help.
per https://github.com/nushell/nushell/issues/8928.
I found unexpected ramifications in one completer (NuHelpCompleter) and
plugins, which both use the flag-formatting routine from builtin help.
For the moment I made the minimum necessary changes to get the mainline
scenario to pass tests and run. But we should circle back on what to do
with plugins and help completer..
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
1. New `parameter_default` column to `signatures` table in
`$nu.scope.commands`
It is populated with whatever parameters can be defaulted: currently
positional args and named flags.
2. Built in help (both `help <command>` and `<command> --help` will
display the defaults
3. Help completer will display defaults for flags, but not for
positionals.
Example:
A custom command with some default parameters:
```
〉cat ~/work/dflts.nu
# sample function to show defaults in help
export def main [
arg1: string # mandatory positional
arg2:string=abc # optional positional
--switch # no default here
--named:int # named flag, no default
--other:string=def # flag
--hard:record<foo:int bar:string, bas:bool> # default can be compound type
= {foo:22, bar:"other worlds", bas:false}
] { {arg1: $arg1,
arg2: $arg2,
switch: $switch,
named: $named,
other: $other,
hard: $hard, }
}
〉use ~/work/dflts.nu
〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion
╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮
│ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │
├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤
│ 0 │ │ input │ any │ false │ │
│ 1 │ arg1 │ positional │ string │ false │ │
│ 2 │ arg2 │ positional │ string │ true │ abc │
│ 3 │ switch │ switch │ │ true │ │
│ 4 │ named │ named │ int │ true │ │
│ 5 │ other │ named │ string │ true │ def │
│ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │
│ │ │ │ │ │ │ foo │ 22 │ │
│ │ │ │ │ │ │ bar │ other worlds │ │
│ │ │ │ │ │ │ bas │ false │ │
│ │ │ │ │ │ ╰───────┴───────────────╯ │
│ 7 │ │ output │ any │ false │ │
╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯
〉help dflts
sample function to show defaults in help
Usage:
> dflts {flags} <arg1> (arg2)
Flags:
--switch - switch -- no default here
--named <Int> - named flag, typed, but no default
--other <String> - flag with default (default: 'def')
--hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false})
-h, --help - Display the help message for this command
Parameters:
arg1 <string>: mandatory positional
arg2 <string>: optional positional (optional, default: 'abc')
```
Compared to (relevant bits of) help output previously:
```
Flags:
-h, --help - Display the help message for this command
-, --switch - no default here
-, --named <int> - named flag, no default
-, --other <string> - flag
-, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type
Signatures:
<any> | dflts <string> <string> -> <any>
Parameters:
arg1 <string>: mandatory positional
(optional) arg2 <string>: optional positional
```
# 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 -- crates/nu-std/tests/run.nu` 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
> [x] 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.
-->
2023-05-11 20:59:56 +02:00
|
|
|
if let Some(val) = &named.default_value {
|
|
|
|
val.clone()
|
|
|
|
} else {
|
|
|
|
Value::nothing(span)
|
|
|
|
},
|
2022-11-11 23:20:28 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
sig_records.push(Value::Record {
|
|
|
|
cols: sig_cols.clone(),
|
|
|
|
vals: sig_vals,
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
}
|
2022-11-12 23:26:20 +01:00
|
|
|
|
|
|
|
// output
|
|
|
|
sig_records.push(Value::Record {
|
|
|
|
cols: sig_cols,
|
|
|
|
vals: vec![
|
|
|
|
Value::nothing(span),
|
|
|
|
Value::string("output", span),
|
|
|
|
Value::string(output_type.to_shape().to_string(), span),
|
2023-07-21 15:20:33 +02:00
|
|
|
Value::bool(false, span),
|
2022-11-12 23:26:20 +01:00
|
|
|
Value::nothing(span),
|
|
|
|
Value::nothing(span),
|
|
|
|
Value::nothing(span),
|
Parameter defaults to $nu.scope.commands (#9152)
(*third* try at posting this PR, #9104, like #9084, got polluted with
unrelated commits. I'm never going to pull from the github feature
branch again!)
# 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.
-->
Show parameter defaults in scope command signature, where they're
available for display by help.
per https://github.com/nushell/nushell/issues/8928.
I found unexpected ramifications in one completer (NuHelpCompleter) and
plugins, which both use the flag-formatting routine from builtin help.
For the moment I made the minimum necessary changes to get the mainline
scenario to pass tests and run. But we should circle back on what to do
with plugins and help completer..
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
1. New `parameter_default` column to `signatures` table in
`$nu.scope.commands`
It is populated with whatever parameters can be defaulted: currently
positional args and named flags.
2. Built in help (both `help <command>` and `<command> --help` will
display the defaults
3. Help completer will display defaults for flags, but not for
positionals.
Example:
A custom command with some default parameters:
```
〉cat ~/work/dflts.nu
# sample function to show defaults in help
export def main [
arg1: string # mandatory positional
arg2:string=abc # optional positional
--switch # no default here
--named:int # named flag, no default
--other:string=def # flag
--hard:record<foo:int bar:string, bas:bool> # default can be compound type
= {foo:22, bar:"other worlds", bas:false}
] { {arg1: $arg1,
arg2: $arg2,
switch: $switch,
named: $named,
other: $other,
hard: $hard, }
}
〉use ~/work/dflts.nu
〉$nu.scope.commands | where name == 'dflts' | get signatures.0.any | reject short_flag description custom_completion
╭───┬────────────────┬────────────────┬──────────────────────────────────────────┬─────────────┬───────────────────────────╮
│ # │ parameter_name │ parameter_type │ syntax_shape │ is_optional │ parameter_default │
├───┼────────────────┼────────────────┼──────────────────────────────────────────┼─────────────┼───────────────────────────┤
│ 0 │ │ input │ any │ false │ │
│ 1 │ arg1 │ positional │ string │ false │ │
│ 2 │ arg2 │ positional │ string │ true │ abc │
│ 3 │ switch │ switch │ │ true │ │
│ 4 │ named │ named │ int │ true │ │
│ 5 │ other │ named │ string │ true │ def │
│ 6 │ hard │ named │ record<foo: int, bar: string, bas: bool> │ true │ ╭───────┬───────────────╮ │
│ │ │ │ │ │ │ foo │ 22 │ │
│ │ │ │ │ │ │ bar │ other worlds │ │
│ │ │ │ │ │ │ bas │ false │ │
│ │ │ │ │ │ ╰───────┴───────────────╯ │
│ 7 │ │ output │ any │ false │ │
╰───┴────────────────┴────────────────┴──────────────────────────────────────────┴─────────────┴───────────────────────────╯
〉help dflts
sample function to show defaults in help
Usage:
> dflts {flags} <arg1> (arg2)
Flags:
--switch - switch -- no default here
--named <Int> - named flag, typed, but no default
--other <String> - flag with default (default: 'def')
--hard <Record([("foo", Int), ("bar", String), ("bas", Boolean)])> - default can be compound type (default: {foo: 22, bar: 'other worlds', bas: false})
-h, --help - Display the help message for this command
Parameters:
arg1 <string>: mandatory positional
arg2 <string>: optional positional (optional, default: 'abc')
```
Compared to (relevant bits of) help output previously:
```
Flags:
-h, --help - Display the help message for this command
-, --switch - no default here
-, --named <int> - named flag, no default
-, --other <string> - flag
-, --hard <record<foo: int, bar: string, bas: bool>> - default can be compound type
Signatures:
<any> | dflts <string> <string> -> <any>
Parameters:
arg1 <string>: mandatory positional
(optional) arg2 <string>: optional positional
```
# 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 -- crates/nu-std/tests/run.nu` 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
> [x] 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.
-->
2023-05-11 20:59:56 +02:00
|
|
|
Value::nothing(span),
|
2022-11-12 23:26:20 +01:00
|
|
|
],
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
2022-11-11 23:20:28 +01:00
|
|
|
sig_records
|
|
|
|
}
|
|
|
|
|
2023-03-15 18:40:27 +01:00
|
|
|
pub fn collect_externs(&self, span: Span) -> Vec<Value> {
|
|
|
|
let mut externals = vec![];
|
2023-08-17 10:58:38 +02:00
|
|
|
|
2023-07-13 21:05:03 +02:00
|
|
|
for (command_name, decl_id) in &self.decls_map {
|
2023-03-15 18:40:27 +01:00
|
|
|
let decl = self.engine_state.get_decl(**decl_id);
|
|
|
|
|
|
|
|
if decl.is_known_external() {
|
|
|
|
let mut cols = vec![];
|
|
|
|
let mut vals = vec![];
|
|
|
|
|
|
|
|
cols.push("name".into());
|
|
|
|
vals.push(Value::String {
|
|
|
|
val: String::from_utf8_lossy(command_name).to_string(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
|
|
|
cols.push("usage".to_string());
|
|
|
|
vals.push(Value::String {
|
|
|
|
val: decl.usage().into(),
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
|
2023-08-17 10:58:38 +02:00
|
|
|
cols.push("decl_id".into());
|
|
|
|
vals.push(Value::int(**decl_id as i64, span));
|
|
|
|
|
2023-03-15 18:40:27 +01:00
|
|
|
externals.push(Value::Record { cols, vals, span })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-17 16:37:01 +02:00
|
|
|
sort_rows(&mut externals);
|
2023-03-15 18:40:27 +01:00
|
|
|
externals
|
|
|
|
}
|
|
|
|
|
2022-12-30 16:44:37 +01:00
|
|
|
pub fn collect_aliases(&self, span: Span) -> Vec<Value> {
|
2022-11-11 23:20:28 +01:00
|
|
|
let mut aliases = vec![];
|
2023-08-17 10:58:38 +02:00
|
|
|
|
|
|
|
for (decl_name, decl_id) in self.engine_state.get_decls_sorted(false) {
|
2023-03-10 19:14:55 +01:00
|
|
|
if self.visibility.is_decl_id_visible(&decl_id) {
|
|
|
|
let decl = self.engine_state.get_decl(decl_id);
|
|
|
|
if let Some(alias) = decl.as_alias() {
|
2023-08-18 19:47:38 +02:00
|
|
|
let aliased_decl_id = if let Expr::Call(wrapped_call) = &alias.wrapped_call.expr
|
|
|
|
{
|
|
|
|
Value::int(wrapped_call.decl_id as i64, span)
|
|
|
|
} else {
|
|
|
|
Value::nothing(span)
|
|
|
|
};
|
|
|
|
|
2023-03-10 19:14:55 +01:00
|
|
|
aliases.push(Value::Record {
|
2023-08-17 10:58:38 +02:00
|
|
|
cols: vec![
|
|
|
|
"name".into(),
|
|
|
|
"expansion".into(),
|
|
|
|
"usage".into(),
|
|
|
|
"decl_id".into(),
|
2023-08-18 19:47:38 +02:00
|
|
|
"aliased_decl_id".into(),
|
2023-08-17 10:58:38 +02:00
|
|
|
],
|
2023-03-10 19:14:55 +01:00
|
|
|
vals: vec![
|
2023-08-17 10:58:38 +02:00
|
|
|
Value::String {
|
|
|
|
val: String::from_utf8_lossy(&decl_name).to_string(),
|
|
|
|
span,
|
|
|
|
},
|
2023-03-10 19:14:55 +01:00
|
|
|
Value::String {
|
|
|
|
val: String::from_utf8_lossy(
|
2023-07-31 21:47:46 +02:00
|
|
|
self.engine_state.get_span_contents(alias.wrapped_call.span),
|
2023-03-10 19:14:55 +01:00
|
|
|
)
|
|
|
|
.to_string(),
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
Value::String {
|
2023-08-17 10:58:38 +02:00
|
|
|
val: alias.usage().to_string(),
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
Value::Int {
|
|
|
|
val: decl_id as i64,
|
2023-03-10 19:14:55 +01:00
|
|
|
span,
|
|
|
|
},
|
2023-08-18 19:47:38 +02:00
|
|
|
aliased_decl_id,
|
2023-03-10 19:14:55 +01:00
|
|
|
],
|
|
|
|
span,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-11-11 23:20:28 +01:00
|
|
|
|
2023-08-17 16:37:01 +02:00
|
|
|
sort_rows(&mut aliases);
|
|
|
|
// aliases.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal));
|
2022-11-11 23:20:28 +01:00
|
|
|
aliases
|
|
|
|
}
|
|
|
|
|
2023-08-17 10:58:38 +02:00
|
|
|
fn collect_module(&self, module_name: &[u8], module_id: &ModuleId, span: Span) -> Value {
|
|
|
|
let module = self.engine_state.get_module(*module_id);
|
2022-11-11 23:20:28 +01:00
|
|
|
|
2023-08-17 10:58:38 +02:00
|
|
|
let all_decls = module.decls();
|
2022-12-30 16:44:37 +01:00
|
|
|
|
2023-08-17 16:37:01 +02:00
|
|
|
let mut export_commands: Vec<Value> = all_decls
|
2023-08-17 10:58:38 +02:00
|
|
|
.iter()
|
|
|
|
.filter_map(|(name_bytes, decl_id)| {
|
|
|
|
let decl = self.engine_state.get_decl(*decl_id);
|
|
|
|
|
|
|
|
if !decl.is_alias() && !decl.is_known_external() {
|
|
|
|
Some(Value::record(
|
|
|
|
vec!["name".into(), "decl_id".into()],
|
|
|
|
vec![
|
|
|
|
Value::string(String::from_utf8_lossy(name_bytes), span),
|
|
|
|
Value::int(*decl_id as i64, span),
|
|
|
|
],
|
|
|
|
span,
|
|
|
|
))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
2022-12-30 16:44:37 +01:00
|
|
|
|
2023-08-17 16:37:01 +02:00
|
|
|
let mut export_aliases: Vec<Value> = all_decls
|
2023-08-17 10:58:38 +02:00
|
|
|
.iter()
|
|
|
|
.filter_map(|(name_bytes, decl_id)| {
|
|
|
|
let decl = self.engine_state.get_decl(*decl_id);
|
|
|
|
|
|
|
|
if decl.is_alias() {
|
|
|
|
Some(Value::record(
|
|
|
|
vec!["name".into(), "decl_id".into()],
|
|
|
|
vec![
|
|
|
|
Value::string(String::from_utf8_lossy(name_bytes), span),
|
|
|
|
Value::int(*decl_id as i64, span),
|
|
|
|
],
|
2022-12-30 16:44:37 +01:00
|
|
|
span,
|
2023-08-17 10:58:38 +02:00
|
|
|
))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2023-08-17 16:37:01 +02:00
|
|
|
let mut export_externs: Vec<Value> = all_decls
|
2023-08-17 10:58:38 +02:00
|
|
|
.iter()
|
|
|
|
.filter_map(|(name_bytes, decl_id)| {
|
|
|
|
let decl = self.engine_state.get_decl(*decl_id);
|
|
|
|
|
|
|
|
if decl.is_known_external() {
|
|
|
|
Some(Value::record(
|
|
|
|
vec!["name".into(), "decl_id".into()],
|
|
|
|
vec![
|
|
|
|
Value::string(String::from_utf8_lossy(name_bytes), span),
|
|
|
|
Value::int(*decl_id as i64, span),
|
|
|
|
],
|
2022-12-30 16:44:37 +01:00
|
|
|
span,
|
2023-08-17 10:58:38 +02:00
|
|
|
))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2023-08-17 16:37:01 +02:00
|
|
|
let mut export_submodules: Vec<Value> = module
|
2023-08-17 10:58:38 +02:00
|
|
|
.submodules()
|
|
|
|
.iter()
|
|
|
|
.map(|(name_bytes, submodule_id)| self.collect_module(name_bytes, submodule_id, span))
|
|
|
|
.collect();
|
|
|
|
|
2023-08-17 16:37:01 +02:00
|
|
|
let mut export_consts: Vec<Value> = module
|
Recursively export constants from modules (#10049)
<!--
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.
-->
2023-08-20 14:51:35 +02:00
|
|
|
.consts()
|
2023-08-17 10:58:38 +02:00
|
|
|
.iter()
|
|
|
|
.map(|(name_bytes, var_id)| {
|
|
|
|
Value::record(
|
|
|
|
vec!["name".into(), "type".into(), "var_id".into()],
|
|
|
|
vec![
|
|
|
|
Value::string(String::from_utf8_lossy(name_bytes), span),
|
|
|
|
Value::string(self.engine_state.get_var(*var_id).ty.to_string(), span),
|
|
|
|
Value::int(*var_id as i64, span),
|
|
|
|
],
|
|
|
|
span,
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2023-08-17 16:37:01 +02:00
|
|
|
sort_rows(&mut export_commands);
|
|
|
|
sort_rows(&mut export_aliases);
|
|
|
|
sort_rows(&mut export_externs);
|
|
|
|
sort_rows(&mut export_submodules);
|
|
|
|
sort_rows(&mut export_consts);
|
|
|
|
|
2023-08-17 10:58:38 +02:00
|
|
|
let export_env_block = module.env_block.map_or_else(
|
|
|
|
|| Value::nothing(span),
|
|
|
|
|block_id| Value::Block {
|
|
|
|
val: block_id,
|
2022-11-11 23:20:28 +01:00
|
|
|
span,
|
2023-08-17 10:58:38 +02:00
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
let module_usage = self
|
|
|
|
.engine_state
|
|
|
|
.build_module_usage(*module_id)
|
|
|
|
.map(|(usage, _)| usage)
|
|
|
|
.unwrap_or_default();
|
|
|
|
|
|
|
|
Value::Record {
|
|
|
|
cols: vec![
|
|
|
|
"name".into(),
|
|
|
|
"commands".into(),
|
|
|
|
"aliases".into(),
|
|
|
|
"externs".into(),
|
|
|
|
"submodules".into(),
|
|
|
|
"constants".into(),
|
|
|
|
"env_block".into(),
|
|
|
|
"usage".into(),
|
|
|
|
"module_id".into(),
|
|
|
|
],
|
|
|
|
vals: vec![
|
|
|
|
Value::string(String::from_utf8_lossy(module_name), span),
|
|
|
|
Value::List {
|
|
|
|
vals: export_commands,
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
Value::List {
|
|
|
|
vals: export_aliases,
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
Value::List {
|
|
|
|
vals: export_externs,
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
Value::List {
|
|
|
|
vals: export_submodules,
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
Value::List {
|
|
|
|
vals: export_consts,
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
export_env_block,
|
|
|
|
Value::string(module_usage, span),
|
|
|
|
Value::int(*module_id as i64, span),
|
|
|
|
],
|
|
|
|
span,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn collect_modules(&self, span: Span) -> Vec<Value> {
|
|
|
|
let mut modules = vec![];
|
|
|
|
|
|
|
|
for (module_name, module_id) in &self.modules_map {
|
|
|
|
modules.push(self.collect_module(module_name, module_id, span));
|
2022-11-11 23:20:28 +01:00
|
|
|
}
|
2023-08-17 10:58:38 +02:00
|
|
|
|
2022-11-11 23:20:28 +01:00
|
|
|
modules.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal));
|
|
|
|
modules
|
|
|
|
}
|
|
|
|
|
2022-12-30 16:44:37 +01:00
|
|
|
pub fn collect_engine_state(&self, span: Span) -> Value {
|
2022-11-11 23:20:28 +01:00
|
|
|
let engine_state_cols = vec![
|
|
|
|
"source_bytes".to_string(),
|
|
|
|
"num_vars".to_string(),
|
2023-04-07 20:09:38 +02:00
|
|
|
"num_decls".to_string(),
|
2022-11-11 23:20:28 +01:00
|
|
|
"num_blocks".to_string(),
|
|
|
|
"num_modules".to_string(),
|
|
|
|
"num_env_vars".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
let engine_state_vals = vec![
|
|
|
|
Value::int(self.engine_state.next_span_start() as i64, span),
|
|
|
|
Value::int(self.engine_state.num_vars() as i64, span),
|
|
|
|
Value::int(self.engine_state.num_decls() as i64, span),
|
|
|
|
Value::int(self.engine_state.num_blocks() as i64, span),
|
|
|
|
Value::int(self.engine_state.num_modules() as i64, span),
|
|
|
|
Value::int(
|
|
|
|
self.engine_state
|
|
|
|
.env_vars
|
|
|
|
.values()
|
|
|
|
.map(|overlay| overlay.len() as i64)
|
|
|
|
.sum(),
|
|
|
|
span,
|
|
|
|
),
|
|
|
|
];
|
2023-08-17 10:58:38 +02:00
|
|
|
|
2022-11-11 23:20:28 +01:00
|
|
|
Value::Record {
|
|
|
|
cols: engine_state_cols,
|
|
|
|
vals: engine_state_vals,
|
|
|
|
span,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn extract_custom_completion_from_arg(engine_state: &EngineState, shape: &SyntaxShape) -> String {
|
|
|
|
return match shape {
|
|
|
|
SyntaxShape::Custom(_, custom_completion_decl_id) => {
|
|
|
|
let custom_completion_command = engine_state.get_decl(*custom_completion_decl_id);
|
|
|
|
let custom_completion_command_name: &str = custom_completion_command.name();
|
|
|
|
custom_completion_command_name.to_string()
|
|
|
|
}
|
|
|
|
_ => "".to_string(),
|
|
|
|
};
|
|
|
|
}
|
2023-08-17 16:37:01 +02:00
|
|
|
|
|
|
|
fn sort_rows(decls: &mut [Value]) {
|
|
|
|
decls.sort_by(|a, b| match (a, b) {
|
|
|
|
(Value::Record { vals: rec_a, .. }, Value::Record { vals: rec_b, .. }) => {
|
|
|
|
// Comparing the first value from the record
|
|
|
|
// It is expected that the first value is the name of the entry (command, module, alias, etc.)
|
|
|
|
match (rec_a.get(0), rec_b.get(0)) {
|
|
|
|
(Some(val_a), Some(val_b)) => match (val_a, val_b) {
|
|
|
|
(Value::String { val: str_a, .. }, Value::String { val: str_b, .. }) => {
|
|
|
|
str_a.cmp(str_b)
|
|
|
|
}
|
|
|
|
_ => Ordering::Equal,
|
|
|
|
},
|
|
|
|
_ => Ordering::Equal,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => Ordering::Equal,
|
|
|
|
});
|
|
|
|
}
|