Skip to content

Commit

Permalink
Add Screen to replace cli::Runner (#1040)
Browse files Browse the repository at this point in the history
`cli::Runner` is a bit difficult to update for adding new features,
so I want to replace it with the new implementation, `Screen`.

`Screen` will behave like `cli::Runner`, but it's written for
extensibility. Still, this struct is huge, but I believe it's better
than `cli::Runner`.

This patch just adds `Screen`. I will replace `cli::Runner` with it
later.
  • Loading branch information
yykamei committed Aug 15, 2024
1 parent 29a1356 commit 1a8447b
Show file tree
Hide file tree
Showing 5 changed files with 623 additions and 19 deletions.
40 changes: 29 additions & 11 deletions src/candidates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ impl Candidates {
)?;
paths.sort();
paths.truncate(visible_paths_length);
Ok(Self {
paths,
selected: None,
})
let selected = if paths.is_empty() { None } else { Some(0) };

Ok(Self { paths, selected })
}

pub(crate) fn paths(&self) -> &[MatchedPath] {
Expand Down Expand Up @@ -242,15 +241,15 @@ mod tests {
let query = Query::new("");
let repo = Repository::open(dir.path()).unwrap();
let mut candidates = Candidates::new(3, &starting_point, &query, Some(&repo)).unwrap();
assert_eq!(candidates.selected, None);
candidates.move_down();
assert_eq!(candidates.selected, Some(0));
candidates.move_down();
assert_eq!(candidates.selected, Some(1));
candidates.move_down();
assert_eq!(candidates.selected, Some(2));
candidates.move_down();
assert_eq!(candidates.selected, Some(2));
candidates.move_down();
assert_eq!(candidates.selected, Some(2));

let mut candidates = Candidates::new(0, &starting_point, &query, Some(&repo)).unwrap();
candidates.move_down();
Expand All @@ -266,9 +265,9 @@ mod tests {
let query = Query::new("");
let repo = Repository::open(dir.path()).unwrap();
let mut candidates = Candidates::new(3, &starting_point, &query, Some(&repo)).unwrap();
assert_eq!(candidates.selected, None);
assert_eq!(candidates.selected, Some(0));
candidates.move_up();
assert_eq!(candidates.selected, None);
assert_eq!(candidates.selected, Some(0));
candidates.move_down();
candidates.move_down();
candidates.move_down();
Expand All @@ -294,9 +293,6 @@ mod tests {
let query = Query::new("");
let repo = Repository::open(dir.path()).unwrap();
let mut candidates = Candidates::new(3, &starting_point, &query, Some(&repo)).unwrap();
assert_eq!(candidates.selected(), None);

candidates.move_down();
assert_eq!(candidates.selected().unwrap().relative(), ".browserslistrc");

candidates.move_down();
Expand All @@ -306,10 +302,32 @@ mod tests {
.relative()
.ends_with("bar.toml"));

candidates.move_down();
assert!(candidates
.selected()
.unwrap()
.relative()
.ends_with("ok.toml"));

candidates.move_up();
candidates.move_up();
assert_eq!(candidates.selected().unwrap().relative(), ".browserslistrc");
}

#[test]
fn test_selected_none_at_started() {
let dir = create_tree().unwrap();
let starting_point = StartingPoint::new(dir.path()).unwrap();
let query = Query::new("ABCABC!!!!!!!!!");
let mut candidates = Candidates::new(3, &starting_point, &query, None).unwrap();
assert_eq!(candidates.selected(), None);

candidates.move_down();
assert_eq!(candidates.selected(), None);

candidates.move_down();
}

#[test]
fn test_paths() {
let dir = create_tree().unwrap();
Expand Down
6 changes: 3 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::ffi::{CString, OsString};
use std::env;
use std::ffi::OsString;
use std::io::{self, Stderr, Stdout, Write};
use std::os::raw::c_char;
use std::process::exit;
use std::time::Duration;
use std::{env, ptr};

use copypasta::{ClipboardContext, ClipboardProvider};
use crossterm::event::{KeyEventKind, KeyEventState};
Expand All @@ -23,6 +22,7 @@ use crate::invoke::{invoke, Libc};
use crate::matched_path::MatchedPath;
use crate::preferences::Preferences;
use crate::query::Query;
use crate::screen::Screen;
use crate::starting_point::StartingPoint;
use crate::status_line::StatusLine;
use crate::terminal::Terminal;
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod logger;
mod matched_path;
mod preferences;
mod query;
mod screen;
mod starting_point;
mod status_line;
mod terminal;
35 changes: 30 additions & 5 deletions src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use unicode_width::UnicodeWidthStr;
pub(crate) struct Query {
value: Vec<String>,
idx: usize,
pub(crate) terminal_pos: usize,
}

impl Query {
Expand All @@ -18,21 +19,30 @@ impl Query {
.map(|s| s.to_string())
.collect();
let idx = value.len();
let terminal_pos = value.iter().map(|s| get_cjk_width(s)).sum();

Self { value, idx }
Self {
value,
idx,
terminal_pos: terminal_pos,
}
}

pub(crate) fn push<S: ToString>(&mut self, s: S) -> usize {
self.value.insert(self.idx, s.to_string());
self.idx += 1;
get_cjk_width(&s.to_string())
let d = get_cjk_width(&s.to_string());
self.terminal_pos += d;
d
}

pub(crate) fn pop(&mut self) -> usize {
if self.idx > 0 {
let popped = self.value.remove(self.idx - 1);
self.idx -= 1;
return get_cjk_width(&popped);
let d = get_cjk_width(&popped);
self.terminal_pos -= d;
return d;
}
0
}
Expand All @@ -44,7 +54,9 @@ impl Query {
.get(self.idx - 1)
.expect("Unexpected out of bounds");
self.idx -= 1;
return get_cjk_width(char_before_move);
let d = get_cjk_width(char_before_move);
self.terminal_pos -= d;
return d;
}
0
}
Expand All @@ -56,7 +68,9 @@ impl Query {
.value
.get(self.idx - 1)
.expect("Unexpected out of bounds");
return get_cjk_width(char_after_move);
let d = get_cjk_width(char_after_move);
self.terminal_pos += d;
return d;
}
0
}
Expand Down Expand Up @@ -89,23 +103,28 @@ mod tests {
let mut query = Query::new("👩‍🔬!");
assert_eq!(query.value, vec!["👩‍🔬", "!"]);
assert_eq!(query.idx, 2);
assert_eq!(query.terminal_pos, 3);

assert_eq!(query.push("💇‍♂️"), 2);
assert_eq!(query.push("a"), 1);
assert_eq!(query.push("b"), 1);
assert_eq!(query.value, vec!["👩‍🔬", "!", "💇‍♂️", "a", "b"]);
assert_eq!(query.idx, 5);
assert_eq!(query.terminal_pos, 7);

assert_eq!(query.pop(), 1);
assert_eq!(query.value, vec!["👩‍🔬", "!", "💇‍♂️", "a"]);
assert_eq!(query.idx, 4);
assert_eq!(query.terminal_pos, 6);

assert_eq!(query.move_left(), 1);
assert_eq!(query.idx, 3);
assert_eq!(query.terminal_pos, 5);

assert_eq!(query.pop(), 2);
assert_eq!(query.value, vec!["👩‍🔬", "!", "a"]);
assert_eq!(query.idx, 2);
assert_eq!(query.terminal_pos, 3);

assert_eq!(query.move_left(), 1);
assert_eq!(query.move_left(), 2);
Expand All @@ -115,10 +134,12 @@ mod tests {
assert_eq!(query.move_right(), 0);
assert_eq!(query.move_right(), 0);
assert_eq!(query.idx, 3);
assert_eq!(query.terminal_pos, 4);

assert_eq!(query.push("?"), 1);
assert_eq!(query.value, vec!["👩‍🔬", "!", "a", "?"]);
assert_eq!(query.idx, 4);
assert_eq!(query.terminal_pos, 5);

assert_eq!(query.move_left(), 1);
assert_eq!(query.move_left(), 1);
Expand All @@ -127,14 +148,17 @@ mod tests {
assert_eq!(query.move_left(), 0);
assert_eq!(query.move_left(), 0);
assert_eq!(query.idx, 0);
assert_eq!(query.terminal_pos, 0);

assert_eq!(query.pop(), 0);
assert_eq!(query.value, vec!["👩‍🔬", "!", "a", "?"]);
assert_eq!(query.idx, 0);
assert_eq!(query.terminal_pos, 0);

assert_eq!(query.push("😇"), 2);
assert_eq!(query.value, vec!["😇", "👩‍🔬", "!", "a", "?"]);
assert_eq!(query.idx, 1);
assert_eq!(query.terminal_pos, 2);
}

#[test]
Expand All @@ -145,6 +169,7 @@ mod tests {
vec!["S", "u", "p", "e", "r", " ", "c", "o", "o", "l", " ", "q", "u", "e", "r", "y"]
);
assert_eq!(query.idx, 16);
assert_eq!(query.terminal_pos, 16);
assert_eq!(query.to_string(), "Super cool query");
}

Expand Down
Loading

0 comments on commit 1a8447b

Please sign in to comment.