summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2020-10-04 11:09:17 +0200
committerGitHub <noreply@github.com>2020-10-04 11:09:17 +0200
commit409a1020c5acad6ad2920e165107f0a9b12b8463 (patch)
treef23ebda3a1094bf881f457abf7e371579ec239f7
parenta2e48f122e94acf45e9c88956f13eed0d5c4d9ed (diff)
parent607900d9f1a71c37c0ed93f4a3f46829de2af776 (diff)
Merge pull request #286 from Canop/search-modes-help
Search modes help
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/help/help_content.rs112
-rw-r--r--src/help/help_features.rs24
-rw-r--r--src/help/help_search_modes.rs41
-rw-r--r--src/help/help_state.rs11
-rw-r--r--src/help/help_verbs.rs73
-rw-r--r--src/help/mod.rs3
-rw-r--r--src/pattern/mod.rs2
-rw-r--r--src/pattern/search_mode.rs44
10 files changed, 206 insertions, 108 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e1c5be4..0f92d0d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -115,7 +115,7 @@ dependencies = [
[[package]]
name = "broot"
-version = "1.0.1"
+version = "1.0.2-dev"
dependencies = [
"ansi_colours",
"bet",
diff --git a/Cargo.toml b/Cargo.toml
index b9be161..d4c66c9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "broot"
-version = "1.0.1"
+version = "1.0.2-dev"
authors = ["dystroy <denys.seguret@gmail.com>"]
repository = "https://github.com/Canop/broot"
documentation = "https://dystroy.org/broot"
diff --git a/src/help/help_content.rs b/src/help/help_content.rs
index 8b7c0e9..a1fba9d 100644
--- a/src/help/help_content.rs
+++ b/src/help/help_content.rs
@@ -1,9 +1,4 @@
use {
- crate::{
- app::AppContext,
- pattern::*,
- verb::*,
- },
minimad::{TextTemplate, TextTemplateExpander},
};
@@ -16,12 +11,13 @@ It's best used when launched as **br**.
See **https://dystroy.org/broot** for a complete guide.
The *esc* key gets you back to the previous state.
-Typing some letters searches the tree and selects the most relevant file.
-To use a regular expression, prefix with a slash eg `/j(ava|s)$`.
-To search by file content, prefix with `c/` eg `c/TODO`.
The *↑* and *↓* arrow keys can be used to change selection.
The mouse can be used to select (on click) or open (on double-click).
+## Configuration
+
+Verbs, skin, and more, can be configured in **${config-path}**.
+
## Verbs
To execute a verb, type a space or `:` then start of its name or shortcut.
@@ -33,9 +29,18 @@ ${verb-rows
}
|-:
-## Configuration
+## Search Modes
-Verbs and skin can be configured in **${config-path}**.
+Typing some letters searches the tree and selects the most relevant file.
+To use a regular expression, prefix with a slash eg `/j(ava|s)$/i`.
+To search by file content, prefix with `c/` eg `c/TODO`.
+|:-:|:-:
+|**prefix**|**search**
+|:-:|:-
+${search-mode-rows
+|${search-prefix}|${search-type}
+}
+|-:
## Launch Arguments
@@ -60,29 +65,6 @@ ${features
}
"#;
-/// find the list of optional features which are enabled
-pub fn determine_features() -> Vec<(&'static str, &'static str)> {
- #[allow(unused_mut)]
- let mut features: Vec<(&'static str, &'static str)> = Vec::new();
-
- #[cfg(not(any(target_family="windows",target_os="android")))]
- features.push(("permissions", "allow showing file mode, owner and group"));
-
- #[cfg(feature="client-server")]
- features.push((
- "client-server",
- "see https://github.com/Canop/broot/blob/master/client-server.md"
- ));
-
- #[cfg(feature="clipboard")]
- features.push((
- "clipboard",
- ":copy_path (copying the current path), and :input_paste (pasting into the input)"
- ));
-
- features
-}
-
/// build a markdown expander which will need to be
/// completed with data and which then would be used to
/// produce the markdown of the help page
@@ -93,67 +75,3 @@ pub fn expander() -> TextTemplateExpander<'static, 'static> {
}
TEMPLATE.expander()
}
-
-/// what should be shown for a verb in the help screen, after
-/// filtering
-pub struct MatchingVerbRow<'v> {
- name: Option<String>,
- shortcut: Option<String>,
- pub verb: &'v Verb,
-}
-
-impl MatchingVerbRow<'_> {
- /// the name in markdown (with matching chars in bold if
- /// some filtering occured)
- pub fn name(&self) -> &str {
- // there should be a better way to write this
- self.name.as_deref().unwrap_or_else(|| match self.verb.names.get(0) {
- Some(s) => &s.as_str(),
- _ => " ",
- })
- }
- pub fn shortcut(&self) -> &str {
- // there should be a better way to write this
- self.shortcut.as_deref().unwrap_or_else(|| match self.verb.names.get(1) {
- Some(s) => &s.as_str(),
- _ => " ",
- })
- }
-}
-
-pub fn matching_verb_rows<'v>(
- pat: &Pattern,
- con: &'v AppContext,
-) -> Vec<MatchingVerbRow<'v>> {
- let mut rows = Vec::new();
- for verb in &con.verb_store.verbs {
- let mut name = None;
- let mut shortcut = None;
- if pat.is_some() {
- let mut ok = false;
- name = verb.names.get(0)
- .and_then(|s|
- pat.search_string(s).map(|nm| {
- ok = true;
- nm.wrap(s, "**", "**")
- })
- );
- shortcut = verb.names.get(1)
- .and_then(|s|
- pat.search_string(s).map(|nm| {
- ok = true;
- nm.wrap(s, "**", "**")
- })
- );
- if !ok {
- continue;
- }
- }
- rows.push(MatchingVerbRow {
- name,
- shortcut,
- verb,
- });
- }
- rows
-}
diff --git a/src/help/help_features.rs b/src/help/help_features.rs
new file mode 100644
index 0000000..ae07346
--- /dev/null
+++ b/src/help/help_features.rs
@@ -0,0 +1,24 @@
+
+
+/// find the list of optional features which are enabled
+pub fn list() -> Vec<(&'static str, &'static str)> {
+ #[allow(unused_mut)]
+ let mut features: Vec<(&'static str, &'static str)> = Vec::new();
+
+ #[cfg(not(any(target_family="windows",target_os="android")))]
+ features.push(("permissions", "allow showing file mode, owner and group"));
+
+ #[cfg(feature="client-server")]
+ features.push((
+ "client-server",
+ "see https://github.com/Canop/broot/blob/master/client-server.md"
+ ));
+
+ #[cfg(feature="clipboard")]
+ features.push((
+ "clipboard",
+ ":copy_path (copying the current path), and :input_paste (pasting into the input)"
+ ));
+
+ features
+}
diff --git a/src/help/help_search_modes.rs b/src/help/help_search_modes.rs
new file mode 100644
index 0000000..7c795c0
--- /dev/null
+++ b/src/help/help_search_modes.rs
@@ -0,0 +1,41 @@
+use {
+ crate::{
+ app::AppContext,
+ pattern::*,
+ },
+};
+
+/// what should be shown for a search_mode in the help screen, after
+/// filtering
+pub struct MatchingSearchModeRow {
+ pub prefix: String,
+ pub description: String,
+}
+
+/// return the rows of the "Search Modes" table in help.
+pub fn search_mode_rows(
+ con: &AppContext,
+) -> Vec<MatchingSearchModeRow> {
+ SEARCH_MODES.iter().map(|mode| {
+ let prefix = con.search_modes.key(*mode).map_or_else(
+ || "".to_string(),
+ |k| format!("{:>3}/", k),
+ );
+ let description = format!(
+ "{} search on {}",
+ match mode.kind() {
+ SearchKind::Exact => "exact string",
+ SearchKind::Fuzzy => "fuzzy",
+ SearchKind::Regex => "regex",
+ _ => "???", // should not happen
+ },
+ match mode.object() {
+ SearchObject::Name => "file name",
+ SearchObject::Path => "sub path",
+ SearchObject::Content => "file content",
+ },
+ );
+ MatchingSearchModeRow { prefix, description }
+ }).collect()
+}
+
diff --git a/src/help/help_state.rs b/src/help/help_state.rs
index df31fdd..e0e9ab7 100644
--- a/src/help/help_state.rs
+++ b/src/help/help_state.rs
@@ -87,7 +87,7 @@ impl AppState for HelpState {
expander
.set("version", env!("CARGO_PKG_VERSION"))
.set("config-path", &con.config_path);
- let verb_rows = help_content::matching_verb_rows(&self.pattern, con);
+ let verb_rows = super::help_verbs::matching_verb_rows(&self.pattern, con);
for row in &verb_rows {
let sub = expander
.sub("verb-rows")
@@ -102,7 +102,14 @@ impl AppState for HelpState {
sub.set("execution", "");
}
}
- let features = help_content::determine_features();
+ let search_rows = super::help_search_modes::search_mode_rows(con);
+ for row in &search_rows {
+ expander
+ .sub("search-mode-rows")
+ .set("search-prefix", &row.prefix)
+ .set("search-type", &row.description);
+ }
+ let features = super::help_features::list();
expander.set(
"features-text",
if features.is_empty() {
diff --git a/src/help/help_verbs.rs b/src/help/help_verbs.rs
new file mode 100644
index 0000000..383671e
--- /dev/null
+++ b/src/help/help_verbs.rs
@@ -0,0 +1,73 @@
+use {
+ crate::{
+ app::AppContext,
+ pattern::*,
+ verb::*,
+ },
+};
+
+/// what should be shown for a verb in the help screen, after
+/// filtering
+pub struct MatchingVerbRow<'v> {
+ name: Option<String>,
+ shortcut: Option<String>,
+ pub verb: &'v Verb,
+}
+
+impl MatchingVerbRow<'_> {
+ /// the name in markdown (with matching chars in bold if
+ /// some filtering occured)
+ pub fn name(&self) -> &str {
+ // there should be a better way to write this
+ self.name.as_deref().unwrap_or_else(|| match self.verb.names.get(0) {
+ Some(s) => &s.as_str(),
+ _ => " ",
+ })
+ }
+ pub fn shortcut(&self) -> &str {
+ // there should be a better way to write this
+ self.shortcut.as_deref().unwrap_or_else(|| match self.verb.names.get(1) {
+ Some(s) => &s.as_str(),
+ _ => " ",
+ })
+ }
+}
+
+/// return the rows of the verbs table in help, taking the current filter
+/// into account
+pub fn matching_verb_rows<'v>(
+ pat: &Pattern,
+ con: &'v AppContext,
+) -> Vec<MatchingVerbRow<'v>> {
+ let mut rows = Vec::new();
+ for verb in &con.verb_store.verbs {
+ let mut name = None;
+ let mut shortcut = None;
+ if pat.is_some() {
+ let mut ok = false;
+ name = verb.names.get(0)
+ .and_then(|s|
+ pat.search_string(s).map(|nm| {
+ ok = true;
+ nm.wrap(s, "**", "**")
+ })
+ );
+ shortcut = verb.names.get(1)
+ .and_then(|s|
+ pat.search_string(s).map(|nm| {
+ ok = true;
+ nm.wrap(s, "**", "**")
+ })
+ );
+ if !ok {
+ continue;
+ }
+ }
+ rows.push(MatchingVerbRow {
+ name,
+ shortcut,
+ verb,
+ });
+ }
+ rows
+}
diff --git a/src/help/mod.rs b/src/help/mod.rs
index 80a21ed..a737754 100644
--- a/src/help/mod.rs
+++ b/src/help/mod.rs
@@ -1,4 +1,7 @@
mod help_content;
+mod help_features;
+mod help_search_modes;
mod help_state;
+mod help_verbs;
pub use help_state::HelpState;
diff --git a/src/pattern/mod.rs b/src/pattern/mod.rs
index 68ede18..85167b5 100644
--- a/src/pattern/mod.rs
+++ b/src/pattern/mod.rs
@@ -28,7 +28,7 @@ pub use {
pattern_parts::PatternParts,
operator::PatternOperator,
regex_pattern::RegexPattern,
- search_mode::{SearchMode, SearchModeMap, SearchModeMapEntry},
+ search_mode::*,
};
use crate::errors::PatternError;
diff --git a/src/pattern/search_mode.rs b/src/pattern/search_mode.rs
index bc2fefa..99faf4d 100644
--- a/src/pattern/search_mode.rs
+++ b/src/pattern/search_mode.rs
@@ -6,13 +6,15 @@ use {
};
/// where to search
-enum SearchObject {
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum SearchObject {
Name,
Path,
Content,
}
/// how to search
-enum SearchKind {
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum SearchKind {
Exact,
Fuzzy,
Regex,
@@ -21,7 +23,7 @@ enum SearchKind {
/// a valid combination of SearchObject and SearchKind,
/// determine how a pattern will be used
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SearchMode {
NameExact,
NameFuzzy,
@@ -33,6 +35,17 @@ pub enum SearchMode {
ContentRegex,
}
+pub static SEARCH_MODES: &[SearchMode] = &[
+ SearchMode::NameFuzzy,
+ SearchMode::NameRegex,
+ SearchMode::NameExact,
+ SearchMode::PathFuzzy,
+ SearchMode::PathExact,
+ SearchMode::PathRegex,
+ SearchMode::ContentExact,
+ SearchMode::ContentRegex,
+];
+
impl SearchMode {
fn new(search_object: SearchObject, search_kind: SearchKind) -> Option<Self> {
use {
@@ -56,21 +69,40 @@ impl SearchMode {
(Content, Regex) => Some(Self::ContentRegex),
}
}
+ pub fn object(&self) -> SearchObject {
+ match self {
+ Self::NameExact | Self::NameFuzzy | Self::NameRegex => SearchObject::Name,
+ Self::PathExact | Self::PathFuzzy | Self::PathRegex => SearchObject::Path,
+ Self::ContentExact | Self::ContentRegex => SearchObject::Content,
+ }
+ }
+ pub fn kind(&self) -> SearchKind {
+ match self {
+ Self::NameExact => SearchKind::Exact,
+ Self::NameFuzzy => SearchKind::Fuzzy,
+ Self::NameRegex => SearchKind::Regex,
+ Self::PathExact => SearchKind::Exact,
+ Self::PathFuzzy => SearchKind::Fuzzy,
+ Self::PathRegex => SearchKind::Regex,
+ Self::ContentExact => SearchKind::Exact,
+ Self::ContentRegex => SearchKind::Regex,
+ }
+ }
}
/// define a mapping from a search mode which can be typed in
/// the input to a SearchMode value
#[derive(Debug, Clone)]
pub struct SearchModeMapEntry {
- key: Option<String>,
- mode: SearchMode,
+ pub key: Option<String>,
+ pub mode: SearchMode,
}
/// manage how to find the search mode to apply to a
/// pattern taking the config in account.
#[derive(Debug, Clone)]
pub struct SearchModeMap {
- entries: Vec<SearchModeMapEntry>,
+ pub entries: Vec<SearchModeMapEntry>,
}
impl SearchModeMapEntry {