Wrap code snippets in Code struct
In commit 729414cbfe16324379ac0b886ba65349bbf44ff6, we introduced the Text struct that wraps HTML and plain text to make it clear what data we store in the fields of the Doc and Example structs. This patch adds the Code struct that stores a plain-text representation of code snippets to make the structs even clearer and to make it easier to transition to plain-text-only code, e. g. provided by the new JSON backend.
This commit is contained in:
parent
fefac9f2fc
commit
861a2e8861
60
src/doc.rs
60
src/doc.rs
@ -26,6 +26,9 @@ pub struct Text {
|
||||
pub html: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Code(String);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, serde_repr::Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum ItemType {
|
||||
@ -62,7 +65,7 @@ pub struct Doc {
|
||||
pub name: Fqn,
|
||||
pub ty: ItemType,
|
||||
pub description: Option<Text>,
|
||||
pub definition: Option<Text>,
|
||||
pub definition: Option<Code>,
|
||||
pub groups: Vec<(ItemType, Vec<MemberGroup>)>,
|
||||
}
|
||||
|
||||
@ -75,7 +78,7 @@ pub struct MemberGroup {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Example {
|
||||
pub description: Option<Text>,
|
||||
pub code: Text,
|
||||
pub code: Code,
|
||||
}
|
||||
|
||||
impl Name {
|
||||
@ -211,6 +214,26 @@ impl ops::Deref for Fqn {
|
||||
}
|
||||
}
|
||||
|
||||
impl Code {
|
||||
pub fn new(s: String) -> Code {
|
||||
Code(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Code {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", &self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for Code {
|
||||
type Target = String;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemType {
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
@ -273,37 +296,6 @@ impl ItemType {
|
||||
ItemType::TraitAlias => "Trait Aliases",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn group_id(&self) -> &str {
|
||||
match self {
|
||||
ItemType::Module => "modules",
|
||||
ItemType::ExternCrate => "extern-crates",
|
||||
ItemType::Import => "imports",
|
||||
ItemType::Struct => "structs",
|
||||
ItemType::Enum => "enums",
|
||||
ItemType::Function => "functions",
|
||||
ItemType::Typedef => "types",
|
||||
ItemType::Static => "statics",
|
||||
ItemType::Trait => "traits",
|
||||
ItemType::Impl => "impls",
|
||||
ItemType::TyMethod => "required-methods",
|
||||
ItemType::Method => "methods",
|
||||
ItemType::StructField => "fields",
|
||||
ItemType::Variant => "variants",
|
||||
ItemType::Macro => "macros",
|
||||
ItemType::Primitive => "primitives",
|
||||
ItemType::AssocType => "associated-types",
|
||||
ItemType::Constant => "constants",
|
||||
ItemType::AssocConst => "associated-consts",
|
||||
ItemType::Union => "unions",
|
||||
ItemType::ForeignType => "foreign-types",
|
||||
ItemType::Keyword => "keywords",
|
||||
ItemType::OpaqueTy => "opaque-types",
|
||||
ItemType::ProcAttribute => "proc-attributes",
|
||||
ItemType::ProcDerive => "proc-derives",
|
||||
ItemType::TraitAlias => "trait-aliases",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for ItemType {
|
||||
@ -382,7 +374,7 @@ impl MemberGroup {
|
||||
}
|
||||
|
||||
impl Example {
|
||||
pub fn new(description: Option<Text>, code: Text) -> Self {
|
||||
pub fn new(description: Option<Text>, code: Code) -> Self {
|
||||
Example { description, code }
|
||||
}
|
||||
}
|
||||
|
@ -158,6 +158,24 @@ impl<T> From<kuchiki::NodeDataRef<T>> for doc::Text {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<kuchiki::NodeRef> for doc::Code {
|
||||
fn from(node: kuchiki::NodeRef) -> doc::Code {
|
||||
doc::Code::from(&node)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&kuchiki::NodeRef> for doc::Code {
|
||||
fn from(node: &kuchiki::NodeRef) -> doc::Code {
|
||||
doc::Code::new(node_to_text(node))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<kuchiki::NodeDataRef<T>> for doc::Code {
|
||||
fn from(node: kuchiki::NodeDataRef<T>) -> doc::Code {
|
||||
node.as_node().into()
|
||||
}
|
||||
}
|
||||
|
||||
fn node_to_text(node: &kuchiki::NodeRef) -> String {
|
||||
let mut s = String::new();
|
||||
push_node_to_text(&mut s, node);
|
||||
@ -272,7 +290,7 @@ fn get_fields(
|
||||
|
||||
let mut next = heading.as_ref().and_then(NodeRefExt::next_sibling_element);
|
||||
let mut name: Option<String> = None;
|
||||
let mut definition: Option<doc::Text> = None;
|
||||
let mut definition: Option<doc::Code> = None;
|
||||
|
||||
while let Some(element) = &next {
|
||||
if element.is_element(&local_name!("span")) && element.has_class("structfield") {
|
||||
@ -449,7 +467,7 @@ fn get_method_group(
|
||||
let mut methods = MemberDocs::new(parent, ty);
|
||||
|
||||
let mut name: Option<String> = None;
|
||||
let mut definition: Option<doc::Text> = None;
|
||||
let mut definition: Option<doc::Code> = None;
|
||||
for element in impl_items.children() {
|
||||
if element.is_element(heading_type) && element.has_class("method") {
|
||||
methods.push(&mut name, &mut definition, None)?;
|
||||
@ -473,7 +491,7 @@ fn get_variants(
|
||||
|
||||
let mut next = heading.as_ref().and_then(NodeRefExt::next_sibling_element);
|
||||
let mut name: Option<String> = None;
|
||||
let mut definition: Option<doc::Text> = None;
|
||||
let mut definition: Option<doc::Code> = None;
|
||||
while let Some(element) = &next {
|
||||
if element.is_element(&local_name!("div")) {
|
||||
if element.has_class("variant") {
|
||||
@ -604,7 +622,7 @@ impl<'a> MemberDocs<'a> {
|
||||
pub fn push(
|
||||
&mut self,
|
||||
name: &mut Option<String>,
|
||||
definition: &mut Option<doc::Text>,
|
||||
definition: &mut Option<doc::Code>,
|
||||
description: Option<doc::Text>,
|
||||
) -> anyhow::Result<()> {
|
||||
let name = name.take();
|
||||
@ -719,13 +737,9 @@ mod tests {
|
||||
assert_eq!(name, doc.name);
|
||||
assert_eq!(doc::ItemType::Method, doc.ty);
|
||||
let definition = doc.definition.unwrap();
|
||||
assert_eq!("pub fn as_node(&self) -> &NodeRef", &definition.plain);
|
||||
assert_eq!(
|
||||
"<code id=\"as_node.v\">\
|
||||
pub fn <a class=\"fnname\" href=\"#method.as_node\">as_node</a>(&self) \
|
||||
-> &<a class=\"struct\" href=\"../kuchiki/struct.NodeRef.html\" \
|
||||
title=\"struct kuchiki::NodeRef\">NodeRef</a></code>",
|
||||
&definition.html
|
||||
doc::Code::new("pub fn as_node(&self) -> &NodeRef".to_owned()),
|
||||
definition
|
||||
);
|
||||
assert!(doc.description.is_some());
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ pub trait Printer: fmt::Debug + marker::Sized {
|
||||
|
||||
fn print_html(&self, indent: usize, s: &doc::Text, show_links: bool) -> io::Result<()>;
|
||||
|
||||
fn print_code(&self, indent: usize, code: &doc::Text) -> io::Result<()>;
|
||||
fn print_code(&self, indent: usize, code: &doc::Code) -> io::Result<()>;
|
||||
|
||||
fn println(&self) -> io::Result<()>;
|
||||
}
|
||||
|
@ -44,8 +44,8 @@ impl super::Printer for PlainTextRenderer {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_code(&self, indent: usize, code: &doc::Text) -> io::Result<()> {
|
||||
for line in code.plain.split('\n') {
|
||||
fn print_code(&self, indent: usize, code: &doc::Code) -> io::Result<()> {
|
||||
for line in code.split('\n') {
|
||||
writeln!(io::stdout(), "{}{}", " ".repeat(indent), line)?;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -97,19 +97,21 @@ impl super::Printer for RichTextRenderer {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_code(&self, indent: usize, code: &doc::Text) -> io::Result<()> {
|
||||
fn print_code(&self, indent: usize, code: &doc::Code) -> io::Result<()> {
|
||||
if self.highlight {
|
||||
let syntax = self.syntax_set.find_syntax_by_extension("rs").unwrap();
|
||||
let mut h = syntect::easy::HighlightLines::new(syntax, &self.theme);
|
||||
|
||||
for line in syntect::util::LinesWithEndings::from(&code.plain) {
|
||||
for line in syntect::util::LinesWithEndings::from(code.as_ref()) {
|
||||
let ranges = h.highlight(line, &self.syntax_set);
|
||||
write!(io::stdout(), "{}", " ".repeat(indent))?;
|
||||
self.render_syntax(&ranges)?;
|
||||
}
|
||||
writeln!(io::stdout())?;
|
||||
} else {
|
||||
self.print_html(indent, code, false)?;
|
||||
for line in code.split('\n') {
|
||||
writeln!(io::stdout(), "{}{}", " ".repeat(indent), line)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
Loading…
Reference in New Issue
Block a user