mirror of
https://github.com/nushell/nushell.git
synced 2025-08-12 08:19:12 +02:00
Adding plist support (#13545)
# Description Provides the ability convert from and to plist format. <img width="1250" alt="Screenshot 2024-08-05 at 10 21 26" src="https://github.com/user-attachments/assets/970f3366-eb70-4d74-a396-649374556f66"> <img width="730" alt="Screenshot 2024-08-05 at 10 22 38" src="https://github.com/user-attachments/assets/6ec317d0-686e-47c6-bf35-8ab6e5d802db"> # User-Facing Changes - Introduction of `from plist` command - Introduction of `to plist`command --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
This commit is contained in:
1
crates/nu_plugin_formats/src/to/mod.rs
Normal file
1
crates/nu_plugin_formats/src/to/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub(crate) mod plist;
|
113
crates/nu_plugin_formats/src/to/plist.rs
Normal file
113
crates/nu_plugin_formats/src/to/plist.rs
Normal file
@ -0,0 +1,113 @@
|
||||
use std::time::SystemTime;
|
||||
|
||||
use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand, SimplePluginCommand};
|
||||
use nu_protocol::{Category, Example, LabeledError, Record, Signature, Span, Value as NuValue};
|
||||
use plist::{Integer, Value as PlistValue};
|
||||
|
||||
use crate::FormatCmdsPlugin;
|
||||
|
||||
pub(crate) struct IntoPlist;
|
||||
|
||||
impl SimplePluginCommand for IntoPlist {
|
||||
type Plugin = FormatCmdsPlugin;
|
||||
|
||||
fn name(&self) -> &str {
|
||||
"to plist"
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Convert Nu values into plist"
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![Example {
|
||||
example: "{ a: 3 } | to plist",
|
||||
description: "Convert a table into a plist file",
|
||||
result: None,
|
||||
}]
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build(PluginCommand::name(self))
|
||||
.switch("binary", "Output plist in binary format", Some('b'))
|
||||
.category(Category::Formats)
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_plugin: &FormatCmdsPlugin,
|
||||
_engine: &EngineInterface,
|
||||
call: &EvaluatedCall,
|
||||
input: &NuValue,
|
||||
) -> Result<NuValue, LabeledError> {
|
||||
let plist_val = convert_nu_value(input)?;
|
||||
let mut out = Vec::new();
|
||||
if call.has_flag("binary")? {
|
||||
plist::to_writer_binary(&mut out, &plist_val)
|
||||
.map_err(|e| build_label_error(format!("{}", e), input.span()))?;
|
||||
Ok(NuValue::binary(out, input.span()))
|
||||
} else {
|
||||
plist::to_writer_xml(&mut out, &plist_val)
|
||||
.map_err(|e| build_label_error(format!("{}", e), input.span()))?;
|
||||
Ok(NuValue::string(
|
||||
String::from_utf8(out)
|
||||
.map_err(|e| build_label_error(format!("{}", e), input.span()))?,
|
||||
input.span(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_label_error(msg: String, span: Span) -> LabeledError {
|
||||
LabeledError::new("Cannot convert plist").with_label(msg, span)
|
||||
}
|
||||
|
||||
fn convert_nu_value(nu_val: &NuValue) -> Result<PlistValue, LabeledError> {
|
||||
let span = Span::test_data();
|
||||
match nu_val {
|
||||
NuValue::String { val, .. } => Ok(PlistValue::String(val.to_owned())),
|
||||
NuValue::Bool { val, .. } => Ok(PlistValue::Boolean(*val)),
|
||||
NuValue::Float { val, .. } => Ok(PlistValue::Real(*val)),
|
||||
NuValue::Int { val, .. } => Ok(PlistValue::Integer(Into::<Integer>::into(*val))),
|
||||
NuValue::Binary { val, .. } => Ok(PlistValue::Data(val.to_owned())),
|
||||
NuValue::Record { val, .. } => convert_nu_dict(val),
|
||||
NuValue::List { vals, .. } => Ok(PlistValue::Array(
|
||||
vals.iter()
|
||||
.map(convert_nu_value)
|
||||
.collect::<Result<_, _>>()?,
|
||||
)),
|
||||
NuValue::Date { val, .. } => Ok(PlistValue::Date(SystemTime::from(val.to_owned()).into())),
|
||||
NuValue::Filesize { val, .. } => Ok(PlistValue::Integer(Into::<Integer>::into(*val))),
|
||||
_ => Err(build_label_error(
|
||||
format!("{:?} is not convertible", nu_val),
|
||||
span,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_nu_dict(record: &Record) -> Result<PlistValue, LabeledError> {
|
||||
Ok(PlistValue::Dictionary(
|
||||
record
|
||||
.iter()
|
||||
.map(|(k, v)| convert_nu_value(v).map(|v| (k.to_owned(), v)))
|
||||
.collect::<Result<_, _>>()?,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use nu_plugin_test_support::PluginTest;
|
||||
use nu_protocol::ShellError;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() -> Result<(), ShellError> {
|
||||
let plugin = FormatCmdsPlugin {};
|
||||
let cmd = IntoPlist {};
|
||||
|
||||
let mut plugin_test = PluginTest::new("polars", plugin.into())?;
|
||||
plugin_test.test_command_examples(&cmd)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user