Skip to content

Commit 8672275

Browse files
stevenpollackclaude
andcommitted
fix(input): share input reader across app restarts
Switching repos (enter submodule/worktree) rebuilds the whole App. Previously each App spun up its own input-reader thread, so during the teardown window the outgoing reader could read and drop the first keystroke after a switch (its channel receiver was already gone). Create the Input once in main and thread it into each Gitui, mirroring how the terminal is already reused across restarts. Keystrokes read during the swap are buffered in the channel and delivered to the new App instead of being lost. Fixes the swallowed keypress for both worktree and submodule switching. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BMQxBdr5f3B3jmDtdvGtTu
1 parent 33e2840 commit 8672275

3 files changed

Lines changed: 23 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
* support rewording non-HEAD commits when `commit.gpgsign` is enabled (gpg format only) [[@guerinoni](https://github.com/guerinoni)] ([#2959](https://github.com/gitui-org/gitui/pull/2959))
1919

2020
### Fixes
21+
* first keystroke after switching to a submodule or worktree was dropped
2122
* crash when opening submodule ([#2895](https://github.com/gitui-org/gitui/issues/2895))
2223
* when staging the last file in a directory, the first item after the directory is no longer skipped [[@Tillerino](https://github.com/Tillerino)] ([#2748](https://github.com/gitui-org/gitui/issues/2748))
2324
* index-out-of-bounds panic when unstaging lines near the end of a diff ([#2953](https://github.com/gitui-org/gitui/issues/2953))

src/gitui.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,11 @@ impl Gitui {
3737
theme: Theme,
3838
key_config: &KeyConfig,
3939
updater: Updater,
40+
input: &Input,
4041
) -> Result<Self, anyhow::Error> {
4142
let (tx_git, rx_git) = unbounded();
4243
let (tx_app, rx_app) = unbounded();
4344

44-
let input = Input::new();
45-
4645
let (rx_ticker, rx_watcher) = match updater {
4746
Updater::NotifyWatcher => {
4847
let repo_watcher = RepoWatcher::new(
@@ -212,7 +211,7 @@ mod tests {
212211
use ratatui::{backend::TestBackend, Terminal};
213212

214213
use crate::{
215-
args::CliArgs, gitui::Gitui, keys::KeyConfig,
214+
args::CliArgs, gitui::Gitui, input::Input, keys::KeyConfig,
216215
ui::style::Theme, AsyncNotification, Updater,
217216
};
218217

@@ -248,10 +247,16 @@ mod tests {
248247

249248
let theme = Theme::init(&PathBuf::new());
250249
let key_config = KeyConfig::default();
250+
let input = Input::new();
251251

252-
let mut gitui =
253-
Gitui::new(cliargs, theme, &key_config, Updater::Ticker)
254-
.unwrap();
252+
let mut gitui = Gitui::new(
253+
cliargs,
254+
theme,
255+
&key_config,
256+
Updater::Ticker,
257+
&input,
258+
)
259+
.unwrap();
255260

256261
let mut terminal =
257262
Terminal::new(TestBackend::new(90, 12)).unwrap();

src/main.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ use crossterm::{
9797
ExecutableCommand,
9898
};
9999
use gitui::Gitui;
100-
use input::InputEvent;
100+
use input::{Input, InputEvent};
101101
use keys::KeyConfig;
102102
use ratatui::backend::CrosstermBackend;
103103
use scopeguard::defer;
@@ -184,6 +184,12 @@ fn main() -> Result<()> {
184184
let mut terminal =
185185
start_terminal(io::stdout(), &cliargs.repo_path)?;
186186

187+
// the input reader is created once and shared across app restarts
188+
// (e.g. switching to a submodule or worktree). recreating it per
189+
// app would let the outgoing reader consume and drop the first
190+
// keystroke after a switch; a shared reader buffers it instead.
191+
let input = Input::new();
192+
187193
let updater = if cliargs.notify_watcher {
188194
Updater::NotifyWatcher
189195
} else {
@@ -199,6 +205,7 @@ fn main() -> Result<()> {
199205
theme.clone(),
200206
&key_config,
201207
updater,
208+
&input,
202209
&mut terminal,
203210
)?;
204211

@@ -226,9 +233,11 @@ fn run_app(
226233
theme: Theme,
227234
key_config: &KeyConfig,
228235
updater: Updater,
236+
input: &Input,
229237
terminal: &mut Terminal,
230238
) -> Result<QuitState, anyhow::Error> {
231-
let mut gitui = Gitui::new(cliargs, theme, key_config, updater)?;
239+
let mut gitui =
240+
Gitui::new(cliargs, theme, key_config, updater, input)?;
232241

233242
log::trace!("app start: {} ms", app_start.elapsed().as_millis());
234243

0 commit comments

Comments
 (0)