diff --git a/src/lib.rs b/src/lib.rs index 63ea700..3bb7b66 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,6 +45,7 @@ pub mod help; pub mod history; pub mod menu; pub mod phetchdir; +pub mod terminal; pub mod text; pub mod ui; diff --git a/src/menu.rs b/src/menu.rs index 872e4ff..6f2102c 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -9,10 +9,10 @@ use crate::{ config::Config, gopher::{self, Type}, + terminal, ui::{self, Action, Key, View, MAX_COLS, SCROLL_LINES}, }; use std::fmt; -use termion::{clear, cursor}; /// The Menu holds our Gopher Lines, a list of links, and maintains /// both where the cursor is on screen and which lines need to be @@ -333,12 +333,12 @@ impl Menu { out.push_str(color!(Reset)); // clear rest of line - out.push_str(clear::UntilNewline.as_ref()); + out.push_str(terminal::ClearUntilNewline.as_ref()); out.push_str("\r\n"); } // clear remainder of screen - out.push_str(clear::AfterCursor.as_ref()); + out.push_str(terminal::ClearAfterCursor.as_ref()); out } @@ -364,7 +364,7 @@ impl Menu { return None; } let (x, y) = self.screen_coords(link)?; - Some(format!("{} {}", cursor::Goto(x, y), cursor::Hide)) + Some(format!("{} {}", terminal::Goto(x, y), terminal::HideCursor)) } /// Print this string to draw the cursor on screen. @@ -376,8 +376,8 @@ impl Menu { let (x, y) = self.screen_coords(self.link)?; Some(format!( "{}\x1b[97;1m*\x1b[0m{}", - cursor::Goto(x, y), - cursor::Hide + terminal::Goto(x, y), + terminal::HideCursor )) } @@ -388,14 +388,14 @@ impl Menu { /// User input field. fn render_input(&self) -> String { - format!("Find: {}{}", self.input, cursor::Show) + format!("Find: {}{}", self.input, terminal::ShowCursor) } fn redraw_input(&self) -> Action { if self.searching { Action::Status(self.render_input()) } else { - Action::Status(cursor::Hide.to_string()) + Action::Status(terminal::HideCursor.to_string()) } } diff --git a/src/terminal.rs b/src/terminal.rs new file mode 100644 index 0000000..a564996 --- /dev/null +++ b/src/terminal.rs @@ -0,0 +1,18 @@ +//! The terminal module mostly provides terminal escape sequences for +//! things like clearing the screen or going into alternate mode. +//! +//! It wraps termion for now, but we may move away from termion in the +//! future and this will help. + +use termion; + +pub use termion::cursor::Goto; +pub use termion::cursor::Hide as HideCursor; +pub use termion::cursor::Show as ShowCursor; + +pub use termion::screen::ToAlternateScreen; +pub use termion::screen::ToMainScreen; + +pub use termion::clear::AfterCursor as ClearAfterCursor; +pub use termion::clear::CurrentLine as ClearCurrentLine; +pub use termion::clear::UntilNewline as ClearUntilNewline; diff --git a/src/text.rs b/src/text.rs index bd1d6d3..3147256 100644 --- a/src/text.rs +++ b/src/text.rs @@ -4,10 +4,10 @@ use crate::{ config::Config, + terminal, ui::{self, Action, Key, View, MAX_COLS, SCROLL_LINES}, }; use std::fmt; -use termion::clear; /// The Text View holds the raw Gopher response as well as information /// about which lines should currently be displayed on screen. @@ -156,13 +156,13 @@ impl View for Text { out.push_str(&line); // clear rest of line - out.push_str(&format!("{}", clear::UntilNewline)); + out.push_str(&format!("{}", terminal::ClearUntilNewline)); out.push_str("\r\n"); } // clear remainder of screen - out.push_str(&format!("{}", clear::AfterCursor)); + out.push_str(&format!("{}", terminal::ClearAfterCursor)); out } diff --git a/src/ui.rs b/src/ui.rs index 5236fb9..97ac70a 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -22,6 +22,7 @@ use crate::{ gopher::{self, Type}, help, history, menu::Menu, + terminal, text::Text, utils, BUG_URL, }; @@ -109,14 +110,14 @@ impl UI { pub fn startup(&mut self) { let mut out = self.out.borrow_mut(); out.activate_raw_mode().expect(ERR_RAW_MODE); - write!(out, "{}", termion::screen::ToAlternateScreen).expect(ERR_SCREEN); + write!(out, "{}", terminal::ToAlternateScreen).expect(ERR_SCREEN); } /// Clean up after ourselves. Should only be used after running in /// interactive mode. pub fn shutdown(&mut self) { let mut out = self.out.borrow_mut(); - write!(out, "{}", termion::screen::ToMainScreen).expect(ERR_SCREEN); + write!(out, "{}", terminal::ToMainScreen).expect(ERR_SCREEN); } /// Main loop. @@ -139,8 +140,8 @@ impl UI { write!( out, "{}{}{}{}", - termion::cursor::Goto(1, 1), - termion::cursor::Hide, + terminal::Goto(1, 1), + terminal::HideCursor, screen, status, )?; @@ -161,7 +162,7 @@ impl UI { self.status.clear(); } if let Err(e) = self.process_action(action) { - self.set_status(&format!("{}{}{}", color::Red, e, termion::cursor::Hide)); + self.set_status(&format!("{}{}{}", color::Red, e, terminal::HideCursor)); } } @@ -300,13 +301,13 @@ impl UI { } print!( "{}{}{}{}{}{}{}", - termion::cursor::Goto(1, rows), - termion::cursor::Hide, + terminal::Goto(1, rows), + terminal::HideCursor, label, ".".repeat(i), - termion::clear::UntilNewline, + terminal::ClearUntilNewline, color::Reset, - termion::cursor::Show, + terminal::ShowCursor, ); stdout().flush().expect(ERR_STDOUT); thread::sleep(Duration::from_millis(500)); @@ -354,14 +355,14 @@ impl UI { let status = color_string!("TLS", Black, GreenBG); return Some(format!( "{}{}", - termion::cursor::Goto(self.cols() - 3, self.rows()), + terminal::Goto(self.cols() - 3, self.rows()), if self.config.emoji { "🔐" } else { &status }, )); } else if view.is_tor() { let status = color_string!("TOR", Bold, White, MagentaBG); return Some(format!( "{}{}", - termion::cursor::Goto(self.cols() - 3, self.rows()), + terminal::Goto(self.cols() - 3, self.rows()), if self.config.emoji { "🧅" } else { &status }, )); } @@ -372,9 +373,9 @@ impl UI { fn render_status(&self) -> String { format!( "{}{}{}{}{}{}", - termion::cursor::Hide, - termion::cursor::Goto(1, self.rows()), - termion::clear::CurrentLine, + terminal::HideCursor, + terminal::Goto(1, self.rows()), + terminal::ClearCurrentLine, self.status, self.render_conn_status().unwrap_or_else(|| "".into()), color::Reset, @@ -402,10 +403,10 @@ impl UI { out, "{}{}{}{} [Y/n]: {}", color::Reset, - termion::cursor::Goto(1, rows), - termion::clear::CurrentLine, + terminal::Goto(1, rows), + terminal::ClearCurrentLine, question, - termion::cursor::Show, + terminal::ShowCursor, ) .expect(ERR_STDOUT); out.flush().expect(ERR_STDOUT); @@ -431,11 +432,11 @@ impl UI { out, "{}{}{}{}{}{}", color::Reset, - termion::cursor::Goto(1, rows), - termion::clear::CurrentLine, + terminal::Goto(1, rows), + terminal::ClearCurrentLine, prompt, input, - termion::cursor::Show, + terminal::ShowCursor, ) .expect(ERR_STDOUT); out.flush().expect(ERR_STDOUT); @@ -447,8 +448,8 @@ impl UI { write!( out, "{}{}", - termion::clear::CurrentLine, - termion::cursor::Hide + terminal::ClearCurrentLine, + terminal::HideCursor ) .expect(ERR_STDOUT); out.flush().expect(ERR_STDOUT); @@ -459,8 +460,8 @@ impl UI { write!( out, "{}{}", - termion::clear::CurrentLine, - termion::cursor::Hide + terminal::ClearCurrentLine, + terminal::HideCursor ) .expect(ERR_STDOUT); out.flush().expect(ERR_STDOUT); @@ -478,8 +479,8 @@ impl UI { write!( out, "{}{}{}{}", - termion::cursor::Goto(1, rows), - termion::clear::CurrentLine, + terminal::Goto(1, rows), + terminal::ClearCurrentLine, prompt, input, ) @@ -531,10 +532,10 @@ impl UI { /// Ctrl-Z: Suspend Unix process w/ SIGTSTP. fn suspend(&mut self) { let mut out = self.out.borrow_mut(); - write!(out, "{}", termion::screen::ToMainScreen).expect(ERR_SCREEN); + write!(out, "{}", terminal::ToMainScreen).expect(ERR_SCREEN); out.flush().expect(ERR_STDOUT); unsafe { libc::raise(libc::SIGTSTP) }; - write!(out, "{}", termion::screen::ToAlternateScreen).expect(ERR_SCREEN); + write!(out, "{}", terminal::ToAlternateScreen).expect(ERR_SCREEN); out.flush().expect(ERR_STDOUT); self.dirty = true; } @@ -647,7 +648,7 @@ impl UI { impl Drop for UI { fn drop(&mut self) { let mut out = self.out.borrow_mut(); - write!(out, "{}{}", color::Reset, termion::cursor::Show).expect(ERR_STDOUT); + write!(out, "{}{}", color::Reset, terminal::ShowCursor).expect(ERR_STDOUT); out.flush().expect(ERR_STDOUT); } }