mirror of
https://github.com/bobwen-dev/hunter
synced 2025-04-12 00:55:41 +02:00
multi-file selection
This commit is contained in:
parent
626ba13239
commit
ea9d6d4d92
19
src/files.rs
19
src/files.rs
@ -170,6 +170,10 @@ impl Files {
|
|||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.files.len()
|
self.files.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_selected(&self) -> Vec<&File> {
|
||||||
|
self.files.iter().filter(|f| f.is_selected()).collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
@ -210,6 +214,7 @@ pub struct File {
|
|||||||
pub mode: u32,
|
pub mode: u32,
|
||||||
pub user: u32,
|
pub user: u32,
|
||||||
pub group: u32,
|
pub group: u32,
|
||||||
|
pub selected: bool
|
||||||
// flags: Option<String>,
|
// flags: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,10 +239,8 @@ impl File {
|
|||||||
color: color,
|
color: color,
|
||||||
mode: mode,
|
mode: mode,
|
||||||
user: user,
|
user: user,
|
||||||
group: group
|
group: group,
|
||||||
// owner: None,
|
selected: false
|
||||||
// group: None,
|
|
||||||
// flags: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,6 +323,14 @@ impl File {
|
|||||||
self.path.clone()
|
self.path.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle_selection(&mut self) {
|
||||||
|
self.selected = !self.selected
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_selected(&self) -> bool {
|
||||||
|
self.selected
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pretty_print_permissions(&self) -> String {
|
pub fn pretty_print_permissions(&self) -> String {
|
||||||
let perms: usize = format!("{:o}", self.mode).parse().unwrap();
|
let perms: usize = format!("{:o}", self.mode).parse().unwrap();
|
||||||
let perms: usize = perms % 800;
|
let perms: usize = perms % 800;
|
||||||
|
@ -20,8 +20,6 @@ where
|
|||||||
selection: usize,
|
selection: usize,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
buffer: Vec<String>,
|
buffer: Vec<String>,
|
||||||
// dimensions: (u16, u16),
|
|
||||||
// position: (u16, u16),
|
|
||||||
coordinates: Coordinates,
|
coordinates: Coordinates,
|
||||||
seeking: bool,
|
seeking: bool,
|
||||||
}
|
}
|
||||||
@ -94,6 +92,12 @@ where
|
|||||||
let name = &file.name;
|
let name = &file.name;
|
||||||
let (size, unit) = file.calculate_size();
|
let (size, unit) = file.calculate_size();
|
||||||
|
|
||||||
|
let selection_gap = " ".to_string();
|
||||||
|
let (name, selection_color) = if file.is_selected() {
|
||||||
|
(selection_gap + name, crate::term::color_yellow())
|
||||||
|
} else { (name.clone(), "".to_string()) };
|
||||||
|
|
||||||
|
|
||||||
let xsize = self.get_size().xsize();
|
let xsize = self.get_size().xsize();
|
||||||
let sized_string = term::sized_string(&name, xsize);
|
let sized_string = term::sized_string(&name, xsize);
|
||||||
let size_pos = xsize - (size.to_string().len() as u16
|
let size_pos = xsize - (size.to_string().len() as u16
|
||||||
@ -105,13 +109,17 @@ where
|
|||||||
"{}{}{}{}{}{}{}",
|
"{}{}{}{}{}{}{}",
|
||||||
termion::cursor::Save,
|
termion::cursor::Save,
|
||||||
match &file.color {
|
match &file.color {
|
||||||
Some(color) => format!("{}{:padding$}",
|
Some(color) => format!("{}{}{:padding$}{}",
|
||||||
term::from_lscolor(color),
|
term::from_lscolor(color),
|
||||||
|
selection_color,
|
||||||
&sized_string,
|
&sized_string,
|
||||||
|
term::normal_color(),
|
||||||
padding = padding as usize),
|
padding = padding as usize),
|
||||||
_ => format!("{}{:padding$}",
|
_ => format!("{}{}{:padding$}{}",
|
||||||
term::normal_color(),
|
term::normal_color(),
|
||||||
|
selection_color,
|
||||||
&sized_string,
|
&sized_string,
|
||||||
|
term::normal_color(),
|
||||||
padding = padding as usize),
|
padding = padding as usize),
|
||||||
} ,
|
} ,
|
||||||
termion::cursor::Restore,
|
termion::cursor::Restore,
|
||||||
@ -135,6 +143,12 @@ where
|
|||||||
file
|
file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn selected_file_mut(&mut self) -> &mut File {
|
||||||
|
let selection = self.selection;
|
||||||
|
let file = &mut self.content.files[selection];
|
||||||
|
file
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clone_selected_file(&self) -> File {
|
pub fn clone_selected_file(&self) -> File {
|
||||||
let selection = self.selection;
|
let selection = self.selection;
|
||||||
let file = self.content[selection].clone();
|
let file = self.content[selection].clone();
|
||||||
@ -247,9 +261,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let file = self.clone_selected_file();
|
let file = self.clone_selected_file();
|
||||||
// self.content.dirs_first = dir_settings;
|
self.content.dirs_first = dir_settings;
|
||||||
// self.content.sort = sort_settings;
|
self.content.sort = sort_settings;
|
||||||
// self.content.sort();
|
self.content.sort();
|
||||||
self.select_file(&file);
|
self.select_file(&file);
|
||||||
self.seeking = true;
|
self.seeking = true;
|
||||||
|
|
||||||
@ -273,21 +287,44 @@ where
|
|||||||
self.show_status(&format!("Direcories first: {}", self.content.dirs_first));
|
self.show_status(&format!("Direcories first: {}", self.content.dirs_first));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn multi_select_file(&mut self) {
|
||||||
|
let file = self.selected_file_mut();
|
||||||
|
file.toggle_selection();
|
||||||
|
self.move_down();
|
||||||
|
self.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
fn exec_cmd(&mut self) {
|
fn exec_cmd(&mut self) {
|
||||||
match self.minibuffer("exec ($s for selected files)") {
|
let selected_files = self.content.get_selected();
|
||||||
|
let file_names
|
||||||
|
= selected_files.iter().map(|f| f.name.clone()).collect::<Vec<String>>();
|
||||||
|
|
||||||
|
match self.minibuffer("exec ($s for selected file(s))") {
|
||||||
Some(cmd) => {
|
Some(cmd) => {
|
||||||
self.show_status(&format!("Running: \"{}\"", &cmd));
|
self.show_status(&format!("Running: \"{}\"", &cmd));
|
||||||
|
|
||||||
let filename = self.selected_file().name.clone();
|
let filename = self.selected_file().name.clone();
|
||||||
let cmd = cmd.replace("$s", &format!("{}", &filename));
|
|
||||||
|
let cmd = if file_names.len() == 0 {
|
||||||
|
cmd.replace("$s", &format!("{}", &filename))
|
||||||
|
} else {
|
||||||
|
let args = file_names.iter().map(|f| {
|
||||||
|
format!(" \"{}\" ", f)
|
||||||
|
}).collect::<String>();
|
||||||
|
let clean_cmd = cmd.replace("$s", "");
|
||||||
|
|
||||||
|
clean_cmd + &args
|
||||||
|
};
|
||||||
|
|
||||||
let status = std::process::Command::new("sh")
|
let status = std::process::Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(&cmd)
|
.arg(&cmd)
|
||||||
.status();
|
.status();
|
||||||
match status {
|
match status {
|
||||||
Ok(status) => self.show_status(&format!("\"{}\" exited with {}", cmd, status)),
|
Ok(status) => self.show_status(&format!("\"{}\" exited with {}",
|
||||||
Err(err) => self.show_status(&format!("Can't run this \"{}\": {}", cmd, err)),
|
cmd, status)),
|
||||||
|
Err(err) => self.show_status(&format!("Can't run this \"{}\": {}",
|
||||||
|
cmd, err)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => self.show_status(""),
|
None => self.show_status(""),
|
||||||
@ -380,6 +417,7 @@ impl Widget for ListView<Files> {
|
|||||||
}
|
}
|
||||||
Key::Left => self.goto_grand_parent(),
|
Key::Left => self.goto_grand_parent(),
|
||||||
Key::Right => self.goto_selected(),
|
Key::Right => self.goto_selected(),
|
||||||
|
Key::Char(' ') => self.multi_select_file(),
|
||||||
Key::Char('h') => self.toggle_hidden(),
|
Key::Char('h') => self.toggle_hidden(),
|
||||||
Key::Char('r') => self.reverse_sort(),
|
Key::Char('r') => self.reverse_sort(),
|
||||||
Key::Char('s') => self.cycle_sort(),
|
Key::Char('s') => self.cycle_sort(),
|
||||||
|
@ -17,7 +17,6 @@ lazy_static! {
|
|||||||
fn kill_procs() {
|
fn kill_procs() {
|
||||||
let mut pids = PIDS.lock().unwrap();
|
let mut pids = PIDS.lock().unwrap();
|
||||||
for pid in &*pids {
|
for pid in &*pids {
|
||||||
let msg = format!("KILLING PROC: {}", pid);
|
|
||||||
unsafe { libc::kill(*pid, 9); }
|
unsafe { libc::kill(*pid, 9); }
|
||||||
}
|
}
|
||||||
pids.clear();
|
pids.clear();
|
||||||
|
@ -148,11 +148,12 @@ pub fn minibuffer(query: &str) -> Option<String> {
|
|||||||
return Some(buffer);
|
return Some(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Key::Char('\t') => buffer += "$s",
|
||||||
Key::Backspace => {
|
Key::Backspace => {
|
||||||
buffer.pop();
|
buffer.pop();
|
||||||
}
|
}
|
||||||
Key::Char(key) => {
|
Key::Char(key) => {
|
||||||
buffer = buffer + &format!("{}", key);
|
buffer += &format!("{}", key);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user