mirror of https://github.com/bobwen-dev/hunter
215 lines
5.9 KiB
Rust
215 lines
5.9 KiB
Rust
use termion::event::Key;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use crate::fail::{HResult, HError, ErrorLog};
|
|
use crate::widget::{Widget, WidgetCore};
|
|
use crate::coordinates::Coordinates;
|
|
use crate::term;
|
|
|
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
|
pub struct Bookmarks {
|
|
mapping: HashMap<char, String>,
|
|
}
|
|
|
|
impl Bookmarks {
|
|
pub fn new() -> Bookmarks {
|
|
let mut bm = Bookmarks { mapping: HashMap::new() };
|
|
bm.load().log();
|
|
bm
|
|
}
|
|
pub fn add(&mut self, key: char, path: &str) -> HResult<()> {
|
|
self.mapping.insert(key, path.to_string());
|
|
self.save()?;
|
|
Ok(())
|
|
}
|
|
pub fn get(&self, key: char) -> HResult<&String> {
|
|
let path = self.mapping.get(&key)?;
|
|
Ok(path)
|
|
}
|
|
pub fn load(&mut self) -> HResult<()> {
|
|
let bm_file = crate::paths::bookmark_path()?;
|
|
|
|
if !bm_file.exists() {
|
|
self.import().log();
|
|
}
|
|
|
|
let bm_content = std::fs::read_to_string(bm_file)?;
|
|
let mapping = bm_content.lines()
|
|
.fold(HashMap::new(), |mut bm, line| {
|
|
let parts = line.splitn(2, ":").collect::<Vec<&str>>();
|
|
if parts.len() == 2 {
|
|
if let Some(key) = parts[0].chars().next() {
|
|
let path = parts[1].to_string();
|
|
bm.insert(key, path);
|
|
}
|
|
}
|
|
bm
|
|
});
|
|
|
|
self.mapping = mapping;
|
|
Ok(())
|
|
}
|
|
pub fn import(&self) -> HResult<()> {
|
|
let mut ranger_bm_path = crate::paths::ranger_path()?;
|
|
ranger_bm_path.push("bookmarks");
|
|
|
|
if ranger_bm_path.exists() {
|
|
let bm_file = crate::paths::bookmark_path()?;
|
|
std::fs::copy(ranger_bm_path, bm_file)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn save(&self) -> HResult<()> {
|
|
let bm_file = crate::paths::bookmark_path()?;
|
|
let bookmarks = self.mapping.iter().map(|(key, path)| {
|
|
format!("{}:{}\n", key, path)
|
|
}).collect::<String>();
|
|
|
|
std::fs::write(bm_file, bookmarks)?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
pub struct BMPopup {
|
|
core: WidgetCore,
|
|
bookmarks: Bookmarks,
|
|
bookmark_path: Option<String>,
|
|
add_mode: bool,
|
|
}
|
|
|
|
impl BMPopup {
|
|
pub fn new(core: &WidgetCore) -> BMPopup {
|
|
let mut bmpopup = BMPopup {
|
|
core: core.clone(),
|
|
bookmarks: Bookmarks::new(),
|
|
bookmark_path: None,
|
|
add_mode: false
|
|
};
|
|
bmpopup.set_coordinates(&core.coordinates).log();
|
|
bmpopup
|
|
}
|
|
|
|
pub fn pick(&mut self, cwd: String) -> HResult<String> {
|
|
self.bookmark_path = Some(cwd);
|
|
self.refresh()?;
|
|
match self.popup() {
|
|
Ok(_) => {},
|
|
Err(HError::PopupFinnished) => {},
|
|
err @ Err(HError::TerminalResizedError) => err?,
|
|
err @ Err(HError::WidgetResizedError) => err?,
|
|
err @ Err(_) => err?,
|
|
}
|
|
self.clear()?;
|
|
|
|
let bookmark = self.bookmark_path.take();
|
|
Ok(bookmark?)
|
|
}
|
|
|
|
pub fn add(&mut self, path: &str) -> HResult<()> {
|
|
self.add_mode = true;
|
|
self.bookmark_path = Some(path.to_string());
|
|
self.refresh()?;
|
|
self.clear()?;
|
|
self.popup()?;
|
|
self.clear()?;
|
|
Ok(())
|
|
}
|
|
|
|
fn resize(&mut self) -> HResult<()> {
|
|
HError::terminal_resized()?
|
|
}
|
|
|
|
pub fn render_line(&self, n: u16, key: &char, path: &str) -> String {
|
|
let xsize = term::xsize();
|
|
let padding = xsize - 4;
|
|
|
|
format!(
|
|
"{}{}{}: {:padding$}",
|
|
crate::term::goto_xy(1, n),
|
|
crate::term::reset(),
|
|
key,
|
|
path,
|
|
padding = padding as usize)
|
|
}
|
|
}
|
|
|
|
|
|
impl Widget for BMPopup {
|
|
fn get_core(&self) -> HResult<&WidgetCore> {
|
|
Ok(&self.core)
|
|
}
|
|
fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> {
|
|
Ok(&mut self.core)
|
|
}
|
|
fn refresh(&mut self) -> HResult<()> {
|
|
Ok(())
|
|
}
|
|
|
|
fn resize(&mut self) -> HResult<()> {
|
|
HError::terminal_resized()
|
|
}
|
|
|
|
fn set_coordinates(&mut self, _: &Coordinates) -> HResult<()> {
|
|
let (xsize, ysize) = crate::term::size()?;
|
|
let len = self.bookmarks.mapping.len();
|
|
let ysize = ysize.saturating_sub( len + 1 );
|
|
|
|
self.core.coordinates.set_size_u(xsize.saturating_sub(1), len);
|
|
self.core.coordinates.set_position_u(1, ysize);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn get_drawlist(&self) -> HResult<String> {
|
|
let ypos = self.get_coordinates()?.ypos();
|
|
|
|
let mut drawlist = String::new();
|
|
|
|
if !self.add_mode {
|
|
let cwd = self.bookmark_path.as_ref()?;
|
|
drawlist += &self.render_line(ypos, &'`', cwd);
|
|
}
|
|
|
|
let bm_list = self.bookmarks.mapping.iter().enumerate().map(|(i, (key, path))| {
|
|
let line = i as u16 + ypos + 1;
|
|
self.render_line(line, key, path)
|
|
}).collect::<String>();
|
|
|
|
drawlist += &bm_list;
|
|
|
|
Ok(drawlist)
|
|
}
|
|
fn on_key(&mut self, key: Key) -> HResult<()> {
|
|
match key {
|
|
Key::Ctrl('c') => {
|
|
self.bookmark_path = None;
|
|
return HError::popup_finnished()
|
|
},
|
|
Key::Char('`') => return HError::popup_finnished(),
|
|
Key::Char(key) => {
|
|
if self.add_mode {
|
|
let path = self.bookmark_path.take()?;
|
|
self.bookmarks.add(key, &path)?;
|
|
self.add_mode = false;
|
|
self.bookmarks.save().log();
|
|
return HError::popup_finnished();
|
|
}
|
|
if let Ok(path) = self.bookmarks.get(key) {
|
|
self.bookmark_path.replace(path.clone());
|
|
return HError::popup_finnished();
|
|
}
|
|
}
|
|
Key::Alt(key) => {
|
|
self.bookmarks.mapping.remove(&key);
|
|
self.bookmarks.save().log();
|
|
return HError::widget_resized();
|
|
}
|
|
_ => {}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|