mirror of
https://github.com/chylex/Bark-Browser.git
synced 2025-05-08 04:34:05 +02:00
Refactor construction of filesystem action map
This commit is contained in:
parent
63b56de63f
commit
aef1a0011b
14
src/app.rs
14
src/app.rs
@ -1,4 +1,4 @@
|
||||
use std::path::Path;
|
||||
use std::io;
|
||||
|
||||
use crossterm::event::{Event, KeyEventKind};
|
||||
|
||||
@ -6,14 +6,12 @@ use crate::input::keymap::KeyBinding;
|
||||
use crate::state::{Environment, State};
|
||||
use crate::state::action::ActionResult;
|
||||
use crate::state::event::EventResult;
|
||||
use crate::state::init::StateInitializer;
|
||||
use crate::state::view::View;
|
||||
|
||||
pub fn run(start_path: &Path) -> std::io::Result<()> {
|
||||
View::restore_terminal_on_panic();
|
||||
let mut view = View::stdout()?;
|
||||
|
||||
let environment = Environment::try_from(&view)?;
|
||||
let mut state = State::with_root_path(start_path, environment);
|
||||
pub fn run(state_initializer: &StateInitializer, view: &mut View) -> io::Result<()> {
|
||||
let environment = Environment::try_from(&*view)?;
|
||||
let mut state = State::new(state_initializer, environment);
|
||||
|
||||
loop {
|
||||
match state.handle_events() {
|
||||
@ -69,7 +67,7 @@ pub fn run(start_path: &Path) -> std::io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
view.close()
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
|
@ -1,104 +1,5 @@
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::component::filesystem::action::application::{Quit, RedrawScreen};
|
||||
use crate::component::filesystem::action::count::PushCountDigit;
|
||||
use crate::component::filesystem::action::file::{CreateDirectoryInParentOfSelectedEntry, CreateDirectoryInSelectedDirectory, CreateFileInParentOfSelectedEntry, CreateFileInSelectedDirectory, DeleteSelectedEntry, EditSelectedEntry, RenameSelectedEntry};
|
||||
use crate::component::filesystem::action::movement::{CollapseSelectedOr, ExpandSelectedOr, MoveBetweenFirstAndLastSibling, MoveDown, MovementWithCountFactory, MovementWithFallbackFactory, MoveOrTraverseUpParent, MoveToFirst, MoveToLast, MoveToLineOr, MoveToNextSibling, MoveToParent, MoveToPreviousSibling, MoveUp, ScreenHeightRatio};
|
||||
use crate::component::filesystem::action::tree::{ExpandCollapse, RefreshChildrenOfSelected};
|
||||
use crate::component::filesystem::FsLayer;
|
||||
use crate::input::keymap::KeyMap;
|
||||
use crate::state::action::Action;
|
||||
|
||||
mod application;
|
||||
mod count;
|
||||
mod file;
|
||||
mod movement;
|
||||
mod tree;
|
||||
|
||||
type ActionKeyMap = KeyMap<Box<dyn Action<FsLayer> + Sync>>;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref ACTION_MAP: ActionKeyMap = create_action_map();
|
||||
}
|
||||
|
||||
fn create_action_map() -> ActionKeyMap {
|
||||
let mut me = ActionKeyMap::new();
|
||||
|
||||
map(&mut me, "0", PushCountDigit(0));
|
||||
map(&mut me, "1", PushCountDigit(1));
|
||||
map(&mut me, "2", PushCountDigit(2));
|
||||
map(&mut me, "3", PushCountDigit(3));
|
||||
map(&mut me, "4", PushCountDigit(4));
|
||||
map(&mut me, "5", PushCountDigit(5));
|
||||
map(&mut me, "6", PushCountDigit(6));
|
||||
map(&mut me, "7", PushCountDigit(7));
|
||||
map(&mut me, "8", PushCountDigit(8));
|
||||
map(&mut me, "9", PushCountDigit(9));
|
||||
|
||||
map(&mut me, "af", CreateFileInSelectedDirectory);
|
||||
map(&mut me, "ad", CreateDirectoryInSelectedDirectory);
|
||||
map(&mut me, "e", EditSelectedEntry);
|
||||
map(&mut me, "d", DeleteSelectedEntry);
|
||||
map(&mut me, "gg", MoveToLineOr(MoveToFirst));
|
||||
map(&mut me, "G", MoveToLineOr(MoveToLast));
|
||||
map(&mut me, "h", CollapseSelectedOr(MoveToParent));
|
||||
map(&mut me, "H", MoveOrTraverseUpParent);
|
||||
map(&mut me, "if", CreateFileInSelectedDirectory);
|
||||
map(&mut me, "id", CreateDirectoryInSelectedDirectory);
|
||||
map(&mut me, "j", MoveDown);
|
||||
map(&mut me, "J", MoveToNextSibling.with_fallback(MoveDown));
|
||||
map(&mut me, "k", MoveUp);
|
||||
map(&mut me, "K", MoveToPreviousSibling.with_fallback(MoveUp));
|
||||
map(&mut me, "l", ExpandSelectedOr(MoveDown));
|
||||
map(&mut me, "of", CreateFileInParentOfSelectedEntry);
|
||||
map(&mut me, "od", CreateDirectoryInParentOfSelectedEntry);
|
||||
map(&mut me, "q", Quit);
|
||||
map(&mut me, "r", RenameSelectedEntry { prefill: true });
|
||||
map(&mut me, "R", RenameSelectedEntry { prefill: false });
|
||||
|
||||
map(&mut me, "%", MoveBetweenFirstAndLastSibling);
|
||||
|
||||
map(&mut me, "<Ctrl-B>", MoveUp.with_custom_count(ScreenHeightRatio(1)));
|
||||
map(&mut me, "<Ctrl-C>", Quit);
|
||||
map(&mut me, "<Ctrl-D>", MoveDown.with_default_count(ScreenHeightRatio(2)));
|
||||
map(&mut me, "<Ctrl-F>", MoveDown.with_custom_count(ScreenHeightRatio(1)));
|
||||
map(&mut me, "<Ctrl-L>", RedrawScreen);
|
||||
map(&mut me, "<Ctrl-N>", MoveDown);
|
||||
map(&mut me, "<Ctrl-P>", MoveUp);
|
||||
map(&mut me, "<Ctrl-U>", MoveUp.with_default_count(ScreenHeightRatio(2)));
|
||||
|
||||
map(&mut me, "<Space>", ExpandCollapse { default_depth: 1 });
|
||||
map(&mut me, "<Ctrl-Space>", ExpandCollapse { default_depth: 1000 });
|
||||
|
||||
map(&mut me, "<Down>", MoveDown);
|
||||
map(&mut me, "<Shift-Down>", MoveDown.with_custom_count(ScreenHeightRatio(1)));
|
||||
map(&mut me, "<Alt-Down>", MoveToNextSibling.with_fallback(MoveDown));
|
||||
|
||||
map(&mut me, "<Up>", MoveUp);
|
||||
map(&mut me, "<Shift-Up>", MoveUp.with_custom_count(ScreenHeightRatio(1)));
|
||||
map(&mut me, "<Alt-Up>", MoveToPreviousSibling.with_fallback(MoveUp));
|
||||
|
||||
map(&mut me, "<Left>", CollapseSelectedOr(MoveToParent));
|
||||
map(&mut me, "<Alt-Left>", MoveOrTraverseUpParent);
|
||||
|
||||
map(&mut me, "<Right>", ExpandSelectedOr(MoveDown));
|
||||
|
||||
map(&mut me, "<Del>", DeleteSelectedEntry);
|
||||
|
||||
map(&mut me, "<PageDown>", MoveDown.with_custom_count(ScreenHeightRatio(1)));
|
||||
map(&mut me, "<PageUp>", MoveUp.with_custom_count(ScreenHeightRatio(1)));
|
||||
|
||||
map(&mut me, "<F2>", RenameSelectedEntry { prefill: true });
|
||||
map(&mut me, "<Shift-F2>", RenameSelectedEntry { prefill: false });
|
||||
|
||||
map(&mut me, "<F5>", RefreshChildrenOfSelected);
|
||||
|
||||
me
|
||||
}
|
||||
|
||||
fn map(map: &mut ActionKeyMap, key_binding_str: &str, action: impl Action<FsLayer> + Sync + 'static) {
|
||||
// Panic on error, since we are hard-coding the key bindings.
|
||||
if let Err(err) = map.insert(key_binding_str, Box::new(action)) {
|
||||
panic!("Failed to insert key binding '{}'. {}", err.sequence(), err.error());
|
||||
}
|
||||
}
|
||||
pub mod application;
|
||||
pub mod count;
|
||||
pub mod file;
|
||||
pub mod movement;
|
||||
pub mod tree;
|
||||
|
98
src/component/filesystem/defaults.rs
Normal file
98
src/component/filesystem/defaults.rs
Normal file
@ -0,0 +1,98 @@
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::component::filesystem::{ActionKeyMap, FsLayer};
|
||||
use crate::component::filesystem::action::application::{EnterCommandMode, Quit, RedrawScreen};
|
||||
use crate::component::filesystem::action::count::PushCountDigit;
|
||||
use crate::component::filesystem::action::file::{CreateDirectoryInParentOfSelectedEntry, CreateDirectoryInSelectedDirectory, CreateFileInParentOfSelectedEntry, CreateFileInSelectedDirectory, DeleteSelectedEntry, EditSelectedEntry, RenameSelectedEntry};
|
||||
use crate::component::filesystem::action::movement::{CollapseSelectedOr, ExpandSelectedOr, MoveBetweenFirstAndLastSibling, MoveDown, MovementWithCountFactory, MovementWithFallbackFactory, MoveOrTraverseUpParent, MoveToFirst, MoveToLast, MoveToLineOr, MoveToNextSibling, MoveToParent, MoveToPreviousSibling, MoveUp, ScreenHeightRatio};
|
||||
use crate::component::filesystem::action::tree::{ExpandCollapse, RefreshChildrenOfSelected};
|
||||
use crate::input::keymap::KeyMapInsertError;
|
||||
use crate::state::action::Action;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref ACTION_MAP: Result<ActionKeyMap, KeyMapInsertError> = create_action_map();
|
||||
}
|
||||
|
||||
pub fn get_action_map() -> Result<&'static ActionKeyMap, &'static KeyMapInsertError> {
|
||||
return ACTION_MAP.as_ref();
|
||||
}
|
||||
|
||||
fn create_action_map() -> Result<ActionKeyMap, KeyMapInsertError> {
|
||||
let mut me = ActionKeyMap::new();
|
||||
|
||||
map(&mut me, "0", PushCountDigit(0))?;
|
||||
map(&mut me, "1", PushCountDigit(1))?;
|
||||
map(&mut me, "2", PushCountDigit(2))?;
|
||||
map(&mut me, "3", PushCountDigit(3))?;
|
||||
map(&mut me, "4", PushCountDigit(4))?;
|
||||
map(&mut me, "5", PushCountDigit(5))?;
|
||||
map(&mut me, "6", PushCountDigit(6))?;
|
||||
map(&mut me, "7", PushCountDigit(7))?;
|
||||
map(&mut me, "8", PushCountDigit(8))?;
|
||||
map(&mut me, "9", PushCountDigit(9))?;
|
||||
|
||||
map(&mut me, "af", CreateFileInSelectedDirectory)?;
|
||||
map(&mut me, "ad", CreateDirectoryInSelectedDirectory)?;
|
||||
map(&mut me, "e", EditSelectedEntry)?;
|
||||
map(&mut me, "d", DeleteSelectedEntry)?;
|
||||
map(&mut me, "gg", MoveToLineOr(MoveToFirst))?;
|
||||
map(&mut me, "G", MoveToLineOr(MoveToLast))?;
|
||||
map(&mut me, "h", CollapseSelectedOr(MoveToParent))?;
|
||||
map(&mut me, "H", MoveOrTraverseUpParent)?;
|
||||
map(&mut me, "if", CreateFileInSelectedDirectory)?;
|
||||
map(&mut me, "id", CreateDirectoryInSelectedDirectory)?;
|
||||
map(&mut me, "j", MoveDown)?;
|
||||
map(&mut me, "J", MoveToNextSibling.with_fallback(MoveDown))?;
|
||||
map(&mut me, "k", MoveUp)?;
|
||||
map(&mut me, "K", MoveToPreviousSibling.with_fallback(MoveUp))?;
|
||||
map(&mut me, "l", ExpandSelectedOr(MoveDown))?;
|
||||
map(&mut me, "of", CreateFileInParentOfSelectedEntry)?;
|
||||
map(&mut me, "od", CreateDirectoryInParentOfSelectedEntry)?;
|
||||
map(&mut me, "q", Quit)?;
|
||||
map(&mut me, "r", RenameSelectedEntry { prefill: true })?;
|
||||
map(&mut me, "R", RenameSelectedEntry { prefill: false })?;
|
||||
|
||||
map(&mut me, "%", MoveBetweenFirstAndLastSibling)?;
|
||||
map(&mut me, ":", EnterCommandMode)?;
|
||||
|
||||
map(&mut me, "<Ctrl-B>", MoveUp.with_custom_count(ScreenHeightRatio(1)))?;
|
||||
map(&mut me, "<Ctrl-C>", Quit)?;
|
||||
map(&mut me, "<Ctrl-D>", MoveDown.with_default_count(ScreenHeightRatio(2)))?;
|
||||
map(&mut me, "<Ctrl-F>", MoveDown.with_custom_count(ScreenHeightRatio(1)))?;
|
||||
map(&mut me, "<Ctrl-L>", RedrawScreen)?;
|
||||
map(&mut me, "<Ctrl-N>", MoveDown)?;
|
||||
map(&mut me, "<Ctrl-P>", MoveUp)?;
|
||||
map(&mut me, "<Ctrl-U>", MoveUp.with_default_count(ScreenHeightRatio(2)))?;
|
||||
|
||||
map(&mut me, "<Space>", ExpandCollapse { default_depth: 1 })?;
|
||||
map(&mut me, "<Ctrl-Space>", ExpandCollapse { default_depth: 1000 })?;
|
||||
|
||||
map(&mut me, "<Down>", MoveDown)?;
|
||||
map(&mut me, "<Shift-Down>", MoveDown.with_custom_count(ScreenHeightRatio(1)))?;
|
||||
map(&mut me, "<Alt-Down>", MoveToNextSibling.with_fallback(MoveDown))?;
|
||||
|
||||
map(&mut me, "<Up>", MoveUp)?;
|
||||
map(&mut me, "<Shift-Up>", MoveUp.with_custom_count(ScreenHeightRatio(1)))?;
|
||||
map(&mut me, "<Alt-Up>", MoveToPreviousSibling.with_fallback(MoveUp))?;
|
||||
|
||||
map(&mut me, "<Left>", CollapseSelectedOr(MoveToParent))?;
|
||||
map(&mut me, "<Alt-Left>", MoveOrTraverseUpParent)?;
|
||||
|
||||
map(&mut me, "<Right>", ExpandSelectedOr(MoveDown))?;
|
||||
|
||||
map(&mut me, "<Del>", DeleteSelectedEntry)?;
|
||||
|
||||
map(&mut me, "<PageDown>", MoveDown.with_custom_count(ScreenHeightRatio(1)))?;
|
||||
map(&mut me, "<PageUp>", MoveUp.with_custom_count(ScreenHeightRatio(1)))?;
|
||||
|
||||
map(&mut me, "<F2>", RenameSelectedEntry { prefill: true })?;
|
||||
map(&mut me, "<Shift-F2>", RenameSelectedEntry { prefill: false })?;
|
||||
|
||||
map(&mut me, "<F5>", RefreshChildrenOfSelected)?;
|
||||
|
||||
Ok(me)
|
||||
}
|
||||
|
||||
fn map(map: &mut ActionKeyMap, key_binding_str: &str, action: impl Action<FsLayer> + Sync + 'static) -> Result<(), KeyMapInsertError> {
|
||||
map.insert(key_binding_str, Box::new(action))
|
||||
}
|
@ -3,23 +3,28 @@ use std::path::Path;
|
||||
use crate::component::filesystem::registers::FsTreeRegisters;
|
||||
use crate::component::filesystem::tree::FsTree;
|
||||
use crate::file::FileOwnerNameCache;
|
||||
use crate::input::keymap::{KeyBinding, KeyMapLookupResult};
|
||||
use crate::state::action::ActionResult;
|
||||
use crate::input::keymap::{KeyBinding, KeyMap, KeyMapLookupResult};
|
||||
use crate::state::action::{Action, ActionResult};
|
||||
use crate::state::Environment;
|
||||
use crate::state::event::{EventQueue, EventResult};
|
||||
use crate::state::layer::Layer;
|
||||
use crate::state::view::Frame;
|
||||
|
||||
mod action;
|
||||
mod command;
|
||||
mod registers;
|
||||
mod render;
|
||||
mod tree;
|
||||
mod registers;
|
||||
pub mod defaults;
|
||||
|
||||
pub type ActionKeyMap = KeyMap<Box<dyn Action<FsLayer> + Sync>>;
|
||||
|
||||
pub struct FsLayer {
|
||||
action_map: &'static ActionKeyMap,
|
||||
pub tree: FsTree,
|
||||
tree_structure_version: u32,
|
||||
pub registers: FsTreeRegisters,
|
||||
cursor_y: u16,
|
||||
pub registers: FsTreeRegisters,
|
||||
pending_keys: Vec<KeyBinding>,
|
||||
event_queue: EventQueue<FsLayer>,
|
||||
file_owner_name_cache: FileOwnerNameCache,
|
||||
@ -27,11 +32,9 @@ pub struct FsLayer {
|
||||
}
|
||||
|
||||
impl FsLayer {
|
||||
pub fn with_root_path(root_path: &Path) -> Self {
|
||||
// Initialize action map early in case it errors.
|
||||
let _ = *action::ACTION_MAP;
|
||||
|
||||
pub fn new(root_path: &Path, action_map: &'static ActionKeyMap) -> Self {
|
||||
Self {
|
||||
action_map,
|
||||
tree: FsTree::with_root_path(root_path),
|
||||
tree_structure_version: 0,
|
||||
cursor_y: 0,
|
||||
@ -56,7 +59,7 @@ impl Layer for FsLayer {
|
||||
fn handle_input(&mut self, environment: &Environment, key_binding: KeyBinding) -> ActionResult {
|
||||
self.pending_keys.push(key_binding);
|
||||
|
||||
match action::ACTION_MAP.lookup(&self.pending_keys) {
|
||||
match self.action_map.lookup(&self.pending_keys) {
|
||||
KeyMapLookupResult::Prefix => {
|
||||
ActionResult::Nothing
|
||||
}
|
||||
|
57
src/main.rs
57
src/main.rs
@ -50,11 +50,13 @@
|
||||
#![allow(clippy::redundant_else)]
|
||||
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::ExitCode;
|
||||
|
||||
use crate::state::init::StateInitializer;
|
||||
use crate::state::view::View;
|
||||
|
||||
mod app;
|
||||
mod component;
|
||||
mod file;
|
||||
@ -65,11 +67,11 @@ mod util;
|
||||
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");
|
||||
|
||||
#[allow(clippy::print_stdout)]
|
||||
fn main() -> Result<ExitCode, Box<dyn Error>> {
|
||||
fn main() -> ExitCode {
|
||||
let args = env::args_os().skip(1).collect::<Vec<_>>();
|
||||
if args.len() == 1 && args.get(0).is_some_and(|arg| arg == "-v" || arg == "--version") {
|
||||
println!("{}", VERSION.unwrap_or("unknown"));
|
||||
return Ok(ExitCode::SUCCESS);
|
||||
return ExitCode::SUCCESS;
|
||||
}
|
||||
|
||||
#[allow(clippy::indexing_slicing)] // Guarded by condition.
|
||||
@ -81,21 +83,20 @@ fn main() -> Result<ExitCode, Box<dyn Error>> {
|
||||
|
||||
if args.len() > 1 {
|
||||
println!("Too many arguments!");
|
||||
return Ok(ExitCode::SUCCESS);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
|
||||
match get_start_path(args.get(0)) {
|
||||
StartPathResult::Ok(path) => {
|
||||
app::run(&path)?;
|
||||
Ok(ExitCode::SUCCESS)
|
||||
prepare_and_run_app(&path)
|
||||
},
|
||||
StartPathResult::InvalidPathArgument(path) => {
|
||||
println!("Invalid path: {}", path.to_string_lossy());
|
||||
Ok(ExitCode::FAILURE)
|
||||
ExitCode::FAILURE
|
||||
},
|
||||
StartPathResult::InvalidWorkingDirectory => {
|
||||
println!("Invalid working directory!");
|
||||
Ok(ExitCode::FAILURE)
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,3 +120,43 @@ fn get_start_path(path_arg: Option<&OsString>) -> StartPathResult {
|
||||
StartPathResult::InvalidWorkingDirectory
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::print_stdout)]
|
||||
fn prepare_and_run_app(start_path: &Path) -> ExitCode {
|
||||
match component::filesystem::defaults::get_action_map() {
|
||||
Ok(action_map) => {
|
||||
run_app(&StateInitializer {
|
||||
filesystem_start_path: start_path,
|
||||
filesystem_action_map: action_map,
|
||||
})
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Failed to initialize action map, could not insert key sequence: '{}'\nReason: {}", e.sequence(), e.error());
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::print_stdout)]
|
||||
fn run_app(state_initializer: &StateInitializer) -> ExitCode {
|
||||
View::restore_terminal_on_panic();
|
||||
|
||||
match View::stdout() {
|
||||
Err(e) => {
|
||||
View::restore_terminal();
|
||||
println!("Failed to initialize terminal: {e}");
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
Ok(mut view) => {
|
||||
let result = app::run(state_initializer, &mut view);
|
||||
let _ = view.close();
|
||||
|
||||
if let Err(e) = result {
|
||||
println!("Runtime error: {e}");
|
||||
ExitCode::FAILURE
|
||||
} else {
|
||||
ExitCode::SUCCESS
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
8
src/state/init.rs
Normal file
8
src/state/init.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use std::path::Path;
|
||||
|
||||
use crate::component::filesystem::ActionKeyMap;
|
||||
|
||||
pub struct StateInitializer<'a> {
|
||||
pub filesystem_start_path: &'a Path,
|
||||
pub filesystem_action_map: &'static ActionKeyMap,
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
use std::path::Path;
|
||||
|
||||
use crate::component::filesystem::FsLayer;
|
||||
use crate::input::keymap::KeyBinding;
|
||||
use crate::state::action::ActionResult;
|
||||
use crate::state::event::EventResult;
|
||||
use crate::state::init::StateInitializer;
|
||||
use crate::state::layer::Layer;
|
||||
use crate::state::view::Frame;
|
||||
|
||||
@ -12,6 +11,7 @@ pub use self::environment::Environment;
|
||||
mod environment;
|
||||
pub mod action;
|
||||
pub mod event;
|
||||
pub mod init;
|
||||
pub mod layer;
|
||||
pub mod view;
|
||||
|
||||
@ -21,9 +21,9 @@ pub struct State {
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn with_root_path(root_path: &Path, environment: Environment) -> Self {
|
||||
pub fn new(initializer: &StateInitializer, environment: Environment) -> Self {
|
||||
Self {
|
||||
layers: vec![Box::new(FsLayer::with_root_path(root_path))],
|
||||
layers: vec![Box::new(FsLayer::new(initializer.filesystem_start_path, initializer.filesystem_action_map))],
|
||||
environment
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,15 @@ impl View {
|
||||
let prev_hook = panic::take_hook();
|
||||
|
||||
panic::set_hook(Box::new(move |panic_info| {
|
||||
let _ = terminal::disable_raw_mode();
|
||||
Self::restore_terminal();
|
||||
prev_hook(panic_info);
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn restore_terminal() {
|
||||
let _ = terminal::disable_raw_mode();
|
||||
}
|
||||
|
||||
pub fn close(mut self) -> io::Result<()> {
|
||||
self.term.show_cursor()?;
|
||||
self.term.backend_mut().execute(terminal::LeaveAlternateScreen)?;
|
||||
|
Loading…
Reference in New Issue
Block a user