mirror of
https://github.com/notohh/rustlings.git
synced 2024-12-18 06:58:10 -05:00
Merge branch 'main' of https://github.com/frroossst/rustlings
This commit is contained in:
commit
e1e316b931
4 changed files with 91 additions and 4 deletions
|
@ -55,6 +55,7 @@ fn run_bin(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See `info_file::ExerciseInfo`
|
/// See `info_file::ExerciseInfo`
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Exercise {
|
pub struct Exercise {
|
||||||
pub dir: Option<&'static str>,
|
pub dir: Option<&'static str>,
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
|
|
55
src/list.rs
55
src/list.rs
|
@ -1,4 +1,4 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Ok, Result};
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
cursor,
|
cursor,
|
||||||
event::{
|
event::{
|
||||||
|
@ -21,6 +21,7 @@ mod state;
|
||||||
|
|
||||||
fn handle_list(app_state: &mut AppState, stdout: &mut StdoutLock) -> Result<()> {
|
fn handle_list(app_state: &mut AppState, stdout: &mut StdoutLock) -> Result<()> {
|
||||||
let mut list_state = ListState::new(app_state, stdout)?;
|
let mut list_state = ListState::new(app_state, stdout)?;
|
||||||
|
let mut is_searching = false;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match event::read().context("Failed to read terminal event")? {
|
match event::read().context("Failed to read terminal event")? {
|
||||||
|
@ -32,8 +33,49 @@ fn handle_list(app_state: &mut AppState, stdout: &mut StdoutLock) -> Result<()>
|
||||||
|
|
||||||
list_state.message.clear();
|
list_state.message.clear();
|
||||||
|
|
||||||
|
let curr_key = key.code;
|
||||||
|
|
||||||
|
if is_searching {
|
||||||
|
match curr_key {
|
||||||
|
KeyCode::Esc | KeyCode::Enter => {
|
||||||
|
is_searching = false; // not sure why rust analyzer thinks this is unused
|
||||||
|
list_state.search_query.clear();
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
KeyCode::Char(k) => {
|
||||||
|
eprintln!("pressed while searching {:?}", curr_key);
|
||||||
|
|
||||||
|
list_state.search_query.push(k);
|
||||||
|
list_state.message.push_str("search:");
|
||||||
|
list_state.message.push_str(&list_state.search_query);
|
||||||
|
list_state.message.push_str("|");
|
||||||
|
|
||||||
|
list_state.select_if_matches_search_query();
|
||||||
|
|
||||||
|
list_state.draw(stdout)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
KeyCode::Backspace => {
|
||||||
|
list_state.search_query.pop();
|
||||||
|
list_state.message.push_str("search:");
|
||||||
|
list_state.message.push_str(&list_state.search_query);
|
||||||
|
list_state.message.push_str("|");
|
||||||
|
|
||||||
|
list_state.select_if_matches_search_query();
|
||||||
|
|
||||||
|
list_state.draw(stdout)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Char('q') => return Ok(()),
|
KeyCode::Char('q') => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
KeyCode::Down | KeyCode::Char('j') => list_state.select_next(),
|
KeyCode::Down | KeyCode::Char('j') => list_state.select_next(),
|
||||||
KeyCode::Up | KeyCode::Char('k') => list_state.select_previous(),
|
KeyCode::Up | KeyCode::Char('k') => list_state.select_previous(),
|
||||||
KeyCode::Home | KeyCode::Char('g') => list_state.select_first(),
|
KeyCode::Home | KeyCode::Char('g') => list_state.select_first(),
|
||||||
|
@ -66,9 +108,16 @@ fn handle_list(app_state: &mut AppState, stdout: &mut StdoutLock) -> Result<()>
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
KeyCode::Char('s') | KeyCode::Char('/') => {
|
||||||
|
eprintln!("starting search");
|
||||||
|
list_state.message.push_str("search:|");
|
||||||
|
is_searching = true;
|
||||||
|
}
|
||||||
// Redraw to remove the message.
|
// Redraw to remove the message.
|
||||||
KeyCode::Esc => (),
|
KeyCode::Esc => (),
|
||||||
_ => continue,
|
_ => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::Mouse(event) => match event.kind {
|
Event::Mouse(event) => match event.kind {
|
||||||
|
|
|
@ -46,7 +46,7 @@ impl ScrollState {
|
||||||
self.selected
|
self.selected
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_selected(&mut self, selected: usize) {
|
pub fn set_selected(&mut self, selected: usize) {
|
||||||
self.selected = Some(selected);
|
self.selected = Some(selected);
|
||||||
self.update_offset();
|
self.update_offset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ pub struct ListState<'a> {
|
||||||
term_width: u16,
|
term_width: u16,
|
||||||
term_height: u16,
|
term_height: u16,
|
||||||
show_footer: bool,
|
show_footer: bool,
|
||||||
|
pub search_query: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ListState<'a> {
|
impl<'a> ListState<'a> {
|
||||||
|
@ -76,6 +77,7 @@ impl<'a> ListState<'a> {
|
||||||
term_width: 0,
|
term_width: 0,
|
||||||
term_height: 0,
|
term_height: 0,
|
||||||
show_footer: true,
|
show_footer: true,
|
||||||
|
search_query: String::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
slf.set_term_size(width, height);
|
slf.set_term_size(width, height);
|
||||||
|
@ -345,6 +347,41 @@ impl<'a> ListState<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn select_if_matches_search_query(&mut self) {
|
||||||
|
eprintln!("search query: {:?}", self.search_query);
|
||||||
|
|
||||||
|
let idx = self
|
||||||
|
.app_state
|
||||||
|
.exercises()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find_map(|(i, s)| {
|
||||||
|
if s.name.contains(self.search_query.as_str()) {
|
||||||
|
Some(i)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
eprintln!("idx: {:?}", idx);
|
||||||
|
|
||||||
|
match idx {
|
||||||
|
Some(i) => {
|
||||||
|
// ? do we need this function call?
|
||||||
|
// let exercise_ind = self.selected_to_exercise_ind(i).unwrap();
|
||||||
|
let exercise_ind = i;
|
||||||
|
self.scroll_state.set_selected(exercise_ind);
|
||||||
|
eprintln!("exercise_ind: {:?}", exercise_ind);
|
||||||
|
self.update_rows();
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let msg = String::from("[NOT FOUND]") + &self.message.clone();
|
||||||
|
self.message.clear();
|
||||||
|
self.message.push_str(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Return `true` if there was something to select.
|
// Return `true` if there was something to select.
|
||||||
pub fn selected_to_current_exercise(&mut self) -> Result<bool> {
|
pub fn selected_to_current_exercise(&mut self) -> Result<bool> {
|
||||||
let Some(selected) = self.scroll_state.selected() else {
|
let Some(selected) = self.scroll_state.selected() else {
|
||||||
|
|
Loading…
Reference in a new issue