command bar update

This commit is contained in:
pointer-to-bios 2024-09-25 09:30:11 +00:00
parent c2a0942902
commit 934452beda
9 changed files with 107 additions and 37 deletions

View File

@ -1,10 +1,12 @@
[colortheme] [colortheme]
background = [0x26, 0x26, 0x28] background = [0x26, 0x26, 0x28]
command-bar = [0x20, 0x28, 0x20] command-bar = [0x20, 0x28, 0x20]
cmdbar-prompt = [0x40, 0x40, 0x40] cmdbar-prompt = [0x60, 0x60, 0x60]
cmdbar-cmdexist = [0x40, 0xff, 0x40] cmdbar-cmdexist = [0x40, 0xff, 0x40]
cmdbar-cmdunexist = [0xff, 0x40, 0x40] cmdbar-cmdunexist = [0xff, 0x40, 0x40]
[command] [command]
new-window = "n" new-window = "n"
quit = "q" quit = "q"
abcdefg = "abcd"
fdsafdsa = "fdsa"

5
src/api.rs Normal file
View File

@ -0,0 +1,5 @@
use crate::window::Window;
pub fn new_window() -> Box<dyn Window> {
todo!()
}

7
src/api.rs~ Normal file
View File

@ -0,0 +1,7 @@
use std::collection::HashMap;
use crate::window::Window;
pub fn new_window() -> Box<dyn Window> {
todo!()
}

View File

