use super::EmitOptions;
use crate::model::Attribute;
use crate::model::Block;
use crate::model::Docstring;
use crate::model::ExceptionEntry;
use crate::model::FreeSectionKind;
use crate::model::Method;
use crate::model::Parameter;
use crate::model::Reference;
use crate::model::Return;
use crate::model::Section;
use crate::model::SectionKind;
use crate::model::SeeAlsoEntry;
pub fn emit_numpy(doc: &Docstring, options: &EmitOptions) -> String {
let mut out = String::new();
if let Some(ref summary) = doc.summary {
out.push_str(summary);
out.push('\n');
}
for directive in &doc.directives {
out.push('\n');
super::emit_directive(&mut out, directive);
}
if let Some(ref ext) = doc.extended_summary {
out.push('\n');
out.push_str(ext);
out.push('\n');
}
for section in &doc.sections {
out.push('\n');
emit_section(&mut out, section);
}
if options.base_indent == 0 {
return out;
}
super::indent_lines(&out, options.base_indent)
}
fn section_header(kind: &SectionKind) -> &str {
match kind {
SectionKind::Parameters => "Parameters",
SectionKind::KeywordParameters => "Keyword Parameters",
SectionKind::OtherParameters => "Other Parameters",
SectionKind::Receives => "Receives",
SectionKind::Returns => "Returns",
SectionKind::Yields => "Yields",
SectionKind::Raises => "Raises",
SectionKind::Warns => "Warns",
SectionKind::Attributes => "Attributes",
SectionKind::Methods => "Methods",
SectionKind::SeeAlso => "See Also",
SectionKind::References => "References",
SectionKind::FreeText(kind) => free_section_name(kind),
}
}
fn free_section_name(kind: &FreeSectionKind) -> &str {
match kind {
FreeSectionKind::Notes => "Notes",
FreeSectionKind::Examples => "Examples",
FreeSectionKind::Warnings => "Warnings",
FreeSectionKind::Todo => "Todo",
FreeSectionKind::Attention => "Attention",
FreeSectionKind::Caution => "Caution",
FreeSectionKind::Danger => "Danger",
FreeSectionKind::Error => "Error",
FreeSectionKind::Hint => "Hint",
FreeSectionKind::Important => "Important",
FreeSectionKind::Tip => "Tip",
FreeSectionKind::Unknown(name) => name.as_str(),
}
}
fn emit_section_header(out: &mut String, name: &str) {
out.push_str(name);
out.push('\n');
for _ in 0..name.chars().count() {
out.push('-');
}
out.push('\n');
}
fn emit_section(out: &mut String, section: &Section) {
emit_section_header(out, section_header(§ion.kind));
let mut prev_paragraph = false;
for block in §ion.blocks {
if let Block::Paragraph(text) = block {
if prev_paragraph {
out.push('\n');
}
out.push_str(text);
out.push('\n');
prev_paragraph = true;
continue;
}
prev_paragraph = false;
match block {
Block::Parameter(p) => emit_parameter(out, p),
Block::Return(r) => emit_return(out, r),
Block::Exception(e) => emit_exception(out, e),
Block::Attribute(a) => emit_attribute(out, a),
Block::Method(m) => emit_method(out, m),
Block::SeeAlso(item) => emit_see_also(out, item),
Block::Reference(r) => emit_reference(out, r),
Block::Paragraph(_) => unreachable!("handled above"),
}
}
}
fn emit_parameter(out: &mut String, p: &Parameter) {
out.push_str(&p.names.join(", "));
if p.type_annotation.is_some() || p.is_optional || p.default_value.is_some() {
out.push_str(" : ");
if let Some(ref ty) = p.type_annotation {
out.push_str(ty);
}
if p.is_optional {
if p.type_annotation.is_some() {
out.push_str(", ");
}
out.push_str("optional");
}
if let Some(ref dv) = p.default_value {
if p.type_annotation.is_some() || p.is_optional {
out.push_str(", ");
}
out.push_str("default: ");
out.push_str(dv);
}
}
out.push('\n');
if let Some(ref desc) = p.description {
emit_indented_body(out, desc);
}
}
fn emit_return(out: &mut String, r: &Return) {
if let Some(ref name) = r.name {
out.push_str(name);
if let Some(ref ty) = r.type_annotation {
out.push_str(" : ");
out.push_str(ty);
}
} else if let Some(ref ty) = r.type_annotation {
out.push_str(ty);
}
out.push('\n');
if let Some(ref desc) = r.description {
emit_indented_body(out, desc);
}
}
fn emit_exception(out: &mut String, e: &ExceptionEntry) {
out.push_str(&e.type_name);
out.push('\n');
if let Some(ref desc) = e.description {
emit_indented_body(out, desc);
}
}
fn emit_attribute(out: &mut String, a: &Attribute) {
out.push_str(&a.names.join(", "));
if let Some(ref ty) = a.type_annotation {
out.push_str(" : ");
out.push_str(ty);
}
out.push('\n');
if let Some(ref desc) = a.description {
emit_indented_body(out, desc);
}
}
fn emit_method(out: &mut String, m: &Method) {
out.push_str(&m.name);
if let Some(ref ty) = m.type_annotation {
out.push_str(" (");
out.push_str(ty);
out.push(')');
}
out.push('\n');
if let Some(ref desc) = m.description {
emit_indented_body(out, desc);
}
}
fn emit_see_also(out: &mut String, item: &SeeAlsoEntry) {
out.push_str(&item.names.join(", "));
out.push('\n');
if let Some(ref desc) = item.description {
emit_indented_body(out, desc);
}
}
fn emit_reference(out: &mut String, r: &Reference) {
if let Some(ref label) = r.label {
out.push_str(".. [");
out.push_str(label);
out.push(']');
if let Some(ref content) = r.content {
out.push(' ');
emit_with_indented_continuations(out, content);
}
} else if let Some(ref content) = r.content {
emit_with_indented_continuations(out, content);
}
out.push('\n');
}
fn emit_with_indented_continuations(out: &mut String, content: &str) {
super::emit_multiline_with_indentation(out, content, 4);
}
fn emit_indented_body(out: &mut String, body: &str) {
for line in body.lines() {
if !line.is_empty() {
out.push_str(" ");
out.push_str(line);
}
out.push('\n');
}
}