From 03c5baf35c4d36c4a587a3bdab19366604c95aed Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Fri, 17 Apr 2026 14:56:21 +0200 Subject: [PATCH 1/5] Emphasize hotkeys in footer with color --- src/list/state.rs | 53 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/src/list/state.rs b/src/list/state.rs index 4fcbd3c353..6e52eec180 100644 --- a/src/list/state.rs +++ b/src/list/state.rs @@ -233,15 +233,38 @@ impl<'a> ListState<'a> { )?; next_ln(stdout)?; + let hotkey = |writer: &mut MaxLenWriter, hotkey| -> io::Result<()> { + writer + .stdout + .queue(SetForegroundColor(Color::Yellow))? + .queue(SetAttribute(Attribute::Bold))?; + writer.write_ascii(hotkey)?; + writer.stdout.queue(ResetColor)?; + Ok(()) + }; + let mut writer = MaxLenWriter::new(stdout, self.term_width as usize); if self.message.is_empty() { // Help footer message if self.scroll_state.selected().is_some() { - writer.write_str("↓/j ↑/k home/g end/G | ontinue at | eset exercise")?; + writer.write_str("↓/")?; + hotkey(&mut writer, b"j")?; + writer.write_str(" ↑/")?; + hotkey(&mut writer, b"k")?; + writer.write_ascii(b" home/")?; + hotkey(&mut writer, b"g")?; + writer.write_ascii(b" end/")?; + hotkey(&mut writer, b"G")?; + writer.write_ascii(b" | ")?; + hotkey(&mut writer, b"c")?; + writer.write_ascii(b"ontinue at | ")?; + hotkey(&mut writer, b"r")?; + writer.write_ascii(b"eset exercise")?; next_ln(stdout)?; writer = MaxLenWriter::new(stdout, self.term_width as usize); - writer.write_ascii(b"earch | filter ")?; + hotkey(&mut writer, b"s")?; + writer.write_ascii(b"earch | filter ")?; } else { // Nothing selected (and nothing shown), so only display filter and quit. writer.write_ascii(b"filter ")?; @@ -249,27 +272,41 @@ impl<'a> ListState<'a> { match self.filter { Filter::Done => { + writer.stdout.queue(SetAttribute(Attribute::Underlined))?; + hotkey(&mut writer, b"d")?; writer .stdout .queue(SetForegroundColor(Color::Magenta))? .queue(SetAttribute(Attribute::Underlined))?; - writer.write_ascii(b"one")?; + writer.write_str("one")?; writer.stdout.queue(ResetColor)?; - writer.write_ascii(b"/

ending")?; + writer.write_ascii(b"/")?; + hotkey(&mut writer, b"p")?; + writer.write_ascii(b"ending")?; } Filter::Pending => { - writer.write_ascii(b"one/")?; + hotkey(&mut writer, b"d")?; + writer.write_ascii(b"one/")?; + writer.stdout.queue(SetAttribute(Attribute::Underlined))?; + hotkey(&mut writer, b"p")?; writer .stdout .queue(SetForegroundColor(Color::Magenta))? .queue(SetAttribute(Attribute::Underlined))?; - writer.write_ascii(b"

ending")?; + writer.write_ascii(b"ending")?; writer.stdout.queue(ResetColor)?; } - Filter::None => writer.write_ascii(b"one/

ending")?, + Filter::None => { + hotkey(&mut writer, b"d")?; + writer.write_ascii(b"one/")?; + hotkey(&mut writer, b"p")?; + writer.write_ascii(b"ending")?; + } } - writer.write_ascii(b" | uit list")?; + writer.write_ascii(b" | ")?; + hotkey(&mut writer, b"q")?; + writer.write_ascii(b"uit list")?; } else { writer.stdout.queue(SetForegroundColor(Color::Magenta))?; writer.write_str(&self.message)?; From 870776d03bc612f473c8dbf1b19d3d78200ae3e7 Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Sun, 19 Apr 2026 00:37:10 +0200 Subject: [PATCH 2/5] Allow selecting next exercise with enter key --- src/list.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/list.rs b/src/list.rs index c60a5299ef..db466c2f61 100644 --- a/src/list.rs +++ b/src/list.rs @@ -83,7 +83,7 @@ fn handle_list(app_state: &mut AppState, stdout: &mut StdoutLock) -> Result<()> } } KeyCode::Char('r') => list_state.reset_selected()?, - KeyCode::Char('c') => { + KeyCode::Char('c') | KeyCode::Enter => { if list_state.selected_to_current_exercise()? { return Ok(()); } From c658a997f3dde7e5d3d15126428e0546370ef0d4 Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Mon, 20 Apr 2026 13:49:17 +0200 Subject: [PATCH 3/5] Turn unnecessary closure into regular function --- src/list/state.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/list/state.rs b/src/list/state.rs index 6e52eec180..c31cf8ae6d 100644 --- a/src/list/state.rs +++ b/src/list/state.rs @@ -233,7 +233,7 @@ impl<'a> ListState<'a> { )?; next_ln(stdout)?; - let hotkey = |writer: &mut MaxLenWriter, hotkey| -> io::Result<()> { + fn hotkey(writer: &mut MaxLenWriter, hotkey: &[u8]) -> io::Result<()> { writer .stdout .queue(SetForegroundColor(Color::Yellow))? @@ -241,7 +241,7 @@ impl<'a> ListState<'a> { writer.write_ascii(hotkey)?; writer.stdout.queue(ResetColor)?; Ok(()) - }; + } let mut writer = MaxLenWriter::new(stdout, self.term_width as usize); if self.message.is_empty() { From b86a532e2848d71d103a5bc677eaf4b9d277ce54 Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Sat, 25 Apr 2026 13:53:25 +0200 Subject: [PATCH 4/5] Document enter keybind in list footer --- src/list/state.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/list/state.rs b/src/list/state.rs index 4fcbd3c353..e9386b8ede 100644 --- a/src/list/state.rs +++ b/src/list/state.rs @@ -237,7 +237,8 @@ impl<'a> ListState<'a> { if self.message.is_empty() { // Help footer message if self.scroll_state.selected().is_some() { - writer.write_str("↓/j ↑/k home/g end/G | ontinue at | eset exercise")?; + writer + .write_str("↓/j ↑/k home/g end/G | ↩️/ontinue at | eset exercise")?; next_ln(stdout)?; writer = MaxLenWriter::new(stdout, self.term_width as usize); From e0334f79fe6c8ee522841154a48c34932b4346cf Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Sat, 25 Apr 2026 14:04:29 +0200 Subject: [PATCH 5/5] Avoid nested function definition --- src/list/state.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/list/state.rs b/src/list/state.rs index c31cf8ae6d..1bfdf58db5 100644 --- a/src/list/state.rs +++ b/src/list/state.rs @@ -233,16 +233,6 @@ impl<'a> ListState<'a> { )?; next_ln(stdout)?; - fn hotkey(writer: &mut MaxLenWriter, hotkey: &[u8]) -> io::Result<()> { - writer - .stdout - .queue(SetForegroundColor(Color::Yellow))? - .queue(SetAttribute(Attribute::Bold))?; - writer.write_ascii(hotkey)?; - writer.stdout.queue(ResetColor)?; - Ok(()) - } - let mut writer = MaxLenWriter::new(stdout, self.term_width as usize); if self.message.is_empty() { // Help footer message @@ -446,3 +436,14 @@ impl<'a> ListState<'a> { Ok(true) } } + +/// Draw an emphasized hotkey in the list footer. +fn hotkey(writer: &mut MaxLenWriter, hotkey: &[u8]) -> io::Result<()> { + writer + .stdout + .queue(SetForegroundColor(Color::Yellow))? + .queue(SetAttribute(Attribute::Bold))?; + writer.write_ascii(hotkey)?; + writer.stdout.queue(ResetColor)?; + Ok(()) +}