english_lint/lib.rs
1//! Find common stylistic problems in english texts. Works well for technical or
2//! scientific documents. Based on [write-good][npm-write-good] and
3//! [this article][matt].
4//!
5//! [npm-write-good]: https://github.com/btford/write-good
6//! [matt]: http://matt.might.net/articles/shell-scripts-for-passive-voice-weasel-words-duplicates/
7#![deny(missing_docs, dead_code)]
8
9extern crate aho_corasick;
10extern crate regex;
11#[macro_use] extern crate lazy_static;
12
13mod range_map;
14
15mod data;
16mod hint;
17mod matcher;
18mod pattern_groups;
19
20use aho_corasick::AcAutomaton;
21
22pub use hint::Hint;
23
24/// Lint a string of english text
25///
26/// Given some english text, this function will try to give suggestions on how
27/// to improve the language.
28///
29/// # Examples
30///
31/// ```
32/// extern crate english_lint;
33///
34/// let text: &str = "This chapter consists of relatively independent tutorials";
35/// let suggestions: Vec<english_lint::Hint> = english_lint::lint(text);
36///
37/// assert_eq!(suggestions, vec![
38/// english_lint::Hint { group: Some("adverbs"),
39/// value: "relatively".to_owned(),
40/// line: Some(1), start: 25, end: 35 },
41/// ]);
42/// ```
43pub fn lint(input: &str) -> Vec<Hint> {
44 let mut pattern_groups = pattern_groups::PatternGroups::with_capacity(32_000);
45 pattern_groups.push(data::ADVERBS, "adverbs");
46 pattern_groups.push(data::WEAKENS, "weakens");
47 pattern_groups.push(data::CLICHES, "cliches");
48 pattern_groups.push(data::WORDY, "wordy");
49 pattern_groups.push(data::WEASELS, "weasels");
50
51 let automaton = AcAutomaton::new(pattern_groups.patterns.clone());
52
53 input
54 .lines().enumerate()
55 .flat_map(|(index, line)| {
56 let line_number = index + 1;
57
58 let irregulars = data::PASSIVE.find_iter(line)
59 .map(move |(start, end)| Hint {
60 group: Some("passive"),
61 value: line[start..end].to_owned(),
62 line: Some(line_number.clone()),
63 start: start,
64 end: end,
65 });
66
67 matcher::matcher(&automaton, &pattern_groups, line)
68 .into_iter()
69 .map(move |hint| Hint { line: Some(line_number.clone()), ..hint.clone()})
70 .chain(irregulars)
71 })
72 .collect()
73}