use std::path; use crate::context::AppContext; use crate::error::{AppError, AppErrorKind, AppResult}; use crate::ui::AppBackend; pub fn lazy_load_directory_size(context: &mut AppContext) { let directory_size = match context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .and_then(|l| l.curr_entry_ref()) { Some(curr_entry) => { if let Some(size) = curr_entry.metadata.directory_size() { let history = context.tab_context_ref().curr_tab_ref().history_ref(); match history.get(curr_entry.file_path()).map(|d| d.len()) { Some(len) if size != len => Some(len), _ => None, } } else if !curr_entry.metadata.file_type().is_dir() { None } else { let history = context.tab_context_ref().curr_tab_ref().history_ref(); history.get(curr_entry.file_path()).map(|d| d.len()) } } None => None, }; if let Some(s) = directory_size { if let Some(curr_entry) = context .tab_context_mut() .curr_tab_mut() .curr_list_mut() .and_then(|l| l.curr_entry_mut()) { curr_entry.metadata.update_directory_size(s); } } } pub fn cursor_move(context: &mut AppContext, new_index: usize) { lazy_load_directory_size(context); let mut new_index = new_index; let ui_context = context.ui_context_ref().clone(); let display_options = context.config_ref().display_options_ref().clone(); if let Some(curr_list) = context.tab_context_mut().curr_tab_mut().curr_list_mut() { if !curr_list.is_empty() { let dir_len = curr_list.len(); if new_index >= dir_len { new_index = dir_len - 1; } curr_list.set_index(Some(new_index), &ui_context, &display_options); } } } pub fn to_path(context: &mut AppContext, path: &path::Path) -> AppResult { // This error should never happen let err = || AppError::new(AppErrorKind::UnknownError, String::from("Unexpected error")); let ui_context = context.ui_context_ref().clone(); let display_options = context.config_ref().display_options_ref().clone(); if let Some(curr_list) = context.tab_context_mut().curr_tab_mut().curr_list_mut() { if let path::Component::Normal(name) = path.components().next().ok_or_else(err)? { let index = curr_list.get_index_from_name(name.to_str().ok_or_else(err)?); curr_list.set_index(index, &ui_context, &display_options); } } Ok(()) } pub fn up(context: &mut AppContext, u: usize) -> AppResult { let movement = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .and_then(|list| list.get_index().map(|idx| idx.saturating_sub(u))); if let Some(s) = movement { cursor_move(context, s); } Ok(()) } pub fn down(context: &mut AppContext, u: usize) -> AppResult { let movement = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .and_then(|list| list.get_index().map(|idx| idx.saturating_add(u))); if let Some(s) = movement { cursor_move(context, s); } Ok(()) } pub fn home(context: &mut AppContext) -> AppResult { let movement = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .and_then(|curr_list| { let len = curr_list.len(); if len == 0 { None } else { Some(0) } }); if let Some(s) = movement { cursor_move(context, s); } Ok(()) } pub fn end(context: &mut AppContext) -> AppResult { let movement = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .and_then(|curr_list| { let len = curr_list.len(); if len == 0 { None } else { Some(len - 1) } }); if let Some(s) = movement { cursor_move(context, s); } Ok(()) } fn get_page_size(context: &AppContext, backend: &AppBackend) -> Option { let config = context.config_ref(); let rect = backend.terminal.as_ref().map(|t| t.size())?.ok()?; let rect_height = rect.height as usize; if config.display_options_ref().show_borders() { if rect_height >= 4 { Some(rect_height - 4) } else { None } } else if rect_height >= 2 { Some(rect_height - 2) } else { None } } pub fn page_up(context: &mut AppContext, backend: &mut AppBackend, proportion: f64) -> AppResult { let page_size = get_page_size(context, backend).unwrap_or(10) as f64 * proportion; let page_size = page_size as usize; let movement = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .and_then(|list| list.get_index().map(|idx| idx.saturating_sub(page_size))); if let Some(s) = movement { cursor_move(context, s); } Ok(()) } pub fn page_down(context: &mut AppContext, backend: &mut AppBackend, proportion: f64) -> AppResult { let page_size = get_page_size(context, backend).unwrap_or(10) as f64 * proportion; let page_size = page_size as usize; let new_index = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .and_then(|list| list.get_index().map(|idx| idx.saturating_add(page_size))); if let Some(idx) = new_index { cursor_move(context, idx); } Ok(()) } pub fn page_home(context: &mut AppContext, _: &mut AppBackend) -> AppResult { let new_index = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .map(|curr_list| curr_list.first_index_for_viewport()); if let Some(idx) = new_index { cursor_move(context, idx); } Ok(()) } pub fn page_middle(context: &mut AppContext, backend: &mut AppBackend) -> AppResult { let movement = get_page_size(context, backend).unwrap_or(10) / 2; let new_index = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .map(|curr_list| curr_list.first_index_for_viewport() + movement); if let Some(idx) = new_index { cursor_move(context, idx); } Ok(()) } pub fn page_end(context: &mut AppContext, backend: &mut AppBackend) -> AppResult { let movement = get_page_size(context, backend).unwrap_or(10) - 1; let new_index = context .tab_context_ref() .curr_tab_ref() .curr_list_ref() .map(|curr_list| curr_list.first_index_for_viewport() + movement); if let Some(idx) = new_index { cursor_move(context, idx); } Ok(()) }