summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2020-06-06 14:51:03 +0200
committerCanop <cano.petrole@gmail.com>2020-06-06 14:51:03 +0200
commit1cd64478226284d4266d441135041b2f710976b8 (patch)
tree672196300dc7d97d683f1b1b66938809206101dc
parentfe80fc4f9e86f0603ecf39d3a3b7bae828905965 (diff)
a few minor refactorings and cleanings
-rw-r--r--CHANGELOG.md1
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rwxr-xr-xclippy.sh26
-rw-r--r--src/app/cmd_context.rs21
-rw-r--r--src/app/mod.rs2
-rw-r--r--src/app/panel.rs13
-rw-r--r--src/app/state.rs38
-rw-r--r--src/browser/browser_state.rs21
-rw-r--r--src/cli.rs13
-rw-r--r--src/conf/conf.rs (renamed from src/conf.rs)205
-rw-r--r--src/conf/default_conf.rs195
-rw-r--r--src/conf/mod.rs25
-rw-r--r--src/file_sizes/mod.rs1
-rw-r--r--src/git/ignore.rs7
-rw-r--r--src/git/status.rs5
-rw-r--r--src/git/status_computer.rs2
-rw-r--r--src/help/help_state.rs13
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs1
-rw-r--r--src/pattern/fuzzy_patterns.rs2
-rw-r--r--src/permissions/permissions_unix.rs3
-rw-r--r--src/shell_install/mod.rs8
-rw-r--r--src/skin/help_mad_skin.rs6
-rw-r--r--src/task_sync.rs2
-rw-r--r--src/tree_build/builder.rs11
-rw-r--r--src/verb/external_execution.rs10
-rw-r--r--src/verb/external_execution_mode.rs4
-rw-r--r--src/verb/internal_focus.rs3
-rw-r--r--src/verb/verb.rs3
-rw-r--r--src/verb/verb_store.rs4
31 files changed, 352 insertions, 298 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bb46023..983fe04 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,5 @@
### next version
+[documentation of this version](https://dystroy.org/broot-master/)
#### Major feature: new input syntax - Breaking Change
- new search modes: fuzzy or regex on sub-paths (the path starting from the displayed root)
- it's possible to configure how search modes are selected in config
diff --git a/Cargo.lock b/Cargo.lock
index 9bd3651..8d89928 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -93,7 +93,7 @@ dependencies = [
[[package]]
name = "broot"
-version = "0.14.3-dev"
+version = "0.15.0-alpha"
dependencies = [
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/Cargo.toml b/Cargo.toml
index 3909a97..e514648 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "broot"
-version = "0.14.3-dev"
+version = "0.15.0-alpha"
authors = ["dystroy <denys.seguret@gmail.com>"]
repository = "https://github.com/Canop/broot"
documentation = "https://dystroy.org/broot"
diff --git a/clippy.sh b/clippy.sh
new file mode 100755
index 0000000..7181935
--- /dev/null
+++ b/clippy.sh
@@ -0,0 +1,26 @@
+# run clippy, with some lints disabled:
+#
+# clippy_regex_macro
+# the regex_macro clippy lint doesn't check *what* macro
+# it finds so it produces a lot of false positives.
+#
+# clippy::collapsible_if
+# my experience is that the collapsible_if lint is mostly
+# a nuisance which pushes towards hiding intent in code.
+#
+# clippy::module_inception
+# I don't know whether it's bad or not to have sub modules
+# named the same as their parent, and I'm willing to discuss
+# it if you want, but I don't need clippy to tell me every
+# time.
+#
+
+# there's a issue somewhere about clippy unable to run
+# its lints twice. This part will disappear when the issue
+# is solved
+rm -rf target
+cargo build
+
+
+# do the clippy
+cargo clippy -- -A clippy::regex_macro -A clippy::collapsible_if -A clippy::module_inception
diff --git a/src/app/cmd_context.rs b/src/app/cmd_context.rs
new file mode 100644
index 0000000..4411cb9
--- /dev/null
+++ b/src/app/cmd_context.rs
@@ -0,0 +1,21 @@
+
+use {
+ super::*,
+ crate::{
+ command::*,
+ display::Areas,
+ skin::PanelSkin,
+ },
+ std::path::PathBuf,
+};
+
+/// short lived wrapping of a few things which are needed for the handling
+/// of a command in a panel and won't be modified during the operation.
+pub struct CmdContext<'c> {
+ pub cmd: &'c Command,
+ pub other_path: &'c Option<PathBuf>,
+ pub panel_skin: &'c PanelSkin,
+ pub con: &'c AppContext,
+ pub areas: &'c Areas,
+ pub panel_purpose: PanelPurpose,
+}
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 028c022..1a08687 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -1,4 +1,5 @@
mod app;
+mod cmd_context;
mod cmd_result;
mod context;
mod panel;
@@ -10,6 +11,7 @@ mod status;
pub use {
app::App,
cmd_result::*,
+ cmd_context::CmdContext,
context::AppContext,
panel::Panel,
panel_id::PanelId,
diff --git a/src/app/panel.rs b/src/app/panel.rs
index 250ba6e..272589f 100644
--- a/src/app/panel.rs
+++ b/src/app/panel.rs
@@ -55,17 +55,16 @@ impl Panel {
panel_skin: &PanelSkin,
con: &AppContext,
) -> Result<AppStateCmdResult, ProgramError> {
- let purpose = self.purpose;
let state_idx = self.states.len()-1;
- let result = self.states[state_idx].on_command(
+ let cc = CmdContext {
cmd,
other_path,
- &self.areas,
- screen,
panel_skin,
con,
- purpose,
- );
+ areas: &self.areas,
+ panel_purpose: self.purpose,
+ };
+ let result = self.states[state_idx].on_command(&cc, screen);
self.status = Some(self.state().get_status(cmd, other_path, con));
debug!("result in panel {:?}: {:?}", &self.id, &result);
result
@@ -209,7 +208,7 @@ impl Panel {
.filter_map(|v| v.keys.first())
.map(|&k| keys::key_event_desc(k))
.next()
- .unwrap_or(":start_end_panel".to_string());
+ .unwrap_or_else(|| ":start_end_panel".to_string());
let md = format!("hit *{}* to fill arg ", shortcut);
// Add verbindex in purpose ?
diff --git a/src/app/state.rs b/src/app/state.rs
index 9943733..312d4dd 100644
--- a/src/app/state.rs
+++ b/src/app/state.rs
@@ -2,7 +2,7 @@ use {
super::*,
crate::{
command::{Command, TriggerType},
- display::{Areas, Screen, W},
+ display::{Screen, W},
errors::ProgramError,
flag::Flag,
pattern::Pattern,
@@ -59,26 +59,19 @@ pub trait AppState {
internal_exec: &InternalExecution,
input_invocation: Option<&VerbInvocation>,
trigger_type: TriggerType,
- areas: &Areas,
+ cc: &CmdContext,
screen: &mut Screen,
- panel_skin: &PanelSkin,
- con: &AppContext,
- panel_purpose: PanelPurpose,
) -> Result<AppStateCmdResult, ProgramError>;
/// change the state, does no rendering
fn on_command(
&mut self,
- cmd: &Command,
- other_path: &Option<PathBuf>,
- areas: &Areas,
+ cc: &CmdContext,
screen: &mut Screen,
- panel_skin: &PanelSkin,
- con: &AppContext,
- panel_purpose: PanelPurpose,
) -> Result<AppStateCmdResult, ProgramError> {
self.clear_pending();
- match cmd {
+ let con = &cc.con;
+ match cc.cmd {
Command::Click(x, y) => self.on_click(*x, *y, screen, con),
Command::DoubleClick(x, y) => self.on_double_click(*x, *y, screen, con),
Command::PatternEdit(parts) => {
@@ -98,15 +91,12 @@ pub trait AppState {
internal_exec,
input_invocation.as_ref(),
TriggerType::Other,
- areas,
+ cc,
screen,
- panel_skin,
- con,
- panel_purpose,
),
VerbExecution::External(external) => external.to_cmd_result(
self.selected_path(),
- other_path,
+ &cc.other_path,
if let Some(inv) = &input_invocation {
&inv.args
} else {
@@ -123,15 +113,12 @@ pub trait AppState {
&InternalExecution::from_internal(*internal),
input_invocation.as_ref(),
TriggerType::Other,
- areas,
+ cc,
screen,
- panel_skin,
- con,
- panel_purpose,
),
Command::VerbInvocate(invocation) => match con.verb_store.search(&invocation.name) {
PrefixSearchResult::Match(_, verb) => {
- if let Some(err) = verb.check_args(invocation, other_path) {
+ if let Some(err) = verb.check_args(invocation, &cc.other_path) {
Ok(AppStateCmdResult::DisplayError(err))
} else {
match &verb.execution {
@@ -139,16 +126,13 @@ pub trait AppState {
internal_exec,
Some(invocation),
TriggerType::Input,
- areas,
+ cc,
screen,
- panel_skin,
- con,
- panel_purpose,
),
VerbExecution::External(external) => {
external.to_cmd_result(
self.selected_path(),
- other_path,
+ &cc.other_path,
&invocation.args,
con,
)
diff --git a/src/browser/browser_state.rs b/src/browser/browser_state.rs
index b39600f..c49d50e 100644
--- a/src/browser/browser_state.rs
+++ b/src/browser/browser_state.rs
@@ -2,7 +2,7 @@ use {
crate::{
app::*,
command::{Command, TriggerType},
- display::{Areas, DisplayableTree, Screen, W},
+ display::{DisplayableTree, Screen, W},
errors::{ProgramError, TreeBuildError},
flag::Flag,
git,
@@ -359,12 +359,10 @@ impl AppState for BrowserState {
internal_exec: &InternalExecution,
input_invocation: Option<&VerbInvocation>,
trigger_type: TriggerType,
- areas: &Areas,
+ cc: &CmdContext,
screen: &mut Screen,
- panel_skin: &PanelSkin,
- con: &AppContext,
- panel_purpose: PanelPurpose,
) -> Result<AppStateCmdResult, ProgramError> {
+ let con = &cc.con;
let page_height = BrowserState::page_height(screen);
let bang = input_invocation
.map(|inv| inv.bang)
@@ -450,7 +448,7 @@ impl AppState for BrowserState {
AppStateCmdResult::Keep
}
Internal::panel_left => {
- if areas.is_first() {
+ if cc.areas.is_first() {
// we ask for the creation of a panel to the left
internal_focus::new_panel_on_path(
self.selected_path().to_path_buf(),
@@ -466,7 +464,7 @@ impl AppState for BrowserState {
}
}
Internal::panel_right => {
- if areas.is_last() {
+ if cc.areas.is_last() {
// we ask for the creation of a panel to the left
internal_focus::new_panel_on_path(
self.selected_path().to_path_buf(),
@@ -491,7 +489,7 @@ impl AppState for BrowserState {
print::print_relative_path(path, con)?
}
Internal::print_tree => {
- print::print_tree(&self.displayed_tree(), screen, panel_skin, con)?
+ print::print_tree(&self.displayed_tree(), screen, &cc.panel_skin, con)?
}
Internal::refresh => AppStateCmdResult::RefreshState { clear_cache: true },
Internal::select_first => {
@@ -503,7 +501,7 @@ impl AppState for BrowserState {
AppStateCmdResult::Keep
}
Internal::start_end_panel => {
- if panel_purpose.is_arg_edition() {
+ if cc.panel_purpose.is_arg_edition() {
debug!("start_end understood as end");
AppStateCmdResult::ClosePanel {
validate_purpose: true,
@@ -514,8 +512,7 @@ impl AppState for BrowserState {
if let Some(input_invocation) = input_invocation {
// we'll go for input arg editing
let path = if let Some(input_arg) = &input_invocation.args {
- let path = path::path_from(self.root(), input_arg);
- PathBuf::from(path)
+ path::path_from(self.root(), input_arg)
} else {
self.root().to_path_buf()
};
@@ -686,7 +683,7 @@ impl AppState for BrowserState {
} else {
self.filtered_tree.as_ref()
.map(|t| t.options.pattern.as_input(&con.search_modes))
- .unwrap_or_else(|| String::new())
+ .unwrap_or_else(String::new)
}
}
}
diff --git a/src/cli.rs b/src/cli.rs
index 601697f..b417d4c 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -22,6 +22,7 @@ use {
env,
io::{self, Write},
path::{Path, PathBuf},
+ str::FromStr,
},
};
@@ -81,9 +82,9 @@ fn get_root_path(cli_args: &ArgMatches<'_>) -> Result<PathBuf, ProgramError> {
.value_of("root")
.map_or(env::current_dir()?, PathBuf::from);
if !root.exists() {
- Err(TreeBuildError::FileNotFound {
+ return Err(TreeBuildError::FileNotFound {
path: format!("{:?}", &root),
- })?;
+ }.into());
}
if !root.is_dir() {
// we try to open the parent directory if the passed file isn't one
@@ -92,9 +93,9 @@ fn get_root_path(cli_args: &ArgMatches<'_>) -> Result<PathBuf, ProgramError> {
root = parent.to_path_buf();
} else {
// let's give up
- Err(TreeBuildError::NotADirectory {
+ return Err(TreeBuildError::NotADirectory {
path: format!("{:?}", &root),
- })?;
+ }.into());
}
}
Ok(canonicalize_root(&root)?)
@@ -169,7 +170,7 @@ pub fn run() -> Result<Option<Launchable>, ProgramError> {
}
// verb store is completed from the config file(s)
- let mut verb_store = VerbStore::new();
+ let mut verb_store = VerbStore::default();
verb_store.init(&config);
// reading the other arguments
@@ -214,7 +215,7 @@ pub fn ask_authorization() -> Result<bool, ProgramError> {
let mut answer = String::new();
io::stdin().read_line(&mut answer)?;
let answer = answer.trim();
- Ok(match answer.as_ref() {
+ Ok(match answer {
"n" | "N" => false,
_ => true,
})
diff --git a/src/conf.rs b/src/conf/conf.rs
index 55db7af..67f21fe 100644
--- a/src/conf.rs
+++ b/src/conf/conf.rs
@@ -2,6 +2,9 @@
//! initializing if if it doesn't yet exist
use {
+ super::{
+ default_conf::DEFAULT_CONF_FILE,
+ },
crate::{
errors::ConfError,
keys,
@@ -12,7 +15,6 @@ use {
verb::VerbConf,
},
crossterm::style::Attribute,
- directories::ProjectDirs,
std::{
collections::HashMap,
fs, io,
@@ -53,21 +55,11 @@ fn bool_field(value: &Value, field_name: &str) -> Option<bool> {
None
}
-/// return the instance of ProjectDirs holding broot's specific paths
-pub fn app_dirs() -> ProjectDirs {
- ProjectDirs::from("org", "dystroy", "broot").expect("Unable to find configuration directories")
-}
-
-/// return the path to the config directory, based on XDG
-pub fn dir() -> PathBuf {
- app_dirs().config_dir().to_path_buf()
-}
-
impl Conf {
pub fn default_location() -> &'static Path {
lazy_static! {
- static ref CONF_PATH: PathBuf = dir().join("conf.toml");
+ static ref CONF_PATH: PathBuf = super::dir().join("conf.toml");
}
&*CONF_PATH
}
@@ -228,192 +220,3 @@ impl Conf {
}
}
-const DEFAULT_CONF_FILE: &str = r#"
-###############################################################
-# This configuration file lets you
-# - define new commands
-# - change the shortcut or triggering keys of built-in verbs
-# - change the colors
-# - set default values for flags
-#
-# Configuration documentation is available at
-# https://dystroy.org/broot
-###############################################################
-
-###############################################################
-# Default flags
-# You can set up flags you want broot to start with by
-# default, for example `default_flags="ihp"` if you usually want
-# to see hidden and gitignored files and the permissions (then
-# if you don't want the hidden files you can launch `br -H`)
-# A popular flag is the `g` one which displays git related info.
-#
-default_flags = ""
-
-###############################################################
-# Date/Time format
-# If you want to change the format for date/time, uncomment the
-# following line and change it according to
-# https://docs.rs/chrono/0.4.11/chrono/format/strftime/index.html
-#
-# date_time_format = "%Y/%m/%d %R "
-
-###############################################################
-# Special paths
-# If some paths must be handled specially, uncomment (and change
-# this section as per the examples
-#
-# [special-paths]
-# "/media/slow-backup-disk" = "no-enter"
-# "/home/dys/useless" = "hide"
-# "/home/dys/my-link-I-want-to-explore" = "enter"
-
-###############################################################
-# Verbs and shortcuts
-# You can define your own commands which would be applied to
-# the selection.
-#
-# Exemple 1: launching `tail -n` on the selected file (leaving broot)
-# [[verbs]]
-# name = "tail_lines"
-# invocation = "tl {lines_count}"
-# execution = "tail -f -n {lines_count} {file}"
-#
-# Exemple 2: creating a new file without leaving broot
-# [[verbs]]
-# name = "touch"
-# invocation = "touch {new_file}"
-# execution = "touch {directory}/{new_file}"
-# leave_broot = false
-
-# If $EDITOR isn't set on your computer, you should either set it using
-# something similar to
-# export EDITOR=/usr/bin/nvim
-# or just replace it with your editor of choice in the 'execution'
-# pattern.
-# Example:
-# execution = "/usr/bin/nvim {file}"
-[[verbs]]
-invocation = "edit"
-key = "F2"
-shortcut = "e"
-execution = "$EDITOR {file}"
-
-[[verbs]]
-invocation = "create {subpath}"
-execution = "$EDITOR {directory}/{subpath}"
-
-[[verbs]]
-invocation = "git_diff"
-shortcut = "gd"
-leave_broot = false
-execution = "git diff {file}"
-
-# If $PAGER isn't set on your computer, you should either set it
-# or just replace it with your viewer of choice in the 'execution'
-# pattern.
-# Example:
-# execution = "less {file}"
-[[verbs]]
-name = "view"
-invocation = "view"
-execution = "$PAGER {file}"
-
-# A popular set of shorctuts for going up and down:
-#
-# [[verbs]]
-# key = "ctrl-j"
-# execution = ":line_down"
-#
-# [[verbs]]
-# key = "ctrl-k"
-# execution = ":line_up"
-#
-# [[verbs]]
-# key = "ctrl-d"
-# execution = ":page_down"
-#
-# [[verbs]]
-# key = "ctrl-u"
-# execution = ":page_up"
-
-# If you develop using git, you might like to often switch
-# to the "git status" filter:
-# [[verbs]]
-# key = "ctrl-g"
-# execution = ":toggle_git_status"
-
-# You can reproduce the bindings of Norton Commander
-# on copying or moving to the other panel:
-#
-# [[verbs]]
-# key = "F5"
-# execution = ":copy_to_panel"
-#
-# [[verbs]]
-# key = "F6"
-# execution = ":move_to_panel"
-
-
-###############################################################
-# Skin
-# If you want to change the colors of broot,
-# uncomment the following bloc and start messing
-# with the various values.
-#
-# [skin]
-# default = "gray(23) none / gray(20) none"
-# tree = "ansi(94) None / gray(3) None"
-# file = "gray(18) None / gray(15) None"
-# directory = "ansi(208) None Bold / ansi(172) None bold"
-# exe = "Cyan None"
-# link = "Magenta None"
-# pruning = "gray(12) None Italic"
-# perm__ = "gray(5) None"
-# perm_r = "ansi(94) None"
-# perm_w = "ansi(132) None"
-# perm_x = "ansi(65) None"
-# owner = "ansi(138) None"
-# group = "ansi(131) None"
-# dates = "ansi(66) None"
-# sparse = "ansi(214) None"
-# git_branch = "ansi(229) None"
-# git_insertions = "ansi(28) None"
-# git_deletions = "ansi(160) None"
-# git_status_current = "gray(5) None"
-# git_status_modified = "ansi(28) None"
-# git_status_new = "ansi(94) None Bold"
-# git_status_ignored = "gray(17) None"
-# git_status_conflicted = "ansi(88) None"
-# git_status_other = "ansi(88) None"
-# selected_line = "None gray(5) / None gray(4)"
-# char_match = "Yellow None"
-# file_error = "Red None"
-# flag_label = "gray(15) None"
-# flag_value = "ansi(208) None Bold"
-# input = "White None / gray(15) gray(2)"
-# status_error = "gray(22) ansi(124)"
-# status_job = "ansi(220) gray(5)"
-# status_normal = "gray(20) gray(3) / gray(2) gray(2)"
-# status_italic = "ansi(208) gray(3) / gray(2) gray(2)"
-# status_bold = "ansi(208) gray(3) Bold / gray(2) gray(2)"
-# status_code = "ansi(229) gray(3) / gray(2) gray(2)"
-# status_ellipsis = "gray(19) gray(1) / gray(2) gray(2)"
-# purpose_normal = "gray(20) gray(2)"
-# purpose_italic = "ansi(178) gray(2)"
-# purpose_bold = "ansi(178) gray(2) Bold"
-# purpose_ellipsis = "gray(20) gray(2)"
-# scrollbar_track = "gray(7) None / gray(4) None"
-# scrollbar_thumb = "gray(22) None / gray(14) None"
-# help_paragraph = "gray(20) None"
-# help_bold = "ansi(208) None Bold"
-# help_italic = "ansi(166) None"
-# help_code = "gray(21) gray(3)"
-# help_headers = "ansi(208) None"
-# help_table_border = "ansi(239) None"
-
-# You may find explanations and other skins on
-# https://dystroy.org/broot/skins
-# for example a skin suitable for white backgrounds
-
-"#;
diff --git a/src/conf/default_conf.rs b/src/conf/default_conf.rs
new file mode 100644
index 0000000..b36e878
--- /dev/null
+++ b/src/conf/default_conf.rs
@@ -0,0 +1,195 @@
+
+/// the content a the conf.toml file broot creates
+/// when there's none. It features some default
+/// configuration and many completable
+/// or uncommentable sections to help the user
+/// define her own configuration.
+pub const DEFAULT_CONF_FILE: &str = r#"
+###############################################################
+# This configuration file lets you
+# - define new commands
+# - change the shortcut or triggering keys of built-in verbs
+# - change the colors
+# - set default values for flags
+#
+# Configuration documentation is available at
+# https://dystroy.org/broot
+###############################################################
+
+###############################################################
+# Default flags
+# You can set up flags you want broot to start with by
+# default, for example `default_flags="ihp"` if you usually want
+# to see hidden and gitignored files and the permissions (then
+# if you don't want the hidden files you can launch `br -H`)
+# A popular flag is the `g` one which displays git related info.
+#
+default_flags = ""
+
+###############################################################
+# Date/Time format
+# If you want to change the format for date/time, uncomment the
+# following line and change it according to
+# https://docs.rs/chrono/0.4.11/chrono/format/strftime/index.html
+#
+# date_time_format = "%Y/%m/%d %R "
+
+###############################################################
+# Special paths
+# If some paths must be handled specially, uncomment (and change
+# this section as per the examples
+#
+# [special-paths]
+# "/media/slow-backup-disk" = "no-enter"
+# "/home/dys/useless" = "hide"
+# "/home/dys/my-link-I-want-to-explore" = "enter"
+
+###############################################################
+# Verbs and shortcuts
+# You can define your own commands which would be applied to
+# the selection.
+#
+# Exemple 1: launching `tail -n` on the selected file (leaving broot)
+# [[verbs]]
+# name = "tail_lines"
+# invocation = "tl {lines_count}"
+# execution = "tail -f -n {lines_count} {file}"
+#
+# Exemple 2: creating a new file without leaving broot
+# [[verbs]]
+# name = "touch"
+# invocation = "touch {new_file}"
+# execution = "touch {directory}/{new_file}"
+# leave_broot = false
+
+# If $EDITOR isn't set on your computer, you should either set it using
+# something similar to
+# export EDITOR=/usr/bin/nvim
+# or just replace it with your editor of choice in the 'execution'
+# pattern.
+# Example:
+# execution = "/usr/bin/nvim {file}"
+[[verbs]]
+invocation = "edit"
+key = "F2"
+shortcut = "e"
+execution = "$EDITOR {file}"
+
+[[verbs]]
+invocation = "create {subpath}"
+execution = "$EDITOR {directory}/{subpath}"
+
+[[verbs]]
+invocation = "git_diff"
+shortcut = "gd"
+leave_broot = false
+execution = "git diff {file}"
+
+# If $PAGER isn't set on your computer, you should either set it
+# or just replace it with your viewer of choice in the 'execution'
+# pattern.
+# Example:
+# execution = "less {file}"
+[[verbs]]
+name = "view"
+invocation = "view"
+execution = "$PAGER {file}"
+
+# A popular set of shorctuts for going up and down:
+#
+# [[verbs]]
+# key = "ctrl-j"
+# execution = ":line_down"
+#
+# [[verbs]]
+# key = "ctrl-k"
+# execution = ":line_up"
+#
+# [[verbs]]
+# key = "ctrl-d"
+# execution = ":page_down"
+#
+# [[verbs]]
+# key = "ctrl-u"
+# execution = ":page_up"
+
+# If you develop using git, you might like to often switch
+# to the "git status" filter:
+# [[verbs]]
+# key = "ctrl-g"
+# execution = ":toggle_git_status"
+
+# You can reproduce the bindings of Norton Commander
+# on copying or moving to the other panel:
+#
+# [[verbs]]
+# key = "F5"
+# execution = ":copy_to_panel"
+#
+# [[verbs]]
+# key = "F6"
+# execution = ":move_to_panel"
+
+
+###############################################################
+# Skin
+# If you want to change the colors of broot,
+# uncomment the following bloc and start messing
+# with the various values.
+#
+# [skin]
+# default = "gray(23) none / gray(20) none"
+# tree = "ansi(94) None / gray(3) None"
+# file = "gray(18) None / gray(15) None"
+# directory = "ansi(208) None Bold / ansi(172) None bold"
+# exe = "Cyan None"
+# link = "Magenta None"
+# pruning = "gray(12) None Italic"
+# perm__ = "gray(5) None"
+# perm_r = "ansi(94) None"
+# perm_w = "ansi(132) None"
+# perm_x = "ansi(65) None"
+# owner = "ansi(138) None"
+# group = "ansi(131) None"
+# dates = "ansi(66) None"
+# sparse = "ansi(214) None"
+# git_branch = "ansi(229) None"
+# git_insertions = "ansi(28) None"
+# git_deletions = "ansi(160) None"
+# git_status_current = "gray(5) None"
+# git_status_modified = "ansi(28) None"
+# git_status_new = "ansi(94) None Bold"
+# git_status_ignored = "gray(17) None"
+# git_status_conflicted = "ansi(88) None"
+# git_status_other = "ansi(88) None"
+# selected_line = "None gray(5) / None gray(4)"
+# char_match = "Yellow None"
+# file_error = "Red None"
+# flag_label = "gray(15) None"
+# flag_value = "ansi(208) None Bold"
+# input = "White None / gray(15) gray(2)"
+# status_error = "gray(22) ansi(124)"
+# status_job = "ansi(220) gray(5)"
+# status_normal = "gray(20) gray(3) / gray(2) gray(2)"
+# status_italic = "ansi(208) gray(3) / gray(2) gray(2)"
+# status_bold = "ansi(208) gray(3) Bold / gray(2) gray(2)"
+# status_code = "ansi(229) gray(3) / gray(2) gray(2)"
+# status_ellipsis = "gray(19) gray(1) / gray(2) gray(2)"
+# purpose_normal = "gray(20) gray(2)"
+# purpose_italic = "ansi(178) gray(2)"
+# purpose_bold =