frame width, clearing, debug log
This commit is contained in:
parent
a64048104c
commit
9f7be00735
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
debug.log
|
||||||
|
|
|
@ -9,7 +9,7 @@ type Result<T> = std::result::Result<T, anyhow::Error>;
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Body {
|
pub enum Body {
|
||||||
Echo,
|
Echo,
|
||||||
Signin(SigninPage),
|
// Signin(SigninPage),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Body {
|
impl Body {
|
||||||
|
@ -17,9 +17,10 @@ impl Body {
|
||||||
let event = format!("{}", event);
|
let event = format!("{}", event);
|
||||||
write!(
|
write!(
|
||||||
screen,
|
screen,
|
||||||
"{fr}{}",
|
"{clear}{frame}{content}",
|
||||||
env.frame.writeln(&format!("Event: {}", event), 1, 1),
|
clear = clear::All,
|
||||||
fr = env.primary_frame(),
|
frame = env.frame.frame_str(env.theme.primary()),
|
||||||
|
content = env.frame.writeln(&format!("Event: {}", event), 0, 0),
|
||||||
)?;
|
)?;
|
||||||
screen.flush()?;
|
screen.flush()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -34,7 +35,7 @@ impl Page for Body {
|
||||||
event: Event,
|
event: Event,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Body::Signin(b) => b.receive_event(env, screen, event)?,
|
// Body::Signin(b) => b.receive_event(env, screen, event)?,
|
||||||
Body::Echo => Body::echo(env, screen, event)?,
|
Body::Echo => Body::echo(env, screen, event)?,
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -45,7 +46,7 @@ impl Page for Body {
|
||||||
screen,
|
screen,
|
||||||
"{hide}{clear}{fr}{cursor}",
|
"{hide}{clear}{fr}{cursor}",
|
||||||
hide = cursor::Hide,
|
hide = cursor::Hide,
|
||||||
fr = env.frame.frame_str(&env.theme, env.theme.primary()),
|
fr = env.frame.frame_str(env.theme.primary()),
|
||||||
cursor = env.frame.goto(0, 0),
|
cursor = env.frame.goto(0, 0),
|
||||||
clear = clear::All
|
clear = clear::All
|
||||||
)?;
|
)?;
|
||||||
|
@ -54,51 +55,51 @@ impl Page for Body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
// #[derive(Debug, Clone, Default)]
|
||||||
struct SigninPage {
|
// struct SigninPage {
|
||||||
hostname: String,
|
// hostname: String,
|
||||||
username: String,
|
// username: String,
|
||||||
cursor: SigninCursorLocation,
|
// cursor: SigninCursorLocation,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
// #[derive(Debug, Clone)]
|
||||||
enum SigninCursorLocation {
|
// enum SigninCursorLocation {
|
||||||
Hostname,
|
// Hostname,
|
||||||
Username,
|
// Username,
|
||||||
Next,
|
// Next,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Default for SigninCursorLocation {
|
// impl Default for SigninCursorLocation {
|
||||||
fn default() -> Self {
|
// fn default() -> Self {
|
||||||
Self::Hostname
|
// Self::Hostname
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl SigninPage {
|
// impl SigninPage {
|
||||||
fn frame_string() -> String {
|
// fn frame_string() -> String {
|
||||||
format!("")
|
// format!("")
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Page for SigninPage {
|
// impl Page for SigninPage {
|
||||||
fn receive_event(
|
// fn receive_event(
|
||||||
&mut self,
|
// &mut self,
|
||||||
env: Environment,
|
// env: Environment,
|
||||||
screen: &mut RawTerminal<Stdout>,
|
// screen: &mut RawTerminal<Stdout>,
|
||||||
event: Event,
|
// event: Event,
|
||||||
) -> Result<()> {
|
// ) -> Result<()> {
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn init(&self, env: Environment, screen: &mut RawTerminal<Stdout>) -> Result<()> {
|
// fn init(&self, env: Environment, screen: &mut RawTerminal<Stdout>) -> Result<()> {
|
||||||
write!(
|
// write!(
|
||||||
screen,
|
// screen,
|
||||||
"{frame}{hide_cursor}",
|
// "{frame}{hide_cursor}",
|
||||||
frame = env.frame.frame_str(&env.theme, env.theme.primary()),
|
// frame = env.frame.frame_str(&env.theme, env.theme.primary()),
|
||||||
hide_cursor = cursor::Hide,
|
// hide_cursor = cursor::Hide,
|
||||||
)?;
|
// )?;
|
||||||
screen.flush()?;
|
// screen.flush()?;
|
||||||
|
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
pub fn debug_append(s: String) {
|
||||||
|
std::process::Command::new("fish")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(format!("echo \"{}\" >> debug.log", s))
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
macro_rules! debug {
|
||||||
|
($fmt_string:expr, $($arg:tt)*) => {
|
||||||
|
$crate::display::debug::debug_append(
|
||||||
|
format!($fmt_string, $($arg)*)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub(crate) use debug;
|
|
@ -3,10 +3,12 @@ use termion::{clear, cursor};
|
||||||
const ESTIMATED_FRAME_BIT_SIZE: usize = 11;
|
const ESTIMATED_FRAME_BIT_SIZE: usize = 11;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
use crate::display::debug::debug;
|
||||||
|
|
||||||
use super::theme::Theme;
|
use super::theme::Theme;
|
||||||
|
|
||||||
const FRAME_CHAR_HORIZONTAL: char = 'h';
|
const FRAME_CHAR_HORIZONTAL: char = ' ';
|
||||||
const FRAME_CHAR_VERTICAL: char = 'v';
|
const FRAME_CHAR_VERTICAL: char = ' ';
|
||||||
|
|
||||||
pub enum FrameSize {
|
pub enum FrameSize {
|
||||||
ByAbsolute(u16, u16),
|
ByAbsolute(u16, u16),
|
||||||
|
@ -18,72 +20,100 @@ pub struct Frame {
|
||||||
// Both are (w, h)
|
// Both are (w, h)
|
||||||
start: (u16, u16),
|
start: (u16, u16),
|
||||||
end: (u16, u16),
|
end: (u16, u16),
|
||||||
|
width: u16,
|
||||||
|
theme: Theme,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn goto(&self, x: u16, y: u16) -> String {
|
pub fn goto(&self, x: u16, y: u16) -> String {
|
||||||
let cg = cursor::Goto(
|
let cg = cursor::Goto(
|
||||||
(self.start.0 + x).min(self.end.0 - 1),
|
(self.width + self.start.0 + x).min(self.end.0 - self.width),
|
||||||
(self.start.1 + y).min(self.end.1 - 1),
|
(self.width + self.start.1 + y).min(self.end.1 - self.width),
|
||||||
);
|
);
|
||||||
cg.into()
|
cg.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn goto_internal(&self, x: u16, y: u16) -> String {
|
||||||
|
cursor::Goto(
|
||||||
|
(self.start.0 + x).min(self.end.0),
|
||||||
|
(self.start.1 + y).min(self.end.1),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn writeln(&self, s: &str, x: u16, y: u16) -> String {
|
pub fn writeln(&self, s: &str, x: u16, y: u16) -> String {
|
||||||
let words = s.split('\n').collect::<Vec<&str>>();
|
let words = s.split('\n').collect::<Vec<&str>>();
|
||||||
let mut out_words = Vec::with_capacity(words.len());
|
let mut out_words = Vec::with_capacity(words.len());
|
||||||
for i in 0..words.len() {
|
for i in 0..words.len() {
|
||||||
out_words.push(format!(
|
out_words.push(format!(
|
||||||
"{str}{ret}",
|
"{ret}{str}",
|
||||||
str = words[i],
|
str = words[i],
|
||||||
ret = self.goto(1, y + i as u16 + 1)
|
ret = self.goto(x, y + i as u16),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
out_words.concat()
|
out_words.concat()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn size(&self) -> (u16, u16) {
|
pub fn size(&self) -> (u16, u16) {
|
||||||
(self.end.0 - self.start.0, self.end.1 - self.start.1)
|
(self.end.0 - self.start.0, self.end.1 - self.start.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_terminal_size() -> Result<Self, anyhow::Error> {
|
#[inline(always)]
|
||||||
|
pub fn from_terminal_size(theme: Theme, width: u16) -> Result<Self, anyhow::Error> {
|
||||||
let term = termion::terminal_size()?;
|
let term = termion::terminal_size()?;
|
||||||
// Swap term dimensions to use x/y
|
// Swap term dimensions to use x/y
|
||||||
let term = (term.1, term.0);
|
let term = (term.1, term.0);
|
||||||
Ok(Self::from_bottom_right(term, term))
|
Ok(Self::from_bottom_right(term, term, width, theme))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_bottom_right((pos_h, pos_w): (u16, u16), (term_h, term_w): (u16, u16)) -> Self {
|
#[inline(always)]
|
||||||
|
fn from_bottom_right(
|
||||||
|
(pos_h, pos_w): (u16, u16),
|
||||||
|
(term_h, term_w): (u16, u16),
|
||||||
|
width: u16,
|
||||||
|
theme: Theme,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
start: (1.max(term_w - pos_w), 1.max(term_h - pos_h)),
|
start: (1.max(term_w - pos_w), 1.max(term_h - pos_h)),
|
||||||
end: (pos_w, pos_h),
|
end: (pos_w, pos_h),
|
||||||
|
width,
|
||||||
|
theme,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame_str(&self, theme: &Theme, body_theme: String) -> String {
|
pub fn frame_str(&self, body_theme: String) -> String {
|
||||||
self.goto(0, 0);
|
if self.width == 0 {
|
||||||
|
return body_theme + &clear::All.to_string();
|
||||||
|
}
|
||||||
|
self.goto_internal(0, 0);
|
||||||
let (w_len, h_len) = self.size();
|
let (w_len, h_len) = self.size();
|
||||||
let width_str = FRAME_CHAR_HORIZONTAL.to_string().repeat(w_len as usize + 1);
|
let width_str = FRAME_CHAR_HORIZONTAL.to_string().repeat(w_len as usize + 1);
|
||||||
let mut frame = Vec::with_capacity(h_len as usize + 4);
|
let mut frame = Vec::with_capacity(h_len as usize + 4);
|
||||||
let frame_theme = theme.frame();
|
let frame_theme = self.theme.frame();
|
||||||
let body_clear = body_theme.clone() + &clear::CurrentLine.to_string();
|
let body_clear = body_theme.clone() + &clear::CurrentLine.to_string();
|
||||||
frame.push(frame_theme.clone());
|
frame.push(frame_theme.clone());
|
||||||
|
|
||||||
let make_line =
|
let make_line =
|
||||||
|y: u16| format!("{left}{}", width_str, left = cursor::Goto(self.start.0, y));
|
|y: u16| format!("{left}{}", width_str, left = cursor::Goto(self.start.0, y));
|
||||||
frame.push(make_line(self.start.1));
|
for y in 0..self.width {
|
||||||
for y in self.start.1 + 1..self.end.1 {
|
frame.push(make_line(self.start.1 + y));
|
||||||
|
}
|
||||||
|
for y in self.width + self.start.1..self.end.1 - self.width {
|
||||||
frame.push(format!(
|
frame.push(format!(
|
||||||
"{left}{body_clear}{frame_theme}{char}{right}{char}",
|
"{left}{body_clear}{frame_theme}{char}{right}{char}",
|
||||||
body_clear = &body_clear,
|
body_clear = &body_clear,
|
||||||
frame_theme = &frame_theme,
|
frame_theme = &frame_theme,
|
||||||
left = cursor::Goto(self.start.0, y),
|
left = cursor::Goto(self.start.0, y),
|
||||||
right = cursor::Goto(self.start.0 + self.end.0, y),
|
right = cursor::Goto(self.start.0 + self.end.0 - self.width, y),
|
||||||
char = FRAME_CHAR_VERTICAL,
|
char = FRAME_CHAR_VERTICAL.to_string().repeat(self.width as usize),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
for y in self.end.1 - self.width - 1..self.end.1 {
|
||||||
|
frame.push(make_line(self.start.1 + y));
|
||||||
|
}
|
||||||
frame.push(make_line(self.end.1));
|
frame.push(make_line(self.end.1));
|
||||||
frame.push(self.goto(1, 1));
|
frame.push(self.goto(1, 1));
|
||||||
frame.push(body_theme);
|
frame.push(body_theme);
|
||||||
|
@ -92,7 +122,8 @@ impl Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FrameSize {
|
impl FrameSize {
|
||||||
fn abs_size(&self) -> Frame {
|
#[inline(always)]
|
||||||
|
fn abs_size(&self, theme: Theme, width: u16) -> Frame {
|
||||||
let (term_height, term_width) =
|
let (term_height, term_width) =
|
||||||
termion::terminal_size().expect("could not get terminal size");
|
termion::terminal_size().expect("could not get terminal size");
|
||||||
let pos = match self {
|
let pos = match self {
|
||||||
|
@ -108,6 +139,6 @@ impl FrameSize {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Frame::from_bottom_right(pos, (term_height, term_width))
|
Frame::from_bottom_right(pos, (term_height, term_width), width, theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use self::frame::Frame;
|
||||||
use self::theme::{Color, Theme};
|
use self::theme::{Color, Theme};
|
||||||
|
|
||||||
pub mod body;
|
pub mod body;
|
||||||
|
pub mod debug;
|
||||||
pub mod frame;
|
pub mod frame;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
type Result<T> = std::result::Result<T, anyhow::Error>;
|
type Result<T> = std::result::Result<T, anyhow::Error>;
|
||||||
|
@ -66,7 +67,7 @@ impl Into<String> for Environment {
|
||||||
fn into(self) -> String {
|
fn into(self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{frame}{theme}",
|
"{frame}{theme}",
|
||||||
frame = self.frame.frame_str(&self.theme, self.theme.primary()),
|
frame = self.frame.frame_str(self.theme.primary()),
|
||||||
theme = self.theme.primary(),
|
theme = self.theme.primary(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -74,15 +75,18 @@ impl Into<String> for Environment {
|
||||||
|
|
||||||
impl Environment {
|
impl Environment {
|
||||||
fn initial_must(theme: Theme) -> Self {
|
fn initial_must(theme: Theme) -> Self {
|
||||||
|
let w: u16 = std::env::var("FRAME_WIDTH")
|
||||||
|
.map(|f| f.parse().unwrap_or(1))
|
||||||
|
.unwrap_or(1);
|
||||||
Self {
|
Self {
|
||||||
theme,
|
theme,
|
||||||
frame: Frame::from_terminal_size().expect("could not get terminal size"),
|
frame: Frame::from_terminal_size(theme, w).expect("could not get terminal size"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn primary_frame(&self) -> String {
|
pub fn primary_frame(&self) -> String {
|
||||||
self.frame.frame_str(&self.theme, self.theme.primary())
|
self.frame.frame_str(self.theme.primary())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +137,7 @@ impl Screen {
|
||||||
clear = clear::All,
|
clear = clear::All,
|
||||||
show_cursor = cursor::Show,
|
show_cursor = cursor::Show,
|
||||||
)?;
|
)?;
|
||||||
|
scr.flush();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue