summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Isidoro <denisidoro@users.noreply.github.com>2021-04-09 11:55:44 -0300
committerGitHub <noreply@github.com>2021-04-09 11:55:44 -0300
commit307f0c11b2df76268e21924546c51ea7c2774010 (patch)
tree2f359c6ef26c41b6de7e755713ed872b4c38ab70
parent1f3560f7f97482dd24d9249e3a49dff729cbcc76 (diff)
Improve bash and zsh widgets (#486)v2.15.0
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--docs/installation.md2
-rw-r--r--shell/navi.plugin.bash57
-rw-r--r--shell/navi.plugin.zsh155
-rw-r--r--src/cmds/func.rs40
-rw-r--r--src/structures/config.rs3
7 files changed, 89 insertions, 172 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c2f5a70..74200ea 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -308,7 +308,7 @@ dependencies = [
[[package]]
name = "navi"
-version = "2.14.0"
+version = "2.15.0"
dependencies = [
"anyhow",
"clap",
diff --git a/Cargo.toml b/Cargo.toml
index eea9a57..8b7da9b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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>,