Add root doc comment, gemtext module
[?]
Jan 8, 2021, 8:21 AM
J4PKMKJXBUPG4QFHQVATUOXHWLEWMX3LTGWMNFKFAQUTJHU5GSAACDependencies
- [2]
BOFUYB6IAdd documentation and implement some feedback from Discord (https://discord.com/channels/273534239310479360/354038657075904544/796256815024701480) - [3]
NKDEPTTNFix typo - [4]
JS6JZ7IAAdd an initial planned feature list for `gemini` - [5]
5II6T7YEAdd gemini library - [*]
L6GZJGTUAdd READMEs
Change contents
- replacement in gemini/src/lib.rs at line 8
//! TODO//! A general purpose library of types for working with the Gemini protocol//!//! Represented are Gemini requests, responses, headers, and status codes.//! Requests are currently just a small layer of functionality over top of a//! `Url` from the aptly named `url` crate. All types are implemented with an//! eye towards implementing the Gemini specification faithfully and making//! illegal or invalid states unrepresentable. - edit in gemini/src/lib.rs at line 16
pub mod gemtext; - edit in gemini/src/lib.rs at line 22
pub use gemtext::{Builder, Doc, Level}; - file addition: gemtext.rs[3.16]
//! Gemtext documents//!//! The Gemini specification lays out a lightweight document format to//! facilitate highly readable and sufficiently interactive content.//!//! Presently, this module only provides a way to incrementally build up a//! gemtext document programmatically, and serialize as utf-8 text using any//! type that implements `std::fmt::Write`.//!//! ```//! use gemini::Builder;//!//! let doc = Builder::new().text("foo").line().quote("bar");//! assert_eq!(doc.build(), "foo\n\n> bar\n");//! ```use std::fmt::Display;/// Representation of lines in a gemtext document.#[derive(Debug, Clone, Eq, PartialEq)]pub enum Doc {/// Text line, corresponding to a paragraph of plain text.Text(String),/// Link line, with an optional title.Link {/// Link target.to: String,/// Optional name for the link.name: Option<String>,},/// A heading to add structure to a document.Heading(Level, String),/// An individual list item. Repeated items will form a single list.ListItem(String),/// Block quote.Quote(String),/// Preformatted text. This is the only document that should contain line breaks.Preformatted(String),/// Blank line. Technically equivalent to a Text line, but we use a sentinel to avoid allocation.Blank,}/// Heading level.#[derive(Debug, Copy, Clone, Eq, PartialEq)]pub enum Level {/// H1, top level headings.One,/// H2, section headings.Two,/// H3, subsection headings.Three,}impl Display for Level {fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {match self {Level::One => write!(f, "#"),Level::Two => write!(f, "##"),Level::Three => write!(f, "###"),}}}/// A type for incrementally building up a gemtext document that can then be/// reified into text format.#[derive(Debug, Default, Clone, Eq, PartialEq)]pub struct Builder {docs: Vec<Doc>,}impl Builder {/// Create a new builder, representing the empty document.pub fn new() -> Self {Self::default()}fn push(mut self, doc: Doc) -> Self {self.docs.push(doc);self}fn extend(mut self, docs: impl Iterator<Item = Doc>) -> Self {self.docs.extend(docs);self}/// Add a text line to the document.pub fn text(self, text: impl Into<String>) -> Self {self.push(Doc::Text(text.into()))}/// Add a blank line to the document.pub fn line(self) -> Self {self.push(Doc::Blank)}/// Add a link line to the document.pub fn link(self, to: impl Into<String>, name: Option<impl Into<String>>) -> Self {let to = to.into();let name = name.map(Into::into);self.push(Doc::Link { to, name })}/// Add a heading of any level to the document.pub fn heading(self, level: Level, heading: impl Into<String>) -> Self {self.push(Doc::Heading(level, heading.into()))}/// Add a top level heading to the document.pub fn h1(self, heading: impl Into<String>) -> Self {self.heading(Level::One, heading)}/// Add a section heading to the document.pub fn h2(self, heading: impl Into<String>) -> Self {self.heading(Level::Two, heading)}/// Add a subsection heading to the document.pub fn h3(self, heading: impl Into<String>) -> Self {self.heading(Level::Three, heading)}/// Add an individual list item to the document.pub fn list_item(self, item: String) -> Self {self.push(Doc::ListItem(item))}/// Add a list to the document, from an iterator of strings.pub fn list<S: Into<String>>(self, items: impl IntoIterator<Item = S>) -> Self {let items = items.into_iter().map(|s| Doc::ListItem(s.into()));self.extend(items)}/// Add a block quote to the document.pub fn quote(self, quote: impl Into<String>) -> Self {self.push(Doc::Quote(quote.into()))}/// Add some preformatted text to the document.pub fn preformatted(self, preformatted: impl Into<String>) -> Self {self.push(Doc::Preformatted(preformatted.into()))}/// Generate a string representation of a document.pub fn build(self) -> String {format!("{}", self)}}impl Display for Builder {fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {self.docs.iter().try_for_each(|doc| match doc {Doc::Text(t) => {writeln!(f, "{}", t)}Doc::Link { to, name } => {write!(f, "=> {}", to)?;if let Some(name) = name {write!(f, " {}", name)?;}writeln!(f)}Doc::Heading(lvl, h) => {writeln!(f, "{} {}", lvl, h)}Doc::ListItem(i) => {writeln!(f, "* {}", i)}Doc::Quote(q) => {writeln!(f, "> {}", q)}Doc::Preformatted(p) => {writeln!(f, "```\n{}\n```", p)}Doc::Blank => writeln!(f),})}}#[cfg(test)]mod test {use super::*;#[test]pub fn test_builder() {let doc = Builder::new().preformatted(" wooo\n/^^^^\\\n| |\n\\____/").line().h1("GAZE INTO THE SPHERE!").line().text("critics are raving").quote("i love the sphere - bort").quote("the sphere gives me purpose - frelvin").line().list(vec!["always", "trust", "the sphere"]).link("gemini://sphere.gaze", Some("gaze more here"));assert_eq!(doc.build(),r#"```wooo/^^^^\| |\____/```# GAZE INTO THE SPHERE!critics are raving> i love the sphere - bort> the sphere gives me purpose - frelvin* always* trust* the sphere=> gemini://sphere.gaze gaze more here"#)}} - replacement in gemini/README.md at line 8
* a `gemtext` module for representing `text/gemini` content* parsers using `nom`* streaming response bodies* no_std support[3.99][X] a `gemtext` module for representing `text/gemini` content[ ] parsers using `nom`[ ] streaming response bodies[ ] no_std support[ ] improve doc comments with links n such