diff --git a/Cargo.lock b/Cargo.lock index 6949ebb..6b2ffcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,6 +186,7 @@ name = "muxde" version = "0.1.0" dependencies = [ "crossterm", + "once_cell", "serde", "tokio", "toml", @@ -201,6 +202,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "parking_lot" version = "0.12.3" diff --git a/Cargo.toml b/Cargo.toml index 1b9b28c..c57fa87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] crossterm = "0.28.1" +once_cell = "1.19.0" serde = { version = "1.0.210", features = ["derive", "serde_derive"] } tokio = { version = "1.40.0", features = ["full"] } toml = "0.8.19" diff --git a/config/default.toml b/config/default.toml index f85443a..0ae741f 100644 --- a/config/default.toml +++ b/config/default.toml @@ -1,12 +1,13 @@ [colortheme] background = [0x26, 0x26, 0x28] + command-bar = [0x20, 0x28, 0x20] cmdbar-prompt = [0x60, 0x60, 0x60] cmdbar-cmdexist = [0x40, 0xff, 0x40] cmdbar-cmdunexist = [0xff, 0x40, 0x40] +editor-title = [0x30, 0x30, 0x42] + [command] new-window = "n" quit = "q" -abcdefg = "abcd" -fdsafdsa = "fdsa" diff --git a/src/api.rs b/src/api.rs index c0f55a0..816feda 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,5 +1,10 @@ -use crate::window::Window; +use once_cell::sync::OnceCell; -pub fn new_window() -> Box { - todo!() +use crate::{window::Window, window::editor::Editor}; + +pub fn new_window(screen_size: (u16, u16)) -> Box { + static mut ID_COUNT: OnceCell = OnceCell::new(); + let tmp = unsafe { *ID_COUNT.get_or_init(|| 0) }; + let _ = unsafe { ID_COUNT.set(tmp + 1) }; + Box::new(Editor::new(tmp, screen_size)) } diff --git a/src/application.rs b/src/application.rs index 7ac3598..15f4992 100644 --- a/src/application.rs +++ b/src/application.rs @@ -79,18 +79,19 @@ impl Application { fn command_process(&mut self) -> bool { if let toml::Value::Table(map) = &self.config.get("command").unwrap() { let (tx, rx) = mpsc::channel(); - if self.cmdprocessor.process(map, tx) { - while let Ok(pipeobj) = rx.recv() { - match pipeobj { - PipeObj::NewWindow(win) => { - self.windows.insert(win.get_id(), win); - } - } - } + let res = if self.cmdprocessor.process(map, self.size, tx) { true } else { false + }; + while let Ok(pipeobj) = rx.recv() { + match pipeobj { + PipeObj::NewWindow(win) => { + self.windows.insert(win.get_id(), win); + } + } } + res } else { false } @@ -138,6 +139,13 @@ impl Application { style::Print(" ".repeat((self.size.0 - x) as usize)), cursor::RestorePosition, )?; + for (_, win) in self.windows.iter_mut() { + win.render( + &mut self.stdout, + (self.size.0, self.size.1 - 1), + &self.colortheme, + )?; + } self.stdout.flush()?; Ok(()) } diff --git a/src/colortheme.rs b/src/colortheme.rs index c12570d..06062f1 100644 --- a/src/colortheme.rs +++ b/src/colortheme.rs @@ -7,6 +7,7 @@ pub struct ColorTheme { pub cmdbar_prompt: Color, pub cmdbar_cmdexist: Color, pub cmdbar_cmdunexist: Color, + pub editor_title: Color, } impl From<&Table> for ColorTheme { @@ -27,12 +28,14 @@ impl From<&Table> for ColorTheme { let cmdbar_prompt = f("cmdbar-prompt"); let cmdbar_cmdexist = f("cmdbar-cmdexist"); let cmdbar_cmdunexist = f("cmdbar-cmdunexist"); + let editor_title = f("editor-title"); Self { background, command_bar, cmdbar_prompt, cmdbar_cmdexist, cmdbar_cmdunexist, + editor_title, } } } diff --git a/src/command.rs b/src/command.rs index 65a1da0..be2ac55 100644 --- a/src/command.rs +++ b/src/command.rs @@ -45,7 +45,12 @@ impl CommandProcessor { self.command_mode } - pub fn process(&mut self, map: &Config, sender: Sender) -> bool { + pub fn process( + &mut self, + map: &Config, + screen_size: (u16, u16), + sender: Sender, + ) -> bool { if let Some((name, cmd, full)) = iterate_config(map, &self.command) { self.cmdbar_prompt = format!("{}", name); if !full { @@ -68,7 +73,7 @@ impl CommandProcessor { match name.as_str() { "quit" => return true, "new-window" => { - let win = api::new_window(); + let win = api::new_window(screen_size); sender.send(PipeObj::NewWindow(win)).unwrap(); } "abcd" => (), diff --git a/src/lib.rs b/src/lib.rs index 7c50e7f..01f6579 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,6 @@ pub mod colortheme; pub mod command; pub mod innerpipe; pub mod window; -pub mod windows; use std::io; diff --git a/src/window.rs b/src/window.rs deleted file mode 100644 index aad7a05..0000000 --- a/src/window.rs +++ /dev/null @@ -1,10 +0,0 @@ -use std::io::{self, Stdout}; - -pub trait Window { - fn get_pos(&self) -> (u16, u16); - fn get_size(&self) -> (u16, u16); - fn get_name(&self) -> &str; - fn get_id(&self) -> usize; - - fn render(&mut self, stdout: &mut Stdout, screen_size: (u16, u16)) -> io::Result<()>; -} diff --git a/src/window/editor.rs b/src/window/editor.rs new file mode 100644 index 0000000..84ff912 --- /dev/null +++ b/src/window/editor.rs @@ -0,0 +1,62 @@ +use std::io::{self, Stdout}; + +use crossterm::{cursor, queue, style}; +use unicode_width::UnicodeWidthStr; + +use crate::{colortheme::ColorTheme, window::Window}; + +pub struct Editor { + id: usize, + name: String, + pos: (u16, u16), + size: (u16, u16), +} + +impl Editor { + pub fn new(id: usize, screen_size: (u16, u16)) -> Self { + Editor { + id, + name: String::new(), + pos: (0, 0), + size: screen_size, + } + } +} + +impl Window for Editor { + fn get_pos(&self) -> (u16, u16) { + self.pos + } + + fn get_size(&self) -> (u16, u16) { + self.size + } + + fn get_name(&self) -> &str { + &self.name + } + + fn get_id(&self) -> usize { + self.id + } + + fn render( + &mut self, + stdout: &mut Stdout, + screen_size: (u16, u16), + colortheme: &ColorTheme, + ) -> io::Result<()> { + let x = UnicodeWidthStr::width(self.name.as_str()) as u16; + queue!( + stdout, + cursor::SavePosition, + style::SetBackgroundColor(colortheme.editor_title), + cursor::MoveTo(self.pos.0, self.pos.1), + style::Print(self.name.clone()), + style::Print(" ".repeat((screen_size.0 - x) as usize) + "\n\r"), + style::SetBackgroundColor(colortheme.background), + cursor::RestorePosition, + )?; + Ok(()) + } +} diff --git a/src/window/mod.rs b/src/window/mod.rs new file mode 100644 index 0000000..6b41916 --- /dev/null +++ b/src/window/mod.rs @@ -0,0 +1,19 @@ +pub mod editor; + +use std::io::{self, Stdout}; + +use crate::colortheme::ColorTheme; + +pub trait Window { + fn get_pos(&self) -> (u16, u16); + fn get_size(&self) -> (u16, u16); + fn get_name(&self) -> &str; + fn get_id(&self) -> usize; + + fn render( + &mut self, + stdout: &mut Stdout, + screen_size: (u16, u16), + colortheme: &ColorTheme, + ) -> io::Result<()>; +} diff --git a/src/windows/editor.rs b/src/windows/editor.rs deleted file mode 100644 index 90bc844..0000000 --- a/src/windows/editor.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::{ - hash::{DefaultHasher, Hash, Hasher}, - io::{self, Stdout}, -}; - -use crossterm::{cursor, queue}; - -use crate::window::Window; - -pub struct Editor { - name: String, - pos: (u16, u16), - size: (u16, u16), -} - -impl Window for Editor { - fn get_pos(&self) -> (u16, u16) { - self.pos - } - - fn get_size(&self) -> (u16, u16) { - self.size - } - - fn get_name(&self) -> &str { - &self.name - } - - fn get_id(&self) -> usize { - let mut state = DefaultHasher::new(); - self.name.hash(&mut state); - state.finish() as usize - } - - fn render(&mut self, stdout: &mut Stdout, screen_size: (u16, u16)) -> io::Result<()> { - queue!(stdout, cursor::SavePosition, cursor::RestorePosition)?; - Ok(()) - } -} - -impl Hash for Editor { - fn hash(&self, state: &mut H) - where - H: Hasher, - { - self.name.hash(state) - } -} diff --git a/src/windows/mod.rs b/src/windows/mod.rs deleted file mode 100644 index 0769981..0000000 --- a/src/windows/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod editor;