on master help sign in
Move terminal out of compositor
commit264a455c18f765b04c31a613ccc336dd893c4cbe authorBlaž Hrastnik <blaz@mxxn.io> dateTue 29 Mar 2022, 10:11 (5 years ago) parent00d7b18
2 files changed+65−65
helix-term/src/application.rs+59−16 helix-term/src/compositor.rs+6−49
helix-term/src/application.rs+59−16
@@ -10,11 +10,13 @@ use helix_view::{
1010 align_view,
1111 document::DocumentSavedEventResult,
1212 editor::{ConfigEvent, EditorEvent},
13+ graphics::Rect,
1314 theme,
1415 tree::Layout,
1516 Align, Editor,
1617};
1718use serde_json::json;
19+use tui::backend::Backend;
1820
1921use crate::{
2022 args::Args,
@@ -53,8 +55,18 @@ type Signals = futures_util::stream::Empty<()>;
5355
5456const LSP_DEADLINE: Duration = Duration::from_millis(16);
5557
58+#[cfg(not(feature = "integration"))]
59+use tui::backend::CrosstermBackend;
60+
61+#[cfg(not(feature = "integration"))]
62+type Terminal = tui::terminal::Terminal<CrosstermBackend<std::io::Stdout>>;
63+
64+#[cfg(feature = "integration")]
65+type Terminal = tui::terminal::Terminal<TestBackend>;
66+
5667pub struct Application {
5768 compositor: Compositor,
69+ terminal: Terminal,
5870 pub editor: Editor,
5971
6072 config: Arc<ArcSwap<Config>>,
@@ -143,10 +155,18 @@ impl Application {
143155
144156 let syn_loader = std::sync::Arc::new(syntax::Loader::new(syn_loader_conf));
145157
146− let mut compositor = Compositor::new().context("build compositor")?;
158+ #[cfg(not(feature = "integration"))]
159+ let backend = CrosstermBackend::new(stdout());
160+
161+ #[cfg(feature = "integration")]
162+ let backend = TestBackend::new(120, 150);
163+
164+ let terminal = Terminal::new(backend)?;
165+ let area = terminal.size().expect("couldn't get terminal size");
166+ let mut compositor = Compositor::new(area);
147167 let config = Arc::new(ArcSwap::from_pointee(config));
148168 let mut editor = Editor::new(
149− compositor.size(),
169+ area,
150170 theme_loader.clone(),
151171 syn_loader.clone(),
152172 Box::new(Map::new(Arc::clone(&config), |config: &Config| {
@@ -233,6 +253,7 @@ impl Application {
233253
234254 let app = Self {
235255 compositor,
256+ terminal,
236257 editor,
237258
238259 config,
@@ -254,15 +275,26 @@ impl Application {
254275
255276 #[cfg(not(feature = "integration"))]
256277 fn render(&mut self) {
257− let compositor = &mut self.compositor;
258−
259278 let mut cx = crate::compositor::Context {
260279 editor: &mut self.editor,
261280 jobs: &mut self.jobs,
262281 scroll: None,
263282 };
264283
265− compositor.render(&mut cx);
284+ let area = self
285+ .terminal
286+ .autoresize()
287+ .expect("Unable to determine terminal size");
288+
289+ // TODO: need to recalculate view tree if necessary
290+
291+ let surface = self.terminal.current_buffer_mut();
292+
293+ self.compositor.render(area, surface, &mut cx);
294+
295+ let (pos, kind) = self.compositor.cursor(area, &self.editor);
296+ let pos = pos.map(|pos| (pos.col as u16, pos.row as u16));
297+ self.terminal.draw(pos, kind).unwrap();
266298 }
267299
268300 pub async fn event_loop<S>(&mut self, input_stream: &mut S)
@@ -392,17 +424,24 @@ impl Application {
392424
393425 #[cfg(not(windows))]
394426 pub async fn handle_signals(&mut self, signal: i32) {
395− use helix_view::graphics::Rect;
396427 match signal {
397428 signal::SIGTSTP => {
429+ // restore cursor
430+ use helix_view::graphics::CursorKind;
431+ self.terminal
432+ .backend_mut()
433+ .show_cursor(CursorKind::Block)
434+ .ok();
398435 restore_term().unwrap();
399436 low_level::emulate_default_handler(signal::SIGTSTP).unwrap();
400437 }
401438 signal::SIGCONT => {
402439 self.claim_term().await.unwrap();
403440 // redraw the terminal
404− let Rect { width, height, .. } = self.compositor.size();
405− self.compositor.resize(width, height);
441+ let area = self.terminal.size().expect("couldn't get terminal size");
442+ self.compositor.resize(area);
443+ self.terminal.clear().expect("couldn't clear terminal");
444+
406445 self.render();
407446 }
408447 signal::SIGUSR1 => {
@@ -539,7 +578,14 @@ impl Application {
539578 // Handle key events
540579 let should_redraw = match event.unwrap() {
541580 CrosstermEvent::Resize(width, height) => {
542− self.compositor.resize(width, height);
581+ self.terminal
582+ .resize(Rect::new(0, 0, width, height))
583+ .expect("Unable to resize terminal");
584+
585+ let area = self.terminal.size().expect("couldn't get terminal size");
586+
587+ self.compositor.resize(area);
588+
543589 self.compositor
544590 .handle_event(&Event::Resize(width, height), &mut cx)
545591 }
@@ -923,10 +969,9 @@ impl Application {
923969
924970 async fn claim_term(&mut self) -> Result<(), Error> {
925971 use helix_view::graphics::CursorKind;
926− use tui::backend::Backend;
927972 terminal::enable_raw_mode()?;
928− if self.compositor.terminal.cursor_kind() == CursorKind::Hidden {
929− self.compositor.terminal.backend_mut().hide_cursor().ok();
973+ if self.terminal.cursor_kind() == CursorKind::Hidden {
974+ self.terminal.backend_mut().hide_cursor().ok();
930975 }
931976 let mut stdout = stdout();
932977 execute!(
@@ -962,14 +1007,12 @@ impl Application {
9621007
9631008 let close_errs = self.close().await;
9641009
1010+ // restore cursor
9651011 use helix_view::graphics::CursorKind;
966− use tui::backend::Backend;
967− self.compositor
968− .terminal
1012+ self.terminal
9691013 .backend_mut()
9701014 .show_cursor(CursorKind::Block)
9711015 .ok();
972−
9731016 restore_term()?;
9741017
9751018 for err in close_errs {
helix-term/src/compositor.rs+6−49
@@ -75,56 +75,28 @@ pub trait Component: Any + AnyComponent {
7575 }
7676}
7777
78−use anyhow::Context as AnyhowContext;
79−
80−#[cfg(not(feature = "integration"))]
81−use tui::backend::CrosstermBackend;
82−
83−#[cfg(not(feature = "integration"))]
84−use std::io::stdout;
85−
86−#[cfg(not(feature = "integration"))]
87−type Terminal = tui::terminal::Terminal<CrosstermBackend<std::io::Stdout>>;
88−
89−#[cfg(feature = "integration")]
90−type Terminal = tui::terminal::Terminal<TestBackend>;
91−
9278pub struct Compositor {
9379 layers: Vec<Box<dyn Component>>,
94− pub terminal: Terminal,
9580 area: Rect,
9681
9782 pub(crate) last_picker: Option<Box<dyn Component>>,
9883}
9984
10085impl Compositor {
101− pub fn new() -> anyhow::Result<Self> {
102− #[cfg(not(feature = "integration"))]
103− let backend = CrosstermBackend::new(stdout());
104−
105− #[cfg(feature = "integration")]
106− let backend = TestBackend::new(120, 150);
107−
108− let terminal = Terminal::new(backend).context("build terminal")?;
109− let area = terminal.size().expect("couldn't get terminal size");
110− Ok(Self {
86+ pub fn new(area: Rect) -> Self {
87+ Self {
11188 layers: Vec::new(),
11289 area,
113− terminal,
11490 last_picker: None,
115− })
91+ }
11692 }
11793
11894 pub fn size(&self) -> Rect {
11995 self.area
12096 }
12197
122− pub fn resize(&mut self, width: u16, height: u16) {
123− self.terminal
124− .resize(Rect::new(0, 0, width, height))
125− .expect("Unable to resize terminal");
126−
127− self.area = self.terminal.size().expect("couldn't get terminal size");
98+ pub fn resize(&mut self, area: Rect) {
99+ self.area = area;
128100 }
129101
130102 pub fn push(&mut self, mut layer: Box<dyn Component>) {
@@ -192,25 +164,10 @@ impl Compositor {
192164 consumed
193165 }
194166
195− pub fn render(&mut self, cx: &mut Context) {
196− self.terminal
197− .autoresize()
198− .expect("Unable to determine terminal size");
199−
200− // TODO: need to recalculate view tree if necessary
201−
202− let surface = self.terminal.current_buffer_mut();
203−
204− let area = *surface.area();
205−
167+ pub fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
206168 for layer in &mut self.layers {
207169 layer.render(area, surface, cx);
208170 }
209−
210− let (pos, kind) = self.cursor(area, cx.editor);
211− let pos = pos.map(|pos| (pos.col as u16, pos.row as u16));
212−
213− self.terminal.draw(pos, kind).unwrap();
214171 }
215172
216173 pub fn cursor(&self, area: Rect, editor: &Editor) -> (Option<Position>, CursorKind) {