Draw a welcome message
This commit is contained in:
parent
221512f80c
commit
93d3501223
@ -1,48 +1,77 @@
|
|||||||
use std::io::{self, stdout};
|
use crate::Terminal;
|
||||||
use termion::event::Key;
|
use termion::event::Key;
|
||||||
use termion::input::TermRead;
|
|
||||||
use termion::raw::IntoRawMode;
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
pub struct Editor {
|
pub struct Editor {
|
||||||
should_quit: bool,
|
should_quit: bool,
|
||||||
|
terminal: Terminal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Editor {
|
impl Editor {
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
let _stdout = stdout().into_raw_mode().unwrap();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Err(error) = self.process_keypress() {
|
if let Err(error) = self.refresh_screen() {
|
||||||
die(error);
|
die(error);
|
||||||
}
|
}
|
||||||
if self.should_quit {
|
if self.should_quit {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if let Err(error) = self.process_keypress() {
|
||||||
|
die(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default() -> Self {
|
pub fn default() -> Self {
|
||||||
Self { should_quit: false }
|
Self {
|
||||||
|
should_quit: false,
|
||||||
|
terminal: Terminal::default().expect("Failed to initialize terminal"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn refresh_screen(&self) -> Result<(), std::io::Error> {
|
||||||
|
Terminal::cursor_hide();
|
||||||
|
Terminal::cursor_position(0, 0);
|
||||||
|
if self.should_quit {
|
||||||
|
Terminal::clear_screen();
|
||||||
|
println!("Goodbye.\r");
|
||||||
|
} else {
|
||||||
|
self.draw_rows();
|
||||||
|
Terminal::cursor_position(0, 0);
|
||||||
|
}
|
||||||
|
Terminal::cursor_show();
|
||||||
|
Terminal::flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_keypress(&mut self) -> Result<(), std::io::Error> {
|
fn process_keypress(&mut self) -> Result<(), std::io::Error> {
|
||||||
let pressed_key = read_key()?;
|
let pressed_key = Terminal::read_key()?;
|
||||||
match pressed_key {
|
match pressed_key {
|
||||||
Key::Ctrl('q') => self.should_quit = true,
|
Key::Ctrl('q') => self.should_quit = true,
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn read_key() -> Result<Key, std::io::Error> {
|
fn draw_rows(&self) {
|
||||||
loop {
|
let height = self.terminal.size().height;
|
||||||
if let Some(key) = io::stdin().lock().keys().next() {
|
|
||||||
return key;
|
for row in 0..height - 1 {
|
||||||
|
Terminal::clear_current_line();
|
||||||
|
|
||||||
|
if row == height / 3 {
|
||||||
|
let welcome_message = format!("Hecto editor -- version {}", VERSION);
|
||||||
|
|
||||||
|
let width = std::cmp::min(self.terminal.size() as usize, welcome_message.len());
|
||||||
|
println!("{}\r", &welcome_message[..width]);
|
||||||
|
} else {
|
||||||
|
println!("~\r");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn die(e: std::io::Error) {
|
fn die(e: std::io::Error) {
|
||||||
|
Terminal::clear_screen();
|
||||||
panic!(e);
|
panic!(e);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#![warn(clippy::all, clippy::pedantic)]
|
#![warn(clippy::all, clippy::pedantic)]
|
||||||
mod editor;
|
mod editor;
|
||||||
|
mod terminal;
|
||||||
|
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
|
pub use terminal::Terminal;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Editor::default().run();
|
Editor::default().run();
|
||||||
|
66
src/terminal.rs
Normal file
66
src/terminal.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
use std::io::{self, stdout, Write};
|
||||||
|
use termion::event::Key;
|
||||||
|
use termion::input::TermRead;
|
||||||
|
use termion::raw::{IntoRawMode, RawTerminal};
|
||||||
|
|
||||||
|
pub struct Size {
|
||||||
|
pub width: u16,
|
||||||
|
pub height: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Terminal {
|
||||||
|
size: Size,
|
||||||
|
_stdout: RawTerminal<std::io::Stdout>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Terminal {
|
||||||
|
pub fn default() -> Result<Self, std::io::Error> {
|
||||||
|
let size = termion::terminal_size()?;
|
||||||
|
Ok(Self {
|
||||||
|
size: Size {
|
||||||
|
width: size.0,
|
||||||
|
height: size.1,
|
||||||
|
},
|
||||||
|
_stdout: stdout().into_raw_mode()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> &Size {
|
||||||
|
&self.size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_screen() {
|
||||||
|
print!("{}", termion::clear::All);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_position(x: u16, y: u16) {
|
||||||
|
let x = x.saturating_add(1);
|
||||||
|
let y = y.saturating_add(1);
|
||||||
|
|
||||||
|
print!("{}", termion::cursor::Goto(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flush() -> Result<(), std::io::Error> {
|
||||||
|
io::stdout().flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_key() -> Result<Key, std::io::Error> {
|
||||||
|
loop {
|
||||||
|
if let Some(key) = io::stdin().lock().keys().next() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_hide() {
|
||||||
|
print!("{}", termion::cursor::Hide);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_show() {
|
||||||
|
print!("{}", termion::cursor::Show);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_current_line() {
|
||||||
|
print!("{}", termion::clear::CurrentLine);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user