built more of the editor + tui parts
This commit is contained in:
parent
09d26ec97e
commit
a8a978d86e
61
Cargo.lock
generated
61
Cargo.lock
generated
@ -2,6 +2,17 @@
|
||||
# It is not intended for manual editing.
|
||||
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]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@ -20,6 +31,17 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "crossterm"
|
||||
version = "0.25.0"
|
||||
@ -45,13 +67,40 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d91974fbbe88ec1df0c24a4f00f99583667a7e2e6272b2b92d294d81e462173"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lambda"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"crossterm",
|
||||
"ctrlc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.137"
|
||||
@ -89,6 +138,18 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
|
@ -5,3 +5,5 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
crossterm = "0.25"
|
||||
colored = "2"
|
||||
ctrlc = "3.2.3"
|
||||
|
@ -1,7 +1,11 @@
|
||||
enum Mode {
|
||||
Normal,
|
||||
Insert,
|
||||
Select
|
||||
pub struct Config<'a> {
|
||||
pub logo: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Config<'a> {
|
||||
pub fn new() -> Self {
|
||||
Self { logo: "λ" }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Buffer<'a> {
|
||||
@ -10,21 +14,41 @@ pub struct Buffer<'a> {
|
||||
pub path: &'a str,
|
||||
}
|
||||
|
||||
pub enum Mode {
|
||||
Normal,
|
||||
Insert,
|
||||
Select,
|
||||
Command,
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
pub fn as_str(&self) -> &str {
|
||||
match self {
|
||||
Mode::Normal => "NORMAL",
|
||||
Mode::Insert => "INSERT",
|
||||
Mode::Select => "SELECT",
|
||||
Mode::Command => "COMMAND",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Editor<'a> {
|
||||
pub config: Config<'a>,
|
||||
pub buffer: Buffer<'a>,
|
||||
pub cursor: [i32; 2],
|
||||
mode: Mode,
|
||||
pub cursors: Vec<i32>,
|
||||
pub mode: Mode,
|
||||
}
|
||||
|
||||
impl<'a> Editor<'a> {
|
||||
pub fn new() -> Self {
|
||||
Editor {
|
||||
config: Config::new(),
|
||||
buffer: Buffer {
|
||||
data: Vec::from([String::from("Hello"), String::from("World")]),
|
||||
name: "[No Name]",
|
||||
path: "/home/spy",
|
||||
},
|
||||
cursor: [0, 0],
|
||||
cursors: Vec::from([0]),
|
||||
mode: Mode::Normal,
|
||||
}
|
||||
}
|
||||
|
17
src/main.rs
17
src/main.rs
@ -1,18 +1,9 @@
|
||||
use std::time::Duration;
|
||||
|
||||
mod terminal;
|
||||
mod editor;
|
||||
mod terminal;
|
||||
mod tui;
|
||||
|
||||
fn main() {
|
||||
let lambda = editor::Editor::new();
|
||||
let mut term = terminal::Terminal::new().unwrap();
|
||||
loop {
|
||||
for line in lambda.buffer.data {
|
||||
terminal::Terminal::write(format!("{line}"));
|
||||
mut term.cursor.move_to(0, 1);
|
||||
};
|
||||
std::thread::sleep(Duration::from_secs(3));
|
||||
break;
|
||||
};
|
||||
terminal::Terminal::exit();
|
||||
let mut screen = terminal::Screen::new().unwrap();
|
||||
tui::start(&mut screen, lambda);
|
||||
}
|
||||
|
112
src/terminal.rs
112
src/terminal.rs
@ -1,76 +1,124 @@
|
||||
use crossterm::cursor::{Hide, MoveTo, Show};
|
||||
use crossterm::style::Print;
|
||||
use crossterm::terminal;
|
||||
use crossterm::{execute, ErrorKind};
|
||||
use crossterm::style::Print;
|
||||
use crossterm::cursor::{CursorShape, MoveTo};
|
||||
use std::io::{stdout, Write};
|
||||
|
||||
pub struct Size {
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
}
|
||||
use std::io::stdout;
|
||||
|
||||
// Struct for holding coordinates
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Coords {
|
||||
pub x: usize,
|
||||
pub y: usize,
|
||||
}
|
||||
|
||||
// Creating a coordinates from two values
|
||||
impl Coords {
|
||||
pub fn from(x: usize, y: usize) -> Self {
|
||||
Self {
|
||||
x: 0,
|
||||
y: 0,
|
||||
}
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
// A cursor for writing to the terminal screen
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Cursor {
|
||||
pub position: Coords,
|
||||
pub shape: CursorShape,
|
||||
pub hidden: bool,
|
||||
}
|
||||
|
||||
// When a cursor is created
|
||||
impl Cursor {
|
||||
pub fn new() -> Result<Self, ErrorKind> {
|
||||
let cursor = Self {
|
||||
let mut cursor = Self {
|
||||
position: Coords::from(0, 0),
|
||||
shape: CursorShape::Block,
|
||||
hidden: true,
|
||||
};
|
||||
Cursor::move_to(&mut cursor, 0, 0);
|
||||
Cursor::move_to(&mut cursor, Coords::from(0, 0));
|
||||
Cursor::hide(&mut cursor);
|
||||
Ok(cursor)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_to(&mut self, x: u16, y: u16) {
|
||||
self.position = Coords::from(x as usize, y as usize);
|
||||
execute!(stdout(), MoveTo(x, y)).unwrap()
|
||||
// Cursor methods
|
||||
impl Cursor {
|
||||
pub fn move_to(&mut self, position: Coords) {
|
||||
// Set the new position of the cursor
|
||||
self.position = position;
|
||||
|
||||
// Move the cursor to the desired posiition in the terminal
|
||||
execute!(stdout(), MoveTo(position.x as u16, position.y as u16)).unwrap();
|
||||
}
|
||||
|
||||
pub fn hide(&mut self) {
|
||||
// Remember that the cursor is hidden
|
||||
self.hidden = true;
|
||||
|
||||
// Hide the cursor from the terminal screen
|
||||
execute!(stdout(), Hide).unwrap();
|
||||
}
|
||||
|
||||
pub fn show(&mut self) {
|
||||
// Remember that the cursor isn't hidden
|
||||
self.hidden = false;
|
||||
|
||||
// Show the cursor to the terminal screen
|
||||
execute!(stdout(), Show).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Terminal {
|
||||
// A struct for holding the size of the terminal
|
||||
pub struct Size {
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
}
|
||||
|
||||
// The terminal screen
|
||||
pub struct Screen {
|
||||
pub size: Size,
|
||||
pub cursor: Cursor,
|
||||
}
|
||||
|
||||
impl Terminal {
|
||||
// For when a new terminal screen is created
|
||||
impl Screen {
|
||||
pub fn new() -> Result<Self, ErrorKind> {
|
||||
// Get the size of the terminal
|
||||
let size = terminal::size()?;
|
||||
Terminal::clear();
|
||||
Terminal::enter();
|
||||
Ok(Self {
|
||||
|
||||
// Define a new terminal screen struct
|
||||
let mut screen = Self {
|
||||
size: Size {
|
||||
width: size.0 as usize,
|
||||
height: size.1 as usize,
|
||||
},
|
||||
cursor: Cursor::new().unwrap(),
|
||||
})
|
||||
};
|
||||
|
||||
// Empty the terminal screen
|
||||
Screen::clear();
|
||||
|
||||
// Enter the terminal screen
|
||||
screen.enter();
|
||||
|
||||
// Return a result containing the terminal
|
||||
Ok(screen)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enter() {
|
||||
// Enter the current terminal
|
||||
// Terminal functions and methods for managing the terminal
|
||||
impl Screen {
|
||||
pub fn enter(&mut self) {
|
||||
// Hide the cursor
|
||||
self.cursor.hide();
|
||||
|
||||
// Enter the terminal screen
|
||||
terminal::enable_raw_mode().unwrap();
|
||||
execute!(stdout(), terminal::EnterAlternateScreen).unwrap();
|
||||
}
|
||||
|
||||
pub fn exit() {
|
||||
// Exit the current terminal
|
||||
pub fn exit(&mut self) {
|
||||
// Show the cursor
|
||||
self.cursor.show();
|
||||
|
||||
// Exit the terminal screen
|
||||
execute!(stdout(), terminal::LeaveAlternateScreen).unwrap();
|
||||
terminal::disable_raw_mode().unwrap();
|
||||
}
|
||||
@ -84,4 +132,10 @@ impl Terminal {
|
||||
// Clears the terminal screen
|
||||
execute!(stdout(), terminal::Clear(terminal::ClearType::All)).unwrap();
|
||||
}
|
||||
|
||||
pub fn write_at(&mut self, text: String, position: Coords) {
|
||||
// Writes a line at a set of coordinates
|
||||
self.cursor.move_to(position);
|
||||
Screen::write(text);
|
||||
}
|
||||
}
|
||||
|
56
src/tui.rs
Normal file
56
src/tui.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use crate::editor::Editor;
|
||||
use crate::terminal::{Coords, Screen};
|
||||
use colored::Colorize;
|
||||
use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers};
|
||||
|
||||
pub fn draw_status(screen: &mut Screen, editor: &Editor) {
|
||||
// Calculate where to draw the status bar
|
||||
let status_height = screen.size.height - 2;
|
||||
|
||||
// Get the editor logo from the config
|
||||
let editor_logo = &format!(" {} ", 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
|
||||
let mode_string = &format!(" {} ", 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
|
||||
let file_name = &format!(" {} ", editor.buffer.name) as &str;
|
||||
// Calculate where to write the file name
|
||||
let x = editor_logo.len() + mode_string.len() - 1;
|
||||
// Write the current file name
|
||||
screen.write_at(
|
||||
file_name.magenta().bold().reversed().to_string(),
|
||||
Coords::from(x, status_height),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn start(screen: &mut Screen, editor: Editor) {
|
||||
loop {
|
||||
// Draw the status bar
|
||||
draw_status(screen, &editor);
|
||||
|
||||
// Check for any key presses
|
||||
match read().unwrap() {
|
||||
Event::Key(KeyEvent {
|
||||
code: KeyCode::Char('q'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
..
|
||||
}) => break,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
screen.exit();
|
||||
}
|
Loading…
Reference in New Issue
Block a user