Skip to main content

novel_segment/
options.rs

1//! Public options.
2
3/// Segmenter construction options.
4///
5/// `auto_cjk` defaults to `false`, matching JS `new Segment()`.
6/// Tests and the novel CLI pass `autoCjk: true`.
7#[derive(Clone, Debug, Default)]
8pub struct SegmentOptions {
9    /// Expand CJK variants when adding dictionary words.
10    pub auto_cjk: bool,
11    /// Also enable `ZhtSynonymOptimizer` (JS `all_mod`).
12    pub all_mod: bool,
13    /// Load extra node-novel synonym files.
14    pub node_novel_mode: bool,
15    /// Skip built-in tokenizers/optimizers.
16    pub nomod: bool,
17    /// Skip built-in dictionaries.
18    pub nodict: bool,
19    /// Default `do_segment` options.
20    pub options_do_segment: DoSegmentOptions,
21    /// DictTokenizer max chunk count (JS default 40).
22    pub max_chunk_count: Option<usize>,
23    /// DictTokenizer min chunk count (JS default 30).
24    pub min_chunk_count: Option<usize>,
25    /// Module names to disable.
26    pub disable_modules: Vec<String>,
27}
28
29/// Per-call segmentation options.
30///
31/// `None` means inherit from `SegmentOptions.options_do_segment` then default `false`
32/// (JS `Object.assign({}, defaults, optionsDoSegment, options)`).
33#[derive(Clone, Debug, Default)]
34pub struct DoSegmentOptions {
35    pub simple: Option<bool>,
36    pub strip_punctuation: Option<bool>,
37    pub convert_synonym: Option<bool>,
38    pub strip_stopword: Option<bool>,
39    pub strip_space: Option<bool>,
40    pub disable_modules: Vec<String>,
41}
42
43impl DoSegmentOptions {
44    pub fn convert_synonym() -> Self {
45        Self {
46            convert_synonym: Some(true),
47            ..Default::default()
48        }
49    }
50
51    pub fn merge(&self, over: &Self) -> Self {
52        Self {
53            simple: over.simple.or(self.simple),
54            strip_punctuation: over.strip_punctuation.or(self.strip_punctuation),
55            convert_synonym: over.convert_synonym.or(self.convert_synonym),
56            strip_stopword: over.strip_stopword.or(self.strip_stopword),
57            strip_space: over.strip_space.or(self.strip_space),
58            disable_modules: if over.disable_modules.is_empty() {
59                self.disable_modules.clone()
60            } else {
61                over.disable_modules.clone()
62            },
63        }
64    }
65
66    pub fn simple_flag(&self) -> bool {
67        self.simple.unwrap_or(false)
68    }
69    pub fn strip_punctuation_flag(&self) -> bool {
70        self.strip_punctuation.unwrap_or(false)
71    }
72    pub fn convert_synonym_flag(&self) -> bool {
73        self.convert_synonym.unwrap_or(false)
74    }
75    pub fn strip_stopword_flag(&self) -> bool {
76        self.strip_stopword.unwrap_or(false)
77    }
78    pub fn strip_space_flag(&self) -> bool {
79        self.strip_space.unwrap_or(false)
80    }
81}