summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--src/app/mod.rs2
-rw-r--r--src/app/state.rs13
-rw-r--r--src/browser/browser_state.rs6
-rw-r--r--src/filesystems/filesystems_state.rs10
-rw-r--r--src/help/help_state.rs4
-rw-r--r--src/preview/preview.rs15
-rw-r--r--src/preview/preview_state.rs6
-rw-r--r--src/syntactic/syntactic_view.rs39
-rw-r--r--src/tree/tree.rs4
-rw-r--r--src/verb/internal.rs4
-rw-r--r--src/verb/mod.rs2
-rw-r--r--website/docs/conf_verbs.md2
13 files changed, 60 insertions, 48 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 835a0ff..b52aa26 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,6 @@
### next
* dev.log renamed into broot.log
+* `:line_up` and `:line_down` accept an optional count as argument - Fix #301
<a name="v1.0.5"></a>
### v1.0.5 - 2020-11-05
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 24c59f4..7cc3ea6 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -20,7 +20,7 @@ pub use {
panel_id::PanelId,
panel_purpose::PanelPurpose,
selection::{LineNumber, Selection, SelectionType},
- state::AppState,
+ state::*,
state_type::AppStateType,
status::Status,
standard_status::StandardStatus,
diff --git a/src/app/state.rs b/src/app/state.rs
index 43fe3dd..eae7e0d 100644
--- a/src/app/state.rs
+++ b/src/app/state.rs
@@ -16,6 +16,7 @@ use {
},
std::{
path::{Path, PathBuf},
+ str::FromStr,
},
termimad::Area,
};
@@ -558,3 +559,15 @@ pub trait AppState {
}
}
}
+
+pub fn get_arg<T: Copy + FromStr>(
+ verb_invocation: Option<&VerbInvocation>,
+ internal_exec: &InternalExecution,
+ default: T,
+) -> T {
+ verb_invocation.and_then(|vi| vi.args.as_ref())
+ .or(internal_exec.arg.as_ref())
+ .and_then(|s| s.parse::<T>().ok())
+ .unwrap_or(default)
+}
+
diff --git a/src/browser/browser_state.rs b/src/browser/browser_state.rs
index 080452e..8e9d3f8 100644
--- a/src/browser/browser_state.rs
+++ b/src/browser/browser_state.rs
@@ -285,11 +285,13 @@ impl AppState for BrowserState {
Internal::open_stay => self.open_selection_stay_in_broot(screen, con, bang, false)?,
Internal::open_stay_filter => self.open_selection_stay_in_broot(screen, con, bang, true)?,
Internal::line_down => {
- self.displayed_tree_mut().move_selection(1, page_height);
+ let count = get_arg(input_invocation, internal_exec, 1);
+ self.displayed_tree_mut().move_selection(count, page_height);
AppStateCmdResult::Keep
}
Internal::line_up => {
- self.displayed_tree_mut().move_selection(-1, page_height);
+ let count = get_arg(input_invocation, internal_exec, 1);
+ self.displayed_tree_mut().move_selection(-count, page_height);
AppStateCmdResult::Keep
}
Internal::previous_match => {
diff --git a/src/filesystems/filesystems_state.rs b/src/filesystems/filesystems_state.rs
index 9764c03..71b19a3 100644
--- a/src/filesystems/filesystems_state.rs
+++ b/src/filesystems/filesystems_state.rs
@@ -434,25 +434,27 @@ impl AppState for FilesystemState {
}
}
Internal::line_down => {
+ let count = get_arg(input_invocation, internal_exec, 1);
if let Some(f) = self.filtered.as_mut() {
if f.selection_idx + 1 < f.mounts.len() {
- f.selection_idx += 1;
+ f.selection_idx += count.min(f.mounts.len()-f.selection_idx);
}
} else {
if self.selection_idx + 1 < self.count() {
- self.selection_idx += 1;
+ self.selection_idx += count.min(self.mounts.len().get()-self.selection_idx);
}
}
AppStateCmdResult::Keep
}
Internal::line_up => {
+ let count = get_arg(input_invocation, internal_exec, 1);
if let Some(f) = self.filtered.as_mut() {
if f.selection_idx > 0 {
- f.selection_idx -= 1;
+ f.selection_idx -= count.min(f.selection_idx);
}
} else {
if self.selection_idx > 0 {
- self.selection_idx -= 1;
+ self.selection_idx -= count.min(self.selection_idx);
}
}
AppStateCmdResult::Keep
diff --git a/src/help/help_state.rs b/src/help/help_state.rs
index 6455e74..118473f 100644
--- a/src/help/help_state.rs
+++ b/src/help/help_state.rs
@@ -177,11 +177,11 @@ impl AppState for HelpState {
}
help => AppStateCmdResult::Keep,
line_down => {
- self.scroll += 1;
+ self.scroll += get_arg(input_invocation, internal_exec, 1);
AppStateCmdResult::Keep
}
line_up => {
- self.scroll -= 1;
+ self.scroll -= get_arg(input_invocation, internal_exec, 1);
AppStateCmdResult::Keep
}
open_stay => match open::that(&Conf::default_location()) {
diff --git a/src/preview/preview.rs b/src/preview/preview.rs
index 19c444e..564b2d8 100644
--- a/src/preview/preview.rs
+++ b/src/preview/preview.rs
@@ -188,20 +188,11 @@ impl Preview {
_ => false,
}
}
- pub fn select_previous_line(&mut self) {
+ pub fn move_selection(&mut self, dy: i32) {
match self {
- Self::Syntactic(sv) => sv.select_previous_line(),
+ Self::Syntactic(sv) => sv.move_selection(dy),
Self::Hex(hv) => {
- hv.try_scroll(ScrollCommand::Lines(-1));
- }
- _ => {}
- }
- }
- pub fn select_next_line(&mut self) {
- match self {
- Self::Syntactic(sv) => sv.select_next_line(),
- Self::Hex(hv) => {
- hv.try_scroll(ScrollCommand::Lines(1));
+ hv.try_scroll(ScrollCommand::Lines(dy));
}
_ => {}
}
diff --git a/src/preview/preview_state.rs b/src/preview/preview_state.rs
index 3631579..3deac7f 100644
--- a/src/preview/preview_state.rs
+++ b/src/preview/preview_state.rs
@@ -286,11 +286,13 @@ impl AppState for PreviewState {
}
}
Internal::line_down => {
- self.mut_preview().select_next_line();
+ let count = get_arg(input_invocation, internal_exec, 1);
+ self.mut_preview().move_selection(count);
Ok(AppStateCmdResult::Keep)
}
Internal::line_up => {
- self.mut_preview().select_previous_line();
+ let count = get_arg(input_invocation, internal_exec, 1);
+ self.mut_preview().move_selection(-count);
Ok(AppStateCmdResult::Keep)
}
Internal::page_down => {
diff --git a/src/syntactic/syntactic_view.rs b/src/syntactic/syntactic_view.rs
index 12a2393..448cd37 100644
--- a/src/syntactic/syntactic_view.rs
+++ b/src/syntactic/syntactic_view.rs
@@ -230,28 +230,27 @@ impl SyntacticView {
false
}
- pub fn select_previous_line(&mut self) {
- if let Some(idx) = self.selection_idx {
- if idx > 0 {
- self.selection_idx = Some(idx - 1);
- } else {
- self.selection_idx = Some(self.lines.len()-1);
- }
- } else if !self.lines.is_empty() {
- self.selection_idx = Some(self.lines.len()-1);
- }
- self.ensure_selection_is_visible();
- }
-
- pub fn select_next_line(&mut self) {
- if let Some(idx) = self.selection_idx {
- if idx < self.lines.len() - 1 {
- self.selection_idx = Some(idx + 1);
- } else {
+ pub fn move_selection(&mut self, dy: i32) {
+ if dy > 0 {
+ if let Some(idx) = self.selection_idx {
+ if idx < self.lines.len() - 1 {
+ self.selection_idx = Some(idx + dy.min(self.lines.len() as i32 - 1 - dy) as usize);
+ } else {
+ self.selection_idx = Some(0);
+ }
+ } else if !self.lines.is_empty() {
self.selection_idx = Some(0);
}
- } else if !self.lines.is_empty() {
- self.selection_idx = Some(0);
+ } else if dy < 0 {
+ if let Some(idx) = self.selection_idx {
+ if idx > 0 {
+ self.selection_idx = Some(idx - (-dy).min(idx as i32) as usize);
+ } else {
+ self.selection_idx = Some(self.lines.len()-1);
+ }
+ } else if !self.lines.is_empty() {
+ self.selection_idx = Some(self.lines.len()-1);
+ }
}
self.ensure_selection_is_visible();
}
diff --git a/src/tree/tree.rs b/src/tree/tree.rs
index 465e9cf..8ac8a79 100644
--- a/src/tree/tree.rs
+++ b/src/tree/tree.rs
@@ -145,7 +145,7 @@ impl Tree {
///
/// For example the following one if dy is 1.
pub fn move_selection(&mut self, dy: i32, page_height: i32) {
- // only work for +1 or -1
+ // FIXME may not work well if dy is too big
let l = self.lines.len();
loop {
self.selection = (self.selection + ((l as i32) + dy) as usize) % l;
@@ -158,7 +158,6 @@ impl Tree {
let sel = self.selection as i32;
if l > page_height {
if dy < 0 {
- // -1
if sel == l - 1 {
// cycling
self.scroll = l - page_height;
@@ -166,7 +165,6 @@ impl Tree {
self.scroll = (self.scroll + 2 * dy).max(0);
}
} else {
- // +1
if sel == 0 {
// cycling brought us back to top
self.scroll = 0;
diff --git a/src/verb/internal.rs b/src/verb/internal.rs
index 46eec23..ca2f48c 100644
--- a/src/verb/internal.rs
+++ b/src/verb/internal.rs
@@ -113,12 +113,16 @@ impl Internal {
pub fn invocation_pattern(self) -> &'static str {
match self {
Internal::focus => r"focus (?P<path>.*)?",
+ Internal::line_down => r"line_down (?P<count>\d*)?",
+ Internal::line_up => r"line_up (?P<count>\d*)?",
_ => self.name(),
}
}
pub fn exec_pattern(self) -> &'static str {
match self {
Internal::focus => r"focus {path}",
+ Internal::line_down => r"line_down {count}",
+ Internal::line_up => r"line_up {count}",
_ => self.name(),
}
}
diff --git a/src/verb/mod.rs b/src/verb/mod.rs
index 1657e1d..8b16b98 100644
--- a/src/verb/mod.rs
+++ b/src/verb/mod.rs
@@ -25,7 +25,7 @@ pub use {
verb::Verb,
verb_description::VerbDescription,
verb_execution::VerbExecution,
- verb_invocation::VerbInvocation,
+ verb_invocation::*,
verb_store::{PrefixSearchResult, VerbStore},
};
diff --git a/website/docs/conf_verbs.md b/website/docs/conf_verbs.md
index 86d7470..f2a8b9c 100644
--- a/website/docs/conf_verbs.md
+++ b/website/docs/conf_verbs.md
@@ -207,7 +207,7 @@ invocation | default key | default shortcut | behavior / details
:cp {newpath} | - | - | copy the file or directory to the provided name
:help | <kbd>F1</kbd> | - | open the help page. Help page can also be open with <kbd>?</kbd>
:focus | <kbd>enter</kbd> | - | set the selected directory the root of the displayed tree |
-:line_down | <kbd>↓</kbd> | - | scroll one line down or select the next line
+:line_down | <kbd>↓</kbd> | - | scroll one line down or select the next line (can be used with an argument eg `:line_down 4`)
:line_up | <kbd>↑</kbd> | - | scroll one line up or select the previous line
:mkdir {subpath} | - | md | create a directory
:mv {newpath} | - | - | move the file or directory to the provided path