@ -1,14 +1,13 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
io::{self, stdout, Stdout, Write}, io::{self, stdout, Stdout, Write},
sync::mpsc,
thread, thread,
time::Duration, time::Duration,
}; };
use crossterm::{ use crossterm::{
cursor, cursor, event, queue,
event::{self, KeyEvent, KeyModifiers},
queue,
style::{self, Color}, style::{self, Color},
terminal::{self, disable_raw_mode, enable_raw_mode, ClearType}, terminal::{self, disable_raw_mode, enable_raw_mode, ClearType},
}; };
@ -16,7 +15,7 @@ use crossterm::{
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use crate::{ use crate::{
colortheme::ColorTheme, command::CommandProcessor, iterate_config, window::Window, Config, colortheme::ColorTheme, command::CommandProcessor, innerpipe::PipeObj, window::Window, Config,
}; };
pub struct Application { pub struct Application {
@ -24,7 +23,7 @@ pub struct Application {
colortheme: ColorTheme, colortheme: ColorTheme,
stdout: Stdout, stdout: Stdout,
size: (u16, u16), size: (u16, u16),
windows: HashMap<usize, Window>, windows: HashMap<usize, Box<dyn Window>>,
cmdprocessor: CommandProcessor, cmdprocessor: CommandProcessor,
} }
@ -79,7 +78,15 @@ impl Application {
fn command_process(&mut self) -> bool { fn command_process(&mut self) -> bool {
if let toml::Value::Table(map) = &self.config.get("command").unwrap() { 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 true
} else { } else {
false false
@ -98,7 +105,15 @@ impl Application {
} }
} }
let x = UnicodeWidthStr::width(show.as_str()) as u16; 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() { for c in self.cmdprocessor.get_prompt().chars() {
prompt.push(c); prompt.push(c);
if UnicodeWidthStr::width(prompt.as_str()) as u16 >= self.size.0 - 1 - x { if UnicodeWidthStr::width(prompt.as_str()) as u16 >= self.size.0 - 1 - x {
@ -116,8 +131,9 @@ impl Application {
self.colortheme.cmdbar_cmdexist self.colortheme.cmdbar_cmdexist
}), }),
style::Print(show), style::Print(show),
cursor::SavePosition, cursor::SavePosition,
style::SetForegroundColor(self.colortheme.cmdbar_prompt), style::SetForegroundColor(self.colortheme.cmdbar_prompt),
style::Print(suggestion),
style::Print(prompt), style::Print(prompt),
style::Print(" ".repeat((self.size.0 - x) as usize)), style::Print(" ".repeat((self.size.0 - x) as usize)),
cursor::RestorePosition, cursor::RestorePosition,

View File

@ -1,6 +1,8 @@
use std::sync::mpsc::Sender;
use crossterm::event::{self, KeyEvent, KeyModifiers}; use crossterm::event::{self, KeyEvent, KeyModifiers};
use crate::{iterate_config, Config}; use crate::{api, innerpipe::PipeObj, iterate_config, Config};
pub struct CommandProcessor { pub struct CommandProcessor {
command_mode: bool, command_mode: bool,
@ -8,6 +10,7 @@ pub struct CommandProcessor {
unknown_cmd: bool, unknown_cmd: bool,
cmdbar_show: String, cmdbar_show: String,
cmdbar_prompt: String, cmdbar_prompt: String,
cmdbar_suggestion: String,
} }
impl CommandProcessor { impl CommandProcessor {
@ -18,6 +21,7 @@ impl CommandProcessor {
unknown_cmd: false, unknown_cmd: false,
cmdbar_show: String::new(), cmdbar_show: String::new(),
cmdbar_prompt: String::from("New workspace"), cmdbar_prompt: String::from("New workspace"),
cmdbar_suggestion: String::new(),
} }
} }
@ -29,6 +33,10 @@ impl CommandProcessor {
&self.cmdbar_prompt &self.cmdbar_prompt
} }
pub fn get_suggestion(&self) -> &String {
&self.cmdbar_suggestion
}
pub fn unknown(&self) -> bool { pub fn unknown(&self) -> bool {
self.unknown_cmd self.unknown_cmd
} }
@ -37,24 +45,39 @@ impl CommandProcessor {
self.command_mode self.command_mode
} }
pub fn process(&mut self, map: &Config) -> bool { pub fn process(&mut self, map: &Config, sender: Sender<PipeObj>) -> bool {
let f = |_, value| { if let Some((name, cmd, full)) = iterate_config(map, &self.command) {
if let &toml::Value::String(ref s) = value { self.cmdbar_prompt = format!("{}", name);
s == &self.command 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 { } else {
false self.cmdbar_suggestion.clear();
} }
}; self.unknown_cmd = false;
if let Some((name, _)) = iterate_config(map, &f) { if full {
self.command.clear(); self.command.clear();
self.cmdbar_prompt = format!(" - {}", name); match name.as_str() {
self.unknown_cmd = false; "quit" => return true,
match name.as_str() { "new-window" => {
"quit" => return true, let win = api::new_window();
_ => (), sender.send(PipeObj::NewWindow(win)).unwrap();
}
"abcd" => (),
"dfas" => (),
_ => (),
}
} }
} else if !self.cmdbar_show.is_empty() { } 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; self.unknown_cmd = true;
} else { } else {
self.cmdbar_prompt.clear(); self.cmdbar_prompt.clear();

5
src/innerpipe.rs Normal file
View File

@ -0,0 +1,5 @@
use crate::window::Window;
pub enum PipeObj {
NewWindow(Box<dyn Window>),
}

3
src/innerpipe.rs~ Normal file
View File

@ -0,0 +1,3 @@
pub enum PipeObj {
NewWindow(Box<dyn Window>),
}

View File

@ -1,7 +1,9 @@
pub mod api;
pub mod application; pub mod application;
pub mod colortheme; pub mod colortheme;
pub mod window;
pub mod command; pub mod command;
pub mod innerpipe;
pub mod window;
use std::io; use std::io;
@ -10,17 +12,19 @@ use toml::map::Map;
pub type Config = Map<String, toml::Value>; pub type Config = Map<String, toml::Value>;
pub fn iterate_config<'a, 'b: 'a, F>(config: &'b Config, f: &F) -> Option<(String, toml::Value)> pub fn iterate_config<'a, 'b: 'a>(
where config: &'b Config,
F: Fn(&'a str, &'b toml::Value) -> bool, cmd: &'a str,
{ ) -> Option<(String, toml::Value, bool)> {
for (name, value) in config { for (name, value) in config {
if let toml::Value::Table(map) = value { 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); return Some(p);
} }
} else if f(name, value) { } else if cmd == value.as_str().unwrap() {
return Some((name.clone(), value.clone())); return Some((name.clone(), value.clone(), true));
} else if value.as_str().unwrap().starts_with(cmd) {
return Some((name.clone(), value.clone(), false));
} }
} }
None None

View File

@ -1,4 +1,9 @@
pub struct Window { use std::io;
pos: (u16, u16),
size: (u16, u16), 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<()>;
} }