add pretty_string_literal to be able to disable literal strings

This commit is contained in:
Garrett Berg 2017-08-13 16:15:15 -06:00
parent 8554fda201
commit d386be1a49
2 changed files with 112 additions and 11 deletions

View file

@ -169,9 +169,19 @@ impl ArraySettings {
#[doc(hidden)] #[doc(hidden)]
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
/// String settings. Currently empty but may contain settings /// String settings
/// eventually. struct StringSettings {
struct StringSettings(); /// Whether to use literal strings when possible
literal: bool,
}
impl StringSettings {
fn pretty() -> StringSettings {
StringSettings {
literal: true,
}
}
}
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
#[doc(hidden)] #[doc(hidden)]
@ -259,7 +269,7 @@ impl<'a> Serializer<'a> {
state: State::End, state: State::End,
settings: Rc::new(Settings { settings: Rc::new(Settings {
array: Some(ArraySettings::pretty()), array: Some(ArraySettings::pretty()),
string: Some(StringSettings()), string: Some(StringSettings::pretty()),
}), }),
} }
} }
@ -289,13 +299,56 @@ impl<'a> Serializer<'a> {
/// ``` /// ```
pub fn pretty_string(&mut self, value: bool) -> &mut Self { pub fn pretty_string(&mut self, value: bool) -> &mut Self {
Rc::get_mut(&mut self.settings).unwrap().string = if value { Rc::get_mut(&mut self.settings).unwrap().string = if value {
Some(StringSettings()) Some(StringSettings::pretty())
} else { } else {
None None
}; };
self self
} }
/// Enable or Disable Literal strings for pretty strings
///
/// If enabled, literal strings will be used when possible and strings with
/// one or more newlines will use triple quotes (i.e.: `'''` or `"""`)
///
/// If disabled, literal strings will NEVER be used and strings with one or
/// more newlines will use `"""`
///
/// # Examples
///
/// Instead of:
///
/// ```toml,ignore
/// single = "no newlines"
/// text = "\nfoo\nbar\n"
/// ```
///
/// You will have:
///
/// ```toml,ignore
/// single = "no newlines"
/// text = """
/// foo
/// bar
/// """
/// ```
pub fn pretty_string_literal(&mut self, value: bool) -> &mut Self {
let use_default = if let &mut Some(ref mut s) = &mut Rc::get_mut(&mut self.settings)
.unwrap().string {
s.literal = value;
false
} else {
true
};
if use_default {
let mut string = StringSettings::pretty();
string.literal = value;
Rc::get_mut(&mut self.settings).unwrap().string = Some(string);
}
self
}
/// Enable or Disable pretty arrays /// Enable or Disable pretty arrays
/// ///
/// If enabled, arrays will always have each item on their own line. /// If enabled, arrays will always have each item on their own line.
@ -548,7 +601,11 @@ impl<'a> Serializer<'a> {
} }
let repr = if !is_key && self.settings.string.is_some() { let repr = if !is_key && self.settings.string.is_some() {
do_pretty(value) match (&self.settings.string, do_pretty(value)) {
(&Some(StringSettings { literal: false, .. }), Repr::Literal(_, ty)) =>
Repr::Std(ty),
(_, r @ _) => r,
}
} else { } else {
Repr::Std(Type::OnelineSingle) Repr::Std(Type::OnelineSingle)
}; };
@ -569,8 +626,11 @@ impl<'a> Serializer<'a> {
Repr::Std(ty) => { Repr::Std(ty) => {
match ty { match ty {
Type::NewlineTripple => self.dst.push_str("\"\"\"\n"), Type::NewlineTripple => self.dst.push_str("\"\"\"\n"),
Type::OnelineSingle => self.dst.push('"'), // note: OnelineTripple can happen if do_pretty wants to do
_ => unreachable!(), // '''it's one line'''
// but settings.string.literal == false
Type::OnelineSingle |
Type::OnelineTripple => self.dst.push('"'),
} }
for ch in value.chars() { for ch in value.chars() {
match ch { match ch {
@ -593,8 +653,7 @@ impl<'a> Serializer<'a> {
} }
match ty { match ty {
Type::NewlineTripple => self.dst.push_str("\"\"\""), Type::NewlineTripple => self.dst.push_str("\"\"\""),
Type::OnelineSingle => self.dst.push('"'), Type::OnelineSingle | Type::OnelineTripple => self.dst.push('"'),
_ => unreachable!(),
} }
}, },
} }

View file

@ -198,7 +198,7 @@ text = """
this is the first line. this is the first line.
This has a ''' in it and \"\"\" cuz it's tricky yo This has a ''' in it and \"\"\" cuz it's tricky yo
Also ' and \" because why not Also ' and \" because why not
this is the third line this is the fourth line
""" """
"##; "##;
@ -260,3 +260,45 @@ fn table_array() {
println!("\nRESULT:\n{}", result); println!("\nRESULT:\n{}", result);
assert_eq!(toml, &result); assert_eq!(toml, &result);
} }
// FIXME: add the `glass` line to this. Unfortunately there seems to
// be an issue with the deserialization module that treats the first \n
// as a real newline in that case (not cool)
const PRETTY_TRICKY_NON_LITERAL: &'static str = r##"[example]
f = "\f"
plain = """
This has a couple of lines
Because it likes to.
"""
r = "\r"
r_newline = """
\r
"""
single = "this is a single line but has '' cuz it's tricky"
single_tricky = "single line with ''' in it"
tabs = """
this is pretty standard
\texcept for some \ttabs right here
"""
text = """
this is the first line.
This has a ''' in it and \"\"\" cuz it's tricky yo
Also ' and \" because why not
this is the fourth line
"""
"##;
#[test]
fn pretty_tricky_non_literal() {
let toml = PRETTY_TRICKY_NON_LITERAL;
let value: toml::Value = toml::from_str(toml).unwrap();
let mut result = String::with_capacity(128);
{
let mut serializer = toml::Serializer::pretty(&mut result);
serializer.pretty_string_literal(false);
value.serialize(&mut serializer).unwrap();
}
println!("EXPECTED:\n{}", toml);
println!("\nRESULT:\n{}", result);
assert_eq!(toml, &result);
}