Skip to content

Commit f98322f

Browse files
authored
chore!: separate vimdoc from parser (#42)
Resolves #41
1 parent 15d02b1 commit f98322f

30 files changed

Lines changed: 573 additions & 446 deletions

.github/workflows/build.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181

8282
- name: Test
8383
shell: bash
84-
run: ${{ env.CARGO }} test --target=${{ matrix.job.target }}
84+
run: ${{ env.CARGO }} test --features=vimdoc --target=${{ matrix.job.target }}
8585

8686
- name: Package
8787
shell: bash

Cargo.toml

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,13 @@ required-features = ["cli"]
2727

2828
[dependencies]
2929
chumsky = { version = "0.8.0", default-features = false }
30-
31-
[dependencies.textwrap]
32-
version = "0.15.1"
33-
default-features = false
34-
# optional = true
35-
36-
[dependencies.comfy-table]
37-
version = "6.1.0"
38-
default-features = false
39-
# optional = true
40-
41-
[dependencies.lexopt]
42-
version = "0.2.1"
43-
optional = true
30+
textwrap = { version = "0.15.1", default-features = false, optional = true }
31+
comfy-table = { version = "6.1.0", default-features = false, optional = true }
32+
lexopt = { version = "0.2.1", default-features = false, optional = true }
4433

4534
[features]
46-
cli = ["dep:lexopt"]
35+
vimdoc = ["dep:textwrap", "dep:comfy-table"]
36+
cli = ["vimdoc", "dep:lexopt"]
4737

4838
[profile.release]
4939
lto = true

src/cli.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use lemmy_help::{LemmyHelp, Rename};
1+
use lemmy_help::{vimdoc::VimDoc, FromEmmy, LemmyHelp, Rename};
2+
23
use lexopt::{
34
Arg::{Long, Short, Value},
45
Parser,
@@ -73,7 +74,7 @@ impl Cli {
7374
lemmy.for_help(&source).unwrap();
7475
}
7576

76-
print!("{lemmy}");
77+
print!("{}", VimDoc::from_emmy(&lemmy, ()));
7778

7879
if self.modeline {
7980
println!("vim:tw=78:ts=8:noet:ft=help:norl:");

src/lib.rs

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
1+
#[cfg(feature = "vimdoc")]
2+
pub mod vimdoc;
3+
14
pub mod lexer;
25
pub mod parser;
36

4-
use chumsky::prelude::Simple;
5-
use parser::{Module, Node};
67
use std::fmt::Display;
78

9+
use chumsky::prelude::Simple;
10+
use parser::Node;
11+
812
use crate::lexer::TagType;
913

14+
pub trait Nodes {
15+
fn nodes(&self) -> &Vec<Node>;
16+
}
17+
18+
pub trait FromEmmy: Display {
19+
type Settings;
20+
fn from_emmy(t: &impl Nodes, s: Self::Settings) -> Self;
21+
}
22+
23+
pub trait AsDoc<T: FromEmmy> {
24+
fn as_doc(&self, s: T::Settings) -> T;
25+
}
26+
1027
#[derive(Debug, Default)]
1128
pub struct Rename {
1229
/// Prefix `function` name with `---@mod` name
@@ -22,7 +39,19 @@ pub struct Rename {
2239
#[derive(Debug, Default)]
2340
pub struct LemmyHelp {
2441
rename: Rename,
25-
pub nodes: Vec<Node>,
42+
nodes: Vec<Node>,
43+
}
44+
45+
impl Nodes for LemmyHelp {
46+
fn nodes(&self) -> &Vec<Node> {
47+
&self.nodes
48+
}
49+
}
50+
51+
impl<T: FromEmmy> AsDoc<T> for LemmyHelp {
52+
fn as_doc(&self, s: T::Settings) -> T {
53+
T::from_emmy(self, s)
54+
}
2655
}
2756

2857
impl LemmyHelp {
@@ -43,7 +72,9 @@ impl LemmyHelp {
4372
/// Parse given lua source code to generate AST representation
4473
///
4574
/// ```
46-
/// let mut lemmy = lemmy_help::LemmyHelp::default();
75+
/// use lemmy_help::{LemmyHelp, Nodes};
76+
///
77+
/// let mut lemmy = LemmyHelp::default();
4778
/// let src = r#"
4879
/// local U = {}
4980
///
@@ -58,7 +89,7 @@ impl LemmyHelp {
5889
/// "#;
5990
///
6091
/// let ast = lemmy.parse(&src).unwrap();
61-
/// assert!(!ast.nodes.is_empty());
92+
/// assert!(!ast.nodes().is_empty());
6293
/// ```
6394
pub fn parse(&mut self, src: &str) -> Result<&Self, Vec<Simple<TagType>>> {
6495
self.nodes.append(&mut Node::new(src)?);
@@ -115,38 +146,3 @@ impl LemmyHelp {
115146
Ok(self)
116147
}
117148
}
118-
119-
impl Display for LemmyHelp {
120-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121-
for node in &self.nodes {
122-
if let Node::Toc(x) = node {
123-
writeln!(
124-
f,
125-
"{}",
126-
Module {
127-
name: x.to_string(),
128-
desc: Some("Table of Contents".into()),
129-
}
130-
)?;
131-
132-
for nodde in &self.nodes {
133-
if let Node::Module(x) = nodde {
134-
let desc = x.desc.as_deref().unwrap_or_default();
135-
136-
writeln!(
137-
f,
138-
"{desc}{}",
139-
format_args!("{:·>w$}", format!("|{}|", x.name), w = 80 - desc.len())
140-
)?;
141-
}
142-
}
143-
144-
writeln!(f)?;
145-
} else {
146-
writeln!(f, "{node}")?;
147-
}
148-
}
149-
150-
Ok(())
151-
}
152-
}

src/parser.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
1-
mod util;
2-
pub(super) use util::*;
31
mod node;
42
pub use node::*;
53
mod tags;
64
pub use tags::*;
5+
6+
macro_rules! impl_parse {
7+
($id: ident, $ret: ty, $body: expr) => {
8+
impl $id {
9+
pub fn parse() -> impl chumsky::Parser<
10+
$crate::lexer::TagType,
11+
$ret,
12+
Error = chumsky::prelude::Simple<$crate::lexer::TagType>,
13+
> {
14+
$body
15+
}
16+
}
17+
};
18+
($id: ident, $body: expr) => {
19+
crate::parser::impl_parse!($id, Self, $body);
20+
};
21+
}
22+
23+
pub(super) use impl_parse;

src/parser/node.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::fmt::Display;
2-
31
use chumsky::{
42
prelude::{any, choice, Simple},
53
select, Parser, Stream,
@@ -73,19 +71,3 @@ impl Node {
7371
Node::parse().repeated().flatten().parse(stream)
7472
}
7573
}
76-
77-
impl Display for Node {
78-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79-
match &self {
80-
Self::Brief(x) => x.fmt(f),
81-
Self::Tag(x) => x.fmt(f),
82-
Self::Func(x) => x.fmt(f),
83-
Self::Class(x) => x.fmt(f),
84-
Self::Alias(x) => x.fmt(f),
85-
Self::Type(x) => x.fmt(f),
86-
Self::Module(x) => x.fmt(f),
87-
Self::Divider(x) => x.fmt(f),
88-
_ => unimplemented!(),
89-
}
90-
}
91-
}

src/parser/tags/alias.rs

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
use std::fmt::Display;
2-
31
use chumsky::{prelude::choice, select, Parser};
42

53
use crate::{
64
lexer::TagType,
7-
parser::{description, header, impl_parse, Prefix, Table},
5+
parser::{impl_parse, Prefix},
86
};
97

108
#[derive(Debug, Clone)]
@@ -51,38 +49,3 @@ impl Alias {
5149
self.prefix.right = Some(tag);
5250
}
5351
}
54-
55-
impl Display for Alias {
56-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57-
if let Some(prefix) = &self.prefix.right {
58-
header!(f, &self.name, format!("{prefix}.{}", self.name))?;
59-
} else {
60-
header!(f, &self.name)?;
61-
}
62-
63-
if !self.desc.is_empty() {
64-
crate::parser::description!(f, &self.desc.join("\n"))?;
65-
}
66-
67-
writeln!(f)?;
68-
69-
match &self.kind {
70-
AliasKind::Type(ty) => {
71-
description!(f, "Type: ~")?;
72-
writeln!(f, "{:>w$}", ty, w = 8 + ty.len())?;
73-
}
74-
AliasKind::Enum(variants) => {
75-
description!(f, "Variants: ~")?;
76-
77-
let mut table = Table::new();
78-
for (ty, desc) in variants {
79-
table.add_row([&format!("({})", ty), desc.as_deref().unwrap_or_default()]);
80-
}
81-
82-
f.write_str(&table.to_string())?;
83-
}
84-
}
85-
86-
writeln!(f)
87-
}
88-
}

src/parser/tags/brief.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::fmt::Display;
2-
31
use chumsky::{prelude::just, select, Parser};
42

53
use crate::{lexer::TagType, parser::impl_parse};
@@ -17,9 +15,3 @@ impl_parse!(Brief, {
1715
.delimited_by(just(TagType::BriefStart), just(TagType::BriefEnd))
1816
.map(|desc| Self { desc })
1917
});
20-
21-
impl Display for Brief {
22-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23-
writeln!(f, "{}", self.desc.join("\n"))
24-
}
25-
}

src/parser/tags/class.rs

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
use std::fmt::Display;
2-
31
use chumsky::{select, Parser};
42

53
use crate::{
64
lexer::{Scope, TagType},
7-
parser::{description, header, impl_parse, Prefix, See, Table},
5+
parser::{impl_parse, Prefix, See},
86
};
97

108
#[derive(Debug, Clone)]
@@ -67,42 +65,3 @@ impl Class {
6765
self.prefix.right = Some(tag);
6866
}
6967
}
70-
71-
impl Display for Class {
72-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73-
if let Some(prefix) = &self.prefix.right {
74-
header!(f, &self.name, format!("{prefix}.{}", self.name))?;
75-
} else {
76-
header!(f, &self.name)?;
77-
}
78-
79-
if !self.desc.is_empty() {
80-
description!(f, &self.desc.join("\n"))?;
81-
}
82-
writeln!(f)?;
83-
84-
if !self.fields.is_empty() {
85-
description!(f, "Fields: ~")?;
86-
87-
let mut table = Table::new();
88-
89-
for field in &self.fields {
90-
if field.scope == Scope::Public {
91-
table.add_row([
92-
&format!("{{{}}}", field.name),
93-
&format!("({})", field.ty),
94-
&field.desc.join("\n"),
95-
]);
96-
}
97-
}
98-
99-
writeln!(f, "{table}")?;
100-
}
101-
102-
if !self.see.refs.is_empty() {
103-
writeln!(f, "{}", self.see)?;
104-
}
105-
106-
Ok(())
107-
}
108-
}

src/parser/tags/divider.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::fmt::Display;
2-
31
use chumsky::select;
42

53
use crate::{lexer::TagType, parser::impl_parse};
@@ -10,9 +8,3 @@ pub struct Divider(pub char);
108
impl_parse!(Divider, {
119
select! { TagType::Divider(rune) => Self(rune) }
1210
});
13-
14-
impl Display for Divider {
15-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16-
writeln!(f, "{}", self.0.to_string().repeat(80))
17-
}
18-
}

0 commit comments

Comments
 (0)