Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ nu-ansi-term = "0.50.3"
nu-cmd-lang = "0.110.0"
nu-parser = "0.110.0"
nu-protocol = "0.110.0"
nu-utils = "0.110.0"
nuon = "0.110.0"
rayon = "1.11.0"
thiserror = "2.0.18"
Expand Down
74 changes: 64 additions & 10 deletions src/formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use nu_protocol::{
RecordItem, RedirectionTarget,
},
engine::{EngineState, StateWorkingSet},
Signature, Span, SyntaxShape,
Completion, Signature, Span, SyntaxShape,
};
use nu_utils::NuCow;

/// Commands that format their block arguments in a special way
const BLOCK_COMMANDS: &[&str] = &["for", "while", "loop", "module"];
Expand Down Expand Up @@ -576,6 +577,60 @@ impl<'a> Formatter<'a> {
}
}

/// Write custom completion if present (e.g., @`completion_name` or @[list items])
fn write_custom_completion(&mut self, completion: &Option<Completion>) {
match completion {
Some(Completion::Command(decl_id)) => {
let decl = self.working_set.get_decl(*decl_id);
let name = decl.name();
self.write("@");
// Quote command names that contain special characters (like spaces)
if name.contains(' ')
|| name.contains('-')
|| name.contains('[')
|| name.contains(']')
{
self.write("\"");
self.write(name);
self.write("\"");
} else {
self.write(name);
}
}
Some(Completion::List(list)) => {
self.write("@[");
match list {
NuCow::Borrowed(items) => {
for (i, item) in items.iter().enumerate() {
if i > 0 {
self.write(" ");
}
self.write(item);
}
}
NuCow::Owned(items) => {
for (i, item) in items.iter().enumerate() {
if i > 0 {
self.write(" ");
}
self.write(item);
}
}
}
self.write("]");
}
None => {}
}
}

/// Write a `SyntaxShape` with any necessary prettifying
fn write_shape(&mut self, shape: &SyntaxShape) {
match shape {
SyntaxShape::Closure(Option::None) => self.write("closure"),
_ => self.write(&format!("{}", shape)),
}
}

/// Format a signature (for def commands)
fn format_signature(&mut self, sig: &Signature) {
self.write("[");
Expand Down Expand Up @@ -612,12 +667,8 @@ impl<'a> Formatter<'a> {
self.write(&param.name);
if param.shape != SyntaxShape::Any {
self.write(": ");
match &param.shape {
// Fixes an issue in which closure type hints were formatted as `closure()`.
// TODO: This feels hacky. Should this be addressed in the `nu-protocol` crate instead?
SyntaxShape::Closure(Option::None) => self.write("closure"),
_ => self.write(&format!("{}", param.shape)),
}
self.write_shape(&param.shape);
self.write_custom_completion(&param.completion);
}
}

Expand All @@ -631,7 +682,8 @@ impl<'a> Formatter<'a> {
}
if param.shape != SyntaxShape::Any {
self.write(": ");
self.write(&format!("{}", param.shape));
self.write_shape(&param.shape);
self.write_custom_completion(&param.completion);
}
if let Some(default) = &param.default_value {
self.write(" = ");
Expand Down Expand Up @@ -664,7 +716,8 @@ impl<'a> Formatter<'a> {
}
if let Some(shape) = &flag.arg {
self.write(": ");
self.write(&format!("{}", shape));
self.write_shape(shape);
self.write_custom_completion(&flag.completion);
}
if let Some(default) = &flag.default_value {
self.write(" = ");
Expand All @@ -679,7 +732,8 @@ impl<'a> Formatter<'a> {
self.write(&rest.name);
if rest.shape != SyntaxShape::Any {
self.write(": ");
self.write(&format!("{}", rest.shape));
self.write_shape(&rest.shape);
self.write_custom_completion(&rest.completion);
}
}

Expand Down
5 changes: 5 additions & 0 deletions tests/fixtures/expected/issue81.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def f1 [] { }
def f2 [foo: int@f1 = 1] { }
def f3 [x: string@[a b c]] { }
def "complete foo" [] { }
def test [x: int@"complete foo"] { }
5 changes: 5 additions & 0 deletions tests/fixtures/input/issue81.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def f1 [] { }
def f2 [foo: int@f1 = 1] { }
def f3 [x: string@[a b c]] { }
def "complete foo" [] { }
def test [x: int@"complete foo"] { }
12 changes: 12 additions & 0 deletions tests/ground_truth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,18 @@ fn issue76_test() {
run_ground_truth_test(&test_binary, "issue76");
}

#[test]
fn issue81_test() {
let test_binary = get_test_binary();
run_ground_truth_test(&test_binary, "issue81");
}

#[test]
fn idempotency_issue81_test() {
let test_binary = get_test_binary();
run_idempotency_test(&test_binary, "issue81");
}

#[test]
fn ground_truth_inline_param_comment_issue77() {
let test_binary = get_test_binary();
Expand Down
Loading