nushell/crates/nu_plugin_formats/src/from/ini.rs
WindSoilder 208ffdc1da
Move some from xxx commands to plugin (#7942)
# Description

From nushell 0.8 philosophy:
https://github.com/nushell/nushell.github.io/blob/main/contributor-book/philosophy_0_80.md#core-categories

> The following categories should be moved to plugins:
Uncommon format support

So this pr is trying to move following commands to plugin:
- [X] from eml
- [x] from ics
- [x] from ini
- [x] from vcf

And we can have a new plugin handles for these formatting, currently
it's implemented here:

https://github.com/WindSoilder/nu_plugin_format

The command usage should be the same to original command.

If it's ok, the plugin can support more formats like
[parquet](https://github.com/fdncred/nu_plugin_from_parquet), or [EDN
format](https://github.com/nushell/nushell/issues/6415), or something
else.

Just create a draft pr to show what's the blueprint looks like, and is
it a good direction to move forward?

# User-Facing Changes

_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_

# 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` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass

# 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-02-13 12:42:08 +00:00

83 lines
2.7 KiB
Rust

use nu_plugin::{EvaluatedCall, LabeledError};
use nu_protocol::{PluginExample, ShellError, Span, Value};
pub const CMD_NAME: &str = "from ini";
pub fn from_ini_call(call: &EvaluatedCall, input: &Value) -> Result<Value, LabeledError> {
let span = input.span().unwrap_or(call.head);
let input_string = input.as_string()?;
let head = call.head;
let ini_config: Result<ini::Ini, ini::ParseError> = ini::Ini::load_from_str(&input_string);
match ini_config {
Ok(config) => {
let mut sections: Vec<String> = Vec::new();
let mut sections_key_value_pairs: Vec<Value> = Vec::new();
for (section, properties) in config.iter() {
let mut keys_for_section: Vec<String> = Vec::new();
let mut values_for_section: Vec<Value> = Vec::new();
// section
match section {
Some(section_name) => {
sections.push(section_name.to_owned());
}
None => {
sections.push(String::new());
}
}
// section's key value pairs
for (key, value) in properties.iter() {
keys_for_section.push(key.to_owned());
values_for_section.push(Value::String {
val: value.to_owned(),
span,
});
}
// section with its key value pairs
sections_key_value_pairs.push(Value::Record {
cols: keys_for_section,
vals: values_for_section,
span,
});
}
// all sections with all its key value pairs
Ok(Value::Record {
cols: sections,
vals: sections_key_value_pairs,
span,
})
}
Err(err) => Err(ShellError::UnsupportedInput(
format!("Could not load ini: {err}"),
"value originates from here".into(),
head,
span,
)
.into()),
}
}
pub fn examples() -> Vec<PluginExample> {
vec![PluginExample {
example: "'[foo]
a=1
b=2' | from ini"
.into(),
description: "Converts ini formatted string to record".into(),
result: Some(Value::Record {
cols: vec!["foo".to_string()],
vals: vec![Value::Record {
cols: vec!["a".to_string(), "b".to_string()],
vals: vec![Value::test_string("1"), Value::test_string("2")],
span: Span::test_data(),
}],
span: Span::test_data(),
}),
}]
}