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 = [
|
dependencies = [
|
||||||
"clap 3.0.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -195,6 +196,11 @@ name = "regex-syntax"
|
||||||
version = "0.6.17"
|
version = "0.6.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
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 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 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 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 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 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"
|
"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"
|
termion = "1.5"
|
||||||
regex = "1.3.1"
|
regex = "1.3.1"
|
||||||
clap = { version = "3.0.0-beta.1", features = ["suggestions", "color", "wrap_help", "term_size"]}
|
clap = { version = "3.0.0-beta.1", features = ["suggestions", "color", "wrap_help", "term_size"]}
|
||||||
|
sequence_trie = "0.3.6"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "copyrat"
|
name = "copyrat"
|
||||||
|
|
|
||||||
24
src/state.rs
24
src/state.rs
|
|
@ -1,4 +1,5 @@
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use sequence_trie::SequenceTrie;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
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>> {
|
pub fn matches(&self, unique: bool) -> Vec<Match<'a>> {
|
||||||
let mut raw_matches = self.raw_matches();
|
let mut raw_matches = self.raw_matches();
|
||||||
|
|
||||||
|
|
@ -86,6 +89,9 @@ impl<'a> State<'a> {
|
||||||
matches
|
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>> {
|
fn raw_matches(&self) -> Vec<RawMatch<'a>> {
|
||||||
let mut matches = Vec::new();
|
let mut matches = Vec::new();
|
||||||
|
|
||||||
|
|
@ -219,6 +225,24 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
result
|
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)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
53
src/view.rs
53
src/view.rs
|
|
@ -1,15 +1,17 @@
|
||||||
use super::{colors, state};
|
|
||||||
|
|
||||||
use crate::error::ParseError;
|
|
||||||
use clap::Clap;
|
use clap::Clap;
|
||||||
|
use sequence_trie::SequenceTrie;
|
||||||
use std::char;
|
use std::char;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use termion::{self, color, cursor, event, style};
|
use termion::{self, color, cursor, event, style};
|
||||||
|
|
||||||
|
use crate::error::ParseError;
|
||||||
|
use crate::{colors, state};
|
||||||
|
|
||||||
pub struct View<'a> {
|
pub struct View<'a> {
|
||||||
state: &'a mut state::State<'a>,
|
state: &'a mut state::State<'a>,
|
||||||
matches: Vec<state::Match<'a>>,
|
matches: Vec<state::Match<'a>>,
|
||||||
|
lookup_trie: SequenceTrie<char, usize>,
|
||||||
focus_index: usize,
|
focus_index: usize,
|
||||||
hint_alignment: &'a HintAlignment,
|
hint_alignment: &'a HintAlignment,
|
||||||
rendering_colors: &'a ViewColors,
|
rendering_colors: &'a ViewColors,
|
||||||
|
|
@ -117,11 +119,13 @@ impl<'a> View<'a> {
|
||||||
hint_style: Option<HintStyle>,
|
hint_style: Option<HintStyle>,
|
||||||
) -> View<'a> {
|
) -> View<'a> {
|
||||||
let matches = state.matches(unique_hint);
|
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 };
|
let focus_index = if state.reverse { matches.len() - 1 } else { 0 };
|
||||||
|
|
||||||
View {
|
View {
|
||||||
state,
|
state,
|
||||||
matches,
|
matches,
|
||||||
|
lookup_trie,
|
||||||
focus_index,
|
focus_index,
|
||||||
hint_alignment,
|
hint_alignment,
|
||||||
rendering_colors,
|
rendering_colors,
|
||||||
|
|
@ -385,15 +389,6 @@ impl<'a> View<'a> {
|
||||||
|
|
||||||
let mut typed_hint = String::new();
|
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);
|
self.full_render(writer);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -447,21 +442,26 @@ impl<'a> View<'a> {
|
||||||
|
|
||||||
typed_hint.push_str(&lower_key);
|
typed_hint.push_str(&lower_key);
|
||||||
|
|
||||||
// Find the match that corresponds to the entered key.
|
match self
|
||||||
let found = self.matches
|
.lookup_trie
|
||||||
.iter()
|
.get_node(&typed_hint.chars().collect::<Vec<char>>())
|
||||||
// Avoid cloning typed_hint for comparison.
|
{
|
||||||
.find(|&mat| &mat.hint == &typed_hint);
|
|
||||||
|
|
||||||
match found {
|
|
||||||
Some(mat) => {
|
|
||||||
let text = mat.text.to_string();
|
|
||||||
let uppercased = key != lower_key;
|
|
||||||
return Event::Match((text, uppercased));
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
if typed_hint.len() >= longest_hint.len() {
|
// An unknown key was entered.
|
||||||
break;
|
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));
|
||||||
|
} 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 {
|
let view = View {
|
||||||
state: &mut state,
|
state: &mut state,
|
||||||
matches: vec![], // no matches
|
matches: vec![], // no matches
|
||||||
|
lookup_trie: SequenceTrie::new(),
|
||||||
focus_index: 0,
|
focus_index: 0,
|
||||||
hint_alignment: &hint_alignment,
|
hint_alignment: &hint_alignment,
|
||||||
rendering_colors: &rendering_colors,
|
rendering_colors: &rendering_colors,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue