mirror of
https://github.com/Automattic/harper.git
synced 2025-12-05 19:26:55 -06:00
feat: add ink support (#1894)
* feat: add harper_ink crate with impl and tests * feat: add harper_ink to harper_ls * docs: add `ink` to the list of supported languages --------- Co-authored-by: Elijah Potter <me@elijahpotter.dev>
This commit is contained in:
committed by
GitHub
parent
8a70efa51c
commit
690100cfb3
23
Cargo.lock
generated
23
Cargo.lock
generated
@@ -2299,6 +2299,7 @@ dependencies = [
|
||||
"dirs 6.0.0",
|
||||
"harper-comments",
|
||||
"harper-core",
|
||||
"harper-ink",
|
||||
"harper-literate-haskell",
|
||||
"harper-pos-utils",
|
||||
"harper-stats",
|
||||
@@ -2393,6 +2394,17 @@ dependencies = [
|
||||
"tree-sitter-html",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "harper-ink"
|
||||
version = "0.65.0"
|
||||
dependencies = [
|
||||
"harper-core",
|
||||
"harper-tree-sitter",
|
||||
"paste",
|
||||
"tree-sitter",
|
||||
"tree-sitter-ink-lbz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "harper-literate-haskell"
|
||||
version = "0.65.0"
|
||||
@@ -2416,6 +2428,7 @@ dependencies = [
|
||||
"harper-comments",
|
||||
"harper-core",
|
||||
"harper-html",
|
||||
"harper-ink",
|
||||
"harper-literate-haskell",
|
||||
"harper-stats",
|
||||
"harper-typst",
|
||||
@@ -4836,6 +4849,16 @@ dependencies = [
|
||||
"tree-sitter-language",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-ink-lbz"
|
||||
version = "0.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a44bf578477077d12eb671fd67fc47ab71516a1f3913a5dac96346a8faa33210"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter-language",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-java"
|
||||
version = "0.23.5"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
members = [ "harper-cli", "harper-core", "harper-ls", "harper-comments", "harper-wasm", "harper-tree-sitter", "harper-html", "harper-literate-haskell", "harper-typst" , "harper-stats", "harper-pos-utils", "harper-brill"]
|
||||
members = ["harper-cli", "harper-core", "harper-ls", "harper-comments", "harper-wasm", "harper-tree-sitter", "harper-html", "harper-literate-haskell", "harper-typst", "harper-stats", "harper-pos-utils", "harper-brill", "harper-ink"]
|
||||
resolver = "2"
|
||||
|
||||
# Comment out the below lines if you plan to use a debugger.
|
||||
|
||||
@@ -21,6 +21,7 @@ serde = { version = "1.0.226", features = ["derive"] }
|
||||
serde_json = "1.0.145"
|
||||
strum = "0.27.2"
|
||||
strum_macros = "0.27.2"
|
||||
harper-ink = { version = "0.65.0", path = "../harper-ink" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -20,6 +20,7 @@ use harper_core::{
|
||||
CharStringExt, Dialect, DictWordMetadata, Document, Span, TokenKind, TokenStringExt,
|
||||
dict_word_metadata_orthography::OrthFlags, remove_overlaps,
|
||||
};
|
||||
use harper_ink::InkParser;
|
||||
use harper_literate_haskell::LiterateHaskellParser;
|
||||
#[cfg(feature = "training")]
|
||||
use harper_pos_utils::{BrillChunker, BrillTagger, BurnChunkerCpu};
|
||||
@@ -818,6 +819,7 @@ fn load_file(
|
||||
.map(|v| v.to_str().unwrap())
|
||||
{
|
||||
Some("md") => Box::new(Markdown::default()),
|
||||
Some("ink") => Box::new(InkParser::default()),
|
||||
|
||||
Some("lhs") => Box::new(LiterateHaskellParser::new_markdown(
|
||||
MarkdownOptions::default(),
|
||||
|
||||
16
harper-ink/Cargo.toml
Normal file
16
harper-ink/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "harper-ink"
|
||||
version = "0.65.0"
|
||||
edition = "2024"
|
||||
description = "The language checker for developers."
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/automattic/harper"
|
||||
|
||||
[dependencies]
|
||||
harper-core = { path = "../harper-core", version = "0.65.0" }
|
||||
harper-tree-sitter = { path = "../harper-tree-sitter", version = "0.65.0" }
|
||||
tree-sitter-ink-lbz = "0.0.1"
|
||||
tree-sitter = "0.25.8"
|
||||
|
||||
[dev-dependencies]
|
||||
paste = "1.0.15"
|
||||
39
harper-ink/src/lib.rs
Normal file
39
harper-ink/src/lib.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use harper_core::parsers::{self, Parser, PlainEnglish};
|
||||
use harper_core::{Token, TokenKind};
|
||||
use harper_tree_sitter::TreeSitterMasker;
|
||||
use tree_sitter::Node;
|
||||
|
||||
pub struct InkParser {
|
||||
inner: parsers::Mask<TreeSitterMasker, PlainEnglish>,
|
||||
}
|
||||
|
||||
impl InkParser {
|
||||
fn node_condition(n: &Node) -> bool {
|
||||
matches!(n.kind(), "contentText" | "blockComment" | "lineComment")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for InkParser {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
inner: parsers::Mask::new(
|
||||
TreeSitterMasker::new(tree_sitter_ink_lbz::LANGUAGE.into(), Self::node_condition),
|
||||
PlainEnglish,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parser for InkParser {
|
||||
fn parse(&self, source: &[char]) -> Vec<Token> {
|
||||
let mut tokens = self.inner.parse(source);
|
||||
|
||||
for token in &mut tokens {
|
||||
if let TokenKind::Space(v) = &mut token.kind {
|
||||
*v = (*v).clamp(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
tokens
|
||||
}
|
||||
}
|
||||
41
harper-ink/tests/run_tests.rs
Normal file
41
harper-ink/tests/run_tests.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use harper_core::linting::{LintGroup, Linter};
|
||||
use harper_core::spell::FstDictionary;
|
||||
use harper_core::{Dialect, Document};
|
||||
use harper_ink::InkParser;
|
||||
|
||||
/// Creates a unit test checking that the linting of a Ink document (in
|
||||
/// `tests_sources`) produces the expected number of lints.
|
||||
macro_rules! create_test {
|
||||
($filename:ident.ink, $correct_expected:expr) => {
|
||||
paste::paste! {
|
||||
#[test]
|
||||
fn [<lints_ $filename _correctly>](){
|
||||
let source = include_str!(
|
||||
concat!(
|
||||
"./test_sources/",
|
||||
concat!(stringify!($filename), ".ink")
|
||||
)
|
||||
);
|
||||
|
||||
let dict = FstDictionary::curated();
|
||||
let document = Document::new(&source, &InkParser::default(),
|
||||
&FstDictionary::curated()
|
||||
);
|
||||
|
||||
let mut linter = LintGroup::new_curated(dict, Dialect::American);
|
||||
let lints = linter.lint(&document);
|
||||
|
||||
dbg!(&lints);
|
||||
assert_eq!(lints.len(), $correct_expected);
|
||||
|
||||
// Make sure that all generated tokens span real characters
|
||||
for token in document.tokens(){
|
||||
assert!(token.span.try_get_content(document.get_source()).is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
create_test!(good.ink, 0);
|
||||
create_test!(bad.ink, 6);
|
||||
15
harper-ink/tests/test_sources/bad.ink
Normal file
15
harper-ink/tests/test_sources/bad.ink
Normal file
@@ -0,0 +1,15 @@
|
||||
=== Knot ===
|
||||
text here is checked: chungus
|
||||
|
||||
= Stitch
|
||||
|
||||
~identifiersAreNotchecked = "but strings are: chungus"
|
||||
// comments are also checked -> chungus
|
||||
|
||||
/*
|
||||
chungus
|
||||
*/
|
||||
|
||||
* choices are checked
|
||||
+ chungus
|
||||
+ normal text
|
||||
15
harper-ink/tests/test_sources/good.ink
Normal file
15
harper-ink/tests/test_sources/good.ink
Normal file
@@ -0,0 +1,15 @@
|
||||
=== Knot ===
|
||||
this is a thing
|
||||
|
||||
= Stitch
|
||||
* an option
|
||||
+ another option
|
||||
|
||||
+ normal text
|
||||
+ + indented choice
|
||||
+ + another indented choice
|
||||
|
||||
- gather
|
||||
|
||||
= ThreeWordStitch
|
||||
test
|
||||
@@ -30,6 +30,7 @@ futures = "0.3.31"
|
||||
serde = { version = "1.0.226", features = ["derive"] }
|
||||
indexmap = { version = "2.11.1", features = ["serde"] }
|
||||
globset = "0.4.16"
|
||||
harper-ink = { version = "0.65.0", path = "../harper-ink" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -20,6 +20,7 @@ use harper_core::parsers::{
|
||||
use harper_core::spell::{Dictionary, FstDictionary, MergedDictionary, MutableDictionary};
|
||||
use harper_core::{Dialect, DictWordMetadata, Document, IgnoredLints};
|
||||
use harper_html::HtmlParser;
|
||||
use harper_ink::InkParser;
|
||||
use harper_literate_haskell::LiterateHaskellParser;
|
||||
use harper_stats::{Record, Stats};
|
||||
use harper_typst::Typst;
|
||||
@@ -378,6 +379,7 @@ impl Backend {
|
||||
Some(Box::new(parser))
|
||||
}
|
||||
}
|
||||
"ink" => Some(Box::new(InkParser::default())),
|
||||
"markdown" => Some(Box::new(Markdown::new(markdown_options))),
|
||||
"git-commit" | "gitcommit" => {
|
||||
Some(Box::new(GitCommitParser::new_markdown(markdown_options)))
|
||||
|
||||
@@ -301,6 +301,7 @@ These configs are under the `markdown` key:
|
||||
| Typst | `typst` | |
|
||||
| Kotlin | `kotlin` | ✅ |
|
||||
| Clojure | `clojure` | ✅ |
|
||||
| Ink | `ink` | |
|
||||
|
||||
Want your language added?
|
||||
Let us know by [commenting on this issue](https://github.com/Automattic/harper/issues/79).
|
||||
|
||||
Reference in New Issue
Block a user