Make view source more robust (#12359)

<!--
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.
-->

Resolves #11800.

```
~/CodingProjects/nushell> def "url expand" [$urls:any = []]: [string -> string, list -> table] {    
:::   let urls = ($in | default $urls)
:::   def expand-link [] {
:::     http head --redirect-mode manual $in | where name == location | get value.0
:::   }
:::   match ($urls | describe) {
:::     string => { $urls | expand-link }
:::     $type if ($type =~ list) => { $urls | wrap link | insert expanded {|url| $url.link | expand-link}}
:::   }
::: }; view source "url expand"
def "url expand" [ $urls: any = [] ]: [string -> string, list<any> -> table] {
  let urls = ($in | default $urls)
  def expand-link [] {
    http head --redirect-mode manual $in | where name == location | get value.0
  }
  match ($urls | describe) {
    string => { $urls | expand-link }
    $type if ($type =~ list) => { $urls | wrap link | insert expanded {|url| $url.link | expand-link}}
  }
}
```

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

`view source` now 
- adds quotes to commands with spaces
- shows default argument values
- shows type signatures

# 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.
-->
This commit is contained in:
pwygab 2024-04-06 09:28:15 +08:00 committed by GitHub
parent 394487b3a7
commit 88ff622b16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,4 +1,5 @@
use nu_engine::command_prelude::*;
use nu_protocol::Config;
use std::fmt::Write;
@ -41,6 +42,7 @@ impl Command for ViewSource {
let vec_of_optional = &sig.optional_positional;
let rest = &sig.rest_positional;
let vec_of_flags = &sig.named;
let type_signatures = &sig.input_output_types;
if decl.is_alias() {
if let Some(alias) = &decl.as_alias() {
@ -58,13 +60,36 @@ impl Command for ViewSource {
if let Some(block_span) = block.span {
let contents = engine_state.get_span_contents(block_span);
// name of function
let mut final_contents = format!("def {val} [ ");
let mut final_contents = String::new();
if val.contains(' ') {
let _ = write!(&mut final_contents, "def \"{val}\" [");
} else {
let _ = write!(&mut final_contents, "def {val} [");
};
if !vec_of_required.is_empty()
|| !vec_of_optional.is_empty()
|| vec_of_flags.len() != 1
|| rest.is_some()
{
final_contents.push(' ');
}
for n in vec_of_required {
let _ = write!(&mut final_contents, "{}: {} ", n.name, n.shape);
// positional argu,emts
// positional arguments
}
for n in vec_of_optional {
let _ = write!(&mut final_contents, "{}?: {} ", n.name, n.shape);
if let Some(s) = n.default_value.clone() {
let _ = write!(
&mut final_contents,
"{}: {} = {} ",
n.name,
n.shape,
s.to_expanded_string(" ", &Config::default())
);
} else {
let _ =
write!(&mut final_contents, "{}?: {} ", n.name, n.shape);
}
}
for n in vec_of_flags {
// skip adding the help flag
@ -87,6 +112,19 @@ impl Command for ViewSource {
rest_arg.name, rest_arg.shape
);
}
let len = type_signatures.len();
if len != 0 {
final_contents.push_str("]: [");
let mut c = 0;
for (insig, outsig) in type_signatures {
c += 1;
let s = format!("{} -> {}", insig, outsig);
final_contents.push_str(&s);
if c != len {
final_contents.push_str(", ")
}
}
}
final_contents.push_str("] ");
final_contents.push_str(&String::from_utf8_lossy(contents));
Ok(Value::string(final_contents, call.head).into_pipeline_data())