summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorJiayi Zhao <jeff.no.zhao@gmail.com>2020-02-16 15:45:05 -0500
committerJiayi Zhao <jeff.no.zhao@gmail.com>2020-02-16 15:50:25 -0500
commit98d0ce7e70f9febf804cda7473f5e9f7f180fe91 (patch)
treec8c8dd60d9e6502202b910e64f79cd75b933d05d /src/ui
parentd788f8d740be85bb014ddfa005156723f0a31e99 (diff)
remove ncurses dependency
- clean up code - update theme config - fix localstate tracking file selection not selecting proper files
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/mod.rs2
-rw-r--r--src/ui/ncurses_backend.rs464
-rw-r--r--src/ui/tui_backend.rs4
-rw-r--r--src/ui/widgets/tui_dirlist.rs7
4 files changed, 5 insertions, 472 deletions
diff --git a/src/ui/mod.rs b/src/ui/mod.rs
index e250d20..74f080d 100644
--- a/src/ui/mod.rs
+++ b/src/ui/mod.rs
@@ -1,6 +1,4 @@
-mod ncurses_backend;
mod tui_backend;
pub mod widgets;
-pub use ncurses_backend::*;
pub use tui_backend::*;
diff --git a/src/ui/ncurses_backend.rs b/src/ui/ncurses_backend.rs
deleted file mode 100644
index a55aa9f..0000000
--- a/src/ui/ncurses_backend.rs
+++ /dev/null
@@ -1,464 +0,0 @@
-use crate::config::{JoshutoColorTheme, JoshutoConfig};
-use crate::context::JoshutoContext;
-use crate::fs::{JoshutoDirEntry, JoshutoDirList};
-use crate::unix;
-use crate::window;
-
-use crate::THEME_T;
-
-use std::fs;
-use std::sync::Mutex;
-use std::time;
-
-use lazy_static::lazy_static;
-use users::mock::{Groups, Users};
-use users::UsersCache;
-
-pub const ERR_COLOR: i16 = 240;
-pub const EMPTY_COLOR: i16 = 241;
-
-const MIN_WIN_WIDTH: usize = 4;
-
-pub struct DisplayOptions {
- pub detailed: bool,
-}
-
-pub const PRIMARY_DISPLAY_OPTION: DisplayOptions = DisplayOptions { detailed: true };
-pub const SECONDARY_DISPLAY_OPTION: DisplayOptions = DisplayOptions { detailed: false };
-
-pub fn init_ncurses() {
- ncurses::setlocale(ncurses::LcCategory::all, "");
-
- ncurses::initscr();
- ncurses::cbreak();
-
- ncurses::start_color();
- ncurses::use_default_colors();
- ncurses::noecho();
- ncurses::set_escdelay(0);
- ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE);
-
- process_theme();
-
- ncurses::addstr("Loading...");
- ncurses::refresh();
-}
-
-fn process_theme() {
- for pair in THEME_T.colorpair.iter() {
- ncurses::init_pair(pair.id, pair.fg, pair.bg);
- }
-
- /* error message */
- ncurses::init_pair(ERR_COLOR, ncurses::COLOR_RED, -1);
- /* empty */
- ncurses::init_pair(EMPTY_COLOR, ncurses::COLOR_WHITE, ncurses::COLOR_RED);
-}
-
-pub fn end_ncurses() {
- ncurses::endwin();
-}
-
-pub fn getmaxyx() -> (i32, i32) {
- let mut term_rows: i32 = 0;
- let mut term_cols: i32 = 0;
- ncurses::getmaxyx(ncurses::stdscr(), &mut term_rows, &mut term_cols);
- (term_rows, term_cols)
-}
-
-pub fn display_menu<I, S>(win: &window::JoshutoPanel, items: I)
-where
- I: IntoIterator<Item = S>,
- S: AsRef<str>,
-{
- ncurses::werase(win.win);
- ncurses::mvwhline(win.win, 0, 0, 0, win.cols);
-
- for (i, val) in items.into_iter().enumerate() {
- ncurses::wmove(win.win, (i + 1) as i32, 0);
- ncurses::waddstr(win.win, val.as_ref());
- }
- ncurses::wnoutrefresh(win.win);
-}
-
-pub fn wprint_msg(win: &window::JoshutoPanel, msg: &str) {
- ncurses::werase(win.win);
- ncurses::mvwaddstr(win.win, 0, 0, msg);
- ncurses::wnoutrefresh(win.win);
-}
-
-pub fn wprint_err(win: &window::JoshutoPanel, msg: &str) {
- let attr = ncurses::A_BOLD() | ncurses::COLOR_PAIR(ERR_COLOR);
-
- ncurses::werase(win.win);
- ncurses::wattron(win.win, attr);
-
- ncurses::mvwaddstr(win.win, 0, 0, msg);
-
- ncurses::wattroff(win.win, attr);
- ncurses::wnoutrefresh(win.win);
-}
-
-pub fn wprint_empty(win: &window::JoshutoPanel, msg: &str) {
- ncurses::werase(win.win);
- ncurses::wattron(win.win, ncurses::COLOR_PAIR(EMPTY_COLOR));
- ncurses::mvwaddstr(win.win, 0, 0, msg);
- ncurses::wattroff(win.win, ncurses::COLOR_PAIR(EMPTY_COLOR));
- ncurses::wnoutrefresh(win.win);
-}
-
-fn wprint_file_name(
- win: &window::JoshutoPanel,
- file_name: &str,
- coord: (i32, i32),
- mut space_avail: usize,
-) {
- let name_visual_space = unicode_width::UnicodeWidthStr::width(file_name);
- if name_visual_space < space_avail {
- ncurses::mvwaddstr(win.win, coord.0, coord.1, &file_name);
- return;
- }
- if let Some(ext) = file_name.rfind('.') {
- let extension: &str = &file_name[ext..];
- let ext_len = unicode_width::UnicodeWidthStr::width(extension);
- if space_avail > ext_len {
- space_avail -= ext_len;
- ncurses::mvwaddstr(win.win, coord.0, space_avail as i32, &extension);
- }
- }
- if space_avail < 2 {
- return;
- } else {
- space_avail -= 2;
- }
-
- ncurses::wmove(win.win, coord.0, coord.1);
-
- let mut trim_index: usize = file_name.len();
-
- let mut total: usize = 0;
- for (index, ch) in file_name.char_indices() {
- if total >= space_avail {
- trim_index = index;
- break;
- }
- total += unicode_width::UnicodeWidthChar::width(ch).unwrap_or(2);
- }
- ncurses::waddstr(win.win, &file_name[..trim_index]);
- ncurses::waddstr(win.win, "…");
-}
-
-fn wprint_entry(
- win: &window::JoshutoPanel,
- file: &JoshutoDirEntry,
- prefix: (usize, &str),
- coord: (i32, i32),
-) {
- if win.cols <= prefix.0 as i32 {
- return;
- }
- ncurses::waddstr(win.win, prefix.1);
- let space_avail = win.cols as usize - prefix.0;
-
- wprint_file_name(
- &win,
- file.file_name(),
- (coord.0, coord.1 + prefix.0 as i32),
- space_avail,
- );
-}
-
-fn wprint_entry_detailed(
- win: &window::JoshutoPanel,
- file: &JoshutoDirEntry,
- prefix: (usize, &str),
- coord: (i32, i32),
-) {
- if win.cols <= prefix.0 as i32 {
- return;
- }
- ncurses::waddstr(win.win, prefix.1);
- let mut space_avail = win.cols as usize - prefix.0;
-
- let coord = (coord.0, coord.1 + prefix.0 as i32);
-
- if file.file_path().is_dir() {
- } else {
- let file_size_string = file_size_to_string(file.metadata.len as f64);
- if space_avail > file_size_string.len() {
- space_avail -= file_size_string.len();
- ncurses::mvwaddstr(win.win, coord.0, space_avail as i32, &file_size_string);
- }
- }
- wprint_file_name(win, file.file_name(), coord, space_avail);
-}
-
-pub fn display_contents(
- win: &window::JoshutoPanel,
- dirlist: &mut JoshutoDirList,
- config_t: &JoshutoConfig,
- options: &DisplayOptions,
-) {
- if win.cols < MIN_WIN_WIDTH as i32 {
- return;
- }
- let dir_len = dirlist.contents.len();
- if dir_len == 0 {
- wprint_empty(win, "empty");
- return;
- }
- ncurses::werase(win.win);
- ncurses::wmove(win.win, 0, 0);
-
- let draw_func = if options.detailed {
- wprint_entry_detailed
- } else {
- wprint_entry
- };
-
- let curr_index = dirlist.index.unwrap();
- dirlist
- .pagestate
- .update_page_state(curr_index, win.rows, dir_len, config_t.scroll_offset);
-
- let (start, end) = (dirlist.pagestate.start, dirlist.pagestate.end);
- let dir_contents = &dirlist.contents[start..end];
-
- ncurses::werase(win.win);
- ncurses::wmove(win.win, 0, 0);
-
- for (i, entry) in dir_contents.iter().enumerate() {
- let coord: (i32, i32) = (i as i32, 0);
-
- ncurses::wmove(win.win, coord.0, coord.1);
-
- let attr = if i + start == curr_index {
- ncurses::A_STANDOUT()
- } else {
- 0
- };
- let attrs = get_theme_attr(attr, entry);
-
- draw_func(win, entry, attrs.0, coord);
-
- ncurses::mvwchgat(win.win, coord.0, coord.1, -1, attrs.1, attrs.2);
- }
- win.queue_for_refresh();
-}
-
-lazy_static! {
- static ref USERCACHE: Mutex<UsersCache> = Mutex::new(UsersCache::new());
-}
-
-pub fn wprint_file_status(
- win: &window::JoshutoPanel,
- entry: &JoshutoDirEntry,
- index: usize,
- len: usize,
-) {
- wprint_file_mode(win.win, entry);
-
- ncurses::waddch(win.win, ' ' as ncurses::chtype);
- ncurses::waddstr(win.win, &format!("{}/{} ", index + 1, len));
-
- let usercache = USERCACHE.lock().unwrap();
-
- match usercache.get_user_by_uid(entry.metadata.uid) {
- Some(s) => match s.name().to_str() {
- Some(name) => ncurses::waddstr(win.win, name),
- None => ncurses::waddstr(win.win, "OsStr error"),
- },
- None => ncurses::waddstr(win.win, "unknown user"),
- };
- ncurses::waddch(win.win, ' ' as ncurses::chtype);
- match usercache.get_group_by_gid(entry.metadata.gid) {
- Some(s) => match s.name().to_str() {
- Some(name) => ncurses::waddstr(win.win, name),
- None => ncurses::waddstr(win.win, "OsStr error"),
- },
- None => ncurses::waddstr(win.win, "unknown user"),
- };
-
- ncurses::waddstr(win.win, " ");
- wprint_file_info(win.win, entry);
- win.queue_for_refresh();
-}
-
-pub fn wprint_file_mode(win: ncurses::WINDOW, file: &JoshutoDirEntry) {
- use std::os::unix::fs::PermissionsExt;
-
- let mode = file.metadata.permissions.mode();
-
- ncurses::wattron(win, ncurses::COLOR_PAIR(6));
- ncurses::waddstr(win, unix::stringify_mode(mode).as_str());
- ncurses::wattroff(win, ncurses::COLOR_PAIR(6));
-}
-
-pub fn wprint_file_info(win: ncurses::WINDOW, file: &JoshutoDirEntry) {
- #[cfg(unix)]
- {
- use std::os::unix::fs::PermissionsExt;
-
- let mode = file.metadata.permissions.mode();
-
- let mtime_string = file_mtime_to_string(file.metadata.modified);
- ncurses::waddstr(win, &mtime_string);
- ncurses::waddch(win, ' ' as ncurses::chtype);
-
- if file.file_path().is_dir() {
- let is_link: u32 = libc::S_IFLNK as u32;
- if mode >> 9 & is_link >> 9 == mode >> 9 {
- if let Ok(path) = fs::read_link(&file.file_path()) {
- ncurses::waddstr(win, " -> ");
- ncurses::waddstr(win, path.to_str().unwrap());
- }
- }
- } else {
- let file_size_string = file_size_to_string_detailed(file.metadata.len as f64);
- ncurses::waddstr(win, &file_size_string);
- }
-
- /*
- ncurses::waddstr(win, " ");
- if let Some(s) = tree_magic::from_filepath(&file.file_path()) {
- ncurses::waddstr(win, &s);
- }
- */
- }
-}
-
-pub fn redraw_tab_view(win: &window::JoshutoPanel, context: &JoshutoContext) {
- let tab_len = context.tabs.len();
- ncurses::werase(win.win);
- if tab_len == 1 {
- } else if tab_len >= 6 {
- ncurses::wmove(win.win, 0, 0);
- ncurses::wattron(win.win, ncurses::A_BOLD() | ncurses::A_STANDOUT());
- ncurses::waddstr(win.win, &format!("{}", context.curr_tab_index + 1));
- ncurses::wattroff(win.win, ncurses::A_STANDOUT());
- ncurses::waddstr(win.win, &format!(" {}", tab_len));
- ncurses::wattroff(win.win, ncurses::A_BOLD());
- } else {
- ncurses::wattron(win.win, ncurses::A_BOLD());
- for i in 0..tab_len {
- if i == context.curr_tab_index {
- ncurses::wattron(win.win, ncurses::A_STANDOUT());
- ncurses::waddstr(win.win, &format!("{} ", i + 1));
- ncurses::wattroff(win.win, ncurses::A_STANDOUT());
- } else {
- ncurses::waddstr(win.win, &format!("{} ", i + 1));
- }
- }
- ncurses::wattroff(win.win, ncurses::A_BOLD());
- }
- ncurses::wnoutrefresh(win.win);
-}
-
-pub fn get_theme_attr(
- mut attr: ncurses::attr_t,
- entry: &JoshutoDirEntry,
-) -> ((usize, &str), ncurses::attr_t, i16) {
- use std::os::unix::fs::FileTypeExt;
- use std::os::unix::fs::PermissionsExt;
-
- let theme: &JoshutoColorTheme;
- let colorpair: i16;
-
- let file_type = &entry.metadata.file_type;
- if entry.is_selected() {
- theme = &THEME_T.selection;
- colorpair = THEME_T.selection.colorpair;
- } else if file_type.is_dir() {
- theme = &THEME_T.directory;
- colorpair = THEME_T.directory.colorpair;
- } else if file_type.is_symlink() {
- theme = &THEME_T.link;
- colorpair = THEME_T.link.colorpair;
- } else if file_type.is_block_device()
- || file_type.is_char_device()
- || file_type.is_fifo()
- || file_type.is_socket()
- {
- theme = &THEME_T.socket;
- colorpair = THEME_T.link.colorpair;
- } else {
- let mode = entry.metadata.permissions.mode();
- if unix::is_executable(mode) {
- theme = &THEME_T.executable;
- colorpair = THEME_T.executable.colorpair;
- } else if let Some(ext) = entry.file_name().rfind('.') {
- let extension: &str = &entry.file_name()[ext + 1..];
- if let Some(s) = THEME_T.ext.get(extension) {
- theme = &s;
- colorpair = theme.colorpair;
- } else {
- theme = &THEME_T.regular;
- colorpair = theme.colorpair;
- }
- } else {
- theme = &THEME_T.regular;
- colorpair = theme.colorpair;
- }
- }
-
- if theme.bold {
- attr |= ncurses::A_BOLD();
- }
- if theme.underline {
- attr |= ncurses::A_UNDERLINE();
- }
-
- let prefix = match theme.prefix.as_ref() {
- Some(p) => (p.size(), p.prefix()),
- None => (1, " "),
- };
-
- (prefix, attr, colorpair)
-}
-
-fn file_size_to_string_detailed(mut file_size: f64) -> String {
- const FILE_UNITS: [&str; 6] = ["B", "KB", "MB", "GB", "TB", "EB"];
- const CONV_RATE: f64 = 1024.0;
-
- let mut index = 0;
- while file_size > CONV_RATE {
- file_size /= CONV_RATE;
- index += 1;
- }
-
- if file_size >= 1000.0 {
- format!("{:.0}{}", file_size, FILE_UNITS[index])
- } else if file_size >= 100.0 {
- format!(" {:.0}{}", file_size, FILE_UNITS[index])
- } else if file_size >= 10.0 {
- format!("{:.1}{}", file_size, FILE_UNITS[index])
- } else {
- format!("{:.2}{}", file_size, FILE_UNITS[index])
- }
-}
-
-fn file_mtime_to_string(mtime: time::SystemTime) -> String {
- const MTIME_FORMATTING: &str = "%Y-%m-%d %H:%M";
-
- let datetime: chrono::DateTime<chrono::offset::Utc> = mtime.into();
- datetime.format(MTIME_FORMATTING).to_string()
-}
-
-fn file_size_to_string(mut file_size: f64) -> String {
- const FILE_UNITS: [&str; 6] = ["B", "K", "M", "G", "T", "E"];
- const CONV_RATE: f64 = 1024.0;
-
- let mut index = 0;
- while file_size > CONV_RATE {
- file_size /= CONV_RATE;
- index += 1;
- }
-
- if file_size >= 100.0 {
- format!(" {:.0} {}", file_size, FILE_UNITS[index])
- } else if file_size >= 10.0 {
- format!(" {:.1} {}", file_size, FILE_UNITS[index])
- } else {
- format!(" {:.2} {}", file_size, FILE_UNITS[index])
- }
-}
diff --git a/src/ui/tui_backend.rs b/src/ui/tui_backend.rs
index b5afced..fa923a2 100644
--- a/src/ui/tui_backend.rs
+++ b/src/ui/tui_backend.rs
@@ -6,7 +6,7 @@ use termion::event::Key;
use termion::input::TermRead;
use termion::raw::{IntoRawMode, RawTerminal};
use termion::screen::AlternateScreen;
-use tui::backend::{Backend, TermionBackend};
+use tui::backend::TermionBackend;
use tui::layout::{Constraint, Direction, Layout, Rect};
use tui::style::{Color, Style};
use tui::widgets::{Block, Borders, List, Paragraph, SelectableList, Text, Widget};
@@ -77,5 +77,3 @@ impl TuiBackend {
});
}
}
-
-pub fn rerender(context: &mut JoshutoContext) {}
diff --git a/src/ui/widgets/tui_dirlist.rs b/src/ui/widgets/tui_dirlist.rs
index e2ba9a6..83891b4 100644
--- a/src/ui/widgets/tui_dirlist.rs
+++ b/src/ui/widgets/tui_dirlist.rs
@@ -2,8 +2,8 @@ use std::io::{self, Write};
use tui::buffer::Buffer;
use tui::layout::Rect;
-use tui::style::{Modifier, Style};
-use tui::widgets::{Block, Text, Widget};
+use tui::style::{Color, Modifier, Style};
+use tui::widgets::Widget;
use crate::fs::JoshutoDirList;
/*
@@ -97,7 +97,8 @@ impl<'a> Widget for TuiDirList<'a> {
let dir_len = self.dirlist.contents.len();
if dir_len == 0 {
- buf.set_stringn(x, y, "empty", area.width as usize, Style::default());
+ let style = Style::default().bg(Color::Red).fg(Color::White);
+ buf.set_stringn(x, y, "empty", area.width as usize, style);
return;
}