diff options
author | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-02-16 15:45:05 -0500 |
---|---|---|
committer | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-02-16 15:50:25 -0500 |
commit | 98d0ce7e70f9febf804cda7473f5e9f7f180fe91 (patch) | |
tree | c8c8dd60d9e6502202b910e64f79cd75b933d05d /src/ui | |
parent | d788f8d740be85bb014ddfa005156723f0a31e99 (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.rs | 2 | ||||
-rw-r--r-- | src/ui/ncurses_backend.rs | 464 | ||||
-rw-r--r-- | src/ui/tui_backend.rs | 4 | ||||
-rw-r--r-- | src/ui/widgets/tui_dirlist.rs | 7 |
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; } |