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)]
#[derive(Debug, Default, Clone)]
/// String settings. Currently empty but may contain settings
/// eventually.
struct StringSettings();
/// String settings
struct StringSettings {
/// Whether to use literal strings when possible
literal: bool,
}
impl StringSettings {
fn pretty() -> StringSettings {
StringSettings {
literal: true,
}
}
}
#[derive(Debug, Default, Clone)]
#[doc(hidden)]
@ -259,7 +269,7 @@ impl<'a> Serializer<'a> {
state: State::End,
settings: Rc::new(Settings {
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 {
Rc::get_mut(&mut self.settings).unwrap().string = if value {
Some(StringSettings())
Some(StringSettings::pretty())
} else {
None
};
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
///
/// 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() {
do_pretty(value)
match (&self.settings.string, do_pretty(value)) {
(&Some(StringSettings { literal: false, .. }), Repr::Literal(_, ty)) =>
Repr::Std(ty),
(_, r @ _) => r,
}
} else {
Repr::Std(Type::OnelineSingle)
};
@ -569,8 +626,11 @@ impl<'a> Serializer<'a> {
Repr::Std(ty) => {
match ty {
Type::NewlineTripple => self.dst.push_str("\"\"\"\n"),
Type::OnelineSingle => self.dst.push('"'),
_ => unreachable!(),
// note: OnelineTripple can happen if do_pretty wants to do
// '''it's one line'''
// but settings.string.literal == false
Type::OnelineSingle |
Type::OnelineTripple => self.dst.push('"'),
}
for ch in value.chars() {
match ch {
@ -593,8 +653,7 @@ impl<'a> Serializer<'a> {
}
match ty {
Type::NewlineTripple => self.dst.push_str("\"\"\""),
Type::OnelineSingle => self.dst.push('"'),
_ => unreachable!(),
Type::OnelineSingle | Type::OnelineTripple => self.dst.push('"'),
}
},
}

View file

@ -198,7 +198,7 @@ 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 third line
this is the fourth line
"""
"##;
@ -260,3 +260,45 @@ fn table_array() {
println!("\nRESULT:\n{}", 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);
}