difftreelog
feat dprint support
in: trunk
2 files changed
crates/nixlike/src/lib.rsdiffbeforeafterboth1use std::collections::BTreeMap;23use peg::str::LineCol;4use se_impl::MySerialize;5use serde::{Deserialize, Serialize};67mod de_impl;8mod se_impl;9mod to_string;1011#[derive(thiserror::Error, Debug)]12pub enum Error {13 #[error("bad number")]14 BadNumber,15 #[error("expected {0}")]16 Expected(&'static str),17 #[error("parse error")]18 ParseError(#[from] peg::error::ParseError<LineCol>),19 #[error("{0}")]20 Custom(String),21 #[error("io: {0}")]22 Io(#[from] std::io::Error),23 #[error("fmt: {0}")]24 Fmt(#[from] std::fmt::Error),25}2627#[derive(Debug)]28pub enum Value {29 Number(i64),30 String(String),31 Boolean(bool),32 Object(BTreeMap<String, Value>),33 Array(Vec<Value>),34 Null,35}3637peg::parser! {38pub grammar nixlike() for str {39 rule number() -> i6440 = quiet! { v:$(['0'..='9' | '+' | '-']+) {? v.parse().map_err(|_| "<number>")} } / expected!("<number>")41 rule string_char() -> &'input str42 = "\\\"" { "\"" }43 / "\\\\" { "\\" }44 / c:$([_]) { c }45 rule string() -> String46 = quiet! { "\"" v:(!"\"" c:string_char() {c})* "\"" { v.into_iter().collect() } } / expected!("<string>")47 rule boolean() -> bool48 = quiet! { "true" {true}49 / "false" {false} } / expected!("<boolean>")50 rule indent() -> String51 = quiet! { s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() } } / expected!("<identifier>")52 rule object() -> BTreeMap<String, Value>53 = "{" _54 e:(k:indent()++(_ "." _) _ "=" _ v:value() _ ";" _ {(k, v)})*55 "}" {?56 let mut out = BTreeMap::new();57 for (k, v) in e {58 let mut map = &mut out;59 for v in k.iter().take(k.len() - 1) {60 map = match map.entry(v.clone()).or_insert_with(|| Value::Object(Default::default())) {61 Value::Object(v) => v,62 _ => return Err("expected object"),63 }64 }6566 let key = k.into_iter().last().unwrap();67 if map.contains_key(&key) {68 return Err("can't override object");69 }70 map.insert(key, v);71 }72 Ok(out)73 }7475 rule array() -> Vec<Value>76 = "[" _ v:value()**_ _ "]" {v}7778 rule value() -> Value79 = o:object() { Value::Object(o) }80 / a:array() { Value::Array(a) }81 / s:string() { Value::String(s) }82 / "null" { Value::Null }83 / b:boolean() { Value::Boolean(b) }84 / n:number() { Value::Number(n) }8586 pub rule root() -> Value87 = _ v:value() _ { v }8889 rule _()90 = ( quiet!{ [' ' | '\t' | '\n']+ }91 / "#" (!['\n'] [_])* "\n" )*92}93}9495pub fn parse_str<'de, D: Deserialize<'de>>(s: &str) -> Result<D, Error> {96 let value = nixlike::root(s)?;97 D::deserialize(value)98}99100pub fn parse_value<'de, D: Deserialize<'de>>(value: Value) -> Result<D, Error> {101 D::deserialize(value)102}103104pub fn serialize_value_pretty(value: Value) -> Result<String, Error> {105 to_string::write_nix(&value)106}107108pub fn serialize<S: Serialize>(value: S) -> Result<String, Error> {109 let value: Value = value.serialize(MySerialize)?;110 serialize_value_pretty(value)111}112113#[test]114fn test() {115 let v: serde_json::Value = parse_str(116 r#"117 {118 b.c = 2;119 b.d = "hello";120 c = {121 k = 123;122 p = 231;123 ll = [1 2 3 [] [[4 5 6]] ];124 };125 }126 "#,127 )128 .unwrap();129 let s: String = serialize(v).unwrap();130 println!("{}", s);131}1use std::collections::BTreeMap;23use peg::str::LineCol;4use se_impl::MySerialize;5use serde::{Deserialize, Serialize};67mod de_impl;8mod se_impl;9mod to_string;1011#[derive(thiserror::Error, Debug)]12pub enum Error {13 #[error("bad number")]14 BadNumber,15 #[error("expected {0}")]16 Expected(&'static str),17 #[error("parse error")]18 ParseError(#[from] peg::error::ParseError<LineCol>),19 #[error("{0}")]20 Custom(String),21 #[error("io: {0}")]22 Io(#[from] std::io::Error),23 #[error("fmt: {0}")]24 Fmt(#[from] std::fmt::Error),25}2627#[derive(Debug)]28pub enum Value {29 Number(i64),30 String(String),31 Boolean(bool),32 Object(BTreeMap<String, Value>),33 Array(Vec<Value>),34 Null,35}3637peg::parser! {38pub grammar nixlike() for str {39 rule number() -> i6440 = quiet! { v:$(['0'..='9' | '+' | '-']+) {? v.parse().map_err(|_| "<number>")} } / expected!("<number>")41 rule string_char() -> &'input str42 = "\\\"" { "\"" }43 / "\\\\" { "\\" }44 / c:$([_]) { c }45 rule string() -> String46 = quiet! { "\"" v:(!"\"" c:string_char() {c})* "\"" { v.into_iter().collect() } } / expected!("<string>")47 rule boolean() -> bool48 = quiet! { "true" {true}49 / "false" {false} } / expected!("<boolean>")50 rule indent() -> String51 = quiet! { s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() } } / expected!("<identifier>")52 rule object() -> BTreeMap<String, Value>53 = "{" _54 e:(k:indent()++(_ "." _) _ "=" _ v:value() _ ";" _ {(k, v)})*55 "}" {?56 let mut out = BTreeMap::new();57 for (k, v) in e {58 let mut map = &mut out;59 for v in k.iter().take(k.len() - 1) {60 map = match map.entry(v.clone()).or_insert_with(|| Value::Object(Default::default())) {61 Value::Object(v) => v,62 _ => return Err("expected object"),63 }64 }6566 let key = k.into_iter().last().unwrap();67 if map.contains_key(&key) {68 return Err("can't override object");69 }70 map.insert(key, v);71 }72 Ok(out)73 }7475 rule array() -> Vec<Value>76 = "[" _ v:value()**_ _ "]" {v}7778 rule value() -> Value79 = o:object() { Value::Object(o) }80 / a:array() { Value::Array(a) }81 / s:string() { Value::String(s) }82 / "null" { Value::Null }83 / b:boolean() { Value::Boolean(b) }84 / n:number() { Value::Number(n) }8586 pub rule root() -> Value87 = _ v:value() _ { v }8889 rule _()90 = ( quiet!{ [' ' | '\t' | '\n']+ }91 / "#" (!['\n'] [_])* "\n" )*92}93}9495pub fn parse_str<'de, D: Deserialize<'de>>(s: &str) -> Result<D, Error> {96 let value = nixlike::root(s)?;97 D::deserialize(value)98}99100pub fn parse_value<'de, D: Deserialize<'de>>(value: Value) -> Result<D, Error> {101 D::deserialize(value)102}103104pub fn serialize_value_pretty(value: Value) -> String {105 to_string::write_nix(&value)106}107108pub fn serialize<S: Serialize>(value: S) -> Result<String, Error> {109 let value: Value = value.serialize(MySerialize)?;110 Ok(serialize_value_pretty(value))111}112113#[test]114fn test() {115 let v: serde_json::Value = parse_str(116 r#"117 {118 b.c = 2;119 b.d = "hello";120 c = {121 k = 123;122 p = 231;123 ll = [1 2 3 [] [[4 5 6]] ];124 };125 }126 "#,127 )128 .unwrap();129 let s: String = serialize(v).unwrap();130 println!("{}", s);131}crates/nixlike/src/to_string.rsdiffbeforeafterboth--- a/crates/nixlike/src/to_string.rs
+++ b/crates/nixlike/src/to_string.rs
@@ -1,74 +1,111 @@
-use crate::{Error, Value};
+use crate::Value;
+use dprint_core::formatting::{
+ condition_resolvers, conditions, format, ConditionResolverContext, Info, PrintItems,
+ PrintOptions, Signal,
+};
-fn write_nix_obj_key_buf(
- k: &str,
- v: &Value,
- out: &mut String,
- indent: &mut String,
-) -> Result<(), Error> {
- use std::fmt::Write;
- write!(out, "{}", k)?;
+fn write_nix_obj_key_buf(k: &str, v: &Value, out: &mut PrintItems) {
+ out.push_str(k);
match v {
Value::Object(o) if o.len() == 1 => {
let (k, v) = o.iter().next().unwrap();
- write!(out, ".")?;
- write_nix_obj_key_buf(k, v, out, indent)?;
+
+ out.push_str(".");
+ write_nix_obj_key_buf(k, v, out);
}
v => {
- write!(out, " = ")?;
- write_nix_buf(v, out, indent)?;
- writeln!(out, ";")?;
+ out.push_str(" = ");
+ write_nix_buf(v, out);
+ out.push_str(";");
}
}
- Ok(())
}
-fn write_nix_buf(value: &Value, out: &mut String, indent: &mut String) -> Result<(), Error> {
- use std::fmt::Write;
+fn write_nix_buf(value: &Value, out: &mut PrintItems) {
match value {
- Value::Null => write!(out, "null")?,
- Value::Boolean(v) => write!(out, "{:?}", v)?,
- Value::Number(n) => write!(out, "{}", n)?,
- Value::String(s) => write!(out, "{:?}", s)?,
+ Value::Null => out.push_str("null"),
+ Value::Boolean(v) => out.push_str(if *v { "true" } else { "false" }),
+ Value::Number(n) => out.push_str(&format!("{}", n)),
+ Value::String(s) => out.push_str(&format!("{:?}", s)),
Value::Array(a) => {
if a.is_empty() {
- write!(out, "[ ]")?;
+ out.push_str("[ ]");
} else {
- writeln!(out, "[")?;
- let old_len = indent.len();
- indent.push_str(" ");
+ let start_info = Info::new("start");
+ let end_info = Info::new("end");
+ let is_multiple_lines = move |ctx: &mut ConditionResolverContext| {
+ condition_resolvers::is_multiple_lines(ctx, &start_info, &end_info)
+ };
+ out.push_str("[");
+ out.push_info(start_info);
+ out.push_signal(Signal::StartIndent);
+ out.push_condition(conditions::if_true_or(
+ "array start",
+ is_multiple_lines.clone(),
+ Signal::NewLine.into(),
+ Signal::SpaceOrNewLine.into(),
+ ));
for item in a {
- write!(out, "{}", indent)?;
- write_nix_buf(item, out, indent)?;
- writeln!(out)?;
+ write_nix_buf(item, out);
+ out.push_condition(conditions::if_true_or(
+ "element separator",
+ is_multiple_lines.clone(),
+ Signal::NewLine.into(),
+ Signal::SpaceOrNewLine.into(),
+ ));
}
- indent.truncate(old_len);
- write!(out, "{}]", indent)?;
+ out.push_signal(Signal::FinishIndent);
+ out.push_info(end_info);
+ out.push_str("]");
}
}
Value::Object(obj) => {
if obj.is_empty() {
- write!(out, "{{ }}")?;
+ out.push_str("{ }")
} else {
- writeln!(out, "{{")?;
- let old_len = indent.len();
- indent.push_str(" ");
+ let start_info = Info::new("start");
+ let end_info = Info::new("end");
+ let is_multiple_lines = move |ctx: &mut ConditionResolverContext| {
+ condition_resolvers::is_multiple_lines(ctx, &start_info, &end_info)
+ };
+ out.push_str("{");
+ out.push_info(start_info);
+ out.push_signal(Signal::StartIndent);
+ out.push_condition(conditions::if_true_or(
+ "object start",
+ is_multiple_lines.clone(),
+ Signal::NewLine.into(),
+ Signal::SpaceOrNewLine.into(),
+ ));
for (k, v) in obj {
- write!(out, "{}", indent)?;
- write_nix_obj_key_buf(k, v, out, indent)?;
+ write_nix_obj_key_buf(k, v, out);
+ out.push_condition(conditions::if_true_or(
+ "element separator",
+ is_multiple_lines.clone(),
+ Signal::NewLine.into(),
+ Signal::SpaceOrNewLine.into(),
+ ));
}
- indent.truncate(old_len);
- write!(out, "{}}}", indent)?;
+ out.push_signal(Signal::FinishIndent);
+ out.push_info(end_info);
+ out.push_str("}");
}
}
};
- Ok(())
}
-
-pub fn write_nix(value: &Value) -> Result<String, Error> {
- let mut out = String::new();
- let mut indent = String::new();
- write_nix_buf(value, &mut out, &mut indent)?;
- Ok(out)
+pub fn write_nix(value: &Value) -> String {
+ format(
+ || {
+ let mut items = PrintItems::new();
+ write_nix_buf(value, &mut items);
+ items
+ },
+ PrintOptions {
+ max_width: 120,
+ use_tabs: false,
+ indent_width: 2,
+ new_line_text: "\n",
+ },
+ )
}