use std::cmp::{Ord, Ordering};
use std::ops::Index;
use std::fs::Metadata;
use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, RwLock};
use std::sync::mpsc::Sender;
use std::hash::{Hash, Hasher};
use std::os::unix::ffi::{OsStringExt, OsStrExt};
use std::ffi::{OsStr, OsString};
use lscolors::LsColors;
use mime_detective;
use users::{get_current_username,
get_current_groupname,
get_user_by_uid,
get_group_by_gid};
use chrono::TimeZone;
use failure::Error;
use notify::DebouncedEvent;
use rayon::prelude::*;
use rayon::{ThreadPool, ThreadPoolBuilder};
use crate::fail::{HResult, HError, ErrorLog};
use crate::dirty::{AsyncDirtyBit, DirtyBit, Dirtyable};
use crate::preview::{Async, Stale};
use crate::widget::Events;
lazy_static! {
static ref COLORS: LsColors = LsColors::from_env().unwrap();
static ref TAGS: RwLock<(bool, Vec<PathBuf>)> = RwLock::new((false, vec![]));
}
fn make_pool(sender: Option<Sender<Events>>) -> ThreadPool {
let sender = Arc::new(Mutex::new(sender));
ThreadPoolBuilder::new()
.num_threads(8)
.exit_handler(move |thread_num| {
if thread_num == 0 {
if let Ok(lock) = sender.lock() {
if let Some(sender) = lock.as_ref() {
sender.send(Events::WidgetReady).ok();
}
}
}
})
.build()
.expect("Failed to create thread pool")
}
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.write()?;
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.read()?.1.contains(path);
Ok(tagged)
}
pub fn tags_loaded() -> HResult<()> {
let loaded = TAGS.read()?.0;
if loaded { Ok(()) }
else { HError::tags_not_loaded() }
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct Files {
pub directory: File,
pub files: Vec<File>,
pub meta_upto: Option<usize>,
pub sort: SortBy,
pub dirs_first: bool,
pub reverse: bool,
pub show_hidden: bool,
pub filter: Option<String>,
pub dirty: DirtyBit,
pub dirty_meta: AsyncDirtyBit,
}
impl Index<usize> for Files {
type Output = File;
fn index(&self, pos: usize) -> &File {
&