1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use CaseMatching;
use ArinaeMatcher;
use OnceLock;
/// Lowercases text using Unicode case folding semantics.
///
/// This is stricter than ASCII-only lowercasing, so it is safe to use for
/// case-insensitive matching on user-facing text.
///
/// # Examples
///
/// ```
/// use osp_cli::core::fuzzy::fold_case;
///
/// assert_eq!(fold_case("LDAP"), "ldap");
/// assert_eq!(fold_case("ÅSE"), "åse");
/// ```
/// Conservative fuzzy matcher for completion suggestions.
///
/// Completion should rescue near-misses like `lap -> ldap`, but it should not
/// spill short stubs like `ld` into unrelated commands. Arinae with typo mode
/// disabled keeps that balance while still handling subsequence-style fuzzy
/// matches well.
///
/// # Examples
///
/// ```
/// use osp_cli::core::fuzzy::completion_fuzzy_matcher;
/// use skim::fuzzy_matcher::FuzzyMatcher;
///
/// assert!(completion_fuzzy_matcher()
/// .fuzzy_match("ldap", "lap")
/// .is_some());
/// ```
/// Typo-tolerant fuzzy matcher for config-key recovery suggestions.
///
/// Config lookup failures should help with misspellings like
/// `ui.formt -> ui.format`, but they should still stay narrower than broad
/// search-oriented matching. Callers are expected to pair this matcher with
/// explicit ranking such as same-namespace and last-segment preference.
///
/// # Examples
///
/// ```
/// use osp_cli::core::fuzzy::config_fuzzy_matcher;
/// use skim::fuzzy_matcher::FuzzyMatcher;
///
/// assert!(config_fuzzy_matcher()
/// .fuzzy_match("ui.format", "ui.formt")
/// .is_some());
/// ```
/// Typo-tolerant fuzzy matcher for explicit DSL `%quick` searches.
///
/// `%quick` is the opt-in "be clever" path, so it intentionally accepts a
/// broader set of typo-like matches than shell completion does.
///
/// # Examples
///
/// ```
/// use osp_cli::core::fuzzy::search_fuzzy_matcher;
/// use skim::fuzzy_matcher::FuzzyMatcher;
///
/// assert!(search_fuzzy_matcher()
/// .fuzzy_match("doctor --mreg", "doctr mreg")
/// .is_some());
/// ```