2022-06-06 18:01:49 -04:00
|
|
|
use kakplugin::Selection;
|
|
|
|
use regex::Regex;
|
|
|
|
use std::{
|
|
|
|
collections::hash_map::DefaultHasher,
|
|
|
|
hash::{Hash, Hasher},
|
|
|
|
};
|
|
|
|
|
2022-06-09 18:11:03 -04:00
|
|
|
pub fn get_key(
|
2022-06-06 18:01:49 -04:00
|
|
|
selection: &Selection,
|
|
|
|
skip_whitespace: bool,
|
|
|
|
regex: Option<&Regex>,
|
|
|
|
ignore_case: bool,
|
|
|
|
) -> String {
|
|
|
|
// Strip whitespace if requested
|
|
|
|
let mut key = if skip_whitespace {
|
|
|
|
selection.as_str()
|
|
|
|
} else {
|
|
|
|
selection.trim()
|
|
|
|
};
|
|
|
|
|
|
|
|
// If they requested a regex match, set the key to the string slice of that match
|
|
|
|
if let Some(regex_match) = (|| {
|
|
|
|
let captures = regex.as_ref()?.captures(key)?;
|
|
|
|
captures
|
|
|
|
.get(1)
|
|
|
|
.or_else(|| captures.get(0))
|
|
|
|
.map(|m| m.as_str())
|
|
|
|
})() {
|
|
|
|
key = regex_match;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ignore case if requested
|
|
|
|
// Lowercase at the end to not mangle regex
|
|
|
|
if ignore_case {
|
|
|
|
key.to_lowercase()
|
|
|
|
} else {
|
|
|
|
// TODO: Do not perform an allocation here
|
|
|
|
key.to_string()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get a key out of a selection based on options
|
2022-06-09 18:11:03 -04:00
|
|
|
pub fn get_hash(
|
2022-10-02 10:43:21 -04:00
|
|
|
// TODO: Accept any Into<AsRef<Selection>>
|
2022-06-06 18:01:49 -04:00
|
|
|
selection: &Selection,
|
|
|
|
skip_whitespace: bool,
|
|
|
|
regex: Option<&Regex>,
|
|
|
|
ignore_case: bool,
|
|
|
|
) -> u64 {
|
|
|
|
let mut hasher = DefaultHasher::new();
|
|
|
|
|
|
|
|
get_key(selection, skip_whitespace, regex, ignore_case).hash(&mut hasher);
|
|
|
|
|
|
|
|
hasher.finish()
|
|
|
|
}
|
2022-10-02 09:57:37 -04:00
|
|
|
|
|
|
|
/// Splits an `&str` into (string_value, trailing_newlines)
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// assert_eq!(split_trailing_newlines("asdf\n"), ("asdf", "\n"));
|
|
|
|
/// assert_eq!(split_trailing_newlines("asdf\n\nhjk\n"), ("asdf\n\nhjk", "\n"));
|
|
|
|
/// assert_eq!(split_trailing_newlines("asdf"), ("asdf", ""));
|
|
|
|
/// assert_eq!(split_trailing_newlines(""), ("", ""));
|
|
|
|
/// ```
|
|
|
|
pub fn split_trailing_newlines<'a>(s: &'a str) -> (&'a str, &'a str) {
|
|
|
|
s.rfind(|c| c != '\n')
|
|
|
|
.map(|idx| s.split_at(idx + 1))
|
|
|
|
.unwrap_or((s, ""))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Splits an `&str` into (leading_newlines, string_value, trailing_newlines)
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// assert_eq!(split_newlines("asdf\n"), ("", "asdf", "\n"));
|
|
|
|
/// assert_eq!(split_newlines("asdf\n\nhjk\n"), ("", "asdf\n\nhjk", "\n"));
|
|
|
|
/// assert_eq!(split_newlines("\nasdf\n\nhjk\n"), ("\n", "asdf\n\nhjk", "\n"));
|
|
|
|
/// assert_eq!(split_newlines("asdf"), ("", "asdf", ""));
|
|
|
|
/// assert_eq!(split_newlines("\n\n\nasdf"), ("\n\n\n", "asdf", ""));
|
|
|
|
/// assert_eq!(split_newlines(""), ("", "", ""));
|
|
|
|
/// ```
|
|
|
|
pub fn split_newlines<'a>(s: &'a str) -> (&'a str, &'a str, &'a str) {
|
|
|
|
let (leading_newlines, s) = s
|
|
|
|
.find(|c| c != '\n')
|
|
|
|
.map(|idx| s.split_at(idx))
|
|
|
|
.unwrap_or(("", s));
|
|
|
|
|
|
|
|
let (s, trailing_newlines) = s
|
|
|
|
.rfind(|c| c != '\n')
|
|
|
|
.map(|idx| s.split_at(idx + 1))
|
|
|
|
.unwrap_or((s, ""));
|
|
|
|
|
|
|
|
(leading_newlines, s, trailing_newlines)
|
|
|
|
}
|