diff options
author | Denis Isidoro <denisidoro@users.noreply.github.com> | 2021-04-09 11:55:44 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-09 11:55:44 -0300 |
commit | 307f0c11b2df76268e21924546c51ea7c2774010 (patch) | |
tree | 2f359c6ef26c41b6de7e755713ed872b4c38ab70 | |
parent | 1f3560f7f97482dd24d9249e3a49dff729cbcc76 (diff) |
Improve bash and zsh widgets (#486)v2.15.0
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | docs/installation.md | 2 | ||||
-rw-r--r-- | shell/navi.plugin.bash | 57 | ||||
-rw-r--r-- | shell/navi.plugin.zsh | 155 | ||||
-rw-r--r-- | src/cmds/func.rs | 40 | ||||
-rw-r--r-- | src/structures/config.rs | 3 |
7 files changed, 89 insertions, 172 deletions
@@ -308,7 +308,7 @@ dependencies = [ [[package]] name = "navi" -version = "2.14.0" +version = "2.15.0" dependencies = [ "anyhow", "clap", @@ -1,6 +1,6 @@ [package] name = "navi" -version = "2.14.0" +version = "2.15.0" authors = ["Denis Isidoro <denis_isidoro@live.com>"] edition = "2018" description = "An interactive cheatsheet tool for the command-line" diff --git a/docs/installation.md b/docs/installation.md index bbb7b8e..dd23230 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -75,8 +75,6 @@ Feel free to be the maintainer of **navi** for any package manager you'd like! ### Installing the shell widget -The shell widget maintains your `.history`-like file consistent and allows you to edit commands before executing them. - If you want to install it, add this line to your `.bashrc`-like file: ```sh # bash diff --git a/shell/navi.plugin.bash b/shell/navi.plugin.bash index eeca6cb..8495bf7 100644 --- a/shell/navi.plugin.bash +++ b/shell/navi.plugin.bash @@ -1,46 +1,35 @@ #!/usr/bin/env bash -_call_navi() { - local selected - - if [ -n "${READLINE_LINE}" ]; then - if selected="$(printf "%s" "$(navi --print --fzf-overrides '--no-select-1' --query "${READLINE_LINE}" </dev/tty)")"; then - READLINE_LINE="$selected" - READLINE_POINT=${#READLINE_LINE} - fi - else - if selected="$(printf "%s" "$(navi --print </dev/tty)")"; then - READLINE_LINE="$selected" - READLINE_POINT=${#READLINE_LINE} - fi +_navi_call() { + local result="$(navi "$@" </dev/tty)" + if [ -z "${result}" ]; then + result="$(navi --print </dev/tty)" fi + printf "%s" "$result" } -__call_navi_legacy_versions() { - local -r result="$(navi --print)" - local -r linecount="$(echo "$result" | wc -l)" +_navi_widget() { + local -r input="${READLINE_LINE}" + local -r last_command="$(echo "${input}" | navi fn widget::last_command)" - if [[ "$linecount" -lt 2 ]]; then - printf "%s" "$result" - return 0 + if [ -z "${last_command}" ]; then + local -r output="$(_navi_call --print --fzf-overrides '--no-select-1')" + else + local -r find="$last_command" + local -r replacement="$(_navi_call --print --query "${last_command}")" + local -r output="${input//$find/$replacement}" fi - IFS=$'\n' - local i=1; - for line in $result; do - if echo "$line" | grep -q '\\$'; then - printf "${line::-1} " - elif [[ "$i" -eq "$linecount" ]]; then - printf "$line " - else - printf "${line}; " - fi - i=$((i+1)) - done + READLINE_LINE="$output" + READLINE_POINT=${#READLINE_LINE} +} + +_navi_widget_legacy() { + _navi_call --print } if [ ${BASH_VERSION:0:1} -lt 4 ]; then - bind '"\C-g": " \C-b\C-k \C-u`__call_navi_legacy_versions`\e\C-e\C-a\C-y\C-h\C-e\e \C-y\ey\C-x\C-x\C-f"' + bind '"\C-g": " \C-b\C-k \C-u`_navi_widget_legacy`\e\C-e\C-a\C-y\C-h\C-e\e \C-y\ey\C-x\C-x\C-f"' else - bind -x '"\C-g": _call_navi' -fi + bind -x '"\C-g": _navi_widget' +fi
\ No newline at end of file diff --git a/shell/navi.plugin.zsh b/shell/navi.plugin.zsh index 69ee2ac..492d161 100644 --- a/shell/navi.plugin.zsh +++ b/shell/navi.plugin.zsh @@ -1,147 +1,36 @@ #!/usr/bin/env zsh -# Copy-pasted from https://gist.github.com/enisozgen/2109cc80ea9f405f80c6c383f2375e77 - - -# Change last part of the command -# NOTE Creates sometime problem if there is same word in the input -ChangeLastCommand() -{ - [[ -z "${2// }" ]] && printf "%s" "$(echo "${1}${3}")" || printf "%s" "$(echo "${1/$2/ $3}")" -} - -SendLastCommandAfterPIPE() -{ - # Send last command after pipe - INPUT_STRING="${1}" - a=("${(@s/|/)${INPUT_STRING}}") # | modifier - printf "%s" "$(echo "${a[-1]}")" -} - - -# Is there pipe in the input string -IsPipeExist() -{ - INPUT_STRING=$1 - if [[ $INPUT_STRING == *\|* ]]; then - NAVI_PIPE="true" - else - NAVI_PIPE="false" - fi -} - - -IsOnlySpace () -{ - if [[ -z "${1// }" ]] ; then - return 0 - else - return 1 - fi -} - -NaviUISearch() -{ - NAVI_RET=$(printf "%s" "$(navi --print --fzf-overrides '--no-select-1' --query "${1}" </dev/tty)") - printf ${NAVI_RET} -} - - -NaviOutputControl () -{ - if ! [[ -z "$1" ]] ; then - return 0 - else - return 1 +_navi_call() { + local result="$(navi "$@" </dev/tty)" + if [ -z "${result}" ]; then + result="$(navi --print </dev/tty)" fi + printf "%s" "$result" } +_navi_widget() { + local -r input="${LBUFFER}" + local -r last_command="$(echo "${input}" | navi fn widget::last_command)" + local find="$last_command" + local replacement="$last_command" - -SmartNavi() -{ - if IsOnlySpace $1 ; then - NAVI_RET=$(printf "%s" "$(navi --print --fzf-overrides '--no-select-1' </dev/tty)") + if [ -z "${last_command}" ]; then + replacement="$(_navi_call --print --fzf-overrides '--no-select-1')" + elif [ "${LASTWIDGET}" = "_navi_widget" ] && [ "$input" = "$previous_output" ]; then + find="$input" + replacement="$(_navi_call --print --query "${previous_last_command:-$last_command}")" else - NAVI_RET=$(printf "%s" "$(navi --print --best-match --fzf-overrides '--no-select-1' --query "${1}" </dev/tty)") + replacement="$(_navi_call --print --best-match --query "${last_command}")" fi + previous_last_command="$last_command" + previous_output="${input//$find/$replacement}" - # Return warning if there is no output else return best match - if NaviOutputControl ${NAVI_RET}; then - printf ${NAVI_RET} - else - printf "Navi Returned Empty" - fi -} - - -_call_navi() { - local selected - if [ -n "$LBUFFER" ]; then - if selected="$(printf "%s" "$(navi --print --fzf-overrides '--no-select-1' --query "${LBUFFER}" </dev/tty)")"; then - LBUFFER="$selected" - fi - else - # If there is not any word on list - if selected="$(printf "%s" "$(navi --print </dev/tty)")"; then - LBUFFER="$selected" - fi - fi + zle kill-whole-line + LBUFFER="${previous_output}" region_highlight=("P0 100 bold") zle redisplay } -_call_smart_navi() { - - # set -x - INPUT_STRING=$LBUFFER - IsPipeExist ${INPUT_STRING} - - - # Is there some written stuff in LBUFFER ? - if ! [ -z "$INPUT_STRING" ] ; then - # If last navi output same as current input - # Use this part when you don't like navi best match - if [ "${LASTWIDGET}" = "_call_smart_navi" ] && [ "${OUTPUT_STRING}" = "$INPUT_STRING" ];then - LBUFFER_LAST_COMMAND=$(SendLastCommandAfterPIPE "${INPUT_STRING}") - - # Searching with same input as before but this time we are using navi interactive UI since navi didn't return us what we want - OUTPUT_STRING=$(NaviUISearch ${PREVIOUS_LAST}) - OUTPUT_STRING=$(ChangeLastCommand "$INPUT_STRING" "$LBUFFER_LAST_COMMAND" "$OUTPUT_STRING") - - else - # First search always start from here!!! - if [ "${NAVI_PIPE}" = "false" ] ; then - - # LBUFFER_LAST_COMMAND=$(SendLastCommandAfterPIPE "${INPUT_STRING}") - # PREVIOUS_LAST=$LBUFFER_LAST_COMMAND - - # Remember what was last command after pipe - PREVIOUS_LAST=$INPUT_STRING - OUTPUT_STRING=$(SmartNavi ${INPUT_STRING}) - - else - LBUFFER_LAST_COMMAND=$(SendLastCommandAfterPIPE "${INPUT_STRING}") - - # Remember what was last command after pipe - PREVIOUS_LAST=$LBUFFER_LAST_COMMAND - - OUTPUT_STRING=$(SmartNavi ${LBUFFER_LAST_COMMAND}) - OUTPUT_STRING=$(ChangeLastCommand "$INPUT_STRING" "$LBUFFER_LAST_COMMAND" "$OUTPUT_STRING") - - fi - fi - LBUFFER="$OUTPUT_STRING" - else - # There is nothing use default navi command - _call_navi - fi - - region_highlight=("P0 100 bold") - zle redisplay -} - - -zle -N _call_smart_navi -bindkey '^g' _call_smart_navi
\ No newline at end of file +zle -N _navi_widget +bindkey '^g' _navi_widget diff --git a/src/cmds/func.rs b/src/cmds/func.rs index 3fb910a..92a8eb7 100644 --- a/src/cmds/func.rs +++ b/src/cmds/func.rs @@ -2,11 +2,13 @@ use crate::handler; use crate::structures::config; use crate::url; use anyhow::Error; +use std::io::{self, Read}; #[derive(Debug)] pub enum Func { UrlOpen, Welcome, + WidgetLastCommand, } pub fn main(func: &Func, args: Vec<String>) -> Result<(), Error> { @@ -15,5 +17,43 @@ pub fn main(func: &Func, args: Vec<String>) -> Result<(), Error> { Func::Welcome => handler::handle_config(config::config_from_iter( "navi --path /tmp/navi/irrelevant".split(' ').collect(), )), + Func::WidgetLastCommand => widget_last_command(), } } + +fn widget_last_command() -> Result<(), Error> { + let mut text = String::new(); + io::stdin().read_to_string(&mut text)?; + + let replacements = vec![("|", "ඛ"), ("||", "ග"), ("&&", "ඝ")]; + + let parts = shellwords::split(&text).unwrap_or_else(|_| text.split('|').map(|s| s.to_string()).collect()); + + for p in parts { + for (pattern, escaped) in replacements.clone() { + if p.contains(pattern) && p != pattern { + let replacement = p.replace(pattern, escaped); + text = text.replace(&p, &replacement); + } + } + } + + let mut extracted = text.clone(); + for (pattern, _) in replacements.clone() { + let mut new_parts = text.rsplit(pattern); + if let Some(extracted_attempt) = new_parts.next() { + if extracted_attempt.len() <= extracted.len() { + extracted = extracted_attempt.to_string(); + } + } + } + + for (pattern, escaped) in replacements.clone() { + text = text.replace(&escaped, &pattern); + extracted = extracted.replace(&escaped, &pattern); + } + + println!("{}", extracted.trim_start()); + + Ok(()) +} diff --git a/src/structures/config.rs b/src/structures/config.rs index afb2524..1380036 100644 --- a/src/structures/config.rs +++ b/src/structures/config.rs @@ -38,6 +38,7 @@ impl FromStr for Func { match s { "url::open" => Ok(Func::UrlOpen), "welcome" => Ok(Func::Welcome), + "widget::last_command" => Ok(Func::WidgetLastCommand), _ => Err("no match"), } } @@ -147,7 +148,7 @@ pub enum Command { /// Performs ad-hoc functions provided by navi Fn { /// Function name (example: "url::open") - #[clap(possible_values = &["url::welcome", "open"], case_insensitive = true)] + #[clap(possible_values = &["url::welcome", "open", "widget::last_command"], case_insensitive = true)] func: Func, /// List of arguments (example: "https://google.com") args: Vec<String>, |