Skip to content

Commit 71deeda

Browse files
committed
Redraw UI when returning from external editor
Forces _tui_ to redraw the whole app when returning from the external editor. This is acheived by creating a static channel for sending "app commands".
1 parent 3a4b31d commit 71deeda

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

Diff for: src/components/commit.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::{
22
textinput::TextInputComponent, visibility_blocking,
33
CommandBlocking, CommandInfo, Component, DrawableComponent,
44
};
5+
use crate::poll::QueueEvent;
56
use crate::strings::COMMIT_EDITOR_MSG;
67
use crate::{
78
get_app_config_path,
@@ -133,6 +134,13 @@ impl CommitComponent {
133134
crate::poll::SHOULD_DO_POLL
134135
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
135136
Command::new(command).args(editor).status()?;
137+
// safety: this is set during app setup, and _should_ never be mutated again
138+
unsafe {
139+
crate::COMMANDS_CHANNEL
140+
.as_ref()
141+
.unwrap()
142+
.send(QueueEvent::FullRedraw)?
143+
}
136144
crate::poll::SHOULD_DO_POLL
137145
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
138146

Diff for: src/main.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![forbid(unsafe_code)]
1+
// #![forbid(unsafe_code)]
22
#![deny(clippy::cargo)]
33
//TODO: remove once crossterm upgraded to current mio:
44
//https://github.com/crossterm-rs/crossterm/issues/432
@@ -29,7 +29,7 @@ use clap::{
2929
crate_authors, crate_description, crate_name, crate_version,
3030
App as ClapApp, Arg,
3131
};
32-
use crossbeam_channel::{tick, unbounded, Receiver, Select};
32+
use crossbeam_channel::{tick, unbounded, Receiver, Select, Sender};
3333
use crossterm::{
3434
terminal::{
3535
disable_raw_mode, enable_raw_mode, EnterAlternateScreen,
@@ -58,6 +58,8 @@ use tui::{
5858
static TICK_INTERVAL: Duration = Duration::from_secs(5);
5959
static SPINNER_INTERVAL: Duration = Duration::from_millis(50);
6060

61+
static mut COMMANDS_CHANNEL: Option<Sender<QueueEvent>> = None;
62+
6163
fn main() -> Result<()> {
6264
process_cmdline()?;
6365

@@ -75,6 +77,12 @@ fn main() -> Result<()> {
7577

7678
let mut terminal = start_terminal(io::stdout())?;
7779

80+
let (tx_commands, rx_commands) = unbounded();
81+
// safety: the app hasn't started running yet, so this variable is not yet in use
82+
unsafe {
83+
COMMANDS_CHANNEL = Some(tx_commands);
84+
}
85+
7886
let (tx_git, rx_git) = unbounded();
7987

8088
let mut app = App::new(&tx_git);
@@ -94,6 +102,7 @@ fn main() -> Result<()> {
94102
&rx_git,
95103
&ticker,
96104
&spinner_ticker,
105+
&rx_commands,
97106
)?;
98107

99108
{
@@ -110,6 +119,9 @@ fn main() -> Result<()> {
110119
needs_draw = false;
111120
spinner.update()
112121
}
122+
QueueEvent::FullRedraw => {
123+
terminal.resize(terminal.size()?)?
124+
}
113125
}
114126
}
115127

@@ -161,6 +173,7 @@ fn select_event(
161173
rx_git: &Receiver<AsyncNotification>,
162174
rx_ticker: &Receiver<Instant>,
163175
rx_spinner: &Receiver<Instant>,
176+
rx_commands: &Receiver<QueueEvent>,
164177
) -> Result<Vec<QueueEvent>> {
165178
let mut events: Vec<QueueEvent> = Vec::new();
166179

@@ -170,6 +183,7 @@ fn select_event(
170183
sel.recv(rx_git);
171184
sel.recv(rx_ticker);
172185
sel.recv(rx_spinner);
186+
sel.recv(rx_commands);
173187

174188
let oper = sel.select();
175189
let index = oper.index();
@@ -185,6 +199,7 @@ fn select_event(
185199
3 => oper
186200
.recv(rx_spinner)
187201
.map(|_| events.push(QueueEvent::SpinnerUpdate)),
202+
4 => oper.recv(rx_commands).map(|ev| events.push(ev)),
188203
_ => return Err(anyhow!("unknown select source")),
189204
}?;
190205

Diff for: src/poll.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub enum QueueEvent {
1313
SpinnerUpdate,
1414
GitEvent(AsyncNotification),
1515
InputEvent(Event),
16+
FullRedraw,
1617
}
1718

1819
static MAX_POLL_DURATION: Duration = Duration::from_secs(2);

0 commit comments

Comments
 (0)