From d21fbdebbb0c58bac98e69419c8c4deb7d37a27a Mon Sep 17 00:00:00 2001 From: Canop Date: Mon, 22 Jun 2020 13:51:50 +0200 Subject: new internal to define readline-like input edition shortcuts You may now add this kind of shortcuts: ```toml [[verbs]] key = "alt-b" execution = ":input_go_word_left" [[verbs]] key = "alt-f" execution = ":input_go_word_right" [[verbs]] key = "alt-l" execution = ":input_del_word_left" [[verbs]] key = "alt-r" execution = ":input_del_word_right" ``` Fix #235 --- CHANGELOG.md | 3 +++ Cargo.lock | 4 ++-- Cargo.toml | 4 ++-- src/browser/browser_state.rs | 1 + src/command/event.rs | 32 +++++++++++++++++++++++++++++++- src/verb/internal.rs | 11 +++++++++++ website/docs/conf_file.md | 43 ++++++++++++++++++++++++++++++++++++++++--- website/docs/export.md | 4 ++-- website/docs/input.md | 2 +- website/docs/navigation.md | 16 ++++++++-------- website/docs/skins.md | 6 +++--- website/docs/tricks.md | 8 +++++--- website/docs/verbs.md | 6 +++--- 13 files changed, 112 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd0053b..2a91ec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### next version +- it's possible to define input edition shortcuts - Fix #235 + ### v0.16.0 - 2020-06-20 #### Major feature: composite patterns diff --git a/Cargo.lock b/Cargo.lock index e0b45fe..8a8e61b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1156,9 +1156,9 @@ dependencies = [ [[package]] name = "termimad" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d457a91d0c9fbc663c18961e78f541e61aa9446dc1c0cdd87109543f7289447f" +checksum = "1c6e38d5fad7e4fd43909c4f8bee316de259fc756dd8c470c5afa4fa9069a7bb" dependencies = [ "crossbeam", "crossterm", diff --git a/Cargo.toml b/Cargo.toml index 52c6415..719c96e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "broot" -version = "0.16.0" +version = "0.16.1-dev" authors = ["dystroy "] repository = "https://github.com/Canop/broot" documentation = "https://dystroy.org/broot" @@ -38,7 +38,7 @@ regex = "1.3" secular = "0.2" simplelog = "0.7" strict = "0.1.3" -termimad = "0.8.23" +termimad = "0.8.24" toml = "0.5" umask = "1.0" diff --git a/src/browser/browser_state.rs b/src/browser/browser_state.rs index dea0b5b..9fedacd 100644 --- a/src/browser/browser_state.rs +++ b/src/browser/browser_state.rs @@ -593,6 +593,7 @@ impl AppState for BrowserState { } } Internal::quit => AppStateCmdResult::Quit, + _ => AppStateCmdResult::Keep, }) } diff --git a/src/command/event.rs b/src/command/event.rs index b431d89..7a5bbbe 100644 --- a/src/command/event.rs +++ b/src/command/event.rs @@ -9,7 +9,7 @@ use { errors::ProgramError, keys, skin::PanelSkin, - verb::Internal, + verb::{Internal, Verb, VerbExecution}, }, termimad::{Area, Event, InputField}, }; @@ -69,6 +69,33 @@ impl PanelInput { Ok(cmd) } + /// check whether the verb is an action on the input (like + /// deleting a word) and if it's the case, applies it and + /// return true + fn handle_input_related_verb( + &mut self, + verb: &Verb, + _con: &AppContext, + ) -> bool { + if let VerbExecution::Internal(internal_exec) = &verb.execution { + match internal_exec.internal { + Internal::input_del_char_left => self.input_field.del_char_left(), + Internal::input_del_char_below => self.input_field.del_char_below(), + Internal::input_del_word_left => self.input_field.del_word_left(), + Internal::input_del_word_right => self.input_field.del_word_right(), + Internal::input_go_left => self.input_field.move_left(), + Internal::input_go_right => self.input_field.move_right(), + Internal::input_go_word_left => self.input_field.move_word_left(), + Internal::input_go_word_right => self.input_field.move_word_right(), + Internal::input_go_to_start => self.input_field.move_to_start(), + Internal::input_go_to_end => self.input_field.move_to_end(), + _ => false, + } + } else { + false + } + } + /// consume the event to /// - maybe change the input /// - build a command @@ -177,6 +204,9 @@ impl PanelInput { for (index, verb) in con.verb_store.verbs.iter().enumerate() { for verb_key in &verb.keys { if *verb_key == key { + if self.handle_input_related_verb(verb, con) { + return Command::from_raw(self.input_field.get_content(), false); + } if selection_type.respects(verb.selection_condition) { return Command::VerbTrigger { index, diff --git a/src/verb/internal.rs b/src/verb/internal.rs index e9cc3ae..58a9b30 100644 --- a/src/verb/internal.rs +++ b/src/verb/internal.rs @@ -51,12 +51,23 @@ macro_rules! Internals { } } + Internals! { back: "revert to the previous state (mapped to *esc*)", close_panel_ok: "close the panel, validating the selected path", close_panel_cancel: "close the panel, not using the selected path", focus: "display the directory (mapped to *enter*)", help: "display broot's help", + input_del_char_left: "delete the char left of the cursor", + input_del_char_below: "delete the char left at the cursor's position", + input_del_word_left: "delete the word left of the cursor", + input_del_word_right: "delete the word right of the cursor", + input_go_to_end: "move the cursor to the end of input", + input_go_left: "move the cursor to the left", + input_go_right: "move the cursor to the right", + input_go_to_start: "move the cursor to the start of input", + input_go_word_left: "move the cursor one word to the left", + input_go_word_right: "move the cursor one word to the right", line_down: "move one line down", line_up: "move one line up", open_stay: "open file or directory according to OS (stay in broot)", diff --git a/website/docs/conf_file.md b/website/docs/conf_file.md index bb1209c..8ea49cf 100644 --- a/website/docs/conf_file.md +++ b/website/docs/conf_file.md @@ -223,13 +223,13 @@ execution = "/bin/mkdir -p {directory}/{subpath}" In this case the subpath is read from what you type: -![md sub](../img/20190306-md.png) +![md sub](img/20190306-md.png) As you see, there's a space in this path, but it works. **broot** tries to determine when to wrap path in quotes and when to escape so that such a command correctly works. It also normalizes the paths it finds which eases the use of relative paths: -![mv](../img/20190306-mv.png) +![mv](img/20190306-mv.png) Here's another example, where the invocation pattern defines two arguments by destructuring: @@ -242,7 +242,7 @@ from_shell = true And here's how it would look like: -![blop](../img/20190306-blop.png) +![blop](img/20190306-blop.png) Notice the `\\.` ? That's because the invocation pattern is interpreted as a regular expression (with just a shortcut for the easy case, enabling `{name}`). @@ -303,6 +303,43 @@ Note that - you can always call a verb with its default invocation, you don't *have* to define a shortcut - verbs whose invocation needs an argument (like `{newpath}`) can't be triggered with just a keyboard key. +## Input related verbs + +Some internal actions can be bound to a key shortcut but can't be called explicitely because they directly act on the input field: + +name | default binding | behavior +-|-|- +:input_del_char_left | del | "delete the char left of the cursor", +:input_del_char_below | suppr | "delete the char left at the cursor's position", +:input_del_word_left | - | "delete the word left of the cursor", +:input_del_word_right | - | "delete the word right of the cursor", +:input_go_to_end | end | "move the cursor to the end of input", +:input_go_left | | "move the cursor to the left", +:input_go_right | | "move the cursor to the right", +:input_go_to_start | home | "move the cursor to the start of input", +:input_go_word_left | - | "move the cursor one word to the left", +:input_go_word_right | - | "move the cursor one word to the right", + +You may add this kind of shortcuts: + +```toml +[[verbs]] +key = "alt-b" +execution = ":input_go_word_left" + +[[verbs]] +key = "alt-f" +execution = ":input_go_word_right" + +[[verbs]] +key = "alt-l" +execution = ":input_del_word_left" + +[[verbs]] +key = "alt-r" +execution = ":input_del_word_right" +``` + ## Focus diff --git a/website/docs/export.md b/website/docs/export.md index 81d212d..98aa2c7 100644 --- a/website/docs/export.md +++ b/website/docs/export.md @@ -8,11 +8,11 @@ The easiest is to just execute it from inside the application (the verb is also Example with a filter: -![exported styled tree](../img/20190321-cmd-pt-styled.png) +![exported styled tree](img/20190321-cmd-pt-styled.png) Example without style or color, thanks to `--no-style`: -![exported unstyled tree](../img/20190321-cmd-pt-unstyled.png) +![exported unstyled tree](img/20190321-cmd-pt-unstyled.png) This is also how would look the tree directly exported into a file. diff --git a/website/docs/input.md b/website/docs/input.md index 89a3cfd..7a63bd7 100644 --- a/website/docs/input.md +++ b/website/docs/input.md @@ -50,7 +50,7 @@ The caracters you use as operators and the parenthesis can be useful in patterns Most often you'll just type what feels natural and broot will select the interpretation which makes sense but you might be interested in a few rules: -* parenthesis and operators in the second pattern part (parts being separated by `/`) are part of the pattern, which explains why `/(json|xml)` is interpreted as a regular expression. If you want to do a fuzzy search for a `|` in the name of your files, you'll need to have an explicit pattern mode : `nf/a|b` because `a|b` would search for files whose name contains either `a` or `b`. And to ensure an operator or closing parenthesis isn't interpreted as part of your pattern, just close it with a `/`. +* parenthesis and operators in the second pattern part (parts being separated by `/`) are part of the pattern, which explains why `/(json|xml)` is interpreted as a regular expression. If you want to do a fuzzy search for a `|` in the name of your files, you'll need to either escape it as `\|` or to have an explicit pattern mode : `nf/a|b` because `a|b` would search for files whose name contains either `a` or `b`. And to ensure an operator or closing parenthesis isn't interpreted as part of your pattern, just close it with a `/`. * broot interprets the left operand before the right one and doesn't interpret the second one if it's not necessary. So if you want to search your whole disk for json files containing `abcd`, it will be faster to use `/json$/&c/abcd` rather than `c/abcd/&/json$/` which would look at the file name only after having scanned the content. ## The verb invocation diff --git a/website/docs/navigation.md b/website/docs/navigation.md index 17b3caa..a0f1cf5 100644 --- a/website/docs/navigation.md +++ b/website/docs/navigation.md @@ -9,11 +9,11 @@ The first line is called the root, and is currently selected. From here you may navigate using the following keys: * or : select the next or previous line -* or : focus (or open) a panel to the left or to the right +* ctrl or ctrl : focus (or open) a panel to the left or to the right * on a file : open the file using xdg-open (or your OS equivalent) -* alt + on a file : leave broot and open the file using xdg-open +* alt on a file : leave broot and open the file using xdg-open * on a directory : focus the directory (i.e. make it the new root) -* alt + on a directory : leave broot and `cd` the shell to that directory. +* alt on a directory : leave broot and `cd` the shell to that directory. * on the first line : goes up one level (focus the parent directory) * esc gets you back to the previous state (or leave broot if there's none) * ? brings you to the help screen @@ -36,7 +36,7 @@ The pattern filters the tree while you type. It's interpreted in a fuzzy way so For example: -![search hel](../img/20190305-search-hel.png) +![search hel](img/20190305-search-hel.png) Hitting esc clears the current pattern. @@ -52,7 +52,7 @@ If you want the regex to be case insensitive, add the `i` flag: `/pat+ern/i`. To display only files containing `"memmap"`, type `c/memmap`: -![content](../img/20200620-content-search.png) +![content](img/20200620-content-search.png) (as the search is displayed in real time you'll usually stop as soon as you have the right matches) @@ -64,7 +64,7 @@ For example, if you don't want to see files whose name ends in `"rs"`, you may t And if you want to see all files containing `"pattern"` but not the rust ones, you'll type `!rs&c/pattern`: -![composite](../img/20200620-composite-notrs.png) +![composite](img/20200620-composite-notrs.png) # More about searches @@ -82,7 +82,7 @@ As for other searches, it's interrupted as soon as you type anything. Flags are displayed at the bottom right of the panel, showing the settings regarding hidden files and .gitignore rules. -![flags](../img/20190101-flags.png) +![flags](img/20190101-flags.png) # Toggles @@ -104,7 +104,7 @@ To apply one, just type a space (or `:`), then the start of its shortcut, then h For example typing `:s` then enter will show file and directory sizes: -![dev sizes](../img/20191030-dev-sizes.png) +![dev sizes](img/20191030-dev-sizes.png) You may notice a scrollbar on this screenshot. The first level of the tree is always uncut when you display sizes (you're in a special "whale hunt" mode). diff --git a/website/docs/skins.md b/website/docs/skins.md index b263fde..a075290 100644 --- a/website/docs/skins.md +++ b/website/docs/skins.md @@ -62,7 +62,7 @@ help_table_border = "ansi(239) None" which would look like this: -![custom colors tree](../img/20200525-custom-colors-panels.png) +![custom colors tree](img/20200525-custom-colors-panels.png) Each skin entry value is made of @@ -107,7 +107,7 @@ If you want to set the background of broot transparent (i.e. to be the backgroun default = "gray(23) none / gray(20) none" ``` -![transparent](../img/20200529-transparent-broot.png) +![transparent](img/20200529-transparent-broot.png) # White Background Skin @@ -166,7 +166,7 @@ help_headers = "ansi(202) none" help_table_border = "ansi(239) None" ``` -![light skin](../img/20200526-light-skin.png) +![light skin](img/20200526-light-skin.png) # Solarized Dark diff --git a/website/docs/tricks.md b/website/docs/tricks.md index 751315b..db28b23 100644 --- a/website/docs/tricks.md +++ b/website/docs/tricks.md @@ -24,9 +24,9 @@ This is the *"I'm feeling lucky"* of broot, you can use it to directly jump to d Example: -![dcd ruleset](../img/20190122-dcd_rulset.png) +![dcd ruleset](img/20190122-dcd_rulset.png) -## focus a new directory but keep the current filter +## Focus a new directory but keep the current filter When you hit `enter` on a directory, it's focused and the filter is reset. @@ -38,7 +38,9 @@ If your system is normally configured, just doing `alt`-`enter` on an executable ## Change standard file opening -When you hit enter on a file, broot asks the system to open the file. It's usually OK but you might wish to change that, for example when you're on a server without xdg-open or equivalent. +When you hit enter on a file, broot asks the system to open the file. It's usually the best solution as it selects the program according to the file's type following settings you set system wide. + +You might still wish to change that, for example when you're on a server without xdg-open or equivalent. Here's an example of configuration changing the behaviour on open: diff --git a/website/docs/verbs.md b/website/docs/verbs.md index c05e673..559787e 100644 --- a/website/docs/verbs.md +++ b/website/docs/verbs.md @@ -36,7 +36,7 @@ execution = "/bin/cp -r {file} {other-panel-directory}" When you type a verb, the execution pattern is completed using the selection(s), the exact command is displayed in the status line: -![rm](../img/20190305-rm.png) +![rm](img/20190305-rm.png) As for filters, hitting esc clears the command. @@ -60,11 +60,11 @@ Example: Before you type a subpath, broot tells you, in red, the argument is missing: -![md](../img/20191112-md-missing-subpath.png) +![md](img/20191112-md-missing-subpath.png) If you type an argument, the command to execute is computed and shown: -![md](../img/20191112-md-list.png) +![md](img/20191112-md-list.png) In this screenshot, you didn't type `mkdir` or its start but `md`. That's because the complete definition of this verb includes this line: -- cgit v1.2.3