Format & lint code

pull/395/head
Arijit Basu 3 years ago committed by Arijit Basu
parent 2d7158afc0
commit a797d7b1c7

@ -14,12 +14,13 @@ const PWD: &str = "/tmp/xplr_bench";
fn navigation_benchmark(c: &mut Criterion) {
fs::create_dir_all(PWD).unwrap();
(1..10000).for_each(|i| {
fs::File::create(std::path::Path::new(PWD).join(i.to_string())).unwrap();
fs::File::create(std::path::Path::new(PWD).join(i.to_string()))
.unwrap();
});
let lua = mlua::Lua::new();
let mut app =
app::App::create(PWD.into(), &lua, None, [].into()).expect("failed to create app");
let mut app = app::App::create(PWD.into(), &lua, None, [].into())
.expect("failed to create app");
app = app
.clone()
@ -93,12 +94,13 @@ fn navigation_benchmark(c: &mut Criterion) {
fn draw_benchmark(c: &mut Criterion) {
fs::create_dir_all(PWD).unwrap();
(1..10000).for_each(|i| {
fs::File::create(std::path::Path::new(PWD).join(i.to_string())).unwrap();
fs::File::create(std::path::Path::new(PWD).join(i.to_string()))
.unwrap();
});
let lua = mlua::Lua::new();
let mut app =
app::App::create(PWD.into(), &lua, None, [].into()).expect("failed to create app");
let mut app = app::App::create(PWD.into(), &lua, None, [].into())
.expect("failed to create app");
app = app
.clone()

@ -0,0 +1,4 @@
edition = "2021"
max_width = 80
tab_spaces = 4
use_field_init_shorthand = true

@ -55,7 +55,8 @@ impl Pipe {
let msg_in = path.join("msg_in").to_string_lossy().to_string();
let selection_out = path.join("selection_out").to_string_lossy().to_string();
let selection_out =
path.join("selection_out").to_string_lossy().to_string();
let result_out = path.join("result_out").to_string_lossy().to_string();
@ -71,7 +72,8 @@ impl Pipe {
let logs_out = path.join("logs_out").to_string_lossy().to_string();
let history_out = path.join("history_out").to_string_lossy().to_string();
let history_out =
path.join("history_out").to_string_lossy().to_string();
Ok(Self {
path: path.to_string_lossy().to_string(),
@ -107,7 +109,9 @@ impl ResolvedNode {
let (is_dir, is_file, is_readonly, size) = path
.metadata()
.map(|m| (m.is_dir(), m.is_file(), m.permissions().readonly(), m.len()))
.map(|m| {
(m.is_dir(), m.is_file(), m.permissions().readonly(), m.len())
})
.unwrap_or((false, false, false, 0));
let mime_essence = mime_essence(&path, is_dir);
@ -164,19 +168,21 @@ impl Node {
.map(|p| (false, Some(ResolvedNode::from(p))))
.unwrap_or_else(|_| (true, None));
let (is_symlink, is_dir, is_file, is_readonly, size, permissions) = path
.symlink_metadata()
.map(|m| {
(
m.file_type().is_symlink(),
m.is_dir(),
m.is_file(),
m.permissions().readonly(),
m.len(),
Permissions::from(&m),
)
})
.unwrap_or_else(|_| (false, false, false, false, 0, Permissions::default()));
let (is_symlink, is_dir, is_file, is_readonly, size, permissions) =
path.symlink_metadata()
.map(|m| {
(
m.file_type().is_symlink(),
m.is_dir(),
m.is_file(),
m.permissions().readonly(),
m.len(),
Permissions::from(&m),
)
})
.unwrap_or_else(|_| {
(false, false, false, false, 0, Permissions::default())
});
let mime_essence = mime_essence(&path, is_dir);
let human_size = to_humansize(size);
@ -312,7 +318,9 @@ impl NodeSorterApplicable {
fn apply(&self, a: &Node, b: &Node) -> Ordering {
let order = match self.sorter {
NodeSorter::ByRelativePath => natord::compare(&a.relative_path, &b.relative_path),
NodeSorter::ByRelativePath => {
natord::compare(&a.relative_path, &b.relative_path)
}
NodeSorter::ByIRelativePath => {
natord::compare_ignore_case(&a.relative_path, &b.relative_path)
}
@ -336,16 +344,18 @@ impl NodeSorterApplicable {
.unwrap_or_default(),
),
NodeSorter::ByICanonicalAbsolutePath => natord::compare_ignore_case(
&a.canonical
.as_ref()
.map(|s| s.absolute_path.clone())
.unwrap_or_default(),
&b.canonical
.as_ref()
.map(|s| s.absolute_path.clone())
.unwrap_or_default(),
),
NodeSorter::ByICanonicalAbsolutePath => {
natord::compare_ignore_case(
&a.canonical
.as_ref()
.map(|s| s.absolute_path.clone())
.unwrap_or_default(),
&b.canonical
.as_ref()
.map(|s| s.absolute_path.clone())
.unwrap_or_default(),
)
}
NodeSorter::ByCanonicalExtension => a
.canonical
@ -505,18 +515,26 @@ impl NodeFilter {
fn apply(&self, node: &Node, input: &str) -> bool {
match self {
Self::RelativePathIs => node.relative_path.eq(input),
Self::IRelativePathIs => node.relative_path.eq_ignore_ascii_case(input),
Self::IRelativePathIs => {
node.relative_path.eq_ignore_ascii_case(input)
}
Self::RelativePathIsNot => !node.relative_path.eq(input),
Self::IRelativePathIsNot => !node.relative_path.eq_ignore_ascii_case(input),
Self::IRelativePathIsNot => {
!node.relative_path.eq_ignore_ascii_case(input)
}
Self::RelativePathDoesStartWith => node.relative_path.starts_with(input),
Self::RelativePathDoesStartWith => {
node.relative_path.starts_with(input)
}
Self::IRelativePathDoesStartWith => node
.relative_path
.to_lowercase()
.starts_with(&input.to_lowercase()),
Self::RelativePathDoesNotStartWith => !node.relative_path.starts_with(input),
Self::RelativePathDoesNotStartWith => {
!node.relative_path.starts_with(input)
}
Self::IRelativePathDoesNotStartWith => !node
.relative_path
@ -529,37 +547,51 @@ impl NodeFilter {
.to_lowercase()
.contains(&input.to_lowercase()),
Self::RelativePathDoesNotContain => !node.relative_path.contains(input),
Self::RelativePathDoesNotContain => {
!node.relative_path.contains(input)
}
Self::IRelativePathDoesNotContain => !node
.relative_path
.to_lowercase()
.contains(&input.to_lowercase()),
Self::RelativePathDoesEndWith => node.relative_path.ends_with(input),
Self::RelativePathDoesEndWith => {
node.relative_path.ends_with(input)
}
Self::IRelativePathDoesEndWith => node
.relative_path
.to_lowercase()
.ends_with(&input.to_lowercase()),
Self::RelativePathDoesNotEndWith => !node.relative_path.ends_with(input),
Self::RelativePathDoesNotEndWith => {
!node.relative_path.ends_with(input)
}
Self::IRelativePathDoesNotEndWith => !node
.relative_path
.to_lowercase()
.ends_with(&input.to_lowercase()),
Self::AbsolutePathIs => node.absolute_path.eq(input),
Self::IAbsolutePathIs => node.absolute_path.eq_ignore_ascii_case(input),
Self::IAbsolutePathIs => {
node.absolute_path.eq_ignore_ascii_case(input)
}
Self::AbsolutePathIsNot => !node.absolute_path.eq(input),
Self::IAbsolutePathIsNot => !node.absolute_path.eq_ignore_ascii_case(input),
Self::IAbsolutePathIsNot => {
!node.absolute_path.eq_ignore_ascii_case(input)
}
Self::AbsolutePathDoesStartWith => node.absolute_path.starts_with(input),
Self::AbsolutePathDoesStartWith => {
node.absolute_path.starts_with(input)
}
Self::IAbsolutePathDoesStartWith => node
.absolute_path
.to_lowercase()
.starts_with(&input.to_lowercase()),
Self::AbsolutePathDoesNotStartWith => !node.absolute_path.starts_with(input),
Self::AbsolutePathDoesNotStartWith => {
!node.absolute_path.starts_with(input)
}
Self::IAbsolutePathDoesNotStartWith => !node
.absolute_path
.to_lowercase()
@ -571,19 +603,25 @@ impl NodeFilter {
.to_lowercase()
.contains(&input.to_lowercase()),
Self::AbsolutePathDoesNotContain => !node.absolute_path.contains(input),
Self::AbsolutePathDoesNotContain => {
!node.absolute_path.contains(input)
}
Self::IAbsolutePathDoesNotContain => !node
.absolute_path
.to_lowercase()
.contains(&input.to_lowercase()),
Self::AbsolutePathDoesEndWith => node.absolute_path.ends_with(input),
Self::AbsolutePathDoesEndWith => {
node.absolute_path.ends_with(input)
}
Self::IAbsolutePathDoesEndWith => node
.absolute_path
.to_lowercase()
.ends_with(&input.to_lowercase()),
Self::AbsolutePathDoesNotEndWith => !node.absolute_path.ends_with(input),
Self::AbsolutePathDoesNotEndWith => {
!node.absolute_path.ends_with(input)
}
Self::IAbsolutePathDoesNotEndWith => !node
.absolute_path
.to_lowercase()
@ -1045,7 +1083,10 @@ impl ExternalMsg {
pub fn is_read_only(&self) -> bool {
!matches!(
self,
Self::Call(_) | Self::CallSilently(_) | Self::BashExec(_) | Self::BashExecSilently(_)
Self::Call(_)
| Self::CallSilently(_)
| Self::BashExec(_)
| Self::BashExecSilently(_)
)
}
}
@ -1236,7 +1277,8 @@ impl App {
None
}
} else {
let path = PathBuf::from("/").join("etc").join("xplr").join("init.lua");
let path =
PathBuf::from("/").join("etc").join("xplr").join("init.lua");
if path.exists() {
Some(path)
} else {
@ -1383,13 +1425,21 @@ impl App {
}
}
fn handle_external(self, msg: ExternalMsg, key: Option<Key>) -> Result<Self> {
fn handle_external(
self,
msg: ExternalMsg,
key: Option<Key>,
) -> Result<Self> {
if self.config.general.read_only && !msg.is_read_only() {
self.log_error("Cannot call shell command in read-only mode.".into())
self.log_error(
"Cannot call shell command in read-only mode.".into(),
)
} else {
match msg {
ExternalMsg::ExplorePwd => self.explore_pwd(),
ExternalMsg::ExploreParentsAsync => self.explore_parents_async(),
ExternalMsg::ExploreParentsAsync => {
self.explore_parents_async()
}
ExternalMsg::ExplorePwdAsync => self.explore_pwd_async(),
ExternalMsg::Refresh => self.refresh(),
ExternalMsg::ClearScreen => self.clear_screen(),
@ -1404,52 +1454,80 @@ impl App {
self.focus_previous_by_relative_index_from_input()
}
ExternalMsg::FocusNext => self.focus_next(),
ExternalMsg::FocusNextByRelativeIndex(i) => self.focus_next_by_relative_index(i),
ExternalMsg::FocusNextByRelativeIndex(i) => {
self.focus_next_by_relative_index(i)
}
ExternalMsg::FocusNextByRelativeIndexFromInput => {
self.focus_next_by_relative_index_from_input()
}
ExternalMsg::FocusPath(p) => self.focus_path(&p, true),
ExternalMsg::FocusPathFromInput => self.focus_path_from_input(),
ExternalMsg::FocusByIndex(i) => self.focus_by_index(i),
ExternalMsg::FocusByIndexFromInput => self.focus_by_index_from_input(),
ExternalMsg::FocusByFileName(n) => self.focus_by_file_name(&n, true),
ExternalMsg::ChangeDirectory(dir) => self.change_directory(&dir, true),
ExternalMsg::FocusByIndexFromInput => {
self.focus_by_index_from_input()
}
ExternalMsg::FocusByFileName(n) => {
self.focus_by_file_name(&n, true)
}
ExternalMsg::ChangeDirectory(dir) => {
self.change_directory(&dir, true)
}
ExternalMsg::Enter => self.enter(),
ExternalMsg::Back => self.back(),
ExternalMsg::LastVisitedPath => self.last_visited_path(),
ExternalMsg::NextVisitedPath => self.next_visited_path(),
ExternalMsg::FollowSymlink => self.follow_symlink(),
ExternalMsg::BufferInput(input) => self.buffer_input(&input),
ExternalMsg::BufferInputFromKey => self.buffer_input_from_key(key),
ExternalMsg::SetInputBuffer(input) => self.set_input_buffer(input),
ExternalMsg::BufferInputFromKey => {
self.buffer_input_from_key(key)
}
ExternalMsg::SetInputBuffer(input) => {
self.set_input_buffer(input)
}
ExternalMsg::RemoveInputBufferLastCharacter => {
self.remove_input_buffer_last_character()
}
ExternalMsg::RemoveInputBufferLastWord => self.remove_input_buffer_last_word(),
ExternalMsg::RemoveInputBufferLastWord => {
self.remove_input_buffer_last_word()
}
ExternalMsg::ResetInputBuffer => self.reset_input_buffer(),
ExternalMsg::SwitchMode(mode) => self.switch_mode(&mode),
ExternalMsg::SwitchModeKeepingInputBuffer(mode) => {
self.switch_mode_keeping_input_buffer(&mode)
}
ExternalMsg::SwitchModeBuiltin(mode) => self.switch_mode_builtin(&mode),
ExternalMsg::SwitchModeBuiltin(mode) => {
self.switch_mode_builtin(&mode)
}
ExternalMsg::SwitchModeBuiltinKeepingInputBuffer(mode) => {
self.switch_mode_builtin_keeping_input_buffer(&mode)
}
ExternalMsg::SwitchModeCustom(mode) => self.switch_mode_custom(&mode),
ExternalMsg::SwitchModeCustom(mode) => {
self.switch_mode_custom(&mode)
}
ExternalMsg::SwitchModeCustomKeepingInputBuffer(mode) => {
self.switch_mode_custom_keeping_input_buffer(&mode)
}
ExternalMsg::PopMode => self.pop_mode(),
ExternalMsg::PopModeKeepingInputBuffer => self.pop_mode_keeping_input_buffer(),
ExternalMsg::PopModeKeepingInputBuffer => {
self.pop_mode_keeping_input_buffer()
}
ExternalMsg::SwitchLayout(mode) => self.switch_layout(&mode),
ExternalMsg::SwitchLayoutBuiltin(mode) => self.switch_layout_builtin(&mode),
ExternalMsg::SwitchLayoutCustom(mode) => self.switch_layout_custom(&mode),
ExternalMsg::SwitchLayoutBuiltin(mode) => {
self.switch_layout_builtin(&mode)
}
ExternalMsg::SwitchLayoutCustom(mode) => {
self.switch_layout_custom(&mode)
}
ExternalMsg::Call(cmd) => self.call(cmd),
ExternalMsg::CallSilently(cmd) => self.call_silently(cmd),
ExternalMsg::CallLua(func) => self.call_lua(func),
ExternalMsg::CallLuaSilently(func) => self.call_lua_silently(func),
ExternalMsg::CallLuaSilently(func) => {
self.call_lua_silently(func)
}
ExternalMsg::BashExec(cmd) => self.bash_exec(cmd),
ExternalMsg::BashExecSilently(cmd) => self.bash_exec_silently(cmd),
ExternalMsg::BashExecSilently(cmd) => {
self.bash_exec_silently(cmd)
}
ExternalMsg::Select => self.select(),
ExternalMsg::SelectAll => self.select_all(),
ExternalMsg::SelectPath(p) => self.select_path(p),
@ -1458,21 +1536,33 @@ impl App {
ExternalMsg::UnSelectPath(p) => self.un_select_path(p),
ExternalMsg::ToggleSelection => self.toggle_selection(),
ExternalMsg::ToggleSelectAll => self.toggle_select_all(),
ExternalMsg::ToggleSelectionByPath(p) => self.toggle_selection_by_path(p),
ExternalMsg::ToggleSelectionByPath(p) => {
self.toggle_selection_by_path(p)
}
ExternalMsg::ClearSelection => self.clear_selection(),
ExternalMsg::AddNodeFilter(f) => self.add_node_filter(f),
ExternalMsg::AddNodeFilterFromInput(f) => self.add_node_filter_from_input(f),
ExternalMsg::AddNodeFilterFromInput(f) => {
self.add_node_filter_from_input(f)
}
ExternalMsg::RemoveNodeFilter(f) => self.remove_node_filter(f),
ExternalMsg::RemoveNodeFilterFromInput(f) => self.remove_node_filter_from_input(f),
ExternalMsg::RemoveNodeFilterFromInput(f) => {
self.remove_node_filter_from_input(f)
}
ExternalMsg::ToggleNodeFilter(f) => self.toggle_node_filter(f),
ExternalMsg::RemoveLastNodeFilter => self.remove_last_node_filter(),
ExternalMsg::RemoveLastNodeFilter => {
self.remove_last_node_filter()
}
ExternalMsg::ResetNodeFilters => self.reset_node_filters(),
ExternalMsg::ClearNodeFilters => self.clear_node_filters(),
ExternalMsg::AddNodeSorter(f) => self.add_node_sorter(f),
ExternalMsg::RemoveNodeSorter(f) => self.remove_node_sorter(f),
ExternalMsg::ReverseNodeSorter(f) => self.reverse_node_sorter(f),
ExternalMsg::ReverseNodeSorter(f) => {
self.reverse_node_sorter(f)
}
ExternalMsg::ToggleNodeSorter(f) => self.toggle_node_sorter(f),
ExternalMsg::RemoveLastNodeSorter => self.remove_last_node_sorter(),
ExternalMsg::RemoveLastNodeSorter => {
self.remove_last_node_sorter()
}
ExternalMsg::ReverseNodeSorters => self.reverse_node_sorters(),
ExternalMsg::ResetNodeSorters => self.reset_node_sorters(),
ExternalMsg::ClearNodeSorters => self.clear_node_sorters(),
@ -1488,10 +1578,16 @@ impl App {
ExternalMsg::LogError(l) => self.log_error(l),
ExternalMsg::Quit => self.quit(),
ExternalMsg::PrintPwdAndQuit => self.print_pwd_and_quit(),
ExternalMsg::PrintFocusPathAndQuit => self.print_focus_path_and_quit(),
ExternalMsg::PrintSelectionAndQuit => self.print_selection_and_quit(),
ExternalMsg::PrintFocusPathAndQuit => {
self.print_focus_path_and_quit()
}
ExternalMsg::PrintSelectionAndQuit => {
self.print_selection_and_quit()
}
ExternalMsg::PrintResultAndQuit => self.print_result_and_quit(),
ExternalMsg::PrintAppStateAndQuit => self.print_app_state_and_quit(),
ExternalMsg::PrintAppStateAndQuit => {
self.print_app_state_and_quit()
}
ExternalMsg::Debug(path) => self.debug(path),
ExternalMsg::Terminate => bail!(""),
}
@ -1615,7 +1711,10 @@ impl App {
Ok(self)
}
fn focus_previous_by_relative_index(mut self, index: usize) -> Result<Self> {
fn focus_previous_by_relative_index(
mut self,
index: usize,
) -> Result<Self> {
let mut history = self.history.clone();
if let Some(dir) = self.directory_buffer_mut() {
if let Some(n) = dir.focused_node() {
@ -1691,7 +1790,11 @@ impl App {
}
}
fn change_directory(mut self, dir: &str, save_history: bool) -> Result<Self> {
fn change_directory(
mut self,
dir: &str,
save_history: bool,
) -> Result<Self> {
let mut dir = PathBuf::from(dir);
if dir.is_relative() {
dir = PathBuf::from(self.pwd.clone()).join(dir);
@ -1700,7 +1803,8 @@ impl App {
match env::set_current_dir(&dir) {
Ok(()) => {
let pwd = self.pwd.clone();
let focus = self.focused_node().map(|n| n.relative_path.clone());
let focus =
self.focused_node().map(|n| n.relative_path.clone());
self = self.add_last_focus(pwd, focus)?;
self.pwd = dir.to_string_lossy().to_string();
if save_history {
@ -1841,7 +1945,11 @@ impl App {
}
}
pub fn focus_by_file_name(mut self, name: &str, save_history: bool) -> Result<Self> {
pub fn focus_by_file_name(
mut self,
name: &str,
save_history: bool,
) -> Result<Self> {
let mut history = self.history.clone();
if let Some(dir_buf) = self.directory_buffer_mut() {
if let Some(focus) = dir_buf
@ -1879,8 +1987,14 @@ impl App {
}
if let Some(parent) = pathbuf.parent() {
if let Some(filename) = pathbuf.file_name() {
self.change_directory(&parent.to_string_lossy().to_string(), false)?
.focus_by_file_name(&filename.to_string_lossy().to_string(), save_history)
self.change_directory(
&parent.to_string_lossy().to_string(),
false,
)?
.focus_by_file_name(
&filename.to_string_lossy().to_string(),
save_history,
)
} else {
self.log_error(format!("{} not found", path))
}
@ -1949,7 +2063,10 @@ impl App {
})
}
fn switch_mode_builtin_keeping_input_buffer(mut self, mode: &str) -> Result<Self> {
fn switch_mode_builtin_keeping_input_buffer(
mut self,
mode: &str,
) -> Result<Self> {
if let Some(mode) = self.config.modes.builtin.get(mode).cloned() {
self = self.push_mode();
self.mode = mode.sanitized(self.config.general.read_only);
@ -1967,7 +2084,10 @@ impl App {
})
}
fn switch_mode_custom_keeping_input_buffer(mut self, mode: &str) -> Result<Self> {
fn switch_mode_custom_keeping_input_buffer(
mut self,
mode: &str,
) -> Result<Self> {
if let Some(mode) = self.config.modes.custom.get(mode).cloned() {
self = self.push_mode();
self.mode = mode.sanitized(self.config.general.read_only);
@ -2053,7 +2173,11 @@ impl App {
Ok(self)
}
pub fn add_last_focus(mut self, parent: String, focused_path: Option<String>) -> Result<Self> {
pub fn add_last_focus(
mut self,
parent: String,
focused_path: Option<String>,
) -> Result<Self> {
self.last_focus.insert(parent, focused_path);
Ok(self)
}
@ -2071,7 +2195,8 @@ impl App {
path = PathBuf::from(self.pwd.clone()).join(path);
}
let parent = path.parent().map(|p| p.to_string_lossy().to_string());
let filename = path.file_name().map(|p| p.to_string_lossy().to_string());
let filename =
path.file_name().map(|p| p.to_string_lossy().to_string());
if let (Some(p), Some(n)) = (parent, filename) {
self.selection.insert(Node::new(p, n));
}
@ -2161,7 +2286,10 @@ impl App {
Ok(self)
}
fn add_node_filter_from_input(mut self, filter: NodeFilter) -> Result<Self> {
fn add_node_filter_from_input(
mut self,
filter: NodeFilter,
) -> Result<Self> {
if let Some(input) = self.input_buffer.clone() {
self.explorer_config
.filters
@ -2170,12 +2298,18 @@ impl App {
Ok(self)
}
fn remove_node_filter(mut self, filter: NodeFilterApplicable) -> Result<Self> {
fn remove_node_filter(
mut self,
filter: NodeFilterApplicable,
) -> Result<Self> {
self.explorer_config.filters.retain(|f| f != &filter);
Ok(self)
}
fn remove_node_filter_from_input(mut self, filter: NodeFilter) -> Result<Self> {
fn remove_node_filter_from_input(
mut self,
filter: NodeFilter,
) -> Result<Self> {
if let Some(input) = self.input_buffer.clone() {
let nfa = NodeFilterApplicable::new(filter, input);
self.explorer_config.filters.retain(|f| f != &nfa);
@ -2370,8 +2504,9 @@ impl App {
fn refresh_selection(mut self) -> Result<Self> {
// Should be able to select broken symlink
self.selection
.retain(|n| PathBuf::from(&n.absolute_path).symlink_metadata().is_ok());
self.selection.retain(|n| {
PathBuf::from(&n.absolute_path).symlink_metadata().is_ok()
});
Ok(self)
}

@ -66,7 +66,9 @@ impl Cli {
}
// Options
"-c" | "--config" => cli.config = args.pop_front().map(PathBuf::from),
"-c" | "--config" => {
cli.config = args.pop_front().map(PathBuf::from)
}
"-C" | "--extra-config" => {
while let Some(path) = args.pop_front() {

@ -298,8 +298,10 @@ impl KeyBindings {
.filter_map(|(k, a)| a.sanitized(read_only).map(|a| (k, a)))
.collect();
self.on_alphabet = self.on_alphabet.and_then(|a| a.sanitized(read_only));
self.on_number = self.on_number.and_then(|a| a.sanitized(read_only));
self.on_alphabet =
self.on_alphabet.and_then(|a| a.sanitized(read_only));
self.on_number =
self.on_number.and_then(|a| a.sanitized(read_only));
self.on_special_character = self
.on_special_character
.and_then(|a| a.sanitized(read_only));
@ -353,32 +355,36 @@ impl Mode {
let lines = extra_help_lines
.unwrap_or_default()
.into_iter()
.chain(self.key_bindings.on_key.iter().filter_map(|(k, a)| {
let remaps = self
.key_bindings
.on_key
.iter()
.filter_map(|(rk, ra)| {
if rk == k {
None
} else if a == ra {
Some(rk.clone())
} else {
None
}
.chain(self.key_bindings.on_key.iter().filter_map(
|(k, a)| {
let remaps = self
.key_bindings
.on_key
.iter()
.filter_map(|(rk, ra)| {
if rk == k {
None
} else if a == ra {
Some(rk.clone())
} else {
None
}
})
.collect::<Vec<String>>();
a.help.clone().map(|h| {
HelpMenuLine::KeyMap(k.into(), remaps, h)
})
.collect::<Vec<String>>();
a.help
.clone()
.map(|h| HelpMenuLine::KeyMap(k.into(), remaps, h))
}))
},
))
.chain(
self.key_bindings
.on_alphabet
.iter()
.map(|a| ("[a-Z]", a.help.clone()))
.filter_map(|(k, mh)| {
mh.map(|h| HelpMenuLine::KeyMap(k.into(), vec![], h))
mh.map(|h| {
HelpMenuLine::KeyMap(k.into(), vec![], h)
})
}),
)
.chain(
@ -387,7 +393,9 @@ impl Mode {
.iter()
.map(|a| ("[0-9]", a.help.clone()))
.filter_map(|(k, mh)| {
mh.map(|h| HelpMenuLine::KeyMap(k.into(), vec![], h))
mh.map(|h| {
HelpMenuLine::KeyMap(k.into(), vec![], h)
})
}),
)
.chain(
@ -396,7 +404,9 @@ impl Mode {
.iter()
.map(|a| ("[spcl chars]", a.help.clone()))
.filter_map(|(k, mh)| {
mh.map(|h| HelpMenuLine::KeyMap(k.into(), vec![], h))
mh.map(|h| {
HelpMenuLine::KeyMap(k.into(), vec![], h)
})
}),
)
.chain(
@ -405,7 +415,9 @@ impl Mode {
.iter()
.map(|a| ("[default]", a.help.clone()))
.filter_map(|(k, mh)| {
mh.map(|h| HelpMenuLine::KeyMap(k.into(), vec![], h))
mh.map(|h| {
HelpMenuLine::KeyMap(k.into(), vec![], h)
})
}),
);
@ -414,7 +426,9 @@ impl Mode {
for line in lines {
match line {
HelpMenuLine::Paragraph(p) => result.push(HelpMenuLine::Paragraph(p)),
HelpMenuLine::Paragraph(p) => {
result.push(HelpMenuLine::Paragraph(p))
}
HelpMenuLine::KeyMap(k, r, d) => {
if !remapped.contains(&k) {
for k in r.iter() {
@ -510,10 +524,18 @@ impl BuiltinModesConfig {
"search" => Some(&self.search),
"sort" => Some(&self.sort),
"filter" => Some(&self.filter),
"relative_path_does_contain" => Some(&self.relative_path_does_contain),
"relative path does contain" => Some(&self.relative_path_does_contain),
"relative_path_does_not_contain" => Some(&self.relative_path_does_not_contain),
"relative path does not contain" => Some(&self.relative_path_does_not_contain),
"relative_path_does_contain" => {
Some(&self.relative_path_does_contain)
}
"relative path does contain" => {
Some(&self.relative_path_does_contain)
}
"relative_path_does_not_contain" => {
Some(&self.relative_path_does_not_contain)
}
"relative path does not contain" => {
Some(&self.relative_path_does_not_contain)
}
"switch layout" => Some(&self.switch_layout),
"switch_layout" => Some(&self.switch_layout),
"quit" => Some(&self.quit),

@ -40,12 +40,18 @@ impl EventReader {
}
}
fn keep_reading(tx_msg_in: Sender<Task>, rx_stopper: Receiver<bool>, tx_ack: Sender<()>) {
fn keep_reading(
tx_msg_in: Sender<Task>,
rx_stopper: Receiver<bool>,
tx_ack: Sender<()>,
) {
loop {
if rx_stopper.try_recv().unwrap_or(false) {
tx_ack.send(()).unwrap();
break;
} else if event::poll(std::time::Duration::from_millis(150)).unwrap_or_default() {
} else if event::poll(std::time::Duration::from_millis(150))
.unwrap_or_default()
{
// NOTE: The poll timeout need to stay low, else spawning sub subshell
// and start typing immediately will cause panic.
// To reproduce, press `:`, then press and hold `!`.

@ -1,5 +1,8 @@
use crate::app::{DirectoryBuffer, ExplorerConfig, ExternalMsg, InternalMsg, MsgIn, Node, Task};
use anyhow::{Result, Error};
use crate::app::{
DirectoryBuffer, ExplorerConfig, ExternalMsg, InternalMsg, MsgIn, Node,
Task,
};
use anyhow::{Error, Result};
use std::fs;
use std::path::PathBuf;
use std::sync::mpsc::Sender;

@ -32,7 +32,11 @@ pub fn check_version(version: &str, path: &str) -> Result<()> {
let (rmajor, rminor, rbugfix, rbeta) = parse_version(VERSION)?;
let (smajor, sminor, sbugfix, sbeta) = parse_version(version)?;
if rmajor == smajor && rminor == sminor && rbugfix >= sbugfix && rbeta == sbeta {
if rmajor == smajor
&& rminor == sminor
&& rbugfix >= sbugfix
&& rbeta == sbeta
{
Ok(())
} else {
bail!(
@ -61,7 +65,10 @@ fn resolve_fn_recursive<'lua, 'a>(
}
/// This function resolves paths like `builtin.func_foo`, `custom.func_bar` into lua functions.
pub fn resolve_fn<'lua>(globals: &mlua::Table<'lua>, path: &str) -> Result<mlua::Function<'lua>> {
pub fn resolve_fn<'lua>(
globals: &mlua::Table<'lua>,
path: &str,
) -> Result<mlua::Function<'lua>> {
let path = format!("xplr.fn.{}", path);
resolve_fn_recursive(globals, path.split('.'))
}
@ -98,10 +105,11 @@ pub fn extend(lua: &Lua, path: &str) -> Result<Config> {
lua.load(&script).set_name("init")?.exec()?;
let version: String = match globals.get("version").and_then(|v| lua.from_value(v)) {
Ok(v) => v,
Err(_) => bail!("'version' must be defined globally in {}", path),
};
let version: String =
match globals.get("version").and_then(|v| lua.from_value(v)) {
Ok(v) => v,
Err(_) => bail!("'version' must be defined globally in {}", path),
};
check_version(&version, path)?;

@ -3,7 +3,9 @@
use serde::{Deserialize, Serialize};
use std::fs::Metadata;
#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize, Hash, Default)]
#[derive(
Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize, Hash, Default,
)]
pub struct Permissions {
pub user_read: bool,
pub user_write: bool,

@ -17,27 +17,25 @@ pub fn keep_watching(
thread::spawn(move || loop {
if let Ok(new_pwd) = rx_pwd_watcher.try_recv() {
pwd = PathBuf::from(new_pwd);
} else {
if let Err(e) = pwd
.metadata()
.map_err(Error::new)
.and_then(|m| m.modified().map_err(Error::new))
.and_then(|modified| {
if modified != last_modified {
let msg = MsgIn::External(ExternalMsg::ExplorePwdAsync);
last_modified = modified;
tx_msg_in.send(Task::new(msg, None)).map_err(Error::new)
} else {
thread::sleep(Duration::from_secs(1));
Result::Ok(())
}
})
{
let msg = MsgIn::External(ExternalMsg::LogError(e.to_string()));
tx_msg_in.send(Task::new(msg, None)).unwrap_or_default();
thread::sleep(Duration::from_secs(1));
};
};
} else if let Err(e) = pwd
.metadata()
.map_err(Error::new)
.and_then(|m| m.modified().map_err(Error::new))
.and_then(|modified| {
if modified != last_modified {
let msg = MsgIn::External(ExternalMsg::ExplorePwdAsync);
last_modified = modified;
tx_msg_in.send(Task::new(msg, None)).map_err(Error::new)
} else {
thread::sleep(Duration::from_secs(1));
Result::Ok(())
}
})
{
let msg = MsgIn::External(ExternalMsg::LogError(e.to_string()));
tx_msg_in.send(Task::new(msg, None)).unwrap_or_default();
thread::sleep(Duration::from_secs(1));
}
});
Ok(())
}

@ -151,7 +151,12 @@ impl Runner {
pub fn run(self) -> Result<Option<String>> {
// Why unsafe? See https://github.com/sayanarijit/xplr/issues/309
let lua = unsafe { mlua::Lua::unsafe_new() };
let mut app = app::App::create(self.pwd, &lua, self.config_file, self.extra_config_files)?;
let mut app = app::App::create(
self.pwd,
&lua,
self.config_file,
self.extra_config_files,
)?;
app.config.general.read_only = self.read_only;
fs::create_dir_all(app.session_path.clone())?;
@ -191,19 +196,19 @@ impl Runner {
// let mut stdout = stdout.lock();
execute!(stdout, term::EnterAlternateScreen)?;
let mut fifo: Option<fs::File> = if let Some(path) = app.config.general.start_fifo.as_ref()
{
// TODO remove duplicate segment
match start_fifo(path, &app.focused_node_str()) {
Ok(file) => Some(file),
Err(e) => {
app = app.log_error(e.to_string())?;
None
let mut fifo: Option<fs::File> =
if let Some(path) = app.config.general.start_fifo.as_ref() {
// TODO remove duplicate segment
match start_fifo(path, &app.focused_node_str()) {
Ok(file) => Some(file),
Err(e) => {
app = app.log_error(e.to_string())?;
None
}
}
}
} else {
None
};
} else {
None
};
let mut last_focus: Option<app::Node> = None;
@ -219,7 +224,11 @@ impl Runner {
terminal.hide_cursor()?;
// Threads
pwd_watcher::keep_watching(app.pwd.as_ref(), tx_msg_in.clone(), rx_pwd_watcher)?;
pwd_watcher::keep_watching(
app.pwd.as_ref(),
tx_msg_in.clone(),
rx_pwd_watcher,
)?;
let mut event_reader = EventReader::new(tx_msg_in.clone());
event_reader.start();
@ -291,8 +300,13 @@ impl Runner {
explorer::explore_async(
app.explorer_config.clone(),
app.pwd.clone().into(),
app.focused_node().map(|n| n.relative_path.clone().into()),
app.directory_buffer.as_ref().map(|d| d.focus).unwrap_or(0),
app.focused_node().map(|n| {
n.relative_path.clone().into()
}),
app.directory_buffer
.as_ref()
.map(|d| d.focus)
.unwrap_or(0),
tx_msg_in.clone(),
);
tx_pwd_watcher.send(app.pwd.clone())?;
@ -302,8 +316,13 @@ impl Runner {
explorer::explore_recursive_async(
app.explorer_config.clone(),
app.pwd.clone().into(),
app.focused_node().map(|n| n.relative_path.clone().into()),
app.directory_buffer.as_ref().map(|d| d.focus).unwrap_or(0),
app.focused_node().map(|n| {
n.relative_path.clone().into()
}),
app.directory_buffer
.as_ref()
.map(|d| d.focus)
.unwrap_or(0),
tx_msg_in.clone(),
);
tx_pwd_watcher.send(app.pwd.clone())?;
@ -318,7 +337,11 @@ impl Runner {
let focus = app.focused_node();
if focus != last_focus.as_ref() {
if let Some(ref mut file) = fifo {
writeln!(file, "{}", app.focused_node_str())?;
writeln!(
file,
"{}",
app.focused_node_str()
)?;
};
last_focus = focus.cloned();
}
@ -334,7 +357,8 @@ impl Runner {
mouse_enabled = true;
}
Err(e) => {
app = app.log_error(e.to_string())?;
app =
app.log_error(e.to_string())?;
}
}
}
@ -346,8 +370,10 @@ impl Runner {
} else {
app::ExternalMsg::EnableMouse
};
app = app
.handle_task(app::Task::new(app::MsgIn::External(msg), None))?;
app = app.handle_task(app::Task::new(
app::MsgIn::External(msg),
None,
))?;
}
DisableMouse => {
@ -360,14 +386,18 @@ impl Runner {
mouse_enabled = false;
}
Err(e) => {
app = app.log_error(e.to_string())?;
app =
app.log_error(e.to_string())?;
}
}
}
}
StartFifo(path) => {
fifo = match start_fifo(&path, &app.focused_node_str()) {
fifo = match start_fifo(
&path,
&app.focused_node_str(),
) {
Ok(file) => Some(file),
Err(e) => {
app = app.log_error(e.to_string())?;
@ -388,10 +418,14 @@ impl Runner {
fifo = None;
std::mem::drop(file);
} else {
fifo = match start_fifo(&path, &app.focused_node_str()) {
fifo = match start_fifo(
&path,
&app.focused_node_str(),
) {
Ok(file) => Some(file),
Err(e) => {
app = app.log_error(e.to_string())?;
app =
app.log_error(e.to_string())?;
None
}
}
@ -402,10 +436,12 @@ impl Runner {
match call_lua(&app, &lua, &func, false) {
Ok(Some(msgs)) => {
for msg in msgs {
app = app.handle_task(app::Task::new(
app::MsgIn::External(msg),
None,
))?;
app = app.handle_task(
app::Task::new(
app::MsgIn::External(msg),
None,
),
)?;
}
}
Ok(None) => {}
@ -422,7 +458,10 @@ impl Runner {
if s.success() {
Ok(())
} else {
Err(format!("process exited with code {}", &s))
Err(format!(
"process exited with code {}",
&s
))
}
})
.unwrap_or_else(|e| Err(e.to_string()));
@ -430,10 +469,12 @@ impl Runner {
match pipe_reader::read_all(&app.pipe.msg_in) {
Ok(msgs) => {
for msg in msgs {
app = app.handle_task(app::Task::new(
app::MsgIn::External(msg),
None,
))?;
app = app.handle_task(
app::Task::new(
app::MsgIn::External(msg),
None,
),
)?;
}
}
Err(err) => {
@ -449,8 +490,11 @@ impl Runner {
}
CallLua(func) => {
execute!(terminal.backend_mut(), event::DisableMouseCapture)
.unwrap_or_default();
execute!(
terminal.backend_mut(),
event::DisableMouseCapture
)
.unwrap_or_default();
event_reader.stop();
@ -462,10 +506,12 @@ impl Runner {
match call_lua(&app, &lua, &func, false) {
Ok(Some(msgs)) => {
for msg in msgs {
app = app.handle_task(app::Task::new(
app::MsgIn::External(msg),
None,
))?;
app = app.handle_task(
app::Task::new(
app::MsgIn::External(msg),
None,
),
)?;
}
}
Ok(None) => {}
@ -488,15 +534,19 @@ impl Runner {
mouse_enabled = true;
}
Err(e) => {
app = app.log_error(e.to_string())?;
app =
app.log_error(e.to_string())?;
}
}
}
}
Call(cmd) => {
execute!(terminal.backend_mut(), event::DisableMouseCapture)
.unwrap_or_default();
execute!(
terminal.backend_mut(),
event::DisableMouseCapture
)
.unwrap_or_default();
event_reader.stop();
@ -511,7 +561,10 @@ impl Runner {
if s.success() {
Ok(())
} else {
Err(format!("process exited with code {}", &s))
Err(format!(
"process exited with code {}",
&s
))
}
})
.unwrap_or_else(|e| Err(e.to_string()));
@ -520,10 +573,12 @@ impl Runner {
match pipe_reader::read_all(&app.pipe.msg_in) {
Ok(msgs) => {
for msg in msgs {
app = app.handle_task(app::Task::new(
app::MsgIn::External(msg),
None,
))?;
app = app.handle_task(
app::Task::new(
app::MsgIn::External(msg),
None,
),
)?;
}
}
Err(err) => {
@ -551,7 +606,8 @@ impl Runner {
mouse_enabled = true;
}
Err(e) => {
app = app.log_error(e.to_string())?;
app =
app.log_error(e.to_string())?;
}
}
}
@ -570,7 +626,8 @@ impl Runner {
terminal.clear()?;
terminal.set_cursor(0, 0)?;
execute!(terminal.backend_mut(), term::LeaveAlternateScreen)?;
execute!(terminal.backend_mut(), event::DisableMouseCapture).unwrap_or_default();
execute!(terminal.backend_mut(), event::DisableMouseCapture)
.unwrap_or_default();
term::disable_raw_mode()?;
terminal.show_cursor()?;

@ -17,10 +17,14 @@ use std::env;
use std::ops::BitXor;
use tui::backend::Backend;
use tui::layout::Rect as TuiRect;
use tui::layout::{Constraint as TuiConstraint, Direction, Layout as TuiLayout};
use tui::layout::{
Constraint as TuiConstraint, Direction, Layout as TuiLayout,
};
use tui::style::{Color, Modifier as TuiModifier, Style as TuiStyle};
use tui::text::{Span, Spans, Text};
use tui::widgets::{Block, Borders as TuiBorders, Cell, List, ListItem, Paragraph, Row, Table};
use tui::widgets::{
Block, Borders as TuiBorders, Cell, List, ListItem, Paragraph, Row, Table,
};
use tui::Frame;
lazy_static! {
@ -55,7 +59,8 @@ pub struct LayoutOptions {
impl LayoutOptions {
pub fn extend(mut self, other: &Self) -> Self {
self.margin = other.margin.or(self.margin);
self.horizontal_margin = other.horizontal_margin.or(self.horizontal_margin);
self.horizontal_margin =
other.horizontal_margin.or(self.horizontal_margin);
self.vertical_margin = other.vertical_margin.or(self.vertical_margin);
self.constraints = other.constraints.to_owned().or(self.constraints);
self
@ -157,7 +162,9 @@ impl Layout {
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Serialize, Deserialize)]
#[derive(
Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Serialize, Deserialize,
)]
#[serde(deny_unknown_fields)]
pub enum Border {
Top,
@ -177,7 +184,9 @@ impl Border {
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Serialize, Deserialize)]
#[derive(
Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Serialize, Deserialize,
)]
#[serde(deny_unknown_fields)]
pub enum Modifier {
Bold,
@ -220,8 +229,10 @@ impl Style {
pub fn extend(mut self, other: &Self) -> Self {
self.fg = other.fg.or(self.fg);
self.bg = other.bg.or(self.bg);
self.add_modifiers = other.add_modifiers.to_owned().or(self.add_modifiers);
self.sub_modifiers = other.sub_modifiers.to_owned().or(self.sub_modifiers);
self.add_modifiers =
other.add_modifiers.to_owned().or(self.add_modifiers);
self.sub_modifiers =
other.sub_modifiers.to_owned().or(self.sub_modifiers);
self
}
}
@ -241,8 +252,12 @@ impl Into<TuiStyle> for Style {
TuiStyle {
fg: self.fg,
bg: self.bg,
add_modifier: TuiModifier::from_bits_truncate(xor(self.add_modifiers)),
sub_modifier: TuiModifier::from_bits_truncate(xor(self.sub_modifiers)),
add_modifier: TuiModifier::from_bits_truncate(xor(
self.add_modifiers
)),
sub_modifier: TuiModifier::from_bits_truncate(xor(
self.sub_modifiers
)),
}
}
}
@ -271,7 +286,11 @@ pub enum Constraint {
}
impl Constraint {
pub fn to_tui(self, screen_size: TuiRect, layout_size: TuiRect) -> TuiConstraint {
pub fn to_tui(
self,
screen_size: TuiRect,
layout_size: TuiRect,
) -> TuiConstraint {
match self {
Self::Percentage(n) => TuiConstraint::Percentage(n),
Self::Ratio(x, y) => TuiConstraint::Ratio(x, y),
@ -289,15 +308,31 @@ impl Constraint {
TuiConstraint::Length(layout_size.width.max(n) - n)
}
Self::Max(n) => TuiConstraint::Max(n),
Self::MaxLessThanScreenHeight(n) => TuiConstraint::Max(screen_size.height.max(n) - n),
Self::MaxLessThanScreenWidth(n) => TuiConstraint::Max(screen_size.width.max(n) - n),
Self::MaxLessThanLayoutHeight(n) => TuiConstraint::Max(layout_size.height.max(n) - n),
Self::MaxLessThanLayoutWidth(n) => TuiConstraint::Max(layout_size.width.max(n) - n),
Self::MaxLessThanScreenHeight(n) => {
TuiConstraint::Max(screen_size.height.max(n) - n)
}
Self::MaxLessThanScreenWidth(n) => {
TuiConstraint::Max(screen_size.width.max(n) - n)
}
Self::MaxLessThanLayoutHeight(n) => {
TuiConstraint::Max(layout_size.height.max(n) - n)
}
Self::MaxLessThanLayoutWidth(n) => {
TuiConstraint::Max(layout_size.width.max(n) - n)
}
Self::Min(n) => TuiConstraint::Min(n),
Self::MinLessThanScreenHeight(n) => TuiConstraint::Min(screen_size.height.max(n) - n),
Self::MinLessThanScreenWidth(n) => TuiConstraint::Min(screen_size.width.max(n) - n),
Self::MinLessThanLayoutHeight(n) => TuiConstraint::Min(layout_size.height.max(n) - n),
Self::MinLessThanLayoutWidth(n) => TuiConstraint::Min(layout_size.width.max(n) - n),
Self::MinLessThanScreenHeight(n) => {
TuiConstraint::Min(screen_size.height.max(n) - n)
}
Self::MinLessThanScreenWidth(n) => {
TuiConstraint::Min(screen_size.width.max(n) - n)
}
Self::MinLessThanLayoutHeight(n) => {
TuiConstraint::Min(layout_size.height.max(n) - n)
}
Self::MinLessThanLayoutWidth(n) => {
TuiConstraint::Min(layout_size.width.max(n) - n)
}
}
}
}
@ -437,7 +472,9 @@ fn draw_table<B: Backend>(
let config = panel_config.default.to_owned().extend(&panel_config.table);
let app_config = app.config.to_owned();
let header_height = app_config.general.table.header.height.unwrap_or(1);
let height: usize = (layout_size.height.max(header_height + 2) - (header_height + 2)).into();
let height: usize = (layout_size.height.max(header_height + 2)
- (header_height + 2))
.into();
let rows = app
.directory_buffer
@ -476,8 +513,10 @@ fn draw_table<B: Backend>(
.unwrap_or_default();
let mut me = node.mime_essence.splitn(2, '/');
let mimetype: String = me.next().map(|s| s.into()).unwrap_or_default();
let mimesub: String = me.next().map(|s| s.into()).unwrap_or_default();
let mimetype: String =
me.next().map(|s| s.into()).unwrap_or_default();
let mimesub: String =
me.next().map(|s| s.into()).unwrap_or_default();
let mut node_type = if node.is_symlink {
app_config.node_types.symlink.to_owned()
@ -496,28 +535,39 @@ fn draw_table<B: Backend>(
node_type = node_type.extend(conf);
}
if let Some(conf) = app_config.node_types.extension.get(&node.extension) {
if let Some(conf) =
app_config.node_types.extension.get(&node.extension)
{
node_type = node_type.extend(conf);
}
if let Some(conf) = app_config.node_types.special.get(&node.relative_path) {
if let Some(conf) =
app_config.node_types.special.get(&node.relative_path)
{
node_type = node_type.extend(conf);
}
let (relative_index, is_before_focus, is_after_focus) =
match dir.focus.cmp(&index) {
Ordering::Greater => (dir.focus - index, true, false),
Ordering::Greater => {
(dir.focus - index, true, false)
}
Ordering::Less => (index - dir.focus, false, true),
Ordering::Equal => (0, false, false),
};
let (mut prefix, mut suffix, mut style) = {
let ui = app_config.general.default_ui.to_owned();
(ui.prefix, ui.suffix, ui.style.extend(&node_type.style))
(
ui.prefix,
ui.suffix,
ui.style.extend(&node_type.style),
)
};
if is_focused && is_selected {
let ui = app_config.general.focus_selection_ui.to_owned();
let ui =
app_config.general.focus_selection_ui.to_owned();
prefix = ui.prefix.to_owned().or(prefix);
suffix = ui.suffix.to_owned().or(suffix);
style = style.extend(&ui.style);
@ -561,10 +611,16 @@ fn draw_table<B: Backend>(
.iter()
.filter_map(|c| {
c.format.as_ref().map(|f| {
let out: Result<String> = lua::call(lua, f, v.clone());
let out: Result<String> =
lua::call(lua, f, v.clone());
match out {
Ok(o) => ansi_to_text(o.bytes())
.unwrap_or_else(|e| Text::raw(format!("{:?}", e))),
.unwrap_or_else(|e| {
Text::raw(format!(
"{:?}",
e
))
}),
Err(e) => Text::raw(e.to_string()),
}
})
@ -596,7 +652,9 @@ fn draw_table<B: Backend>(
.widths(&table_constraints)
.style(app_config.general.table.style.to_owned().into())
.highlight_style(app_config.general.focus_ui.style.to_owned().into())
.column_spacing(app_config.general.table.col_spacing.unwrap_or_default())
.column_spacing(
app_config.general.table.col_spacing.unwrap_or_default(),
)
.block(block(
config,
format!(
@ -655,8 +713,8 @@ fn draw_selection<B: Backend>(
.collect();
// Selected items
let selection_list =
List::new(selection).block(block(config, format!(" Selection ({}) ", selection_count)));
let selection_list = List::new(selection)
.block(block(config, format!(" Selection ({}) ", selection_count)));
f.render_widget(selection_list, layout_size);
}
@ -679,9 +737,10 @@ fn draw_help_menu<B: Backend>(
.into_iter()
.map(|l| match l {
HelpMenuLine::Paragraph(p) => Row::new([Cell::from(p)].to_vec()),
HelpMenuLine::KeyMap(k, remaps, h) => {
Row::new([Cell::from(k), Cell::from(remaps.join("|")), Cell::from(h)].to_vec())
}
HelpMenuLine::KeyMap(k, remaps, h) => Row::new(
[Cell::from(k), Cell::from(remaps.join("|")), Cell::from(h)]
.to_vec(),
),
})
.collect::<Vec<Row>>();
@ -751,7 +810,8 @@ fn draw_sort_n_filter<B: Backend>(
.to_owned()
.extend(&panel_config.sort_and_filter);
let ui = app.config.general.sort_and_filter_ui.to_owned();
let filter_by: &IndexSet<NodeFilterApplicable> = &app.explorer_config.filters;
let filter_by: &IndexSet<NodeFilterApplicable> =
&app.explorer_config.filters;
let sort_by: &IndexSet<NodeSorterApplicable> = &app.explorer_config.sorters;
let defaultui = &ui.default_identifier;
let forwardui = defaultui
@ -786,7 +846,10 @@ fn draw_sort_n_filter<B: Backend>(
.map(|u| {
let ui = defaultui.to_owned().extend(u);
(
Span::styled(ui.format.to_owned().unwrap_or_default(), ui.style.into()),
Span::styled(
ui.format.to_owned().unwrap_or_default(),
ui.style.into(),
),
Span::styled(
direction.format.to_owned().unwrap_or_default(),
direction.style.to_owned().into(),
@ -847,7 +910,11 @@ fn draw_logs<B: Backend>(
app::LogLevel::Warning => ListItem::new(format!(
"{} | {} | {}",
&time,
&logs_config.warning.format.to_owned().unwrap_or_default(),
&logs_config
.warning
.format
.to_owned()
.unwrap_or_default(),
l.message
))
.style(logs_config.warning.style.to_owned().into()),
@ -855,7 +922,11 @@ fn draw_logs<B: Backend>(
app::LogLevel::Success => ListItem::new(format!(
"{} | {} | {}",
&time,
&logs_config.success.format.to_owned().unwrap_or_default(),
&logs_config
.success
.format
.to_owned()
.unwrap_or_default(),
l.message
))
.style(logs_config.success.style.to_owned().into()),
@ -863,7 +934,11 @@ fn draw_logs<B: Backend>(
app::LogLevel::Error => ListItem::new(format!(
"{} | {} | {}",
&time,
&logs_config.error.format.to_owned().unwrap_or_default(),
&logs_config
.error
.format
.to_owned()
.unwrap_or_default(),
l.message
))
.style(logs_config.error.style.to_owned().into()),
@ -911,7 +986,8 @@ pub fn draw_custom_content<B: Backend>(
match body {
ContentBody::StaticParagraph { render } => {
let render = ansi_to_text(render.bytes()).unwrap_or_else(|e| Text::raw(e.to_string()));
let render = ansi_to_text(render.bytes())
.unwrap_or_else(|e| Text::raw(e.to_string()));
let content = Paragraph::new(render).block(block(
config,
title.map(|t| format!(" {} ", t)).unwrap_or_default(),
@ -928,10 +1004,14 @@ pub fn draw_custom_content<B: Backend>(
let render = lua
.to_value(&ctx)
.map(|arg| lua::call(lua, &render, arg).unwrap_or_else(|e| format!("{:?}", e)))
.map(|arg| {
lua::call(lua, &render, arg)
.unwrap_or_else(|e| format!("{:?}", e))
})
.unwrap_or_else(|e| e.to_string());
let render = ansi_to_text(render.bytes()).unwrap_or_else(|e| Text::raw(e.to_string()));
let render = ansi_to_text(render.bytes())
.unwrap_or_else(|e| Text::raw(e.to_string()));
let content = Paragraph::new(render).block(block(
config,
@ -943,7 +1023,10 @@ pub fn draw_custom_content<B: Backend>(
ContentBody::StaticList { render } => {
let items = render
.into_iter()
.map(|item| ansi_to_text(item.bytes()).unwrap_or_else(|e| Text::raw(e.to_string())))
.map(|item| {
ansi_to_text(item.bytes())
.unwrap_or_else(|e| Text::raw(e.to_string()))
})
.map(ListItem::new)
.collect::<Vec<ListItem>>();
@ -964,11 +1047,15 @@ pub fn draw_custom_content<B: Backend>(
let items = lua
.to_value(&ctx)
.map(|arg| {
lua::call(lua, &render, arg).unwrap_or_else(|e| vec![format!("{:?}", e)])
lua::call(lua, &render, arg)
.unwrap_or_else(|e| vec![format!("{:?}", e)])
})
.unwrap_or_else(|e| vec![e.to_string()])
.into_iter()
.map(|item| ansi_to_text(item.bytes()).unwrap_or_else(|e| Text::raw(e.to_string())))
.map(|item| {
ansi_to_text(item.bytes())
.unwrap_or_else(|e| Text::raw(e.to_string()))
})
.map(ListItem::new)
.collect::<Vec<ListItem>>();
@ -990,8 +1077,9 @@ pub fn draw_custom_content<B: Backend>(
Row::new(
cols.into_iter()
.map(|item| {
ansi_to_text(item.bytes())
.unwrap_or_else(|e| Text::raw(e.to_string()))
ansi_to_text(item.bytes()).unwrap_or_else(|e| {
Text::raw(e.to_string())
})
})
.map(Cell::from)
.collect::<Vec<Cell>>(),
@ -1029,7 +1117,8 @@ pub fn draw_custom_content<B: Backend>(
let rows = lua
.to_value(&ctx)
.map(|arg| {
lua::call(lua, &render, arg).unwrap_or_else(|e| vec![vec![format!("{:?}", e)]])
lua::call(lua, &render, arg)
.unwrap_or_else(|e| vec![vec![format!("{:?}", e)]])
})
.unwrap_or_else(|e| vec![vec![e.to_string()]])
.into_iter()
@ -1037,8 +1126,9 @@ pub fn draw_custom_content<B: Backend>(
Row::new(
cols.into_iter()
.map(|item| {
ansi_to_text(item.bytes())
.unwrap_or_else(|e| Text::raw(e.to_string()))
ansi_to_text(item.bytes()).unwrap_or_else(|e| {
Text::raw(e.to_string())
})
})
.map(Cell::from)
.collect::<Vec<Cell>>(),
@ -1102,9 +1192,15 @@ pub fn draw_layout<B: Backend>(
match layout {
Layout::Nothing => draw_nothing(f, screen_size, layout_size, app, lua),
Layout::Table => draw_table(f, screen_size, layout_size, app, lua),
Layout::SortAndFilter => draw_sort_n_filter(f, screen_size, layout_size, app, lua),
Layout::HelpMenu => draw_help_menu(f, screen_size, layout_size, app, lua),
Layout::Selection => draw_selection(f, screen_size, layout_size, app, lua),
Layout::SortAndFilter => {
draw_sort_n_filter(f, screen_size, layout_size, app, lua)
}
Layout::HelpMenu => {
draw_help_menu(f, screen_size, layout_size, app, lua)
}
Layout::Selection => {
draw_selection(f, screen_size, layout_size, app, lua)
}
Layout::InputAndLogs => {
if app.input_buffer.is_some() {
draw_input_buffer(f, screen_size, layout_size, app, lua);
@ -1112,9 +1208,15 @@ pub fn draw_layout<B: Backend>(
draw_logs(f, screen_size, layout_size, app, lua);
};
}
Layout::CustomContent { title, body } => {
draw_custom_content(f, screen_size, layout_size, app, title, body, lua)
}
Layout::CustomContent { title, body } => draw_custom_content(
f,
screen_size,
layout_size,
app,
title,
body,
lua,
),
Layout::Horizontal { config, splits } => {
let chunks = TuiLayout::default()
.direction(Direction::Horizontal)
@ -1133,13 +1235,19 @@ pub fn draw_layout<B: Backend>(
.or(config.margin)
.unwrap_or_default(),
)
.vertical_margin(config.vertical_margin.or(config.margin).unwrap_or_default())
.vertical_margin(
config
.vertical_margin
.or(config.margin)
.unwrap_or_default(),
)
.split(layout_size);
splits
.into_iter()
.zip(chunks.into_iter())
.for_each(|(split, chunk)| draw_layout(split, f, screen_size, chunk, app, lua));
splits.into_iter().zip(chunks.into_iter()).for_each(
|(split, chunk)| {
draw_layout(split, f, screen_size, chunk, app, lua)
},
);
}
Layout::Vertical { config, splits } => {
@ -1160,13 +1268,19 @@ pub fn draw_layout<B: Backend>(
.or(config.margin)
.unwrap_or_default(),
)
.vertical_margin(config.vertical_margin.or(config.margin).unwrap_or_default())
.vertical_margin(
config
.vertical_margin
.or(config.margin)
.unwrap_or_default(),
)
.split(layout_size);
splits
.into_iter()
.zip(chunks.into_iter())
.for_each(|(split, chunk)| draw_layout(split, f, screen_size, chunk, app, lua));
splits.into_iter().zip(chunks.into_iter()).for_each(
|(split, chunk)| {
draw_layout(split, f, screen_size, chunk, app, lua)
},
);
}
}
}

Loading…
Cancel
Save