fixes & better structure (done todos)
This commit is contained in:
parent
a06e9bfe26
commit
6f2436c711
38
Cargo.lock
generated
38
Cargo.lock
generated
@ -2,17 +2,6 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atty"
|
|
||||||
version = "0.2.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -31,17 +20,6 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "colored"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
|
|
||||||
dependencies = [
|
|
||||||
"atty",
|
|
||||||
"lazy_static",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossterm"
|
name = "crossterm"
|
||||||
version = "0.25.0"
|
version = "0.25.0"
|
||||||
@ -67,29 +45,13 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.1.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lambda"
|
name = "lambda"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"colored",
|
|
||||||
"crossterm",
|
"crossterm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.137"
|
version = "0.2.137"
|
||||||
|
@ -5,4 +5,3 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
crossterm = "0.25"
|
crossterm = "0.25"
|
||||||
colored = "2"
|
|
||||||
|
8
TODO.md
8
TODO.md
@ -1,4 +1,4 @@
|
|||||||
- [ ] Remove colored in favour of crossterm's styling
|
- [X] Remove colored in favour of crossterm's styling
|
||||||
- [ ] Use &str for writing text
|
- [X] Use &str for writing text -> can't really be done
|
||||||
- [ ] Make sure borrows for Screen and Editor are correct
|
- [X] Make sure borrows for Screen and Editor are correct
|
||||||
- [ ] Fix small terminal screen issues
|
- [X] Fix small terminal screen issues
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
pub struct Config<'a> {
|
pub struct Config<'a> {
|
||||||
pub logo: &'a str,
|
pub logo: &'a str,
|
||||||
|
pub friendly_name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Config<'a> {
|
impl<'a> Config<'a> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { logo: "λ" }
|
Self {
|
||||||
|
logo: "λ",
|
||||||
|
friendly_name: "Lambda",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,6 +18,7 @@ pub struct Buffer<'a> {
|
|||||||
pub path: &'a str,
|
pub path: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
Normal,
|
Normal,
|
||||||
Insert,
|
Insert,
|
||||||
|
@ -105,6 +105,19 @@ impl Screen {
|
|||||||
|
|
||||||
// Terminal functions and methods for managing the terminal
|
// Terminal functions and methods for managing the terminal
|
||||||
impl Screen {
|
impl Screen {
|
||||||
|
pub fn refresh(&mut self) -> Result<(), ErrorKind>{
|
||||||
|
// Clear the screen
|
||||||
|
Screen::clear();
|
||||||
|
|
||||||
|
// Update the screen dimensions
|
||||||
|
let size = terminal::size()?;
|
||||||
|
self.size.width = size.0 as usize;
|
||||||
|
self.size.height = size.1 as usize;
|
||||||
|
|
||||||
|
// Return Ok if was successful
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enter(&mut self) {
|
pub fn enter(&mut self) {
|
||||||
// Hide the cursor
|
// Hide the cursor
|
||||||
self.cursor.hide();
|
self.cursor.hide();
|
||||||
@ -123,19 +136,19 @@ impl Screen {
|
|||||||
terminal::disable_raw_mode().unwrap();
|
terminal::disable_raw_mode().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(text: String) {
|
|
||||||
// Writes a line to a current cursor position
|
|
||||||
execute!(stdout(), Print(text)).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear() {
|
pub fn clear() {
|
||||||
// Clears the terminal screen
|
// Clears the terminal screen
|
||||||
execute!(stdout(), terminal::Clear(terminal::ClearType::All)).unwrap();
|
execute!(stdout(), terminal::Clear(terminal::ClearType::All)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write(text: &str) {
|
||||||
|
// Writes a line to a current cursor position
|
||||||
|
execute!(stdout(), Print(text)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_at(&mut self, text: String, position: Coords) {
|
pub fn write_at(&mut self, text: String, position: Coords) {
|
||||||
// Writes a line at a set of coordinates
|
// Writes a line at a set of coordinates
|
||||||
self.cursor.move_to(position);
|
self.cursor.move_to(position);
|
||||||
Screen::write(text);
|
Screen::write(&text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
122
src/tui.rs
122
src/tui.rs
@ -1,52 +1,74 @@
|
|||||||
use crate::editor::Editor;
|
use crate::editor::Editor;
|
||||||
use crate::terminal::{Coords, Screen};
|
use crate::terminal::{Coords, Screen};
|
||||||
use colored::Colorize;
|
use crossterm::style::Stylize;
|
||||||
use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers};
|
use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers};
|
||||||
|
|
||||||
pub fn draw_status(screen: &mut Screen, editor: &Editor) {
|
// Utils
|
||||||
|
fn with_spaces(text: &str) -> String {
|
||||||
|
format!(" {} ", text)
|
||||||
|
}
|
||||||
|
fn calc_x(screen_width: usize, item_length: usize) -> usize {
|
||||||
|
(screen_width / 2) - (item_length / 2)
|
||||||
|
}
|
||||||
|
fn longest_element_in_array(elements: Vec<&str>) -> usize {
|
||||||
|
elements.iter().max_by_key(|x: &&&str| x.len()).unwrap().len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_status(screen: &mut Screen, editor: &Editor) -> Result<(), ()> {
|
||||||
// Calculate where to draw the status bar
|
// Calculate where to draw the status bar
|
||||||
let status_height = screen.size.height - 2;
|
let status_height = screen.size.height - 2;
|
||||||
|
|
||||||
// Get the editor logo from the config
|
// Get the editor logo from the config
|
||||||
let editor_logo = &format!(" {} ", editor.config.logo) as &str;
|
let editor_logo = &with_spaces(editor.config.logo) as &str;
|
||||||
// Write the editor logo
|
|
||||||
screen.write_at(
|
|
||||||
editor_logo.bright_yellow().bold().reversed().to_string(),
|
|
||||||
Coords::from(0, status_height),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get the current mode into a string
|
// Get the current mode into a string
|
||||||
let mode_string = &format!(" {} ", editor.mode.as_str()) as &str;
|
let mode_string = &with_spaces(editor.mode.as_str()) as &str;
|
||||||
// Calculate where to write the current mode
|
|
||||||
let x = editor_logo.len() - 1;
|
|
||||||
// Write the current mode
|
|
||||||
screen.write_at(
|
|
||||||
mode_string.green().bold().reversed().to_string(),
|
|
||||||
Coords::from(x, status_height),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get the current open file name
|
// Get the current open file name
|
||||||
let file_name = &format!(" {} ", editor.buffer.name) as &str;
|
let file_name = &with_spaces(editor.buffer.name) as &str;
|
||||||
// Calculate where to write the file name
|
|
||||||
let x = x + mode_string.len();
|
|
||||||
// Write the current file name
|
|
||||||
screen.write_at(
|
|
||||||
file_name.magenta().bold().reversed().to_string(),
|
|
||||||
Coords::from(x, status_height),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Draw the rest of the status bar
|
// Calculate the total length of all the status bar components
|
||||||
let x = x + file_name.len();
|
let total_length = editor_logo.len() + mode_string.len() + file_name.len() + 1;
|
||||||
screen.write_at(
|
|
||||||
" ".repeat(screen.size.width - x).reversed().to_string(),
|
// If the screen isn't wide enough, panic as we can't draw the status bar
|
||||||
Coords::from(x, status_height),
|
if screen.size.width < total_length {
|
||||||
);
|
Err(())
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Write the editor logo
|
||||||
|
screen.write_at(
|
||||||
|
editor_logo.yellow().bold().reverse().to_string(),
|
||||||
|
Coords::from(0, status_height),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Calculate where to write the current mode
|
||||||
|
let x = editor_logo.len() - 1;
|
||||||
|
// Write the current mode
|
||||||
|
screen.write_at(
|
||||||
|
mode_string.green().bold().reverse().to_string(),
|
||||||
|
Coords::from(x, status_height),
|
||||||
|
);
|
||||||
|
// Calculate where to write the file name
|
||||||
|
let x = x + mode_string.len();
|
||||||
|
// Write the current file name
|
||||||
|
screen.write_at(
|
||||||
|
file_name.magenta().bold().reverse().to_string(),
|
||||||
|
Coords::from(x, status_height),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Draw the rest of the status bar
|
||||||
|
let x = x + file_name.len();
|
||||||
|
screen.write_at(
|
||||||
|
" ".repeat(screen.size.width - x).reverse().to_string(),
|
||||||
|
Coords::from(x, status_height),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_welcome(screen: &mut Screen, editor: &Editor) {
|
pub fn draw_welcome(screen: &mut Screen, editor: &Editor) {
|
||||||
// The welcome message
|
// The welcome message
|
||||||
let message: [&str; 6] = [
|
let title = format!("{} {}", editor.config.logo, editor.config.friendly_name);
|
||||||
&"λ Lambda".yellow() as &str,
|
let message: [&str; 5] = [
|
||||||
"Hackable text editor for nerds",
|
"Hackable text editor for nerds",
|
||||||
"",
|
"",
|
||||||
"Type :help to open the README.md document",
|
"Type :help to open the README.md document",
|
||||||
@ -54,28 +76,40 @@ pub fn draw_welcome(screen: &mut Screen, editor: &Editor) {
|
|||||||
"Type :q! or <C-c> to quit lambda",
|
"Type :q! or <C-c> to quit lambda",
|
||||||
];
|
];
|
||||||
|
|
||||||
// The starting y position in the centre of the screen
|
// If the screen is big enough, we can draw
|
||||||
let mut y = (screen.size.height / 2) - (message.len() / 2) - 2;
|
if screen.size.width > longest_element_in_array(message.to_vec()) && screen.size.height > message.len() + 4 {
|
||||||
|
// The starting y position in the centre of the screen
|
||||||
|
let mut y = (screen.size.height / 2) - (message.len() / 2) - 2;
|
||||||
|
|
||||||
for line in message {
|
// Calculate where to place the title
|
||||||
// Each line has different width so requires a different x position to center it
|
let x = calc_x(screen.size.width, title.len());
|
||||||
let x = (screen.size.width / 2) - (line.len() / 2);
|
|
||||||
|
|
||||||
// For each line we move downwards so increment y
|
// Write the title to the screen
|
||||||
y += 1;
|
screen.write_at(title.yellow().to_string(), Coords::from(x, y));
|
||||||
|
|
||||||
// Write the line to the screen at position (x, y)
|
for line in message {
|
||||||
screen.write_at(line.to_string(), Coords::from(x, y));
|
// Each line has different width so requires a different x position to center it
|
||||||
|
let x = calc_x(screen.size.width, line.len()) ;
|
||||||
|
|
||||||
|
// For each line we move downwards so increment y
|
||||||
|
y += 1;
|
||||||
|
|
||||||
|
// Write the line to the screen at position (x, y)
|
||||||
|
screen.write_at(line.to_string(), Coords::from(x, y));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(screen: &mut Screen, editor: Editor) {
|
pub fn start(screen: &mut Screen, editor: Editor) {
|
||||||
loop {
|
loop {
|
||||||
|
// Refresh the screen
|
||||||
|
screen.refresh().unwrap();
|
||||||
|
|
||||||
// Draw the welcome message
|
// Draw the welcome message
|
||||||
draw_welcome(screen, &editor);
|
draw_welcome(screen, &editor);
|
||||||
|
|
||||||
// Draw the status bar
|
// Draw the status bar
|
||||||
draw_status(screen, &editor);
|
draw_status(screen, &editor).unwrap();
|
||||||
|
|
||||||
// Check for any key presses
|
// Check for any key presses
|
||||||
match read().unwrap() {
|
match read().unwrap() {
|
||||||
|
Loading…
Reference in New Issue
Block a user