diff --git a/config/default.toml b/config/default.toml index 2a585b7..f85443a 100644 --- a/config/default.toml +++ b/config/default.toml @@ -1,10 +1,12 @@ [colortheme] background = [0x26, 0x26, 0x28] command-bar = [0x20, 0x28, 0x20] -cmdbar-prompt = [0x40, 0x40, 0x40] +cmdbar-prompt = [0x60, 0x60, 0x60] cmdbar-cmdexist = [0x40, 0xff, 0x40] cmdbar-cmdunexist = [0xff, 0x40, 0x40] [command] new-window = "n" quit = "q" +abcdefg = "abcd" +fdsafdsa = "fdsa" diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..c0f55a0 --- /dev/null +++ b/src/api.rs @@ -0,0 +1,5 @@ +use crate::window::Window; + +pub fn new_window() -> Box { + todo!() +} diff --git a/src/api.rs~ b/src/api.rs~ new file mode 100644 index 0000000..5bdb5b1 --- /dev/null +++ b/src/api.rs~ @@ -0,0 +1,7 @@ +use std::collection::HashMap; + +use crate::window::Window; + +pub fn new_window() -> Box { + todo!() +} diff --git a/src/application.rs b/src/application.rs index 68a7f71..31fc466 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,14 +1,13 @@ use std::{ collections::HashMap, io::{self, stdout, Stdout, Write}, + sync::mpsc, thread, time::Duration, }; use crossterm::{ - cursor, - event::{self, KeyEvent, KeyModifiers}, - queue, + cursor, event, queue, style::{self, Color}, terminal::{self, disable_raw_mode, enable_raw_mode, ClearType}, }; @@ -16,7 +15,7 @@ use crossterm::{ use unicode_width::UnicodeWidthStr; use crate::{ - colortheme::ColorTheme, command::CommandProcessor, iterate_config, window::Window, Config, + colortheme::ColorTheme, command::CommandProcessor, innerpipe::PipeObj, window::Window, Config, }; pub struct Application { @@ -24,7 +23,7 @@ pub struct Application { colortheme: ColorTheme, stdout: Stdout, size: (u16, u16), - windows: HashMap, + windows: HashMap>, cmdprocessor: CommandProcessor, } @@ -79,7 +78,15 @@ impl Application { fn command_process(&mut self) -> bool { if let toml::Value::Table(map) = &self.config.get("command").unwrap() { - if self.cmdprocessor.process(map) { + 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); + } + } + } true } else { false @@ -98,7 +105,15 @@ impl Application { } } let x = UnicodeWidthStr::width(show.as_str()) as u16; - let mut prompt = String::new(); + let mut suggestion = String::new(); + for c in self.cmdprocessor.get_suggestion().chars() { + suggestion.push(c); + if UnicodeWidthStr::width(suggestion.as_str()) as u16 >= self.size.0 - 1 - x { + break; + } + } + let x = x + UnicodeWidthStr::width(suggestion.as_str()) as u16; + let mut prompt = String::from(if x == 0 {""}else{" - "}); for c in self.cmdprocessor.get_prompt().chars() { prompt.push(c); if UnicodeWidthStr::width(prompt.as_str()) as u16 >= self.size.0 - 1 - x { @@ -116,8 +131,9 @@ impl Application { self.colortheme.cmdbar_cmdexist }), style::Print(show), - cursor::SavePosition, - style::SetForegroundColor(self.colortheme.cmdbar_prompt), + cursor::SavePosition, + style::SetForegroundColor(self.colortheme.cmdbar_prompt), + style::Print(suggestion), style::Print(prompt), style::Print(" ".repeat((self.size.0 - x) as usize)), cursor::RestorePosition, diff --git a/src/command.rs b/src/command.rs index 9ba3a02..4f4db67 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,6 +1,8 @@ +use std::sync::mpsc::Sender; + use crossterm::event::{self, KeyEvent, KeyModifiers}; -use crate::{iterate_config, Config}; +use crate::{api, innerpipe::PipeObj, iterate_config, Config}; pub struct CommandProcessor { command_mode: bool, @@ -8,6 +10,7 @@ pub struct CommandProcessor { unknown_cmd: bool, cmdbar_show: String, cmdbar_prompt: String, + cmdbar_suggestion: String, } impl CommandProcessor { @@ -18,6 +21,7 @@ impl CommandProcessor { unknown_cmd: false, cmdbar_show: String::new(), cmdbar_prompt: String::from("New workspace"), + cmdbar_suggestion: String::new(), } } @@ -29,6 +33,10 @@ impl CommandProcessor { &self.cmdbar_prompt } + pub fn get_suggestion(&self) -> &String { + &self.cmdbar_suggestion + } + pub fn unknown(&self) -> bool { self.unknown_cmd } @@ -37,24 +45,39 @@ impl CommandProcessor { self.command_mode } - pub fn process(&mut self, map: &Config) -> bool { - let f = |_, value| { - if let &toml::Value::String(ref s) = value { - s == &self.command + pub fn process(&mut self, map: &Config, sender: Sender) -> bool { + if let Some((name, cmd, full)) = iterate_config(map, &self.command) { + self.cmdbar_prompt = format!("{}", name); + if !full { + let mut s = cmd.as_str().unwrap().to_string(); + for _ in self.command.chars() { + s.remove(0); + } + if self.command.is_empty() { + self.cmdbar_suggestion.clear(); + } else { + self.cmdbar_suggestion = s; + } } else { - false - } - }; - if let Some((name, _)) = iterate_config(map, &f) { - self.command.clear(); - self.cmdbar_prompt = format!(" - {}", name); - self.unknown_cmd = false; - match name.as_str() { - "quit" => return true, - _ => (), + self.cmdbar_suggestion.clear(); + } + self.unknown_cmd = false; + if full { + self.command.clear(); + match name.as_str() { + "quit" => return true, + "new-window" => { + let win = api::new_window(); + sender.send(PipeObj::NewWindow(win)).unwrap(); + } + "abcd" => (), + "dfas" => (), + _ => (), + } } } else if !self.cmdbar_show.is_empty() { - self.cmdbar_prompt = String::from(" | Unknown command"); + self.cmdbar_prompt = String::from("Unknown command"); + self.cmdbar_suggestion.clear(); self.unknown_cmd = true; } else { self.cmdbar_prompt.clear(); diff --git a/src/innerpipe.rs b/src/innerpipe.rs new file mode 100644 index 0000000..3f1fdb3 --- /dev/null +++ b/src/innerpipe.rs @@ -0,0 +1,5 @@ +use crate::window::Window; + +pub enum PipeObj { + NewWindow(Box), +} diff --git a/src/innerpipe.rs~ b/src/innerpipe.rs~ new file mode 100644 index 0000000..e0d35c5 --- /dev/null +++ b/src/innerpipe.rs~ @@ -0,0 +1,3 @@ +pub enum PipeObj { + NewWindow(Box), +} diff --git a/src/lib.rs b/src/lib.rs index 3413406..01f6579 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ +pub mod api; pub mod application; pub mod colortheme; -pub mod window; pub mod command; +pub mod innerpipe; +pub mod window; use std::io; @@ -10,17 +12,19 @@ use toml::map::Map; pub type Config = Map; -pub fn iterate_config<'a, 'b: 'a, F>(config: &'b Config, f: &F) -> Option<(String, toml::Value)> -where - F: Fn(&'a str, &'b toml::Value) -> bool, -{ +pub fn iterate_config<'a, 'b: 'a>( + config: &'b Config, + cmd: &'a str, +) -> Option<(String, toml::Value, bool)> { for (name, value) in config { if let toml::Value::Table(map) = value { - if let Some(p) = iterate_config(map, f) { + if let Some(p) = iterate_config(map, cmd) { return Some(p); } - } else if f(name, value) { - return Some((name.clone(), value.clone())); + } else if cmd == value.as_str().unwrap() { + return Some((name.clone(), value.clone(), true)); + } else if value.as_str().unwrap().starts_with(cmd) { + return Some((name.clone(), value.clone(), false)); } } None diff --git a/src/window.rs b/src/window.rs index a95ddd3..dfb2b0b 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,4 +1,9 @@ -pub struct Window { - pos: (u16, u16), - size: (u16, u16), +use std::io; + +pub trait Window { + fn get_pos(&self) -> (u16, u16); + fn get_size(&self) -> (u16, u16); + fn get_id(&self) -> usize; + + fn render(&mut self, screen_size: (u16, u16)) -> io::Result<()>; }