8000 feat(merod): revamp config command with printing, hints, and safe editing by Nathy-bajo · Pull Request #1274 · calimero-network/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat(merod): revamp config command with printing, hints, and safe editing #1274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: master
Choose a base branch
from

Conversation

Nathy-bajo
Copy link
Contributor
@Nathy-bajo Nathy-bajo commented May 22, 2025

Description

Attempts to resolve #1069

This PR overhauls the merod config command to:

Safe Editing by Default

  • No longer modifies config files unless --save is explicitly specified

  • Shows diffs of proposed changes before saving

Enhanced Printing

  • Adds --print flag with output formats: toml (default), json, human

  • Prints full config when no edits are requested

Schema Hints

  • Supports ? syntax to show config structure and documentation

  • Displays type information and descriptions for nested keys

  • Added structured output showing types and descriptions

Improved UX

  • Clear warnings when changes aren't persisted

  • Colorized diff output

  • Validation before saving

Test plan

Documentation update

Comment on lines 182 to 196
fn print_diff(&self, old: &str, new: &str) -> EyreResult<()> {
let diff = TextDiff::from_lines(old, new);
let mut stdout = StandardStream::stdout(ColorChoice::Auto);

// Save the updated TOML back to the file
write(&path, doc.to_string()).await?;
for op in diff.ops() {
for change in diff.iter_changes(op) {
let (sign, color) = match change.tag() {
ChangeTag::Delete => ("-", TermColor::Red),
ChangeTag::Insert => ("+", TermColor::Green),
ChangeTag::Equal => (" ", TermColor::White),
};

info!("Node configuration has been updated");
stdout.set_color(ColorSpec::new().set_fg(Some(color)).set_intense(true))?;
write!(&mut stdout, "{}{}", sign, change)?;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this marked as resolved?

Comment on lines 260 to 262
Item::ArrayOfTables(_) => {
// Handle arrays if needed
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, they are.

you can use this.is.an.[0].item to represent accessing them

sorta like jq, jsonpath

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not resolved, there's no way to edit items inside arrays

Comment on lines 102 to 104
if old_value.to_string() != current[last_key].to_string() {
changes_made = true;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if I specify any of these three:

  1. a.b.c=3 where a.b did not previously exist?

I suspect panic?

2.a.b.c=3 where a.b.c was previously an object

it'll probably be overwritten, but then validated at a later step to be invalid, which is tolerable

  1. a.b.c=3 a.b.c.d=5

a.b.c will probably discard 3 that was set, and make a.b.c an object with .d inside of it

Can you confirm these?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was a prompt, it should be answered, the answers will then inform any further feedback

Default,
Toml,
Json,
Human,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need an explicit human format, since not all cases have one

when viewing, Default is interpreted to mean "toml"
when editing, Default is interpreted to mean "show diff"
when hinting, Default is interpreted to mean "human readable"

@Nathy-bajo
Copy link
Contributor Author

@miraclx I attempted a different method. Kindly take a look!

Comment on lines 182 to 196
fn print_diff(&self, old: &str, new: &str) -> EyreResult<()> {
let diff = TextDiff::from_lines(old, new);
let mut stdout = StandardStream::stdout(ColorChoice::Auto);

// Save the updated TOML back to the file
write(&path, doc.to_string()).await?;
for op in diff.ops() {
for change in diff.iter_changes(op) {
let (sign, color) = match change.tag() {
ChangeTag::Delete => ("-", TermColor::Red),
ChangeTag::Insert => ("+", TermColor::Green),
ChangeTag::Equal => (" ", TermColor::White),
};

info!("Node configuration has been updated");
stdout.set_color(ColorSpec::new().set_fg(Some(color)).set_intense(true))?;
write!(&mut stdout, "{}{}", sign, change)?;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this marked as resolved? 6D4E

Comment on lines +236 to +242
for change in diff.iter_all_changes() {
match change.tag() {
ChangeTag::Delete => print!("-{}", change.red()),
ChangeTag::Insert => print!("+{}", change.green()),
ChangeTag::Equal => print!(" {}", change),
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, use the udiff module

#1274 (comment)

the format you're printing here is not a diff-style output, so it's not compatible with delta and tools like it

.into_iter()
.partition(|kv| kv.key.ends_with('?'));
let original_doc = toml_str.parse::<toml_edit::DocumentMut>()?;
let mut modified_doc = original_doc.clone();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like we can move this to L101?

Comment on lines 337 to 342
let tmp_dir = temp_dir();
let tmp_path = tmp_dir.join(CONFIG_FILE);
write(&tmp_path, doc.to_string()).await?;

if first != self.path {
return None;
}
let tmp_path_utf8 = Utf8PathBuf::try_from(tmp_dir)?;
drop(ConfigFile::load(&tmp_path_utf8).await?);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a temp file is not necessary here, check the implementation of ConfigFile::load, it's pretty much just a deserialization - you can do the same here.

if you can also verify toml.parse::<DocumentMut> is equivalent to toml::from_str, that'll be great

Comment on lines 102 to 104
if old_value.to_string() != current[last_key].to_string() {
changes_made = true;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was a prompt, it should be answered, the answers will then inform any further feedback

Comment on lines +179 to +182
write!(&mut output, "# {}\n", key)?;
for (k, v) in table.iter() {
write!(&mut output, "# .{}: {}\n", k, self.type_hint(v))?;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the toml output here will be fully commented out?

Comment on lines +190 to +192
PrintFormat::Json => println!(
"{}",
serde_json::to_string_pretty(&json!({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Item::Value(value) => {
println!("{} = {}", section.bold(), self.format_value(value));
}
_ => {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None? let's be explicit, so we know for a fact we're not missing anything

Comment on lines +289 to +290
fn print_table(&self, table: &toml_edit::Table, indent: usize) -> EyreResult<()> {
let indent_str = " ".repeat(indent * 2);
Copy link
Member
@miraclx miraclx May 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as mentioned here, when viewing "default == toml"

but I'm curious to see what this looks like (attach some pictures please, if you don't mind)

Comment on lines 260 to 262
Item::ArrayOfTables(_) => {
// Handle arrays if needed
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not resolved, there's no way to edit items inside arrays

Copy link
github-actions bot commented Jun 5, 2025

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

@github-actions github-actions bot added the Stale label Jun 5, 2025
@Nathy-bajo
Copy link
Contributor Author

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

bump

@github-actions github-actions bot removed the Stale label Jun 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

merod config revamp
4 participants
0