mirror of https://github.com/bobwen-dev/hunter
tagging files
This commit is contained in:
parent
5b9a150a10
commit
e63c65ab7d
|
@ -54,6 +54,8 @@ pub enum HError {
|
|||
StripPrefixError{#[cause] error: std::path::StripPrefixError},
|
||||
#[fail(display = "INofify failed: {}", error)]
|
||||
INotifyError{#[cause] error: notify::Error},
|
||||
#[fail(display = "Tags not loaded yet")]
|
||||
TagsNotLoadedYetError
|
||||
}
|
||||
|
||||
impl HError {
|
||||
|
@ -73,6 +75,9 @@ impl HError {
|
|||
pub fn popup_finnished<T>() -> HResult<T> {
|
||||
Err(HError::PopupFinnished)
|
||||
}
|
||||
pub fn tags_not_loaded<T>() -> HResult<T> {
|
||||
Err(HError::TagsNotLoadedYetError)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ErrorLog where Self: Sized {
|
||||
|
|
74
src/files.rs
74
src/files.rs
|
@ -19,6 +19,32 @@ use crate::fail::{HResult, HError};
|
|||
|
||||
lazy_static! {
|
||||
static ref COLORS: LsColors = LsColors::from_env().unwrap();
|
||||
static ref TAGS: Mutex<(bool, Vec<PathBuf>)> = Mutex::new((false, vec![]));
|
||||
}
|
||||
|
||||
pub fn load_tags() -> HResult<()> {
|
||||
std::thread::spawn(|| -> HResult<()> {
|
||||
let tag_path = crate::paths::tagfile_path()?;
|
||||
let tags = std::fs::read_to_string(tag_path)?;
|
||||
let mut tags = tags.lines().map(|f| PathBuf::from(f)).collect::<Vec<PathBuf>>();
|
||||
let mut tag_lock = TAGS.lock()?;
|
||||
tag_lock.0 = true;
|
||||
tag_lock.1.append(&mut tags);
|
||||
Ok(())
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn check_tag(path: &PathBuf) -> HResult<bool> {
|
||||
tags_loaded()?;
|
||||
let tagged = TAGS.lock()?.1.contains(path);
|
||||
Ok(tagged)
|
||||
}
|
||||
|
||||
pub fn tags_loaded() -> HResult<()> {
|
||||
let loaded = TAGS.lock()?.0;
|
||||
if loaded { Ok(()) }
|
||||
else { HError::tags_not_loaded() }
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||
|
@ -312,7 +338,8 @@ pub struct File {
|
|||
pub kind: Kind,
|
||||
pub color: Option<lscolors::Color>,
|
||||
pub meta: Option<std::fs::Metadata>,
|
||||
pub selected: bool
|
||||
pub selected: bool,
|
||||
pub tag: Option<bool>
|
||||
// flags: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -321,13 +348,16 @@ impl File {
|
|||
name: &str,
|
||||
path: PathBuf,
|
||||
) -> File {
|
||||
let tag = check_tag(&path).ok();
|
||||
|
||||
File {
|
||||
name: name.to_string(),
|
||||
kind: if path.is_dir() { Kind::Directory } else { Kind::File },
|
||||
path: path,
|
||||
meta: None,
|
||||
color: None,
|
||||
selected: false
|
||||
selected: false,
|
||||
tag: tag,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,6 +491,46 @@ impl File {
|
|||
self.selected
|
||||
}
|
||||
|
||||
pub fn is_tagged(&self) -> HResult<bool> {
|
||||
if let Some(tag) = self.tag {
|
||||
return Ok(tag);
|
||||
}
|
||||
let tag = check_tag(&self.path)?;
|
||||
Ok(tag)
|
||||
}
|
||||
|
||||
pub fn toggle_tag(&mut self) -> HResult<()> {
|
||||
let new_state = match self.tag {
|
||||
Some(tag) => !tag,
|
||||
None => {
|
||||
let tag = check_tag(&self.path);
|
||||
!tag?
|
||||
}
|
||||
};
|
||||
self.tag = Some(new_state);
|
||||
|
||||
match new_state {
|
||||
true => TAGS.lock()?.1.push(self.path.clone()),
|
||||
false => { TAGS.lock()?.1.remove_item(&self.path); },
|
||||
}
|
||||
self.save_tags()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save_tags(&self) -> HResult<()> {
|
||||
std::thread::spawn(|| -> HResult<()> {
|
||||
let tagfile_path = crate::paths::tagfile_path()?;
|
||||
let tags = TAGS.lock()?.clone();
|
||||
let tags_str = tags.1.iter().map(|p| {
|
||||
let path = p.to_string_lossy().to_string();
|
||||
format!("{}\n", path)
|
||||
}).collect::<String>();
|
||||
std::fs::write(tagfile_path, tags_str)?;
|
||||
Ok(())
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pretty_print_permissions(&self) -> HResult<String> {
|
||||
let perms: usize = format!("{:o}", self.meta()?.mode()).parse().unwrap();
|
||||
let perms: usize = perms % 800;
|
||||
|
|
|
@ -46,6 +46,7 @@ impl Listable for ListView<Files> {
|
|||
Key::Left => self.goto_grand_parent()?,
|
||||
Key::Right => self.goto_selected()?,
|
||||
Key::Char(' ') => self.multi_select_file(),
|
||||
Key::Char('t') => self.toggle_tag()?,
|
||||
Key::Char('h') => self.toggle_hidden(),
|
||||
Key::Char('r') => self.reverse_sort(),
|
||||
Key::Char('s') => self.cycle_sort(),
|
||||
|
@ -136,6 +137,11 @@ where
|
|||
fn render_line(&self, file: &File) -> String {
|
||||
let name = &file.name;
|
||||
let (size, unit) = file.calculate_size().unwrap_or((0, "".to_string()));
|
||||
let tag = match file.is_tagged() {
|
||||
Ok(true) => term::color_red() + "*",
|
||||
_ => "".to_string()
|
||||
};
|
||||
let tag_len = if tag != "" { 1 } else { 0 };
|
||||
|
||||
let selection_gap = " ".to_string();
|
||||
let (name, selection_color) = if file.is_selected() {
|
||||
|
@ -149,18 +155,21 @@ where
|
|||
+ unit.to_string().len() as u16);
|
||||
let padding = sized_string.len() - sized_string.width_cjk();
|
||||
let padding = xsize - padding as u16;
|
||||
let padding = padding - tag_len;
|
||||
|
||||
format!(
|
||||
"{}{}{}{}{}{}{}",
|
||||
termion::cursor::Save,
|
||||
match &file.color {
|
||||
Some(color) => format!("{}{}{:padding$}{}",
|
||||
Some(color) => format!("{}{}{}{:padding$}{}",
|
||||
tag,
|
||||
term::from_lscolor(color),
|
||||
selection_color,
|
||||
&sized_string,
|
||||
term::normal_color(),
|
||||
padding = padding as usize),
|
||||
_ => format!("{}{}{:padding$}{}",
|
||||
_ => format!("{}{}{}{:padding$}{}",
|
||||
tag,
|
||||
term::normal_color(),
|
||||
selection_color,
|
||||
&sized_string,
|
||||
|
@ -335,6 +344,12 @@ impl ListView<Files>
|
|||
self.refresh().log();
|
||||
}
|
||||
|
||||
fn toggle_tag(&mut self) -> HResult<()> {
|
||||
self.selected_file_mut().toggle_tag()?;
|
||||
self.move_down();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn find_file(&mut self) -> HResult<()> {
|
||||
let name = self.minibuffer("find")?;
|
||||
let file = self.content.files.iter().find(|file| {
|
||||
|
|
|
@ -66,6 +66,10 @@ fn main() -> HResult<()> {
|
|||
}
|
||||
|
||||
fn run() -> HResult<()> {
|
||||
// do this early so it might be ready when needed
|
||||
crate::files::load_tags()?;
|
||||
|
||||
|
||||
let bufout = std::io::BufWriter::new(std::io::stdout());
|
||||
// Need to do this here to actually turn terminal into raw mode...
|
||||
let mut screen = AlternateScreen::from(bufout);
|
||||
|
|
Loading…
Reference in New Issue