diff --git a/src/constants.rs b/src/constants.rs new file mode 100644 index 0000000..2ceca23 --- /dev/null +++ b/src/constants.rs @@ -0,0 +1,43 @@ +use crate::*; + +pub(crate) const PAGE_SIZE: usize = 10; + +macro_rules! bytes { + ($name:ident $value:expr) => { pub(crate) const $name: &'static [u8] = $value; } +} +macro_rules! string { + ($name:ident $value:expr) => { pub(crate) const $name: &'static str = $value; } +} +macro_rules! color { + ($name:ident $value:expr) => { pub(crate) const $name: Color = $value; } +} + +bytes!(MAGIC_PNG &[0x89, b'P', b'N', b'G', 0x0D, 0x0A, 0x1A, 0x0A]); +bytes!(MAGIC_JPG_1 &[0xFF, 0xD8, 0xFF, 0xDB]); +bytes!(MAGIC_JPG_2 &[0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01]); +bytes!(MAGIC_JPG_3 &[0xFF, 0xD8, 0xFF, 0xEE]); +bytes!(MAGIC_JPG_4A &[0xFF, 0xD8, 0xFF, 0xE1]); + +string!(ICON_DIRECTORY ""); +string!(ICON_IMAGE "󰋩"); +string!(ICON_MUSIC ""); +string!(ICON_MUSIC_NO_META "󰎇"); +string!(ICON_UNKNOWN ""); +string!(ICON_SCROLL_LEFT "❮"); +string!(ICON_SCROLL_RIGHT "❯"); + +color!(FG_MODAL Color::Rgb(255, 255, 255)); +color!(BG_MODAL Color::Rgb(0, 0, 0)); +color!(FG_BROWSE Color::Rgb(255, 192, 0)); +color!(BG_COLUMN Color::Rgb(0, 0, 0)); +color!(FG_ROW Color::Rgb(0, 0, 0)); +color!(BG_ROW Color::Rgb(192, 128, 0)); +color!(BG_CELL Color::Rgb(224, 192, 0)); +color!(FG_CELL Color::Rgb(255, 255, 255)); +color!(BG_EDIT Color::Rgb(48, 96, 0)); +color!(FG_EDIT Color::Rgb(255, 255, 255)); +color!(BG_BROWSE Color::Rgb(0, 0, 0)); +color!(BG_SAVE Color::Rgb(192, 96, 0)); +color!(FG_SAVE Color::Rgb(255, 255, 255)); +color!(BG_QUIT Color::Rgb(128, 0, 0)); +color!(FG_QUIT Color::Rgb(255, 255, 255)); diff --git a/src/main.rs b/src/main.rs index 2f15b80..bc4097d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,12 +18,11 @@ use xxhash_rust::xxh3::xxh3_64; mod keys; mod view; use self::view::*; mod model; pub(crate) use self::model::*; +mod constants; pub(crate) use self::constants::*; pub(crate) type Usually = std::result::Result>; pub(crate) type Perhaps = Usually>; -pub(crate) const PAGE_SIZE: usize = 10; - fn cli () -> clap::Command { command!() .arg(arg!([path] "Path to root directory") diff --git a/src/model/column.rs b/src/model/column.rs index 57c8c9f..798d8c1 100644 --- a/src/model/column.rs +++ b/src/model/column.rs @@ -58,11 +58,6 @@ pub(crate) fn entries_under ( pub struct Columns(pub Vec>); -impl Columns { - const SCROLL_LEFT: &'static str = "❮"; - const SCROLL_RIGHT: &'static str = "❯"; -} - macro_rules! setter { ($set:ident) => {{ fn $set (state: &mut Taggart, index: usize, value: &str) { diff --git a/src/model/entry.rs b/src/model/entry.rs index b11a14a..b1ce316 100644 --- a/src/model/entry.rs +++ b/src/model/entry.rs @@ -20,11 +20,6 @@ pub struct Entry { } impl Entry { - pub const ICON_DIRECTORY: &'static str = ""; - pub const ICON_IMAGE: &'static str = "󰋩"; - pub const ICON_MUSIC: &'static str = ""; - pub const ICON_MUSIC_NO_META: &'static str = "󰎇"; - pub const ICON_UNKNOWN: &'static str = ""; pub fn new (root: &impl AsRef, path: &impl AsRef, depth: usize) -> Perhaps { let path = path.as_ref(); if path.is_dir() { @@ -71,13 +66,13 @@ impl Entry { } fn icon (&self) -> &'static str { if self.is_directory() { - Self::ICON_DIRECTORY + ICON_DIRECTORY } else if self.is_image() { - Self::ICON_IMAGE + ICON_IMAGE } else if self.is_music() { - Self::ICON_MUSIC + ICON_MUSIC } else { - Self::ICON_UNKNOWN + ICON_UNKNOWN } } pub fn is_modified (&self) -> bool { @@ -156,7 +151,7 @@ impl Metadata { let mut bytes = vec![0;16]; reader.read(&mut bytes)?; // PNG - if bytes.starts_with(&[0x89, b'P', b'N', b'G', 0x0D, 0x0A, 0x1A, 0x0A]) { + if bytes.starts_with(MAGIC_PNG) { let mut bytes = vec![]; BufReader::new(File::open(path)?).read(&mut bytes)?; return Ok(Self::Image { @@ -168,12 +163,10 @@ impl Metadata { }) } // JPG - if bytes.starts_with(&[0xFF, 0xD8, 0xFF, 0xDB]) - || bytes.starts_with(&[0xFF, 0xD8, 0xFF, 0xE0, - 0x00, 0x10, 0x4A, 0x46, - 0x49, 0x46, 0x00, 0x01]) - || bytes.starts_with(&[0xFF, 0xD8, 0xFF, 0xEE]) - || (bytes.starts_with(&[0xFF, 0xD8, 0xFF, 0xE1]) && + if bytes.starts_with(MAGIC_JPG_1) + || bytes.starts_with(MAGIC_JPG_2) + || bytes.starts_with(MAGIC_JPG_3) + || (bytes.starts_with(MAGIC_JPG_4A) && bytes.get(6) == Some(&0x45) && bytes.get(7) == Some(&0x78) && bytes.get(8) == Some(&0x69) && bytes.get(9) == Some(&0x66) && bytes.get(10) == Some(&0x00) && bytes.get(11) == Some(&0x00)) diff --git a/src/view/dialog.rs b/src/view/dialog.rs index 9ea0cac..447b86c 100644 --- a/src/view/dialog.rs +++ b/src/view/dialog.rs @@ -1,11 +1,9 @@ use crate::*; impl Taggart { - pub(crate) const FG_MODAL: Color = Color::Rgb(255, 255, 255); - pub(crate) const BG_MODAL: Color = Color::Rgb(0, 0, 0); fn dialog (content: impl Content) -> impl Content { let pos = |x|Fill::xy( Align::c(x)); - let style = |x|Tui::modify(false, Modifier::DIM, Tui::fg_bg(Self::FG_MODAL, Self::BG_MODAL, x)); + let style = |x|Tui::modify(false, Modifier::DIM, Tui::fg_bg(FG_MODAL, BG_MODAL, x)); let border = |x|Margin::xy(1, 1, Bsp::b(Border(true, Lozenge(true, Default::default())), x)); let bg = |x|Bsp::a(x, Repeat(" ")); pos(style(border(bg(content)))) diff --git a/src/view/status.rs b/src/view/status.rs index 55b8e89..28ec093 100644 --- a/src/view/status.rs +++ b/src/view/status.rs @@ -1,14 +1,6 @@ use crate::*; impl Taggart { - pub(crate) const FG_BROWSE: Color = Color::Rgb(255, 192, 0); - pub(crate) const BG_BROWSE: Color = Color::Rgb(0, 0, 0); - pub(crate) const BG_EDIT: Color = Color::Rgb(48, 128, 0); - pub(crate) const FG_EDIT: Color = Color::Rgb(255, 255, 255); - pub(crate) const BG_SAVE: Color = Color::Rgb(192, 96, 0); - pub(crate) const FG_SAVE: Color = Color::Rgb(255, 255, 255); - pub(crate) const BG_QUIT: Color = Color::Rgb(128, 0, 0); - pub(crate) const FG_QUIT: Color = Color::Rgb(255, 255, 255); pub(crate) fn title_bar (&self) -> impl Content { status_bar( Color::Rgb(0, 0, 0), @@ -40,10 +32,10 @@ impl Taggart { } pub(crate) fn mode_bar (&self, size: String) -> impl Content { let mode = match self.mode { - Some(Mode::Save { .. }) => Tui::bg(Self::BG_SAVE, Tui::fg(Self::FG_SAVE, " SAVE ")), - Some(Mode::Quit { .. }) => Tui::bg(Self::BG_QUIT, Tui::fg(Self::FG_QUIT, " QUIT ")), - Some(Mode::Edit { .. }) => Tui::bg(Self::BG_EDIT, Tui::fg(Self::FG_EDIT, " EDIT ")), - _ => Tui::bg(Self::BG_BROWSE, Tui::fg(Self::FG_BROWSE, " BROWSE ")) + Some(Mode::Save { .. }) => Tui::bg(BG_SAVE, Tui::fg(FG_SAVE, " SAVE ")), + Some(Mode::Quit { .. }) => Tui::bg(BG_QUIT, Tui::fg(FG_QUIT, " QUIT ")), + Some(Mode::Edit { .. }) => Tui::bg(BG_EDIT, Tui::fg(FG_EDIT, " EDIT ")), + _ => Tui::bg(BG_BROWSE, Tui::fg(FG_BROWSE, " BROWSE ")) }; let help = match self.mode { Some(Mode::Save { .. }) => " Esc: cancel, Arrows: select, Enter: confirm", diff --git a/src/view/table.rs b/src/view/table.rs index 1b477c9..cdf04dc 100644 --- a/src/view/table.rs +++ b/src/view/table.rs @@ -14,13 +14,6 @@ impl<'a> Content for TreeTable<'a> { } impl<'a> TreeTable<'a> { - pub(crate) const BG_COLUMN: Color = Color::Rgb(0, 0, 0); - pub(crate) const FG_ROW: Color = Color::Rgb(0, 0, 0); - pub(crate) const BG_ROW: Color = Color::Rgb(192, 128, 0); - pub(crate) const BG_CELL: Color = Color::Rgb(224, 192, 0); - pub(crate) const FG_CELL: Color = Color::Rgb(255, 255, 255); - pub(crate) const BG_EDIT: Color = Color::Rgb(48, 96, 0); - pub(crate) const FG_EDIT: Color = Color::Rgb(255, 255, 255); fn rows (&self, to: &mut TuiOut, area: [u16;4], active_x: u16, active_w: u16) { for (row_index, row_y) in area.iter_y().enumerate() { let row_index_scrolled = row_index + self.0.offset; @@ -44,16 +37,16 @@ impl<'a> TreeTable<'a> { } } fn column_cursor (to: &mut TuiOut, area: [u16;4], active_x: u16, active_w: u16) { - to.fill_bg([area.x() + active_x, area.y(), active_w, area.h()], Self::BG_COLUMN); + to.fill_bg([area.x() + active_x, area.y(), active_w, area.h()], BG_COLUMN); } fn row_cursor (to: &mut TuiOut, x: u16, y: u16, w: u16) { let fill = [x, y, w, 1]; - to.fill_fg(fill, Self::FG_ROW); - to.fill_bg(fill, Self::BG_ROW); + to.fill_fg(fill, FG_ROW); + to.fill_bg(fill, BG_ROW); } fn cell_cursor (&self, to: &mut TuiOut, xa: u16, x0: u16, y: u16, w: u16) { let fill = [xa + x0, y, w, 1]; - to.fill_bg(fill, Self::BG_CELL); + to.fill_bg(fill, BG_CELL); } fn row_data (&self, to: &mut TuiOut, entry: &Entry, cursor: usize, x: &mut u16) { let y = to.area().y(); @@ -65,14 +58,14 @@ impl<'a> TreeTable<'a> { && self.0.column == column_index && self.0.cursor == cursor { - to.fill_bg([*x, y, width as u16, 1], Self::BG_EDIT); - to.fill_fg([*x, y, width as u16, 1], Self::FG_EDIT); + to.fill_bg([*x, y, width as u16, 1], BG_EDIT); + to.fill_fg([*x, y, width as u16, 1], FG_EDIT); to.fill_reversed([*x + *edit_index as u16, y, 1, 1], true); Content::render(&TrimStringRef(width as u16, &value), to); } else if let Some(value) = getter(entry) { Content::render(&TrimStringRef(width as u16, &value), to); if self.0.cursor != cursor { - to.fill_fg([*x, y, width as u16, 1], Self::FG_CELL); + to.fill_fg([*x, y, width as u16, 1], FG_CELL); } } *x += width as u16 + 1;