mirror of
https://github.com/TECHNOFAB11/tmux-copyrat.git
synced 2025-12-12 16:10:07 +01:00
feat: use a Trie for hint check
This commit is contained in:
parent
2e9b5fb7be
commit
be698ab741
4 changed files with 59 additions and 26 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
|
@ -65,6 +65,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"clap 3.0.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sequence_trie 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
|
@ -195,6 +196,11 @@ name = "regex-syntax"
|
|||
version = "0.6.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "sequence_trie"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
|
|
@ -361,6 +367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
|
||||
"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
|
||||
"checksum sequence_trie 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1ee22067b7ccd072eeb64454b9c6e1b33b61cd0d49e895fd48676a184580e0c3"
|
||||
"checksum strsim 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
"checksum syn 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "95b5f192649e48a5302a13f2feb224df883b98933222369e4b3b0fe2a5447269"
|
||||
"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ license = "MIT"
|
|||
termion = "1.5"
|
||||
regex = "1.3.1"
|
||||
clap = { version = "3.0.0-beta.1", features = ["suggestions", "color", "wrap_help", "term_size"]}
|
||||
sequence_trie = "0.3.6"
|
||||
|
||||
[[bin]]
|
||||
name = "copyrat"
|
||||
|
|
|
|||
24
src/state.rs
24
src/state.rs
|
|
@ -1,4 +1,5 @@
|
|||
use regex::Regex;
|
||||
use sequence_trie::SequenceTrie;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
|
|
@ -70,6 +71,8 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a vector of `Match`es, each corresponding to a pattern match
|
||||
/// in the lines, its location (x, y), and associated hint.
|
||||
pub fn matches(&self, unique: bool) -> Vec<Match<'a>> {
|
||||
let mut raw_matches = self.raw_matches();
|
||||
|
||||
|
|
@ -86,6 +89,9 @@ impl<'a> State<'a> {
|
|||
matches
|
||||
}
|
||||
|
||||
/// Internal function that searches the state lines for pattern matches.
|
||||
/// Returns a vector of `RawMatch`es (text, location, pattern id) without
|
||||
/// an associated hint. The hint is attached to `Match`, not to `RawMatch`.
|
||||
fn raw_matches(&self) -> Vec<RawMatch<'a>> {
|
||||
let mut matches = Vec::new();
|
||||
|
||||
|
|
@ -219,6 +225,24 @@ impl<'a> State<'a> {
|
|||
|
||||
result
|
||||
}
|
||||
|
||||
/// Builds a `SequenceTrie` that helps determine if a sequence of keys
|
||||
/// entered by the user corresponds to a match. This kind of lookup
|
||||
/// directly returns a reference to the corresponding `Match` if any.
|
||||
pub fn build_lookup_trie(matches: &'a Vec<Match<'a>>) -> SequenceTrie<char, usize> {
|
||||
let mut trie = SequenceTrie::new();
|
||||
|
||||
for (index, mat) in matches.iter().enumerate() {
|
||||
let hint_chars = mat.hint.chars().collect::<Vec<char>>();
|
||||
|
||||
// no need to insert twice the same hint
|
||||
if trie.get(&hint_chars).is_none() {
|
||||
trie.insert_owned(hint_chars, index);
|
||||
}
|
||||
}
|
||||
|
||||
trie
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
49
src/view.rs
49
src/view.rs
|
|
@ -1,15 +1,17 @@
|
|||
use super::{colors, state};
|
||||
|
||||
use crate::error::ParseError;
|
||||
use clap::Clap;
|
||||
use sequence_trie::SequenceTrie;
|
||||
use std::char;
|
||||
use std::io;
|
||||
use std::str::FromStr;
|
||||
use termion::{self, color, cursor, event, style};
|
||||
|
||||
use crate::error::ParseError;
|
||||
use crate::{colors, state};
|
||||
|
||||
pub struct View<'a> {
|
||||
state: &'a mut state::State<'a>,
|
||||
matches: Vec<state::Match<'a>>,
|
||||
lookup_trie: SequenceTrie<char, usize>,
|
||||
focus_index: usize,
|
||||
hint_alignment: &'a HintAlignment,
|
||||
rendering_colors: &'a ViewColors,
|
||||
|
|
@ -117,11 +119,13 @@ impl<'a> View<'a> {
|
|||
hint_style: Option<HintStyle>,
|
||||
) -> View<'a> {
|
||||
let matches = state.matches(unique_hint);
|
||||
let lookup_trie = state::State::build_lookup_trie(&matches);
|
||||
let focus_index = if state.reverse { matches.len() - 1 } else { 0 };
|
||||
|
||||
View {
|
||||
state,
|
||||
matches,
|
||||
lookup_trie,
|
||||
focus_index,
|
||||
hint_alignment,
|
||||
rendering_colors,
|
||||
|
|
@ -385,15 +389,6 @@ impl<'a> View<'a> {
|
|||
|
||||
let mut typed_hint = String::new();
|
||||
|
||||
// TODO: simplify
|
||||
let longest_hint = self
|
||||
.matches
|
||||
.iter()
|
||||
.map(|m| &m.hint)
|
||||
.max_by(|x, y| x.len().cmp(&y.len()))
|
||||
.unwrap()
|
||||
.clone();
|
||||
|
||||
self.full_render(writer);
|
||||
|
||||
loop {
|
||||
|
|
@ -447,21 +442,26 @@ impl<'a> View<'a> {
|
|||
|
||||
typed_hint.push_str(&lower_key);
|
||||
|
||||
// Find the match that corresponds to the entered key.
|
||||
let found = self.matches
|
||||
.iter()
|
||||
// Avoid cloning typed_hint for comparison.
|
||||
.find(|&mat| &mat.hint == &typed_hint);
|
||||
|
||||
match found {
|
||||
Some(mat) => {
|
||||
match self
|
||||
.lookup_trie
|
||||
.get_node(&typed_hint.chars().collect::<Vec<char>>())
|
||||
{
|
||||
None => {
|
||||
// An unknown key was entered.
|
||||
return Event::Exit;
|
||||
}
|
||||
Some(node) => {
|
||||
if node.is_leaf() {
|
||||
// The last key of a hint was entered.
|
||||
let match_index = node.value().expect("By construction, the Lookup Trie should have a value for each leaf.");
|
||||
let mat = self.matches.get(*match_index).expect("By construction, the value in a leaf should correspond to an existing hint.");
|
||||
let text = mat.text.to_string();
|
||||
let uppercased = key != lower_key;
|
||||
return Event::Match((text, uppercased));
|
||||
}
|
||||
None => {
|
||||
if typed_hint.len() >= longest_hint.len() {
|
||||
break;
|
||||
} else {
|
||||
// The prefix of a hint was entered, but we
|
||||
// still need more keys.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -779,6 +779,7 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
|||
let view = View {
|
||||
state: &mut state,
|
||||
matches: vec![], // no matches
|
||||
lookup_trie: SequenceTrie::new(),
|
||||
focus_index: 0,
|
||||
hint_alignment: &hint_alignment,
|
||||
rendering_colors: &rendering_colors,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue