mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 23:04:49 +00:00
don't run pretty.rs tests
This commit is contained in:
parent
ba16eff24d
commit
51a3c72424
4 changed files with 63 additions and 592 deletions
|
@ -7,13 +7,8 @@ use roc_types::subs::{Content, Subs};
|
||||||
use roc_types::types::{write_error_type, ErrorType};
|
use roc_types::types::{write_error_type, ErrorType};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
// use ven_pretty::termcolor::{Color, ColorChoice, ColorSpec, StandardStream};
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use ven_pretty::{
|
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder, Render, RenderAnnotated};
|
||||||
BoxAllocator, BoxDoc, DocAllocator, DocBuilder, FmtWrite, Render, RenderAnnotated,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Doc<'a> = DocBuilder<'a, BoxAllocator, Annotation>;
|
|
||||||
|
|
||||||
/// A textual report.
|
/// A textual report.
|
||||||
pub struct Report {
|
pub struct Report {
|
||||||
|
@ -210,10 +205,6 @@ pub fn url(str: &str) -> ReportText {
|
||||||
ReportText::Url(Box::from(str))
|
ReportText::Url(Box::from(str))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_indent(n: usize, report_text: ReportText) -> ReportText {
|
|
||||||
ReportText::Indent(n, Box::new(report_text))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const RED_CODE: &str = "\u{001b}[31m";
|
pub const RED_CODE: &str = "\u{001b}[31m";
|
||||||
pub const WHITE_CODE: &str = "\u{001b}[37m";
|
pub const WHITE_CODE: &str = "\u{001b}[37m";
|
||||||
pub const BLUE_CODE: &str = "\u{001b}[34m";
|
pub const BLUE_CODE: &str = "\u{001b}[34m";
|
||||||
|
@ -228,12 +219,6 @@ pub const UNDERLINE_CODE: &str = "\u{001b}[4m";
|
||||||
|
|
||||||
pub const RESET_CODE: &str = "\u{001b}[0m";
|
pub const RESET_CODE: &str = "\u{001b}[0m";
|
||||||
|
|
||||||
struct CiEnv<'a> {
|
|
||||||
home: ModuleId,
|
|
||||||
src_lines: &'a [&'a str],
|
|
||||||
interns: &'a Interns,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CiWrite<W> {
|
pub struct CiWrite<W> {
|
||||||
style_stack: Vec<Annotation>,
|
style_stack: Vec<Annotation>,
|
||||||
upstream: W,
|
upstream: W,
|
||||||
|
@ -445,11 +430,11 @@ impl ReportText {
|
||||||
src_lines: &[&str],
|
src_lines: &[&str],
|
||||||
interns: &Interns,
|
interns: &Interns,
|
||||||
) {
|
) {
|
||||||
let allocator = BoxAllocator;
|
let alloc = BoxAllocator;
|
||||||
|
|
||||||
let err_msg = "<buffer is not a utf-8 encoded string>";
|
let err_msg = "<buffer is not a utf-8 encoded string>";
|
||||||
|
|
||||||
self.pretty::<_>(&allocator, subs, home, src_lines, interns)
|
self.pretty::<_>(&alloc, subs, home, src_lines, interns)
|
||||||
.1
|
.1
|
||||||
.render_raw(70, &mut CiWrite::new(buf))
|
.render_raw(70, &mut CiWrite::new(buf))
|
||||||
.expect(err_msg);
|
.expect(err_msg);
|
||||||
|
@ -465,11 +450,11 @@ impl ReportText {
|
||||||
interns: &Interns,
|
interns: &Interns,
|
||||||
palette: &Palette,
|
palette: &Palette,
|
||||||
) {
|
) {
|
||||||
let allocator = BoxAllocator;
|
let alloc = BoxAllocator;
|
||||||
|
|
||||||
let err_msg = "<buffer is not a utf-8 encoded string>";
|
let err_msg = "<buffer is not a utf-8 encoded string>";
|
||||||
|
|
||||||
self.pretty::<_>(&allocator, subs, home, src_lines, interns)
|
self.pretty::<_>(&alloc, subs, home, src_lines, interns)
|
||||||
.1
|
.1
|
||||||
.render_raw(70, &mut ColorWrite::new(palette, buf))
|
.render_raw(70, &mut ColorWrite::new(palette, buf))
|
||||||
.expect(err_msg);
|
.expect(err_msg);
|
||||||
|
@ -479,7 +464,7 @@ impl ReportText {
|
||||||
/// monospace font, etc) is done in the CiWrite and ColorWrite `RenderAnnotated` instances.
|
/// monospace font, etc) is done in the CiWrite and ColorWrite `RenderAnnotated` instances.
|
||||||
pub fn pretty<'b, D>(
|
pub fn pretty<'b, D>(
|
||||||
self,
|
self,
|
||||||
allocator: &'b D,
|
alloc: &'b D,
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
src_lines: &'b [&'b str],
|
src_lines: &'b [&'b str],
|
||||||
|
@ -492,30 +477,30 @@ impl ReportText {
|
||||||
use ReportText::*;
|
use ReportText::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Plain(string) => allocator
|
Plain(string) => alloc
|
||||||
.text(format!("{}", string))
|
.text(format!("{}", string))
|
||||||
.annotate(Annotation::PlainText),
|
.annotate(Annotation::PlainText),
|
||||||
EmText(string) => allocator
|
EmText(string) => alloc
|
||||||
.text(format!("{}", string))
|
.text(format!("{}", string))
|
||||||
.annotate(Annotation::Emphasized),
|
.annotate(Annotation::Emphasized),
|
||||||
Url(url) => allocator.text(format!("{}", url)).annotate(Annotation::Url),
|
Url(url) => alloc.text(format!("{}", url)).annotate(Annotation::Url),
|
||||||
Keyword(string) => allocator
|
Keyword(string) => alloc
|
||||||
.text(format!("{}", string))
|
.text(format!("{}", string))
|
||||||
.annotate(Annotation::Keyword),
|
.annotate(Annotation::Keyword),
|
||||||
GlobalTag(string) => allocator
|
GlobalTag(string) => alloc
|
||||||
.text(format!("{}", string))
|
.text(format!("{}", string))
|
||||||
.annotate(Annotation::GlobalTag),
|
.annotate(Annotation::GlobalTag),
|
||||||
RecordField(string) => allocator
|
RecordField(string) => alloc
|
||||||
.text(format!(".{}", string))
|
.text(format!(".{}", string))
|
||||||
.annotate(Annotation::RecordField),
|
.annotate(Annotation::RecordField),
|
||||||
PrivateTag(symbol) => {
|
PrivateTag(symbol) => {
|
||||||
if symbol.module_id() == home {
|
if symbol.module_id() == home {
|
||||||
// Render it unqualified if it's in the current module.
|
// Render it unqualified if it's in the current module.
|
||||||
allocator
|
alloc
|
||||||
.text(format!("{}", symbol.ident_string(interns)))
|
.text(format!("{}", symbol.ident_string(interns)))
|
||||||
.annotate(Annotation::PrivateTag)
|
.annotate(Annotation::PrivateTag)
|
||||||
} else {
|
} else {
|
||||||
allocator
|
alloc
|
||||||
.text(format!(
|
.text(format!(
|
||||||
"{}.{}",
|
"{}.{}",
|
||||||
symbol.module_string(interns),
|
symbol.module_string(interns),
|
||||||
|
@ -527,11 +512,11 @@ impl ReportText {
|
||||||
Value(symbol) => {
|
Value(symbol) => {
|
||||||
if symbol.module_id() == home {
|
if symbol.module_id() == home {
|
||||||
// Render it unqualified if it's in the current module.
|
// Render it unqualified if it's in the current module.
|
||||||
allocator
|
alloc
|
||||||
.text(format!("{}", symbol.ident_string(interns)))
|
.text(format!("{}", symbol.ident_string(interns)))
|
||||||
.annotate(Annotation::Symbol)
|
.annotate(Annotation::Symbol)
|
||||||
} else {
|
} else {
|
||||||
allocator
|
alloc
|
||||||
.text(format!(
|
.text(format!(
|
||||||
"{}.{}",
|
"{}.{}",
|
||||||
symbol.module_string(interns),
|
symbol.module_string(interns),
|
||||||
|
@ -541,55 +526,53 @@ impl ReportText {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Module(module_id) => allocator
|
Module(module_id) => alloc
|
||||||
.text(format!("{}", interns.module_name(module_id)))
|
.text(format!("{}", interns.module_name(module_id)))
|
||||||
.annotate(Annotation::Module),
|
.annotate(Annotation::Module),
|
||||||
Type(content) => match content {
|
Type(content) => match content {
|
||||||
Content::FlexVar(_) | Content::RigidVar(_) => allocator
|
Content::FlexVar(_) | Content::RigidVar(_) => alloc
|
||||||
.text(content_to_string(content, subs, home, interns))
|
.text(content_to_string(content, subs, home, interns))
|
||||||
.annotate(Annotation::TypeVariable),
|
.annotate(Annotation::TypeVariable),
|
||||||
|
|
||||||
Content::Structure(_) => allocator
|
Content::Structure(_) => alloc
|
||||||
.text(content_to_string(content, subs, home, interns))
|
.text(content_to_string(content, subs, home, interns))
|
||||||
.annotate(Annotation::Structure),
|
.annotate(Annotation::Structure),
|
||||||
|
|
||||||
Content::Alias(_, _, _) => allocator
|
Content::Alias(_, _, _) => alloc
|
||||||
.text(content_to_string(content, subs, home, interns))
|
.text(content_to_string(content, subs, home, interns))
|
||||||
.annotate(Annotation::Alias),
|
.annotate(Annotation::Alias),
|
||||||
|
|
||||||
Content::Error => allocator.text(content_to_string(content, subs, home, interns)),
|
Content::Error => alloc.text(content_to_string(content, subs, home, interns)),
|
||||||
},
|
},
|
||||||
ErrorType(error_type) => allocator
|
ErrorType(error_type) => alloc
|
||||||
.nil()
|
.nil()
|
||||||
.append(allocator.hardline())
|
.append(alloc.hardline())
|
||||||
.append(
|
.append(
|
||||||
allocator
|
alloc
|
||||||
.text(write_error_type(home, interns, error_type))
|
.text(write_error_type(home, interns, error_type))
|
||||||
.indent(4),
|
.indent(4),
|
||||||
)
|
)
|
||||||
.append(allocator.hardline()),
|
.append(alloc.hardline()),
|
||||||
|
|
||||||
Indent(n, nested) => {
|
Indent(n, nested) => {
|
||||||
let rest = nested.pretty(allocator, subs, home, src_lines, interns);
|
let rest = nested.pretty(alloc, subs, home, src_lines, interns);
|
||||||
allocator.nil().append(rest).indent(n)
|
alloc.nil().append(rest).indent(n)
|
||||||
}
|
}
|
||||||
Docs(_) => {
|
Docs(_) => {
|
||||||
panic!("TODO implment docs");
|
panic!("TODO implment docs");
|
||||||
}
|
}
|
||||||
Concat(report_texts) => allocator.concat(
|
Concat(report_texts) => alloc.concat(
|
||||||
report_texts
|
report_texts
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|rep| rep.pretty(allocator, subs, home, src_lines, interns)),
|
.map(|rep| rep.pretty(alloc, subs, home, src_lines, interns)),
|
||||||
),
|
),
|
||||||
Stack(report_texts) => allocator.intersperse(
|
Stack(report_texts) => alloc.intersperse(
|
||||||
report_texts
|
report_texts
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|rep| (rep.pretty(allocator, subs, home, src_lines, interns))),
|
.map(|rep| (rep.pretty(alloc, subs, home, src_lines, interns))),
|
||||||
allocator.hardline(),
|
alloc.hardline(),
|
||||||
),
|
),
|
||||||
BinOp(bin_op) => allocator
|
BinOp(bin_op) => alloc.text(bin_op.to_string()).annotate(Annotation::BinOp),
|
||||||
.text(bin_op.to_string())
|
|
||||||
.annotate(Annotation::BinOp),
|
|
||||||
Region(region) => {
|
Region(region) => {
|
||||||
let max_line_number_length = (region.end_line + 1).to_string().len();
|
let max_line_number_length = (region.end_line + 1).to_string().len();
|
||||||
let indent = 2;
|
let indent = 2;
|
||||||
|
@ -603,42 +586,42 @@ impl ReportText {
|
||||||
|
|
||||||
let line = src_lines[i as usize];
|
let line = src_lines[i as usize];
|
||||||
let rest_of_line = if line.trim().is_empty() {
|
let rest_of_line = if line.trim().is_empty() {
|
||||||
allocator.nil()
|
alloc.nil()
|
||||||
} else {
|
} else {
|
||||||
allocator
|
alloc
|
||||||
.nil()
|
.nil()
|
||||||
.append(allocator.text(line).indent(2))
|
.append(alloc.text(line).indent(2))
|
||||||
.annotate(Annotation::CodeBlock)
|
.annotate(Annotation::CodeBlock)
|
||||||
};
|
};
|
||||||
|
|
||||||
let source_line = allocator
|
let source_line = alloc
|
||||||
.line()
|
.line()
|
||||||
.append(
|
.append(
|
||||||
allocator
|
alloc
|
||||||
.text(" ".repeat(max_line_number_length - this_line_number_length)),
|
.text(" ".repeat(max_line_number_length - this_line_number_length)),
|
||||||
)
|
)
|
||||||
.append(allocator.text(line_number).annotate(Annotation::LineNumber))
|
.append(alloc.text(line_number).annotate(Annotation::LineNumber))
|
||||||
.append(allocator.text(" ┆").annotate(Annotation::GutterBar))
|
.append(alloc.text(" ┆").annotate(Annotation::GutterBar))
|
||||||
.append(rest_of_line);
|
.append(rest_of_line);
|
||||||
|
|
||||||
let highlight_line = allocator
|
let highlight_line = alloc
|
||||||
.line()
|
.line()
|
||||||
.append(allocator.text(" ".repeat(max_line_number_length)))
|
.append(alloc.text(" ".repeat(max_line_number_length)))
|
||||||
.append(allocator.text(" ┆").annotate(Annotation::GutterBar))
|
.append(alloc.text(" ┆").annotate(Annotation::GutterBar))
|
||||||
.append(
|
.append(
|
||||||
allocator
|
alloc
|
||||||
.text(" ".repeat(region.start_col as usize))
|
.text(" ".repeat(region.start_col as usize))
|
||||||
.indent(indent),
|
.indent(indent),
|
||||||
)
|
)
|
||||||
.append(
|
.append(
|
||||||
allocator
|
alloc
|
||||||
.text("^".repeat((region.end_col - region.start_col) as usize))
|
.text("^".repeat((region.end_col - region.start_col) as usize))
|
||||||
.annotate(Annotation::Error),
|
.annotate(Annotation::Error),
|
||||||
);
|
);
|
||||||
|
|
||||||
source_line.append(highlight_line)
|
source_line.append(highlight_line)
|
||||||
} else {
|
} else {
|
||||||
let mut result = allocator.nil();
|
let mut result = alloc.nil();
|
||||||
for i in region.start_line..=region.end_line {
|
for i in region.start_line..=region.end_line {
|
||||||
let line_number_string = (i + 1).to_string();
|
let line_number_string = (i + 1).to_string();
|
||||||
let line_number = line_number_string;
|
let line_number = line_number_string;
|
||||||
|
@ -646,37 +629,36 @@ impl ReportText {
|
||||||
|
|
||||||
let line = src_lines[i as usize];
|
let line = src_lines[i as usize];
|
||||||
let rest_of_line = if !line.trim().is_empty() {
|
let rest_of_line = if !line.trim().is_empty() {
|
||||||
allocator
|
alloc
|
||||||
.text(line)
|
.text(line)
|
||||||
.annotate(Annotation::CodeBlock)
|
.annotate(Annotation::CodeBlock)
|
||||||
.indent(indent)
|
.indent(indent)
|
||||||
} else {
|
} else {
|
||||||
allocator.nil()
|
alloc.nil()
|
||||||
};
|
};
|
||||||
|
|
||||||
let source_line = allocator
|
let source_line =
|
||||||
.line()
|
alloc
|
||||||
.append(
|
.line()
|
||||||
allocator.text(
|
.append(alloc.text(
|
||||||
" ".repeat(max_line_number_length - this_line_number_length),
|
" ".repeat(max_line_number_length - this_line_number_length),
|
||||||
),
|
))
|
||||||
)
|
.append(alloc.text(line_number).annotate(Annotation::LineNumber))
|
||||||
.append(allocator.text(line_number).annotate(Annotation::LineNumber))
|
.append(alloc.text(" ┆").annotate(Annotation::GutterBar))
|
||||||
.append(allocator.text(" ┆").annotate(Annotation::GutterBar))
|
.append(alloc.text(">").annotate(Annotation::Error))
|
||||||
.append(allocator.text(">").annotate(Annotation::Error))
|
.append(rest_of_line);
|
||||||
.append(rest_of_line);
|
|
||||||
|
|
||||||
result = result.append(source_line);
|
result = result.append(source_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
};
|
};
|
||||||
allocator
|
alloc
|
||||||
.nil()
|
.nil()
|
||||||
.append(allocator.line())
|
.append(alloc.line())
|
||||||
.append(body)
|
.append(body)
|
||||||
.append(allocator.line())
|
.append(alloc.line())
|
||||||
.append(allocator.line())
|
.append(alloc.line())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::report::{
|
use crate::report::{
|
||||||
global_tag_text, keyword_text, plain_text, private_tag_text, record_field_text, with_indent,
|
global_tag_text, keyword_text, plain_text, private_tag_text, record_field_text, Report,
|
||||||
Report, ReportText,
|
ReportText,
|
||||||
};
|
};
|
||||||
use roc_can::expected::{Expected, PExpected};
|
use roc_can::expected::{Expected, PExpected};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
|
|
11
vendor/pretty/Cargo.toml
vendored
11
vendor/pretty/Cargo.toml
vendored
|
@ -22,14 +22,3 @@ termcolor = { version = "1.1.0", optional = true }
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
difference = "2"
|
difference = "2"
|
||||||
criterion = "0.3"
|
criterion = "0.3"
|
||||||
|
|
||||||
[[example]]
|
|
||||||
name = "trees"
|
|
||||||
|
|
||||||
[[example]]
|
|
||||||
name = "colored"
|
|
||||||
required-features = ["termcolor"]
|
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "trees"
|
|
||||||
harness = false
|
|
||||||
|
|
500
vendor/pretty/src/lib.rs
vendored
500
vendor/pretty/src/lib.rs
vendored
|
@ -1,142 +1,3 @@
|
||||||
//! This crate defines a
|
|
||||||
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
|
|
||||||
//! pretty-printing API.
|
|
||||||
//!
|
|
||||||
//! Start with with the static functions of [Doc](enum.Doc.html).
|
|
||||||
//!
|
|
||||||
//! ## Quick start
|
|
||||||
//!
|
|
||||||
//! Let's pretty-print simple sexps! We want to pretty print sexps like
|
|
||||||
//!
|
|
||||||
//! ```lisp
|
|
||||||
//! (1 2 3)
|
|
||||||
//! ```
|
|
||||||
//! or, if the line would be too long, like
|
|
||||||
//!
|
|
||||||
//! ```lisp
|
|
||||||
//! ((1)
|
|
||||||
//! (2 3)
|
|
||||||
//! (4 5 6))
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! A _simple symbolic expression_ consists of a numeric _atom_ or a nested ordered _list_ of
|
|
||||||
//! symbolic expression children.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! # use pretty::*;
|
|
||||||
//! enum SExp {
|
|
||||||
//! Atom(u32),
|
|
||||||
//! List(Vec<SExp>),
|
|
||||||
//! }
|
|
||||||
//! use SExp::*;
|
|
||||||
//! # fn main() { }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! We define a simple conversion to a [Doc](enum.Doc.html). Atoms are rendered as strings; lists
|
|
||||||
//! are recursively rendered, with spaces between children where appropriate. Children are
|
|
||||||
//! [nested]() and [grouped](), allowing them to be laid out in a single line as appropriate.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! # use pretty::*;
|
|
||||||
//! # enum SExp {
|
|
||||||
//! # Atom(u32),
|
|
||||||
//! # List(Vec<SExp>),
|
|
||||||
//! # }
|
|
||||||
//! # use SExp::*;
|
|
||||||
//! impl SExp {
|
|
||||||
//! /// Return a pretty printed format of self.
|
|
||||||
//! pub fn to_doc(&self) -> RcDoc<()> {
|
|
||||||
//! match *self {
|
|
||||||
//! Atom(ref x) => RcDoc::as_string(x),
|
|
||||||
//! List(ref xs) =>
|
|
||||||
//! RcDoc::text("(")
|
|
||||||
//! .append(RcDoc::intersperse(xs.into_iter().map(|x| x.to_doc()), Doc::line()).nest(1).group())
|
|
||||||
//! .append(RcDoc::text(")"))
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! # fn main() { }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! Next, we convert the [Doc](enum.Doc.html) to a plain old string.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! # use pretty::*;
|
|
||||||
//! # enum SExp {
|
|
||||||
//! # Atom(u32),
|
|
||||||
//! # List(Vec<SExp>),
|
|
||||||
//! # }
|
|
||||||
//! # use SExp::*;
|
|
||||||
//! # impl SExp {
|
|
||||||
//! # /// Return a pretty printed format of self.
|
|
||||||
//! # pub fn to_doc(&self) -> BoxDoc<()> {
|
|
||||||
//! # match *self {
|
|
||||||
//! # Atom(ref x) => BoxDoc::as_string(x),
|
|
||||||
//! # List(ref xs) =>
|
|
||||||
//! # BoxDoc::text("(")
|
|
||||||
//! # .append(BoxDoc::intersperse(xs.into_iter().map(|x| x.to_doc()), Doc::line()).nest(1).group())
|
|
||||||
//! # .append(BoxDoc::text(")"))
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! impl SExp {
|
|
||||||
//! pub fn to_pretty(&self, width: usize) -> String {
|
|
||||||
//! let mut w = Vec::new();
|
|
||||||
//! self.to_doc().render(width, &mut w).unwrap();
|
|
||||||
//! String::from_utf8(w).unwrap()
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! # fn main() { }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! And finally we can test that the nesting and grouping behaves as we expected.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! # use pretty::*;
|
|
||||||
//! # enum SExp {
|
|
||||||
//! # Atom(u32),
|
|
||||||
//! # List(Vec<SExp>),
|
|
||||||
//! # }
|
|
||||||
//! # use SExp::*;
|
|
||||||
//! # impl SExp {
|
|
||||||
//! # /// Return a pretty printed format of self.
|
|
||||||
//! # pub fn to_doc(&self) -> BoxDoc<()> {
|
|
||||||
//! # match *self {
|
|
||||||
//! # Atom(ref x) => BoxDoc::as_string(x),
|
|
||||||
//! # List(ref xs) =>
|
|
||||||
//! # BoxDoc::text("(")
|
|
||||||
//! # .append(BoxDoc::intersperse(xs.into_iter().map(|x| x.to_doc()), Doc::line()).nest(1).group())
|
|
||||||
//! # .append(BoxDoc::text(")"))
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! # impl SExp {
|
|
||||||
//! # pub fn to_pretty(&self, width: usize) -> String {
|
|
||||||
//! # let mut w = Vec::new();
|
|
||||||
//! # self.to_doc().render(width, &mut w).unwrap();
|
|
||||||
//! # String::from_utf8(w).unwrap()
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! # fn main() {
|
|
||||||
//! let atom = SExp::Atom(5);
|
|
||||||
//! assert_eq!("5", atom.to_pretty(10));
|
|
||||||
//! let list = SExp::List(vec![SExp::Atom(1), SExp::Atom(2), SExp::Atom(3)]);
|
|
||||||
//! assert_eq!("(1 2 3)", list.to_pretty(10));
|
|
||||||
//! assert_eq!("\
|
|
||||||
//! (1
|
|
||||||
//! 2
|
|
||||||
//! 3)", list.to_pretty(5));
|
|
||||||
//! # }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! ## Advanced usage
|
|
||||||
//!
|
|
||||||
//! There's a more efficient pattern that uses the [DocAllocator](trait.DocAllocator.html) trait, as
|
|
||||||
//! implemented by [BoxAllocator](struct.BoxAllocator.html), to allocate
|
|
||||||
//! [DocBuilder](struct.DocBuilder.html) instances. See
|
|
||||||
//! [examples/trees.rs](https://github.com/freebroccolo/pretty.rs/blob/master/examples/trees.rs#L39)
|
|
||||||
//! for this approach.
|
|
||||||
|
|
||||||
#[cfg(feature = "termcolor")]
|
#[cfg(feature = "termcolor")]
|
||||||
pub extern crate termcolor;
|
pub extern crate termcolor;
|
||||||
|
|
||||||
|
@ -547,13 +408,6 @@ where
|
||||||
|
|
||||||
/// Returns a value which implements `std::fmt::Display`
|
/// Returns a value which implements `std::fmt::Display`
|
||||||
///
|
///
|
||||||
/// ```
|
|
||||||
/// use pretty::{Doc, BoxDoc};
|
|
||||||
/// let doc = BoxDoc::<()>::group(
|
|
||||||
/// BoxDoc::text("hello").append(Doc::line()).append(Doc::text("world"))
|
|
||||||
/// );
|
|
||||||
/// assert_eq!(format!("{}", doc.pretty(80)), "hello world");
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pretty<'d>(&'d self, width: usize) -> Pretty<'a, 'd, T, A> {
|
pub fn pretty<'d>(&'d self, width: usize) -> Pretty<'a, 'd, T, A> {
|
||||||
Pretty { doc: self, width }
|
Pretty { doc: self, width }
|
||||||
|
@ -664,24 +518,6 @@ where
|
||||||
|
|
||||||
/// Acts like `line` but behaves like `nil` if grouped on a single line
|
/// Acts like `line` but behaves like `nil` if grouped on a single line
|
||||||
///
|
///
|
||||||
/// ```
|
|
||||||
/// use pretty::{Doc, RcDoc};
|
|
||||||
///
|
|
||||||
/// let doc = RcDoc::<()>::group(
|
|
||||||
/// RcDoc::text("(")
|
|
||||||
/// .append(
|
|
||||||
/// RcDoc::line_()
|
|
||||||
/// .append(Doc::text("test"))
|
|
||||||
/// .append(Doc::line())
|
|
||||||
/// .append(Doc::text("test"))
|
|
||||||
/// .nest(2),
|
|
||||||
/// )
|
|
||||||
/// .append(Doc::line_())
|
|
||||||
/// .append(Doc::text(")")),
|
|
||||||
/// );
|
|
||||||
/// assert_eq!(doc.pretty(5).to_string(), "(\n test\n test\n)");
|
|
||||||
/// assert_eq!(doc.pretty(100).to_string(), "(test test)");
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn line_(&'a self) -> DocBuilder<'a, Self, A> {
|
fn line_(&'a self) -> DocBuilder<'a, Self, A> {
|
||||||
self.hardline().flat_alt(self.nil())
|
self.hardline().flat_alt(self.nil())
|
||||||
|
@ -756,16 +592,6 @@ where
|
||||||
|
|
||||||
/// Allocate a document that acts differently based on the position and page layout
|
/// Allocate a document that acts differently based on the position and page layout
|
||||||
///
|
///
|
||||||
/// ```rust
|
|
||||||
/// use pretty::DocAllocator;
|
|
||||||
///
|
|
||||||
/// let arena = pretty::Arena::<()>::new();
|
|
||||||
/// let doc = arena.text("prefix ")
|
|
||||||
/// .append(arena.column(|l| {
|
|
||||||
/// arena.text("| <- column ").append(arena.as_string(l)).into_doc()
|
|
||||||
/// }));
|
|
||||||
/// assert_eq!(doc.1.pretty(80).to_string(), "prefix | <- column 7");
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn column(&'a self, f: impl Fn(usize) -> Self::Doc + 'a) -> DocBuilder<'a, Self, A> {
|
fn column(&'a self, f: impl Fn(usize) -> Self::Doc + 'a) -> DocBuilder<'a, Self, A> {
|
||||||
DocBuilder(self, Doc::Column(self.alloc_column_fn(f)).into())
|
DocBuilder(self, Doc::Column(self.alloc_column_fn(f)).into())
|
||||||
|
@ -773,16 +599,6 @@ where
|
||||||
|
|
||||||
/// Allocate a document that acts differently based on the current nesting level
|
/// Allocate a document that acts differently based on the current nesting level
|
||||||
///
|
///
|
||||||
/// ```rust
|
|
||||||
/// use pretty::DocAllocator;
|
|
||||||
///
|
|
||||||
/// let arena = pretty::Arena::<()>::new();
|
|
||||||
/// let doc = arena.text("prefix ")
|
|
||||||
/// .append(arena.nesting(|l| {
|
|
||||||
/// arena.text("[Nested: ").append(arena.as_string(l)).append("]").into_doc()
|
|
||||||
/// }).nest(4));
|
|
||||||
/// assert_eq!(doc.1.pretty(80).to_string(), "prefix [Nested: 4]");
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn nesting(&'a self, f: impl Fn(usize) -> Self::Doc + 'a) -> DocBuilder<'a, Self, A> {
|
fn nesting(&'a self, f: impl Fn(usize) -> Self::Doc + 'a) -> DocBuilder<'a, Self, A> {
|
||||||
DocBuilder(self, Doc::Nesting(self.alloc_column_fn(f)).into())
|
DocBuilder(self, Doc::Nesting(self.alloc_column_fn(f)).into())
|
||||||
|
@ -882,28 +698,6 @@ where
|
||||||
|
|
||||||
/// Acts as `self` when laid out on multiple lines and acts as `that` when laid out on a single line.
|
/// Acts as `self` when laid out on multiple lines and acts as `that` when laid out on a single line.
|
||||||
///
|
///
|
||||||
/// ```
|
|
||||||
/// use pretty::{Arena, DocAllocator};
|
|
||||||
///
|
|
||||||
/// let arena = Arena::<()>::new();
|
|
||||||
/// let body = arena.line().append("x");
|
|
||||||
/// let doc = arena.text("let")
|
|
||||||
/// .append(arena.line())
|
|
||||||
/// .append("x")
|
|
||||||
/// .group()
|
|
||||||
/// .append(
|
|
||||||
/// body.clone()
|
|
||||||
/// .flat_alt(
|
|
||||||
/// arena.line()
|
|
||||||
/// .append("in")
|
|
||||||
/// .append(body)
|
|
||||||
/// )
|
|
||||||
/// )
|
|
||||||
/// .group();
|
|
||||||
///
|
|
||||||
/// assert_eq!(doc.1.pretty(100).to_string(), "let x in x");
|
|
||||||
/// assert_eq!(doc.1.pretty(8).to_string(), "let x\nx");
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn flat_alt<E>(self, that: E) -> DocBuilder<'a, D, A>
|
pub fn flat_alt<E>(self, that: E) -> DocBuilder<'a, D, A>
|
||||||
where
|
where
|
||||||
|
@ -970,14 +764,6 @@ where
|
||||||
/// NOTE: The doc pointer type, `D` may need to be cloned. Consider using cheaply cloneable ptr
|
/// NOTE: The doc pointer type, `D` may need to be cloned. Consider using cheaply cloneable ptr
|
||||||
/// like `RefDoc` or `RcDoc`
|
/// like `RefDoc` or `RcDoc`
|
||||||
///
|
///
|
||||||
/// ```rust
|
|
||||||
/// use pretty::DocAllocator;
|
|
||||||
///
|
|
||||||
/// let arena = pretty::Arena::<()>::new();
|
|
||||||
/// let doc = arena.text("lorem").append(arena.text(" "))
|
|
||||||
/// .append(arena.intersperse(["ipsum", "dolor"].iter().cloned(), arena.line_()).align());
|
|
||||||
/// assert_eq!(doc.1.pretty(80).to_string(), "lorem ipsum\n dolor");
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn align(self) -> DocBuilder<'a, D, A>
|
pub fn align(self) -> DocBuilder<'a, D, A>
|
||||||
where
|
where
|
||||||
|
@ -997,17 +783,6 @@ where
|
||||||
/// NOTE: The doc pointer type, `D` may need to be cloned. Consider using cheaply cloneable ptr
|
/// NOTE: The doc pointer type, `D` may need to be cloned. Consider using cheaply cloneable ptr
|
||||||
/// like `RefDoc` or `RcDoc`
|
/// like `RefDoc` or `RcDoc`
|
||||||
///
|
///
|
||||||
/// ```rust
|
|
||||||
/// use pretty::DocAllocator;
|
|
||||||
///
|
|
||||||
/// let arena = pretty::Arena::<()>::new();
|
|
||||||
/// let doc = arena.text("prefix").append(arena.text(" "))
|
|
||||||
/// .append(arena.reflow("Indenting these words with nest").hang(4));
|
|
||||||
/// assert_eq!(
|
|
||||||
/// doc.1.pretty(24).to_string(),
|
|
||||||
/// "prefix Indenting these\n words with\n nest",
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn hang(self, adjust: isize) -> DocBuilder<'a, D, A>
|
pub fn hang(self, adjust: isize) -> DocBuilder<'a, D, A>
|
||||||
where
|
where
|
||||||
|
@ -1021,21 +796,6 @@ where
|
||||||
/// NOTE: The doc pointer type, `D` may need to be cloned. Consider using cheaply cloneable ptr
|
/// NOTE: The doc pointer type, `D` may need to be cloned. Consider using cheaply cloneable ptr
|
||||||
/// like `RefDoc` or `RcDoc`
|
/// like `RefDoc` or `RcDoc`
|
||||||
///
|
///
|
||||||
/// ```rust
|
|
||||||
/// use pretty::DocAllocator;
|
|
||||||
///
|
|
||||||
/// let arena = pretty::Arena::<()>::new();
|
|
||||||
/// let doc = arena.text("prefix").append(arena.text(" "))
|
|
||||||
/// .append(arena.reflow("The indent function indents these words!").indent(4));
|
|
||||||
/// assert_eq!(
|
|
||||||
/// doc.1.pretty(24).to_string(),
|
|
||||||
/// "
|
|
||||||
/// prefix The indent
|
|
||||||
/// function
|
|
||||||
/// indents these
|
|
||||||
/// words!".trim_start(),
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn indent(self, adjust: usize) -> DocBuilder<'a, D, A>
|
pub fn indent(self, adjust: usize) -> DocBuilder<'a, D, A>
|
||||||
where
|
where
|
||||||
|
@ -1061,16 +821,6 @@ where
|
||||||
/// NOTE: The doc pointer type, `D` may need to be cloned. Consider using cheaply cloneable ptr
|
/// NOTE: The doc pointer type, `D` may need to be cloned. Consider using cheaply cloneable ptr
|
||||||
/// like `RefDoc` or `RcDoc`
|
/// like `RefDoc` or `RcDoc`
|
||||||
///
|
///
|
||||||
/// ```rust
|
|
||||||
/// use pretty::DocAllocator;
|
|
||||||
///
|
|
||||||
/// let arena = pretty::Arena::<()>::new();
|
|
||||||
/// let doc = arena.text("prefix ")
|
|
||||||
/// .append(arena.column(|l| {
|
|
||||||
/// arena.text("| <- column ").append(arena.as_string(l)).into_doc()
|
|
||||||
/// }));
|
|
||||||
/// assert_eq!(doc.1.pretty(80).to_string(), "prefix | <- column 7");
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn width(self, f: impl Fn(isize) -> D::Doc + 'a) -> DocBuilder<'a, D, A>
|
pub fn width(self, f: impl Fn(isize) -> D::Doc + 'a) -> DocBuilder<'a, D, A>
|
||||||
where
|
where
|
||||||
|
@ -1271,253 +1021,3 @@ impl<'a, A> DocAllocator<'a, A> for Arena<'a, A> {
|
||||||
self.alloc_any(f)
|
self.alloc_any(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use difference;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
#[test]
|
|
||||||
fn doc_size() {
|
|
||||||
// Safeguard against accidentally growing Doc
|
|
||||||
assert_eq!(8 * 3, std::mem::size_of::<Doc<RefDoc>>());
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! test {
|
|
||||||
($size:expr, $actual:expr, $expected:expr) => {
|
|
||||||
let mut s = String::new();
|
|
||||||
$actual.render_fmt($size, &mut s).unwrap();
|
|
||||||
difference::assert_diff!(&s, $expected, "\n", 0);
|
|
||||||
};
|
|
||||||
($actual:expr, $expected:expr) => {
|
|
||||||
test!(70, $actual, $expected)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn box_doc_inference() {
|
|
||||||
let doc: BoxDoc<()> = BoxDoc::group(
|
|
||||||
BoxDoc::text("test")
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(BoxDoc::text("test")),
|
|
||||||
);
|
|
||||||
|
|
||||||
test!(doc, "test test");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn newline_in_text() {
|
|
||||||
let doc: BoxDoc<()> = BoxDoc::group(
|
|
||||||
BoxDoc::text("test").append(
|
|
||||||
BoxDoc::line()
|
|
||||||
.append(BoxDoc::text("\"test\n test\""))
|
|
||||||
.nest(4),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
test!(5, doc, "test\n \"test\n test\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn forced_newline() {
|
|
||||||
let doc: BoxDoc<()> = BoxDoc::group(
|
|
||||||
BoxDoc::text("test")
|
|
||||||
.append(BoxDoc::hardline())
|
|
||||||
.append(BoxDoc::text("test")),
|
|
||||||
);
|
|
||||||
|
|
||||||
test!(doc, "test\ntest");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn space_do_not_reset_pos() {
|
|
||||||
let doc: BoxDoc<()> = BoxDoc::group(BoxDoc::text("test").append(BoxDoc::line()))
|
|
||||||
.append(BoxDoc::text("test"))
|
|
||||||
.append(BoxDoc::group(BoxDoc::line()).append(BoxDoc::text("test")));
|
|
||||||
|
|
||||||
test!(9, doc, "test test\ntest");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests that the `BoxDoc::hardline()` does not cause the rest of document to think that it fits on
|
|
||||||
// a single line but instead breaks on the `BoxDoc::line()` to fit with 6 columns
|
|
||||||
#[test]
|
|
||||||
fn newline_does_not_cause_next_line_to_be_to_long() {
|
|
||||||
let doc: RcDoc<()> = RcDoc::group(
|
|
||||||
RcDoc::text("test").append(RcDoc::hardline()).append(
|
|
||||||
RcDoc::text("test")
|
|
||||||
.append(RcDoc::line())
|
|
||||||
.append(RcDoc::text("test")),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
test!(6, doc, "test\ntest\ntest");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn newline_after_group_does_not_affect_it() {
|
|
||||||
let arena = Arena::<()>::new();
|
|
||||||
let doc = arena.text("x").append(arena.line()).append("y").group();
|
|
||||||
|
|
||||||
test!(100, doc.append(arena.hardline()).1, "x y\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn block() {
|
|
||||||
let doc: RcDoc<()> = RcDoc::group(
|
|
||||||
RcDoc::text("{")
|
|
||||||
.append(
|
|
||||||
RcDoc::line()
|
|
||||||
.append(RcDoc::text("test"))
|
|
||||||
.append(RcDoc::line())
|
|
||||||
.append(RcDoc::text("test"))
|
|
||||||
.nest(2),
|
|
||||||
)
|
|
||||||
.append(RcDoc::line())
|
|
||||||
.append(RcDoc::text("}")),
|
|
||||||
);
|
|
||||||
|
|
||||||
test!(5, doc, "{\n test\n test\n}");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn line_comment() {
|
|
||||||
let doc: BoxDoc<()> = BoxDoc::group(
|
|
||||||
BoxDoc::text("{")
|
|
||||||
.append(
|
|
||||||
BoxDoc::line()
|
|
||||||
.append(BoxDoc::text("test"))
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(BoxDoc::text("// a").append(BoxDoc::hardline()))
|
|
||||||
.append(BoxDoc::text("test"))
|
|
||||||
.nest(2),
|
|
||||||
)
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(BoxDoc::text("}")),
|
|
||||||
);
|
|
||||||
|
|
||||||
test!(14, doc, "{\n test\n // a\n test\n}");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn annotation_no_panic() {
|
|
||||||
let doc: BoxDoc<()> = BoxDoc::group(
|
|
||||||
BoxDoc::text("test")
|
|
||||||
.annotate(())
|
|
||||||
.append(BoxDoc::hardline())
|
|
||||||
.annotate(())
|
|
||||||
.append(BoxDoc::text("test")),
|
|
||||||
);
|
|
||||||
|
|
||||||
test!(doc, "test\ntest");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn union() {
|
|
||||||
let arg: BoxDoc<()> = BoxDoc::text("(");
|
|
||||||
let tuple = |line: BoxDoc<'static, ()>| {
|
|
||||||
line.append(BoxDoc::text("x").append(",").group())
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(BoxDoc::text("1234567890").append(",").group())
|
|
||||||
.nest(2)
|
|
||||||
.append(BoxDoc::line_())
|
|
||||||
.append(")")
|
|
||||||
};
|
|
||||||
|
|
||||||
let from = BoxDoc::text("let")
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(BoxDoc::text("x"))
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(BoxDoc::text("="))
|
|
||||||
.group();
|
|
||||||
|
|
||||||
let single = from
|
|
||||||
.clone()
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(arg.clone())
|
|
||||||
.group()
|
|
||||||
.append(tuple(BoxDoc::line_()))
|
|
||||||
.group();
|
|
||||||
|
|
||||||
let hang = from
|
|
||||||
.clone()
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(arg.clone())
|
|
||||||
.group()
|
|
||||||
.append(tuple(BoxDoc::hardline()))
|
|
||||||
.group();
|
|
||||||
|
|
||||||
let break_all = from
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(arg.clone())
|
|
||||||
.append(tuple(BoxDoc::line()))
|
|
||||||
.group()
|
|
||||||
.nest(2);
|
|
||||||
|
|
||||||
let doc = BoxDoc::group(single.union(hang.union(break_all)));
|
|
||||||
|
|
||||||
test!(doc, "let x = (x, 1234567890,)");
|
|
||||||
test!(8, doc, "let x =\n (\n x,\n 1234567890,\n )");
|
|
||||||
test!(14, doc, "let x = (\n x,\n 1234567890,\n)");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn usize_max_value() {
|
|
||||||
let doc: BoxDoc<()> = BoxDoc::group(
|
|
||||||
BoxDoc::text("test")
|
|
||||||
.append(BoxDoc::line())
|
|
||||||
.append(BoxDoc::text("test")),
|
|
||||||
);
|
|
||||||
|
|
||||||
test!(usize::max_value(), doc, "test test");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TestWriter<W> {
|
|
||||||
upstream: W,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W> TestWriter<W> {
|
|
||||||
pub fn new(upstream: W) -> Self {
|
|
||||||
Self { upstream }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W> Render for TestWriter<W>
|
|
||||||
where
|
|
||||||
W: Render,
|
|
||||||
{
|
|
||||||
type Error = W::Error;
|
|
||||||
|
|
||||||
fn write_str(&mut self, s: &str) -> Result<usize, W::Error> {
|
|
||||||
self.upstream.write_str(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_str_all(&mut self, s: &str) -> Result<(), W::Error> {
|
|
||||||
self.upstream.write_str_all(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W> RenderAnnotated<()> for TestWriter<W>
|
|
||||||
where
|
|
||||||
W: Render,
|
|
||||||
{
|
|
||||||
fn push_annotation(&mut self, _: &()) -> Result<(), Self::Error> {
|
|
||||||
self.upstream.write_str_all("[")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pop_annotation(&mut self) -> Result<(), Self::Error> {
|
|
||||||
self.upstream.write_str_all("]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn annotations() {
|
|
||||||
let actual = BoxDoc::text("abc").annotate(()).annotate(());
|
|
||||||
let mut s = String::new();
|
|
||||||
actual
|
|
||||||
.render_raw(70, &mut TestWriter::new(FmtWrite::new(&mut s)))
|
|
||||||
.unwrap();
|
|
||||||
difference::assert_diff!(&s, "[[abc]]", "\n", 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue