mirror of
https://github.com/TECHNOFAB11/tmux-copyrat.git
synced 2025-12-12 16:10:07 +01:00
refactor: model receives buffer & computes matches
This commit is contained in:
parent
893f80a1e2
commit
4ec240c2b1
4 changed files with 304 additions and 279 deletions
12
src/lib.rs
12
src/lib.rs
|
|
@ -10,8 +10,10 @@ pub mod ui;
|
||||||
///
|
///
|
||||||
/// Maybe the decision to take ownership of the buffer is a bit bold.
|
/// Maybe the decision to take ownership of the buffer is a bit bold.
|
||||||
pub fn run(buffer: String, opt: &config::basic::Config) -> Option<ui::Selection> {
|
pub fn run(buffer: String, opt: &config::basic::Config) -> Option<ui::Selection> {
|
||||||
let mut model = textbuf::Model::new(
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
&buffer,
|
|
||||||
|
let model = textbuf::Model::new(
|
||||||
|
&lines,
|
||||||
&opt.alphabet,
|
&opt.alphabet,
|
||||||
opt.use_all_patterns,
|
opt.use_all_patterns,
|
||||||
&opt.named_patterns,
|
&opt.named_patterns,
|
||||||
|
|
@ -20,6 +22,10 @@ pub fn run(buffer: String, opt: &config::basic::Config) -> Option<ui::Selection>
|
||||||
opt.unique_hint,
|
opt.unique_hint,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if model.matches.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let hint_style = match &opt.hint_style {
|
let hint_style = match &opt.hint_style {
|
||||||
None => None,
|
None => None,
|
||||||
Some(style) => match style {
|
Some(style) => match style {
|
||||||
|
|
@ -37,7 +43,7 @@ pub fn run(buffer: String, opt: &config::basic::Config) -> Option<ui::Selection>
|
||||||
|
|
||||||
let selection: Option<ui::Selection> = {
|
let selection: Option<ui::Selection> = {
|
||||||
let mut ui = ui::ViewController::new(
|
let mut ui = ui::ViewController::new(
|
||||||
&mut model,
|
&model,
|
||||||
opt.focus_wrap_around,
|
opt.focus_wrap_around,
|
||||||
default_output_destination,
|
default_output_destination,
|
||||||
&opt.colors,
|
&opt.colors,
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_reverse() {
|
fn match_reverse() {
|
||||||
let buffer = "lorem 127.0.0.1 lorem 255.255.255.255 lorem 127.0.0.1 lorem";
|
let buffer = "lorem 127.0.0.1 lorem 255.255.255.255 lorem 127.0.0.1 lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -22,7 +23,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -30,7 +31,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 3);
|
assert_eq!(results.len(), 3);
|
||||||
assert_eq!(results.first().unwrap().hint, "a");
|
assert_eq!(results.first().unwrap().hint, "a");
|
||||||
|
|
@ -40,6 +41,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_unique() {
|
fn match_unique() {
|
||||||
let buffer = "lorem 127.0.0.1 lorem 255.255.255.255 lorem 127.0.0.1 lorem";
|
let buffer = "lorem 127.0.0.1 lorem 255.255.255.255 lorem 127.0.0.1 lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -47,7 +49,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = true;
|
let unique_hint = true;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -55,7 +57,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 3);
|
assert_eq!(results.len(), 3);
|
||||||
assert_eq!(results.first().unwrap().hint, "a");
|
assert_eq!(results.first().unwrap().hint, "a");
|
||||||
|
|
@ -65,6 +67,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_docker() {
|
fn match_docker() {
|
||||||
let buffer = "latest sha256:30557a29d5abc51e5f1d5b472e79b7e296f595abcf19fe6b9199dbbc809c6ff4 20 hours ago";
|
let buffer = "latest sha256:30557a29d5abc51e5f1d5b472e79b7e296f595abcf19fe6b9199dbbc809c6ff4 20 hours ago";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -72,7 +75,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -80,7 +83,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 1);
|
assert_eq!(results.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -93,6 +96,7 @@ mod tests {
|
||||||
fn match_ansi_colors() {
|
fn match_ansi_colors() {
|
||||||
let buffer =
|
let buffer =
|
||||||
"path: [32m/var/log/nginx.log[m\npath: [32mtest/log/nginx-2.log:32[mfolder/.nginx@4df2.log";
|
"path: [32m/var/log/nginx.log[m\npath: [32mtest/log/nginx-2.log:32[mfolder/.nginx@4df2.log";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -100,7 +104,7 @@ mod tests {
|
||||||
let reverse = true;
|
let reverse = true;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -108,7 +112,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 3);
|
assert_eq!(results.len(), 3);
|
||||||
assert_eq!(results.get(0).unwrap().text, "/var/log/nginx.log");
|
assert_eq!(results.get(0).unwrap().text, "/var/log/nginx.log");
|
||||||
|
|
@ -120,6 +124,7 @@ mod tests {
|
||||||
fn match_paths() {
|
fn match_paths() {
|
||||||
let buffer =
|
let buffer =
|
||||||
"Lorem /tmp/foo/bar_lol, lorem\n Lorem /var/log/boot-strap.log lorem ../log/kern.log lorem";
|
"Lorem /tmp/foo/bar_lol, lorem\n Lorem /var/log/boot-strap.log lorem ../log/kern.log lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -127,7 +132,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -135,7 +140,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 3);
|
assert_eq!(results.len(), 3);
|
||||||
assert_eq!(results.get(0).unwrap().text, "/tmp/foo/bar_lol");
|
assert_eq!(results.get(0).unwrap().text, "/tmp/foo/bar_lol");
|
||||||
|
|
@ -146,6 +151,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_home() {
|
fn match_home() {
|
||||||
let buffer = "Lorem ~/.gnu/.config.txt, lorem";
|
let buffer = "Lorem ~/.gnu/.config.txt, lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -153,7 +159,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -161,7 +167,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 1);
|
assert_eq!(results.len(), 1);
|
||||||
assert_eq!(results.get(0).unwrap().text, "~/.gnu/.config.txt");
|
assert_eq!(results.get(0).unwrap().text, "~/.gnu/.config.txt");
|
||||||
|
|
@ -170,6 +176,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_uuids() {
|
fn match_uuids() {
|
||||||
let buffer = "Lorem ipsum 123e4567-e89b-12d3-a456-426655440000 lorem\n Lorem lorem lorem";
|
let buffer = "Lorem ipsum 123e4567-e89b-12d3-a456-426655440000 lorem\n Lorem lorem lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -177,7 +184,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -185,7 +192,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 1);
|
assert_eq!(results.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
@ -193,6 +200,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_shas() {
|
fn match_shas() {
|
||||||
let buffer = "Lorem fd70b5695 5246ddf f924213 lorem\n Lorem 973113963b491874ab2e372ee60d4b4cb75f717c lorem";
|
let buffer = "Lorem fd70b5695 5246ddf f924213 lorem\n Lorem 973113963b491874ab2e372ee60d4b4cb75f717c lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -200,7 +208,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -208,7 +216,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 4);
|
assert_eq!(results.len(), 4);
|
||||||
assert_eq!(results.get(0).unwrap().text, "fd70b5695");
|
assert_eq!(results.get(0).unwrap().text, "fd70b5695");
|
||||||
|
|
@ -223,6 +231,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_ipv4s() {
|
fn match_ipv4s() {
|
||||||
let buffer = "Lorem ipsum 127.0.0.1 lorem\n Lorem 255.255.10.255 lorem 127.0.0.1 lorem";
|
let buffer = "Lorem ipsum 127.0.0.1 lorem\n Lorem 255.255.10.255 lorem 127.0.0.1 lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -230,7 +239,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -238,7 +247,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 3);
|
assert_eq!(results.len(), 3);
|
||||||
assert_eq!(results.get(0).unwrap().pattern, "ipv4");
|
assert_eq!(results.get(0).unwrap().pattern, "ipv4");
|
||||||
|
|
@ -252,6 +261,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_ipv6s() {
|
fn match_ipv6s() {
|
||||||
let buffer = "Lorem ipsum fe80::2:202:fe4 lorem\n Lorem 2001:67c:670:202:7ba8:5e41:1591:d723 lorem fe80::2:1 lorem ipsum fe80:22:312:fe::1%eth0";
|
let buffer = "Lorem ipsum fe80::2:202:fe4 lorem\n Lorem 2001:67c:670:202:7ba8:5e41:1591:d723 lorem fe80::2:1 lorem ipsum fe80:22:312:fe::1%eth0";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -259,7 +269,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -267,7 +277,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 4);
|
assert_eq!(results.len(), 4);
|
||||||
assert_eq!(results.get(0).unwrap().text, "fe80::2:202:fe4");
|
assert_eq!(results.get(0).unwrap().text, "fe80::2:202:fe4");
|
||||||
|
|
@ -283,6 +293,7 @@ mod tests {
|
||||||
fn match_markdown_urls() {
|
fn match_markdown_urls() {
|
||||||
let buffer =
|
let buffer =
|
||||||
"Lorem ipsum [link](https://github.io?foo=bar)  lorem";
|
"Lorem ipsum [link](https://github.io?foo=bar)  lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -290,7 +301,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -298,7 +309,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 2);
|
assert_eq!(results.len(), 2);
|
||||||
assert_eq!(results.get(0).unwrap().pattern, "markdown-url");
|
assert_eq!(results.get(0).unwrap().pattern, "markdown-url");
|
||||||
|
|
@ -310,6 +321,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_urls() {
|
fn match_urls() {
|
||||||
let buffer = "Lorem ipsum https://www.rust-lang.org/tools lorem\n Lorem ipsumhttps://crates.io lorem https://github.io?foo=bar lorem ssh://github.io";
|
let buffer = "Lorem ipsum https://www.rust-lang.org/tools lorem\n Lorem ipsumhttps://crates.io lorem https://github.io?foo=bar lorem ssh://github.io";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -317,7 +329,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -325,7 +337,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 4);
|
assert_eq!(results.len(), 4);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -345,6 +357,7 @@ mod tests {
|
||||||
fn match_emails() {
|
fn match_emails() {
|
||||||
let buffer =
|
let buffer =
|
||||||
"Lorem ipsum <first.last+social@example.com> john@server.department.company.com lorem";
|
"Lorem ipsum <first.last+social@example.com> john@server.department.company.com lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -352,7 +365,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -360,7 +373,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 2);
|
assert_eq!(results.len(), 2);
|
||||||
assert_eq!(results.get(0).unwrap().pattern, "email");
|
assert_eq!(results.get(0).unwrap().pattern, "email");
|
||||||
|
|
@ -378,6 +391,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_addresses() {
|
fn match_addresses() {
|
||||||
let buffer = "Lorem 0xfd70b5695 0x5246ddf lorem\n Lorem 0x973113tlorem";
|
let buffer = "Lorem 0xfd70b5695 0x5246ddf lorem\n Lorem 0x973113tlorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -385,7 +399,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -393,7 +407,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 3);
|
assert_eq!(results.len(), 3);
|
||||||
assert_eq!(results.get(0).unwrap().pattern, "mem-address");
|
assert_eq!(results.get(0).unwrap().pattern, "mem-address");
|
||||||
|
|
@ -407,6 +421,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_hex_colors() {
|
fn match_hex_colors() {
|
||||||
let buffer = "Lorem #fd7b56 lorem #FF00FF\n Lorem #00fF05 lorem #abcd00 lorem #afRR00";
|
let buffer = "Lorem #fd7b56 lorem #FF00FF\n Lorem #00fF05 lorem #abcd00 lorem #afRR00";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -414,7 +429,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -422,7 +437,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 4);
|
assert_eq!(results.len(), 4);
|
||||||
assert_eq!(results.get(0).unwrap().text, "#fd7b56");
|
assert_eq!(results.get(0).unwrap().text, "#fd7b56");
|
||||||
|
|
@ -434,6 +449,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_ipfs() {
|
fn match_ipfs() {
|
||||||
let buffer = "Lorem QmRdbNSxDJBXmssAc9fvTtux4duptMvfSGiGuq6yHAQVKQ lorem Qmfoobar";
|
let buffer = "Lorem QmRdbNSxDJBXmssAc9fvTtux4duptMvfSGiGuq6yHAQVKQ lorem Qmfoobar";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -441,7 +457,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -449,7 +465,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 1);
|
assert_eq!(results.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -461,6 +477,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_process_port() {
|
fn match_process_port() {
|
||||||
let buffer = "Lorem 5695 52463 lorem\n Lorem 973113 lorem 99999 lorem 8888 lorem\n 23456 lorem 5432 lorem 23444";
|
let buffer = "Lorem 5695 52463 lorem\n Lorem 973113 lorem 99999 lorem 8888 lorem\n 23456 lorem 5432 lorem 23444";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -468,7 +485,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -476,7 +493,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 8);
|
assert_eq!(results.len(), 8);
|
||||||
}
|
}
|
||||||
|
|
@ -484,6 +501,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_diff_a() {
|
fn match_diff_a() {
|
||||||
let buffer = "Lorem lorem\n--- a/src/main.rs";
|
let buffer = "Lorem lorem\n--- a/src/main.rs";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -491,7 +509,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -499,7 +517,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 1);
|
assert_eq!(results.len(), 1);
|
||||||
assert_eq!(results.get(0).unwrap().pattern, "diff-a");
|
assert_eq!(results.get(0).unwrap().pattern, "diff-a");
|
||||||
|
|
@ -509,6 +527,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn match_diff_b() {
|
fn match_diff_b() {
|
||||||
let buffer = "Lorem lorem\n+++ b/src/main.rs";
|
let buffer = "Lorem lorem\n+++ b/src/main.rs";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom = vec![];
|
let custom = vec![];
|
||||||
|
|
@ -516,7 +535,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -524,7 +543,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 1);
|
assert_eq!(results.len(), 1);
|
||||||
assert_eq!(results.get(0).unwrap().pattern, "diff-b");
|
assert_eq!(results.get(0).unwrap().pattern, "diff-b");
|
||||||
|
|
@ -534,6 +553,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn priority_between_regexes() {
|
fn priority_between_regexes() {
|
||||||
let buffer = "Lorem [link](http://foo.bar) ipsum CUSTOM-52463 lorem ISSUE-123 lorem\nLorem /var/fd70b569/9999.log 52463 lorem\n Lorem 973113 lorem 123e4567-e89b-12d3-a456-426655440000 lorem 8888 lorem\n https://crates.io/23456/fd70b569 lorem";
|
let buffer = "Lorem [link](http://foo.bar) ipsum CUSTOM-52463 lorem ISSUE-123 lorem\nLorem /var/fd70b569/9999.log 52463 lorem\n Lorem 973113 lorem 123e4567-e89b-12d3-a456-426655440000 lorem 8888 lorem\n https://crates.io/23456/fd70b569 lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom: Vec<String> = ["CUSTOM-[0-9]{4,}", "ISSUE-[0-9]{3}"]
|
let custom: Vec<String> = ["CUSTOM-[0-9]{4,}", "ISSUE-[0-9]{3}"]
|
||||||
|
|
@ -544,7 +564,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -552,7 +572,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 9);
|
assert_eq!(results.len(), 9);
|
||||||
assert_eq!(results.get(0).unwrap().text, "http://foo.bar");
|
assert_eq!(results.get(0).unwrap().text, "http://foo.bar");
|
||||||
|
|
@ -575,6 +595,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn named_patterns() {
|
fn named_patterns() {
|
||||||
let buffer = "Lorem [link](http://foo.bar) ipsum CUSTOM-52463 lorem ISSUE-123 lorem\nLorem /var/fd70b569/9999.log 52463 lorem\n Lorem 973113 lorem 123e4567-e89b-12d3-a456-426655440000 lorem 8888 lorem\n https://crates.io/23456/fd70b569 lorem";
|
let buffer = "Lorem [link](http://foo.bar) ipsum CUSTOM-52463 lorem ISSUE-123 lorem\nLorem /var/fd70b569/9999.log 52463 lorem\n Lorem 973113 lorem 123e4567-e89b-12d3-a456-426655440000 lorem 8888 lorem\n https://crates.io/23456/fd70b569 lorem";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
|
|
||||||
let use_all_patterns = false;
|
let use_all_patterns = false;
|
||||||
use crate::textbuf::regexes::parse_pattern_name;
|
use crate::textbuf::regexes::parse_pattern_name;
|
||||||
|
|
@ -585,7 +606,7 @@ mod tests {
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let results = Model::new(
|
let results = Model::new(
|
||||||
buffer,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -593,7 +614,7 @@ mod tests {
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
unique_hint,
|
||||||
)
|
)
|
||||||
.matches();
|
.matches;
|
||||||
|
|
||||||
assert_eq!(results.len(), 2);
|
assert_eq!(results.len(), 2);
|
||||||
assert_eq!(results.get(0).unwrap().text, "http://foo.bar");
|
assert_eq!(results.get(0).unwrap().text, "http://foo.bar");
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,16 @@ use super::regexes::{NamedPattern, EXCLUDE_PATTERNS, PATTERNS};
|
||||||
/// Holds data for the `Ui`.
|
/// Holds data for the `Ui`.
|
||||||
pub struct Model<'a> {
|
pub struct Model<'a> {
|
||||||
// buffer: &'a str,
|
// buffer: &'a str,
|
||||||
pub lines: Vec<&'a str>,
|
pub lines: &'a [&'a str],
|
||||||
alphabet: &'a Alphabet,
|
|
||||||
use_all_patterns: bool,
|
|
||||||
named_patterns: &'a [NamedPattern],
|
|
||||||
custom_patterns: &'a [String],
|
|
||||||
pub reverse: bool,
|
pub reverse: bool,
|
||||||
unique_hint: bool,
|
pub matches: Vec<Match<'a>>,
|
||||||
|
pub lookup_trie: SequenceTrie<char, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Model<'a> {
|
impl<'a> Model<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
buffer: &'a str,
|
// buffer: &'a str,
|
||||||
|
lines: &'a [&'a str],
|
||||||
alphabet: &'a Alphabet,
|
alphabet: &'a Alphabet,
|
||||||
use_all_patterns: bool,
|
use_all_patterns: bool,
|
||||||
named_patterns: &'a [NamedPattern],
|
named_patterns: &'a [NamedPattern],
|
||||||
|
|
@ -30,56 +28,55 @@ impl<'a> Model<'a> {
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
unique_hint: bool,
|
unique_hint: bool,
|
||||||
) -> Model<'a> {
|
) -> Model<'a> {
|
||||||
let lines = buffer.split('\n').collect();
|
// let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut raw_matches =
|
||||||
|
raw_matches(&lines, named_patterns, custom_patterns, use_all_patterns);
|
||||||
|
|
||||||
|
if reverse {
|
||||||
|
raw_matches.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut matches = associate_hints(&raw_matches, alphabet, unique_hint);
|
||||||
|
|
||||||
|
if reverse {
|
||||||
|
matches.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
let lookup_trie = build_lookup_trie(&matches);
|
||||||
|
|
||||||
Model {
|
Model {
|
||||||
// buffer,
|
// buffer,
|
||||||
lines,
|
lines,
|
||||||
alphabet,
|
|
||||||
use_all_patterns,
|
|
||||||
named_patterns,
|
|
||||||
custom_patterns,
|
|
||||||
reverse,
|
reverse,
|
||||||
unique_hint,
|
matches,
|
||||||
|
lookup_trie,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a vector of `Match`es, each corresponding to a pattern match
|
/// Internal function that searches the model's lines for pattern matches.
|
||||||
/// in the lines, its location (x, y), and associated hint.
|
/// Returns a vector of `RawMatch`es (text, location, pattern id) without
|
||||||
pub fn matches(&self) -> Vec<Match<'a>> {
|
/// an associated hint. The hint is attached to `Match`, not to `RawMatch`.
|
||||||
let mut raw_matches = self.raw_matches();
|
///
|
||||||
|
/// # Notes
|
||||||
if self.reverse {
|
///
|
||||||
raw_matches.reverse();
|
/// Custom regexes have priority over other regexes.
|
||||||
}
|
///
|
||||||
|
/// If no named patterns were specified, it will search for all available
|
||||||
let mut matches = self.associate_hints(&raw_matches, self.unique_hint);
|
/// patterns from the `PATTERNS` catalog.
|
||||||
|
fn raw_matches<'a>(
|
||||||
if self.reverse {
|
lines: &'a [&'a str],
|
||||||
matches.reverse();
|
named_patterns: &'a [NamedPattern],
|
||||||
}
|
custom_patterns: &'a [String],
|
||||||
|
use_all_patterns: bool,
|
||||||
matches
|
) -> Vec<RawMatch<'a>> {
|
||||||
}
|
|
||||||
|
|
||||||
/// Internal function that searches the model's 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`.
|
|
||||||
///
|
|
||||||
/// # Notes
|
|
||||||
///
|
|
||||||
/// Custom regexes have priority over other regexes.
|
|
||||||
///
|
|
||||||
/// If no named patterns were specified, it will search for all available
|
|
||||||
/// patterns from the `PATTERNS` catalog.
|
|
||||||
fn raw_matches(&self) -> Vec<RawMatch<'a>> {
|
|
||||||
let exclude_regexes = EXCLUDE_PATTERNS
|
let exclude_regexes = EXCLUDE_PATTERNS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(name, pattern)| (name, Regex::new(pattern).unwrap()))
|
.map(|&(name, pattern)| (name, Regex::new(pattern).unwrap()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let custom_regexes = self
|
let custom_regexes = custom_patterns
|
||||||
.custom_patterns
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pattern| {
|
.map(|pattern| {
|
||||||
(
|
(
|
||||||
|
|
@ -89,13 +86,13 @@ impl<'a> Model<'a> {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let regexes = if self.use_all_patterns {
|
let regexes = if use_all_patterns {
|
||||||
PATTERNS
|
PATTERNS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(name, pattern)| (name, Regex::new(pattern).unwrap()))
|
.map(|&(name, pattern)| (name, Regex::new(pattern).unwrap()))
|
||||||
.collect::<Vec<(&str, regex::Regex)>>()
|
.collect::<Vec<(&str, regex::Regex)>>()
|
||||||
} else {
|
} else {
|
||||||
self.named_patterns
|
named_patterns
|
||||||
.iter()
|
.iter()
|
||||||
.map(|NamedPattern(name, pattern)| (name.as_str(), Regex::new(pattern).unwrap()))
|
.map(|NamedPattern(name, pattern)| (name.as_str(), Regex::new(pattern).unwrap()))
|
||||||
.collect::<Vec<(&str, regex::Regex)>>()
|
.collect::<Vec<(&str, regex::Regex)>>()
|
||||||
|
|
@ -105,7 +102,7 @@ impl<'a> Model<'a> {
|
||||||
|
|
||||||
let mut raw_matches = Vec::new();
|
let mut raw_matches = Vec::new();
|
||||||
|
|
||||||
for (index, line) in self.lines.iter().enumerate() {
|
for (index, line) in lines.iter().enumerate() {
|
||||||
// Chunk is the remainder of the line to be searched for matches.
|
// Chunk is the remainder of the line to be searched for matches.
|
||||||
// This advances iteratively, until no matches can be found.
|
// This advances iteratively, until no matches can be found.
|
||||||
let mut chunk: &str = line;
|
let mut chunk: &str = line;
|
||||||
|
|
@ -168,15 +165,19 @@ impl<'a> Model<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_matches
|
raw_matches
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Associate a hint to each `RawMatch`, returning a vector of `Match`es.
|
/// Associate a hint to each `RawMatch`, returning a vector of `Match`es.
|
||||||
///
|
///
|
||||||
/// If `unique` is `true`, all duplicate matches will have the same hint.
|
/// If `unique` is `true`, all duplicate matches will have the same hint.
|
||||||
/// For copying matched text, this seems easier and more natural.
|
/// For copying matched text, this seems easier and more natural.
|
||||||
/// If `unique` is `false`, duplicate matches will have their own hint.
|
/// If `unique` is `false`, duplicate matches will have their own hint.
|
||||||
fn associate_hints(&self, raw_matches: &[RawMatch<'a>], unique: bool) -> Vec<Match<'a>> {
|
fn associate_hints<'a>(
|
||||||
let hints = self.alphabet.make_hints(raw_matches.len());
|
raw_matches: &[RawMatch<'a>],
|
||||||
|
alphabet: &'a Alphabet,
|
||||||
|
unique: bool,
|
||||||
|
) -> Vec<Match<'a>> {
|
||||||
|
let hints = alphabet.make_hints(raw_matches.len());
|
||||||
let mut hints_iter = hints.iter();
|
let mut hints_iter = hints.iter();
|
||||||
|
|
||||||
let mut result: Vec<Match<'a>> = vec![];
|
let mut result: Vec<Match<'a>> = vec![];
|
||||||
|
|
@ -217,12 +218,12 @@ impl<'a> Model<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a `SequenceTrie` that helps determine if a sequence of keys
|
/// Builds a `SequenceTrie` that helps determine if a sequence of keys
|
||||||
/// entered by the user corresponds to a match. This kind of lookup
|
/// entered by the user corresponds to a match. This kind of lookup
|
||||||
/// directly returns a reference to the corresponding `Match` if any.
|
/// directly returns a reference to the corresponding `Match` if any.
|
||||||
pub fn build_lookup_trie(matches: &'a [Match<'a>]) -> SequenceTrie<char, usize> {
|
fn build_lookup_trie<'a>(matches: &'a [Match<'a>]) -> SequenceTrie<char, usize> {
|
||||||
let mut trie = SequenceTrie::new();
|
let mut trie = SequenceTrie::new();
|
||||||
|
|
||||||
for (index, mat) in matches.iter().enumerate() {
|
for (index, mat) in matches.iter().enumerate() {
|
||||||
|
|
@ -235,5 +236,4 @@ impl<'a> Model<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
trie
|
trie
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
54
src/ui/vc.rs
54
src/ui/vc.rs
|
|
@ -2,7 +2,6 @@ use std::char;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use sequence_trie::SequenceTrie;
|
|
||||||
use termion::{self, color, cursor, event, style};
|
use termion::{self, color, cursor, event, style};
|
||||||
|
|
||||||
use super::colors::UiColors;
|
use super::colors::UiColors;
|
||||||
|
|
@ -11,11 +10,9 @@ use super::{HintAlignment, HintStyle};
|
||||||
use crate::{config::extended::OutputDestination, textbuf};
|
use crate::{config::extended::OutputDestination, textbuf};
|
||||||
|
|
||||||
pub struct ViewController<'a> {
|
pub struct ViewController<'a> {
|
||||||
model: &'a mut textbuf::Model<'a>,
|
model: &'a textbuf::Model<'a>,
|
||||||
term_width: u16,
|
term_width: u16,
|
||||||
line_offsets: Vec<usize>,
|
line_offsets: Vec<usize>,
|
||||||
matches: Vec<textbuf::Match<'a>>,
|
|
||||||
lookup_trie: SequenceTrie<char, usize>,
|
|
||||||
focus_index: usize,
|
focus_index: usize,
|
||||||
focus_wrap_around: bool,
|
focus_wrap_around: bool,
|
||||||
default_output_destination: OutputDestination,
|
default_output_destination: OutputDestination,
|
||||||
|
|
@ -28,16 +25,18 @@ impl<'a> ViewController<'a> {
|
||||||
// Initialize {{{1
|
// Initialize {{{1
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
model: &'a mut textbuf::Model<'a>,
|
model: &'a textbuf::Model<'a>,
|
||||||
focus_wrap_around: bool,
|
focus_wrap_around: bool,
|
||||||
default_output_destination: OutputDestination,
|
default_output_destination: OutputDestination,
|
||||||
rendering_colors: &'a UiColors,
|
rendering_colors: &'a UiColors,
|
||||||
hint_alignment: &'a HintAlignment,
|
hint_alignment: &'a HintAlignment,
|
||||||
hint_style: Option<HintStyle>,
|
hint_style: Option<HintStyle>,
|
||||||
) -> ViewController<'a> {
|
) -> ViewController<'a> {
|
||||||
let matches = model.matches();
|
let focus_index = if model.reverse {
|
||||||
let lookup_trie = textbuf::Model::build_lookup_trie(&matches);
|
model.matches.len() - 1
|
||||||
let focus_index = if model.reverse { matches.len() - 1 } else { 0 };
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
let (term_width, _) = termion::terminal_size().unwrap_or((80u16, 30u16)); // .expect("Cannot read the terminal size.");
|
let (term_width, _) = termion::terminal_size().unwrap_or((80u16, 30u16)); // .expect("Cannot read the terminal size.");
|
||||||
let line_offsets = get_line_offsets(&model.lines, term_width);
|
let line_offsets = get_line_offsets(&model.lines, term_width);
|
||||||
|
|
@ -46,8 +45,6 @@ impl<'a> ViewController<'a> {
|
||||||
model,
|
model,
|
||||||
term_width,
|
term_width,
|
||||||
line_offsets,
|
line_offsets,
|
||||||
matches,
|
|
||||||
lookup_trie,
|
|
||||||
focus_index,
|
focus_index,
|
||||||
focus_wrap_around,
|
focus_wrap_around,
|
||||||
default_output_destination,
|
default_output_destination,
|
||||||
|
|
@ -106,7 +103,7 @@ impl<'a> ViewController<'a> {
|
||||||
let old_index = self.focus_index;
|
let old_index = self.focus_index;
|
||||||
if self.focus_wrap_around {
|
if self.focus_wrap_around {
|
||||||
if self.focus_index == 0 {
|
if self.focus_index == 0 {
|
||||||
self.focus_index = self.matches.len() - 1;
|
self.focus_index = self.model.matches.len() - 1;
|
||||||
} else {
|
} else {
|
||||||
self.focus_index -= 1;
|
self.focus_index -= 1;
|
||||||
}
|
}
|
||||||
|
|
@ -122,12 +119,12 @@ impl<'a> ViewController<'a> {
|
||||||
fn next_focus_index(&mut self) -> (usize, usize) {
|
fn next_focus_index(&mut self) -> (usize, usize) {
|
||||||
let old_index = self.focus_index;
|
let old_index = self.focus_index;
|
||||||
if self.focus_wrap_around {
|
if self.focus_wrap_around {
|
||||||
if self.focus_index == self.matches.len() - 1 {
|
if self.focus_index == self.model.matches.len() - 1 {
|
||||||
self.focus_index = 0;
|
self.focus_index = 0;
|
||||||
} else {
|
} else {
|
||||||
self.focus_index += 1;
|
self.focus_index += 1;
|
||||||
}
|
}
|
||||||
} else if self.focus_index < self.matches.len() - 1 {
|
} else if self.focus_index < self.model.matches.len() - 1 {
|
||||||
self.focus_index += 1;
|
self.focus_index += 1;
|
||||||
}
|
}
|
||||||
let new_index = self.focus_index;
|
let new_index = self.focus_index;
|
||||||
|
|
@ -379,7 +376,7 @@ impl<'a> ViewController<'a> {
|
||||||
&self.rendering_colors,
|
&self.rendering_colors,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (index, mat) in self.matches.iter().enumerate() {
|
for (index, mat) in self.model.matches.iter().enumerate() {
|
||||||
let focused = index == self.focus_index;
|
let focused = index == self.focus_index;
|
||||||
self.render_match(stdout, mat, focused);
|
self.render_match(stdout, mat, focused);
|
||||||
}
|
}
|
||||||
|
|
@ -396,12 +393,12 @@ impl<'a> ViewController<'a> {
|
||||||
new_focus_index: usize,
|
new_focus_index: usize,
|
||||||
) {
|
) {
|
||||||
// Render the previously focused match as non-focused
|
// Render the previously focused match as non-focused
|
||||||
let mat = self.matches.get(old_focus_index).unwrap();
|
let mat = self.model.matches.get(old_focus_index).unwrap();
|
||||||
let focused = false;
|
let focused = false;
|
||||||
self.render_match(stdout, mat, focused);
|
self.render_match(stdout, mat, focused);
|
||||||
|
|
||||||
// Render the previously focused match as non-focused
|
// Render the previously focused match as non-focused
|
||||||
let mat = self.matches.get(new_focus_index).unwrap();
|
let mat = self.model.matches.get(new_focus_index).unwrap();
|
||||||
let focused = true;
|
let focused = true;
|
||||||
self.render_match(stdout, mat, focused);
|
self.render_match(stdout, mat, focused);
|
||||||
|
|
||||||
|
|
@ -420,7 +417,7 @@ impl<'a> ViewController<'a> {
|
||||||
fn listen(&mut self, reader: &mut dyn io::Read, writer: &mut dyn io::Write) -> Event {
|
fn listen(&mut self, reader: &mut dyn io::Read, writer: &mut dyn io::Write) -> Event {
|
||||||
use termion::input::TermRead; // Trait for `reader.keys().next()`.
|
use termion::input::TermRead; // Trait for `reader.keys().next()`.
|
||||||
|
|
||||||
if self.matches.is_empty() {
|
if self.model.matches.is_empty() {
|
||||||
return Event::Exit;
|
return Event::Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -487,7 +484,7 @@ impl<'a> ViewController<'a> {
|
||||||
|
|
||||||
// Yank/copy
|
// Yank/copy
|
||||||
event::Key::Char(_ch @ 'y') | event::Key::Char(_ch @ '\n') => {
|
event::Key::Char(_ch @ 'y') | event::Key::Char(_ch @ '\n') => {
|
||||||
let text = self.matches.get(self.focus_index).unwrap().text;
|
let text = self.model.matches.get(self.focus_index).unwrap().text;
|
||||||
return Event::Match(Selection {
|
return Event::Match(Selection {
|
||||||
text: text.to_string(),
|
text: text.to_string(),
|
||||||
uppercased: false,
|
uppercased: false,
|
||||||
|
|
@ -495,7 +492,7 @@ impl<'a> ViewController<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
event::Key::Char(_ch @ 'Y') => {
|
event::Key::Char(_ch @ 'Y') => {
|
||||||
let text = self.matches.get(self.focus_index).unwrap().text;
|
let text = self.model.matches.get(self.focus_index).unwrap().text;
|
||||||
return Event::Match(Selection {
|
return Event::Match(Selection {
|
||||||
text: text.to_string(),
|
text: text.to_string(),
|
||||||
uppercased: true,
|
uppercased: true,
|
||||||
|
|
@ -526,6 +523,7 @@ impl<'a> ViewController<'a> {
|
||||||
typed_hint.push_str(&lower_key);
|
typed_hint.push_str(&lower_key);
|
||||||
|
|
||||||
let node = self
|
let node = self
|
||||||
|
.model
|
||||||
.lookup_trie
|
.lookup_trie
|
||||||
.get_node(&typed_hint.chars().collect::<Vec<char>>());
|
.get_node(&typed_hint.chars().collect::<Vec<char>>());
|
||||||
|
|
||||||
|
|
@ -540,7 +538,7 @@ impl<'a> ViewController<'a> {
|
||||||
let match_index = node.value().expect(
|
let match_index = node.value().expect(
|
||||||
"By construction, the Lookup Trie should have a value for each leaf.",
|
"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 mat = self.model.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 text = mat.text.to_string();
|
||||||
return Event::Match(Selection {
|
return Event::Match(Selection {
|
||||||
text,
|
text,
|
||||||
|
|
@ -880,18 +878,19 @@ path: /usr/local/bin/cargo";
|
||||||
#[test]
|
#[test]
|
||||||
/// Simulates rendering without any match.
|
/// Simulates rendering without any match.
|
||||||
fn test_render_full_without_matches() {
|
fn test_render_full_without_matches() {
|
||||||
let content = "lorem 127.0.0.1 lorem
|
let buffer = "lorem 127.0.0.1 lorem
|
||||||
|
|
||||||
Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
|
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = false;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
let custom_patterns = vec![];
|
let custom_patterns = vec![];
|
||||||
let alphabet = alphabet::Alphabet("abcd".to_string());
|
let alphabet = alphabet::Alphabet("abcd".to_string());
|
||||||
let reverse = false;
|
let reverse = false;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let mut model = textbuf::Model::new(
|
let mut model = textbuf::Model::new(
|
||||||
content,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -918,8 +917,6 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
||||||
model: &mut model,
|
model: &mut model,
|
||||||
term_width,
|
term_width,
|
||||||
line_offsets,
|
line_offsets,
|
||||||
matches: vec![], // no matches
|
|
||||||
lookup_trie: SequenceTrie::new(),
|
|
||||||
focus_index: 0,
|
focus_index: 0,
|
||||||
focus_wrap_around: false,
|
focus_wrap_around: false,
|
||||||
default_output_destination: OutputDestination::Tmux,
|
default_output_destination: OutputDestination::Tmux,
|
||||||
|
|
@ -957,9 +954,10 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
||||||
#[test]
|
#[test]
|
||||||
/// Simulates rendering with matches.
|
/// Simulates rendering with matches.
|
||||||
fn test_render_full_with_matches() {
|
fn test_render_full_with_matches() {
|
||||||
let content = "lorem 127.0.0.1 lorem
|
let buffer = "lorem 127.0.0.1 lorem
|
||||||
|
|
||||||
Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
||||||
|
let lines = buffer.split('\n').collect::<Vec<_>>();
|
||||||
|
|
||||||
let use_all_patterns = true;
|
let use_all_patterns = true;
|
||||||
let named_pat = vec![];
|
let named_pat = vec![];
|
||||||
|
|
@ -968,7 +966,7 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
||||||
let reverse = true;
|
let reverse = true;
|
||||||
let unique_hint = false;
|
let unique_hint = false;
|
||||||
let mut model = textbuf::Model::new(
|
let mut model = textbuf::Model::new(
|
||||||
content,
|
&lines,
|
||||||
&alphabet,
|
&alphabet,
|
||||||
use_all_patterns,
|
use_all_patterns,
|
||||||
&named_pat,
|
&named_pat,
|
||||||
|
|
@ -1092,7 +1090,7 @@ Barcelona https://en.wikipedia.org/wiki/Barcelona - ";
|
||||||
// .find(|(_idx, (&l, &r))| l != r);
|
// .find(|(_idx, (&l, &r))| l != r);
|
||||||
// println!("{:?}", diff_point);
|
// println!("{:?}", diff_point);
|
||||||
|
|
||||||
assert_eq!(2, ui.matches.len());
|
assert_eq!(2, ui.model.matches.len());
|
||||||
|
|
||||||
assert_eq!(writer, expected.as_bytes());
|
assert_eq!(writer, expected.as_bytes());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue