Browse Source

znt: update to v2.1.15

Sebastian Gniazdowski 8 years ago
parent
commit
e2d157d589

+ 31 - 3
plugins/zsh-navigation-tools/.config/znt/n-aliases.conf

@@ -1,5 +1,33 @@
 # How should be current element of the list drawn. Possible values: reverse,
-# underline. Default (without option set) is reverse
+# underline.
 # On Linux virtual terminal this will be enforced to reverse (because of poor
-# underline support on that terminal)
-# local active_text=underline
+# underline support on that terminal). The same for screen/tmux.
+local active_text=reverse
+
+
+
+
+
+
+#
+# Zshrc integration. All below variables can
+# be set in zshrc and will have precedence
+# over config files
+#
+
+# 1. znt_aliases_active_text
+active_text=${znt_aliases_active_text:-$active_text}
+
+# 2. znt_aliases_nlist_coloring_pattern
+NLIST_COLORING_PATTERN=${znt_aliases_nlist_coloring_pattern:-$NLIST_COLORING_PATTERN}
+
+# 3. znt_aliases_nlist_coloring_color
+NLIST_COLORING_COLOR=${znt_aliases_nlist_coloring_color:-$NLIST_COLORING_COLOR}
+
+# 4. znt_aliases_nlist_coloring_match_multiple
+NLIST_COLORING_MATCH_MULTIPLE=${znt_aliases_nlist_coloring_match_multiple:-$NLIST_COLORING_MATCH_MULTIPLE}
+
+# 5. znt_aliases_keywords (array)
+if (( ${+znt_aliases_keywords} )); then
+    keywords=( "${znt_aliases_keywords[@]}" )
+fi

+ 47 - 5
plugins/zsh-navigation-tools/.config/znt/n-cd.conf

@@ -1,6 +1,6 @@
 # Hotlist
-# Try to use $ZSH_VERSION, e.g. /usr/share/zsh/$ZSH_VERSION/functions
-local hotlist
+# Can use e.g. $ZSH_VERSION, e.g. /usr/share/zsh/$ZSH_VERSION/functions
+local -a hotlist
 hotlist=(
     ~/.config/znt
     /usr/share/zsh/site-functions
@@ -8,6 +8,7 @@ hotlist=(
     /usr/local/share/zsh/site-functions
     /usr/local/share/zsh
     /usr/local/bin
+    /usr/lib
 )
 
 # Suppress adding (to directory stack) directories visited by n-cd
@@ -15,12 +16,53 @@ hotlist=(
 local NCD_DONT_PUSHD=0
 
 # How should be current element of the list drawn. Possible values: reverse,
-# underline. Default (without option set) is reverse
+# underline.
 # On Linux virtual terminal this will be enforced to reverse (because of poor
-# underline support on that terminal)
-# local active_text=underline
+# underline support on that terminal). The same for screen/tmux.
+local active_text=reverse
 
 # Colorize last segments of the paths
 # (#s) is ^, (#e) is $, # is *, ## is + (comparing to regex)
 local NLIST_COLORING_PATTERN="[a-zA-Z0-9 ._-]##/#(#e)"
 local NLIST_COLORING_COLOR=$'\x1b[00;33m'
+
+# Search keywords, iterated with F2 or Ctrl-X or Ctrl-/
+local -a keywords
+keywords=( "zsh" "local" "git" )
+
+
+
+
+
+
+
+#
+# Zshrc integration. All below variables can
+# be set in zshrc and will have precedence
+# over config files
+#
+
+# 1. znt_cd_hotlist (array)
+if (( ${+znt_cd_hotlist} )); then
+    hotlist=( "${znt_cd_hotlist[@]}" )
+fi
+
+# 2. znt_cd_dont_pushd
+NCD_DONT_PUSHD=${znt_cd_dont_pushd:-$NCD_DONT_PUSHD}
+
+# 3. znt_cd_active_text
+active_text=${znt_cd_active_text:-$active_text}
+
+# 4. znt_cd_nlist_coloring_pattern
+NLIST_COLORING_PATTERN=${znt_cd_nlist_coloring_pattern:-$NLIST_COLORING_PATTERN}
+
+# 5. znt_cd_nlist_coloring_color
+NLIST_COLORING_COLOR=${znt_cd_nlist_coloring_color:-$NLIST_COLORING_COLOR}
+
+# 6. znt_cd_nlist_coloring_match_multiple
+NLIST_COLORING_MATCH_MULTIPLE=${znt_cd_nlist_coloring_match_multiple:-$NLIST_COLORING_MATCH_MULTIPLE}
+
+# 7. znt_cd_keywords (array)
+if (( ${+znt_cd_keywords} )); then
+    keywords=( "${znt_cd_keywords[@]}" )
+fi

+ 32 - 3
plugins/zsh-navigation-tools/.config/znt/n-env.conf

@@ -1,9 +1,38 @@
 # How should be current element of the list drawn. Possible values: reverse,
-# underline. Default (without option set) is reverse
+# underline.
 # On Linux virtual terminal this will be enforced to reverse (because of poor
-# underline support on that terminal)
-# local active_text=underline
+# underline support on that terminal). The same for screen/tmux.
+local active_text=reverse
 
 # (#s) is ^, (#e) is $, # is *, ## is + (comparing to regex)
 local NLIST_COLORING_PATTERN="[a-zA-Z0-9_]##"
 local NLIST_COLORING_MATCH_MULTIPLE=0
+
+
+
+
+
+
+
+#
+# Zshrc integration. All below variables can
+# be set in zshrc and will have precedence
+# over config files
+#
+
+# 1. znt_env_active_text
+active_text=${znt_env_active_text:-$active_text}
+
+# 2. znt_env_nlist_coloring_pattern
+NLIST_COLORING_PATTERN=${znt_env_nlist_coloring_pattern:-$NLIST_COLORING_PATTERN}
+
+# 3. znt_env_nlist_coloring_color
+NLIST_COLORING_COLOR=${znt_env_nlist_coloring_color:-$NLIST_COLORING_COLOR}
+
+# 4. znt_env_nlist_coloring_match_multiple
+NLIST_COLORING_MATCH_MULTIPLE=${znt_env_nlist_coloring_match_multiple:-$NLIST_COLORING_MATCH_MULTIPLE}
+
+# 5. znt_env_keywords (array)
+if (( ${+znt_env_keywords} )); then
+    keywords=( "${znt_env_keywords[@]}" )
+fi

+ 34 - 3
plugins/zsh-navigation-tools/.config/znt/n-functions.conf

@@ -4,7 +4,38 @@ local feditor="zed"
 # local feditor="vared"
 
 # How should be current element of the list drawn. Possible values: reverse,
-# underline. Default (without option set) is reverse
+# underline.
 # On Linux virtual terminal this will be enforced to reverse (because of poor
-# underline support on that terminal)
-# local active_text=underline
+# underline support on that terminal). The same for screen/tmux.
+local active_text=reverse
+
+
+
+
+
+
+#
+# Zshrc integration. All below variables can
+# be set in zshrc and will have precedence
+# over config files
+#
+
+# 1. znt_functions_feditor
+feditor=${znt_functions_feditor:-$feditor}
+
+# 2. znt_functions_active_text
+active_text=${znt_functions_active_text:-$active_text}
+
+# 3. znt_functions_nlist_coloring_pattern
+NLIST_COLORING_PATTERN=${znt_functions_nlist_coloring_pattern:-$NLIST_COLORING_PATTERN}
+
+# 4. znt_functions_nlist_coloring_color
+NLIST_COLORING_COLOR=${znt_functions_nlist_coloring_color:-$NLIST_COLORING_COLOR}
+
+# 5. znt_functions_nlist_coloring_match_multiple
+NLIST_COLORING_MATCH_MULTIPLE=${znt_functions_nlist_coloring_match_multiple:-$NLIST_COLORING_MATCH_MULTIPLE}
+
+# 6. znt_functions_keywords (array)
+if (( ${+znt_functions_keywords} )); then
+    keywords=( "${znt_functions_keywords[@]}" )
+fi

+ 35 - 2
plugins/zsh-navigation-tools/.config/znt/n-history.conf

@@ -1,10 +1,43 @@
 # How should be current element of the list drawn. Possible values: reverse,
-# underline. Default (without option set) is reverse
+# underline.
 # On Linux virtual terminal this will be enforced to reverse (because of poor
-# underline support on that terminal)
+# underline support on that terminal). The same for screen/tmux.
 local active_text=underline
 
 # Highlight a few keywords
 local NLIST_COLORING_PATTERN="(while|for |sudo|make|(#s)git|vim(#e)|vim |emacs(#e)|emacs )"
 local NLIST_COLORING_COLOR=$'\x1b[00;33m'
 local NLIST_COLORING_MATCH_MULTIPLE=1
+
+# Search keywords, iterated with F2 or Ctrl-X or Ctrl-/
+local -a keywords
+keywords=( "git" "vim" "mplayer" )
+
+
+
+
+
+
+
+#
+# Zshrc integration. All below variables can
+# be set in zshrc and will have precedence
+# over config files
+#
+
+# 1. znt_history_active_text
+active_text=${znt_history_active_text:-$active_text}
+
+# 2. znt_history_nlist_coloring_pattern
+NLIST_COLORING_PATTERN=${znt_history_nlist_coloring_pattern:-$NLIST_COLORING_PATTERN}
+
+# 3. znt_history_nlist_coloring_color
+NLIST_COLORING_COLOR=${znt_history_nlist_coloring_color:-$NLIST_COLORING_COLOR}
+
+# 4. znt_history_nlist_coloring_match_multiple
+NLIST_COLORING_MATCH_MULTIPLE=${znt_history_nlist_coloring_match_multiple:-$NLIST_COLORING_MATCH_MULTIPLE}
+
+# 5. znt_history_keywords (array)
+if (( ${+znt_history_keywords} )); then
+    keywords=( "${znt_history_keywords[@]}" )
+fi

+ 36 - 3
plugins/zsh-navigation-tools/.config/znt/n-kill.conf

@@ -1,8 +1,8 @@
 # How should be current element of the list drawn. Possible values: reverse,
-# underline. Default (without option set) is reverse
+# underline.
 # On Linux virtual terminal this will be enforced to reverse (because of poor
-# underline support on that terminal)
-# local active_text=underline
+# underline support on that terminal). The same for screen/tmux.
+local active_text=reverse
 
 # Colorize first number column and last path segment
 # This doesn't cover scripts named "[0-9]## *", which should be very rare
@@ -11,3 +11,36 @@
 local NLIST_COLORING_PATTERN="((#s) #[0-9]## |[[][^]]#](#e)|[^ 0-9/?\\\\][^/\\\\]#(#e)|[^ /\\\\]##[^0-9/\\\\ ]##[^/\\\\]#(#e))"
 local NLIST_COLORING_COLOR=$'\x1b[00;33m'
 local NLIST_COLORING_MATCH_MULTIPLE=1
+
+# Search keywords, iterated with F2 or Ctrl-X or Ctrl-/
+local -a keywords
+keywords=( "vim" "git" "git commit" "firefox" "mplayer" )
+
+
+
+
+
+
+
+#
+# Zshrc integration. All below variables can
+# be set in zshrc and will have precedence
+# over config files
+#
+
+# 1. znt_kill_active_text
+active_text=${znt_kill_active_text:-$active_text}
+
+# 2. znt_kill_nlist_coloring_pattern
+NLIST_COLORING_PATTERN=${znt_kill_nlist_coloring_pattern:-$NLIST_COLORING_PATTERN}
+
+# 3. znt_kill_nlist_coloring_color
+NLIST_COLORING_COLOR=${znt_kill_nlist_coloring_color:-$NLIST_COLORING_COLOR}
+
+# 4. znt_kill_nlist_coloring_match_multiple
+NLIST_COLORING_MATCH_MULTIPLE=${znt_kill_nlist_coloring_match_multiple:-$NLIST_COLORING_MATCH_MULTIPLE}
+
+# 5. znt_kill_keywords (array)
+if (( ${+znt_kill_keywords} )); then
+    keywords=( "${znt_kill_keywords[@]}" )
+fi

+ 53 - 1
plugins/zsh-navigation-tools/.config/znt/n-list.conf

@@ -1,3 +1,55 @@
 # Should the list (text, borders) be drawn in bold
 # Value 1 is the default
-local bold=1
+local bold=0
+
+# Main color pair (foreground/background)
+local colorpair="white/black"
+
+# Should draw the border?
+local border=1
+
+# Combinations of colors to try out with Ctrl-T and Ctrl-G
+# The last number is the bold option, 0 or 1
+local -a themes
+themes=( "white/black/1" "green/black/0" "green/black/1" "white/blue/0" "white/blue/1"
+         "magenta/black/0" "magenta/black/1" )
+
+# Uncomment when using new (>5.2) Zsh version that supports 256 colors in zcurses
+#themes=( "white/17/0" "10/17/1" "white/24/1" "white/22/0" "white/22/1" "white/25/0" "white/25/1"
+#         "white/59/0" "white/59/1" "white/60/0" "white/60/1" "white/61/0" "white/61/1" "black/65/0"
+#         "black/244/0"  )
+
+# When 1, pressing enter when in search mode will not
+# only leave the mode, but also do selection and leave
+# n-history
+local NLIST_INSTANT_SELECT=0
+
+
+
+
+
+
+
+#
+# Zshrc integration. All below variables can
+# be set in zshrc and will have precedence
+# over config files
+#
+
+# 1. znt_list_bold
+bold=${znt_list_bold:-$bold}
+
+# 2. znt_list_colorpair
+colorpair=${znt_list_colorpair:-$colorpair}
+
+# 3. znt_list_border
+border=${znt_list_border:-$border}
+
+# 4. znt_list_themes (array)
+if (( ${+znt_list_themes} )); then
+    themes=( "${znt_list_themes[@]}" )
+fi
+
+# 5. znt_list_instant_select
+NLIST_INSTANT_SELECT=${znt_list_instant_select:-$NLIST_INSTANT_SELECT}
+

+ 32 - 3
plugins/zsh-navigation-tools/.config/znt/n-options.conf

@@ -1,5 +1,34 @@
 # How should be current element of the list drawn. Possible values: reverse,
-# underline. Default (without option set) is reverse
+# underline.
 # On Linux virtual terminal this will be enforced to reverse (because of poor
-# underline support on that terminal)
-# local active_text=underline
+# underline support on that terminal). The same for screen/tmux.
+local active_text=reverse
+
+
+
+
+
+
+
+#
+# Zshrc integration. All below variables can
+# be set in zshrc and will have precedence
+# over config files
+#
+
+# 1. znt_options_active_text
+active_text=${znt_options_active_text:-$active_text}
+
+# 2. znt_options_nlist_coloring_pattern
+NLIST_COLORING_PATTERN=${znt_options_nlist_coloring_pattern:-$NLIST_COLORING_PATTERN}
+
+# 3. znt_options_nlist_coloring_color
+NLIST_COLORING_COLOR=${znt_options_nlist_coloring_color:-$NLIST_COLORING_COLOR}
+
+# 4. znt_options_nlist_coloring_match_multiple
+NLIST_COLORING_MATCH_MULTIPLE=${znt_options_nlist_coloring_match_multiple:-$NLIST_COLORING_MATCH_MULTIPLE}
+
+# 5. znt_options_keywords (array)
+if (( ${+znt_options_keywords} )); then
+    keywords=( "${znt_options_keywords[@]}" )
+fi

+ 32 - 3
plugins/zsh-navigation-tools/.config/znt/n-panelize.conf

@@ -1,5 +1,34 @@
 # How should be current element of the list drawn. Possible values: reverse,
-# underline. Default (without option set) is reverse
+# underline.
 # On Linux virtual terminal this will be enforced to reverse (because of poor
-# underline support on that terminal)
-# local active_text=underline
+# underline support on that terminal). The same for screen/tmux.
+local active_text=reverse
+
+
+
+
+
+
+
+#
+# Zshrc integration. All below variables can
+# be set in zshrc and will have precedence
+# over config files
+#
+
+# 1. znt_panelize_active_text
+active_text=${znt_panelize_active_text:-$active_text}
+
+# 2. znt_panelize_nlist_coloring_pattern
+NLIST_COLORING_PATTERN=${znt_panelize_nlist_coloring_pattern:-$NLIST_COLORING_PATTERN}
+
+# 3. znt_panelize_nlist_coloring_color
+NLIST_COLORING_COLOR=${znt_panelize_nlist_coloring_color:-$NLIST_COLORING_COLOR}
+
+# 4. znt_panelize_nlist_coloring_match_multiple
+NLIST_COLORING_MATCH_MULTIPLE=${znt_panelize_nlist_coloring_match_multiple:-$NLIST_COLORING_MATCH_MULTIPLE}
+
+# 5. znt_panelize_keywords (array)
+if (( ${+znt_panelize_keywords} )); then
+    keywords=( "${znt_panelize_keywords[@]}" )
+fi

+ 80 - 1
plugins/zsh-navigation-tools/README.md

@@ -1,6 +1,6 @@
 # Zsh Navigation Tools
 
-http://imageshack.com/a/img633/7967/ps6rKR.png
+https://raw.githubusercontent.com/psprint/zsh-navigation-tools/master/doc/img/n-history2.png
 
 Set of tools like n-history – multi-word history searcher, n-cd – directory
 bookmark manager, n-kill – htop like kill utility, and more. Based on
@@ -32,6 +32,26 @@ to key combinations (no need for autoload when using Oh My Zsh):
 Oh My Zsh stores history into ~/.zsh_history. When you switch to OMZ you could
 want to copy your previous data (from e.g. ~/.zhistory) into the new location.
 
+## News
+
+* 30-04-2016
+  - New feature: color themes. Use Ctrl-T and Ctrl-G to browse predefined
+    themes. They are listed in ~/.config/znt/n-list.conf. Use the file to
+    permanently set a color scheme. Also, I sent a patch to Zsh developers
+    and starting from Zsh > 5.2 (not yet released) supported will be 256 colors.
+    The file ~/.config/znt/n-list.conf already has set of 256-color themes prepared :)
+
+* 29-04-2016
+  - New feature: private history – n-history tracks selected history entries,
+    exposes them via new view (activated with F1)
+
+* 28-04-2016
+  - New features:
+    1. New n-history view (activated with F1): Most Frequent History Words
+    2. Predefined search keywords – use F2 to quickly search for chosen
+       keywords (video: [https://youtu.be/DN9QqssAYB8](https://youtu.be/DN9QqssAYB8))
+    3. Configuration option for doing instant selection in search mode
+
 ## Introduction
 
 The tools are:
@@ -60,6 +80,65 @@ cursors. Other keys are:
 - Ctrl-w (in incremental search) - delete whole word
 - Ctrl-k (in incremental search) - delete whole line
 
+## Configuration
+
+`ZNT` has configuration files located in `~/.config/znt`. The files are:
+
+```
+n-aliases.conf
+n-cd.conf
+n-env.conf
+n-functions.conf
+n-history.conf
+n-kill.conf
+n-list.conf
+n-options.conf
+n-panelize.conf
+```
+
+`n-list.conf` contains main configuration variables:
+
+```zsh
+# Should the list (text, borders) be drawn in bold
+local bold=0
+
+# Main color pair (foreground/background)
+local colorpair="white/black"
+
+# Should draw the border?
+local border=1
+
+# Combinations of colors to try out with Ctrl-T and Ctrl-G
+# The last number is the bold option, 0 or 1
+local -a themes
+themes=( "white/black/1" "green/black/0" "green/black/1" "white/blue/0" "white/blue/1"
+         "magenta/black/0" "magenta/black/1" )
+```
+
+Read remaining configuration files to see what's in them. Nevertheless, configuration
+can be also set from `zshrc`. There are `5` standard `zshrc` configuration variables:
+
+```
+znt_history_active_text - underline or reverse - how should be active element highlighted
+znt_history_nlist_coloring_pattern - pattern that can be used to colorize elements
+znt_history_nlist_coloring_color - color with which to colorize
+znt_history_nlist_coloring_match_multiple - should multiple matches be colorized (0 or 1)
+znt_history_keywords (array) - search keywords activated with `Ctrl-X`
+```
+
+Above variables will work for `n-history` tool. For other tools, change `_history_` to
+e.g. `_cd_`, for the `n-cd` tool. The same works for all `8` tools.
+
+Common configuration of the tools uses variables with `_list_` in them:
+
+```
+znt_list_bold - should draw text in bold (0 or 1)
+znt_list_colorpair - main pair of colors to be used, e.g "green/black"
+znt_list_border - should draw borders around windows (0 or 1)
+znt_list_themes (array) - list of themes to try out with Ctrl-T, e.g. ( "white/black/1" "green/black/0" )
+znt_list_instant_select - should pressing enter in search mode leave tool (0 or 1)
+```
+
 ## Programming
 
 The function n-list is used as follows:

+ 41 - 0
plugins/zsh-navigation-tools/_n-kill

@@ -0,0 +1,41 @@
+#compdef n-kill
+
+local context ret=1
+
+typeset -a list linewords
+typeset -aU words wordbits
+local line word
+integer cygwin=0
+
+local IFS="
+"
+
+case "$(uname)" in
+    CYGWIN*) list=( `command ps -Wa` ); cygwin=1 ;;
+    *) list=( `command ps -o pid,uid,command -A` ) ;;
+esac
+
+shift list
+
+IFS=" "
+for line in "${list[@]}"; do
+    linewords=( $=line )
+    if [ "$cygwin" = "1" ]; then
+        linewords=( "${(@)linewords[8,-1]}" )
+    else
+        linewords=( "${(@)linewords[3,-1]}" )
+    fi
+    for word in "${linewords[@]}"; do
+        if [ "$cygwin" = "1" ]; then
+            wordbits=( "${(@s:\:)word}" )
+        else
+            wordbits=( "${(@s:/:)word}" )
+        fi
+        words+=( "${wordbits[@]}" )
+    done
+done
+
+_wanted bits expl "Processes' name bits" \
+    compadd "$@" -a - words && ret=0
+
+return "$ret"

+ 2 - 2
plugins/zsh-navigation-tools/n-aliases

@@ -16,8 +16,8 @@ local IFS="
 
 unset NLIST_COLORING_PATTERN
 
-[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
-[ -f ~/.config/znt/n-aliases.conf ] && . ~/.config/znt/n-aliases.conf
+[ -f ~/.config/znt/n-list.conf ] && builtin source ~/.config/znt/n-list.conf
+[ -f ~/.config/znt/n-aliases.conf ] && builtin source ~/.config/znt/n-aliases.conf
 
 local list
 local selected

+ 10 - 7
plugins/zsh-navigation-tools/n-cd

@@ -16,8 +16,8 @@ local IFS="
 # Unset before configuration is read
 unset NLIST_COLORING_PATTERN
 
-[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
-[ -f ~/.config/znt/n-cd.conf ] && . ~/.config/znt/n-cd.conf
+[ -f ~/.config/znt/n-list.conf ] && builtin source ~/.config/znt/n-list.conf
+[ -f ~/.config/znt/n-cd.conf ] && builtin source ~/.config/znt/n-cd.conf
 
 local list
 local selected
@@ -53,13 +53,16 @@ if [ "$REPLY" -gt 0 ]; then
 
     (( NCD_DONT_PUSHD )) && setopt NO_AUTO_PUSHD
     cd "$selected"
+    local code=$?
     (( NCD_DONT_PUSHD )) && setopt AUTO_PUSHD
 
-    # ZLE?
-    if [ "${(t)CURSOR}" = "integer-local-special" ]; then
-        zle -M "You have selected $selected"
-    else
-        echo "You have selected $selected"
+    if [ "$code" -eq "0" ]; then
+        # ZLE?
+        if [ "${(t)CURSOR}" = "integer-local-special" ]; then
+            zle -M "You have selected $selected"
+        else
+            echo "You have selected $selected"
+        fi
     fi
 else
     [ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay

+ 2 - 2
plugins/zsh-navigation-tools/n-env

@@ -15,8 +15,8 @@ zmodload zsh/curses
 local IFS="
 "
 
-[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
-[ -f ~/.config/znt/n-env.conf ] && . ~/.config/znt/n-env.conf
+[ -f ~/.config/znt/n-list.conf ] && builtin source ~/.config/znt/n-list.conf
+[ -f ~/.config/znt/n-env.conf ] && builtin source ~/.config/znt/n-env.conf
 
 local list
 local selected

+ 2 - 2
plugins/zsh-navigation-tools/n-functions

@@ -16,8 +16,8 @@ local IFS="
 
 unset NLIST_COLORING_PATTERN
 
-[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
-[ -f ~/.config/znt/n-functions.conf ] && . ~/.config/znt/n-functions.conf
+[ -f ~/.config/znt/n-list.conf ] && builtin source ~/.config/znt/n-list.conf
+[ -f ~/.config/znt/n-functions.conf ] && builtin source ~/.config/znt/n-functions.conf
 
 local list
 local selected

+ 96 - 0
plugins/zsh-navigation-tools/n-help

@@ -0,0 +1,96 @@
+autoload colors
+colors
+
+local h1="$fg_bold[cyan]"
+local h2="$fg_bold[green]"
+local h3="$fg_bold[blue]"
+local h4="$fg_bold[yellow]"
+local h5="$fg_bold[magenta]"
+local rst="$reset_color"
+
+LESS="-iRc" less <<<"
+${h1}Key Bindings${rst}
+
+${h2}H${rst}, ${h2}?${rst} (from n-history) - run n-help
+${h2}Ctrl-A${rst} - rotate entered words (1+2+3 -> 3+1+2)
+${h2}Ctrl-F${rst} - fix mode (approximate matching)
+${h2}Ctrl-L${rst} - redraw of whole display
+${h2}Ctrl-T${rst} - browse themes (next theme)
+${h2}Ctrl-G${rst} - browse themes (previous theme)
+${h2}Ctrl-U${rst} - half page up
+${h2}Ctrl-D${rst} - half page down
+${h2}Ctrl-P${rst} - previous element (also done with vim's k)
+${h2}Ctrl-N${rst} - next element (also done with vim's j)
+${h2}[${rst}, ${h2}]${rst} - jump directory bookmarks in n-cd and typical signals in n-kill
+${h2}g, ${h2}G${rst} - beginning and end of the list
+${h2}/${rst} - show incremental search
+${h2}F3${rst} - show/hide incremental search
+${h2}Esc${rst} - exit incremental search, clearing filter
+${h2}Ctrl-W${rst} (in incremental search) - delete whole word
+${h2}Ctrl-K${rst} (in incremental search) - delete whole line
+${h2}Ctrl-O, ${h2}o${rst} - enter uniq mode (no duplicate lines)
+${h2}Ctrl-E, ${h2}e${rst} - edit private history (when in private history view)
+${h2}F1${rst} - (in n-history) - switch view
+${h2}F2${rst}, ${h2}Ctrl-X${rst}, ${h2}Ctrl-/${rst} - search predefined keywords (defined in config files)
+
+${h1}Configuration files${rst}
+
+Location of the files is ${h3}~/.config/znt${rst}. Skeletons are copied there
+when using ${h3}zsh-navigation-tools.plugin.zsh${rst} file (sourcing it or using
+a plugin manager). There's a main config file ${h3}n-list.conf${rst} and files
+for each tool.
+
+To have a skeleton copied again into ${h3}~/.config/znt${rst}, delete it from
+there and restart Zsh a few times (3-7 or so; there's a random check
+that optimizes startup time).
+
+${h1}Predefined search keywords${rst}
+
+Following block of code in e.g. ${h3}~/.config/znt/n-history.conf${rst} defines
+set of keywords that can be invoked (i.e. searched for) via ${h2}F2${rst}, ${h2}Ctrl-X${rst}
+or ${h2}Ctrl-/${rst}:
+
+    ${h4}# Search keywords, iterated with F2 or Ctrl-X or Ctrl-/${rst}
+    ${h2}local${rst} -a keywords
+    keywords=( ${h2}\"git\" \"vim\" \"mplayer\"${rst} )
+
+${h1}Search query rotation${rst}
+
+When searching, after pressing ${h2}Ctrl-A${rst}, words 1 2 3 will become 3 1 2, etc.
+This can be used to edit some not-last word.
+
+${h1}Fix mode${rst}
+
+Approximate matching - pressing ${h2}f${rst} or ${h2}Ctrl-F${rst} will enter "FIX" mode, in which
+1 or 2 errors are allowed in what's searched. This utilizes original Zsh
+approximate matching features and is intended to be used after entering
+search query, when a typo is discovered.
+
+${h1}Color themes${rst}
+
+Following block of code in ${h3}~/.config/znt/n-list.conf${rst} defines set of
+themes that can be browsed with ${h2}Ctrl-T${rst} and ${h2}Ctrl-G${rst}:
+
+    ${h4}# Combinations of colors to try out with Ctrl-T and Ctrl-G
+    # The last number is the bold option, 0 or 1${rst}
+    ${h2}local${rst} -a themes
+    themes=( ${h2}\"white/black/1\" \"green/black/0\" \"green/black/1\"${rst}
+             ${h2}\"white/blue/0\" \"white/blue/1\" \"magenta/black/0\"${rst}
+             ${h2}\"magenta/black/1\"${rst} )
+
+It's \"foreground/background/bold\". There's support for 256-color themes
+for Zsh > 5.2, defined like e.g.: 
+
+    themes=( ${h2}\"white/17/0\" \"10/17/1\" \"white/24/1\"${rst} )
+
+i.e. with use of numbers, from 0 to 254.
+
+${h1}Private history${rst}
+
+N-history stores what's selected in its own history file. It can be
+edited. Use ${h2}e${rst} or ${h2}Ctrl-E${rst} for that when in n-history. Your \$EDITOR will
+start. This is a way to have handy set of bookmarks prepared in private
+history's file.
+
+Private history is instantly shared among sessions.
+"

+ 315 - 14
plugins/zsh-navigation-tools/n-history

@@ -15,27 +15,323 @@ zmodload zsh/parameter
 local IFS="
 "
 
-unset NLIST_COLORING_PATTERN
+# Variables to save list's state when switching views
+# The views are: history and "most frequent history words"
+local one_NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
+local one_NLIST_CURRENT_IDX
+local one_NLIST_IS_SEARCH_MODE
+local one_NLIST_SEARCH_BUFFER
+local one_NLIST_TEXT_OFFSET
+local one_NLIST_IS_UNIQ_MODE
+local one_NLIST_IS_F_MODE
+local one_NLIST_GREP_STRING
+local one_NLIST_NONSELECTABLE_ELEMENTS
+local one_NLIST_REMEMBER_STATE
+local one_NLIST_ENABLED_EVENTS
 
-[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
-[ -f ~/.config/znt/n-history.conf ] && . ~/.config/znt/n-history.conf
+local two_NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
+local two_NLIST_CURRENT_IDX
+local two_NLIST_IS_SEARCH_MODE
+local two_NLIST_SEARCH_BUFFER
+local two_NLIST_TEXT_OFFSET
+local two_NLIST_IS_UNIQ_MODE
+local two_NLIST_IS_F_MODE
+local two_NLIST_GREP_STRING
+local two_NLIST_NONSELECTABLE_ELEMENTS
+local two_NLIST_REMEMBER_STATE
+local two_NLIST_ENABLED_EVENTS
 
-local list
-local selected
+local three_NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
+local three_NLIST_CURRENT_IDX
+local three_NLIST_IS_SEARCH_MODE
+local three_NLIST_SEARCH_BUFFER
+local three_NLIST_TEXT_OFFSET
+local three_NLIST_IS_UNIQ_MODE
+local three_NLIST_IS_F_MODE
+local three_NLIST_GREP_STRING
+local three_NLIST_NONSELECTABLE_ELEMENTS
+local three_NLIST_REMEMBER_STATE
+local three_NLIST_ENABLED_EVENTS
 
-NLIST_REMEMBER_STATE=0
+# history view
+integer active_view=0
 
-list=( "$history[@]" )
-list=( "${(@M)list:#(#i)*$1*}" )
+# Lists are "0", "1", "2" - 1st, 2nd, 3rd
+# Switching is done in cyclic manner
+# i.e. 0 -> 1, 1 -> 2, 2 -> 0
+_nhistory_switch_lists_states() {
+    # First argument is current, newly selected list, i.e. $active_view
+    # This implies that we are switching from previous view
+   
+    if [ "$1" = "0" ]; then
+        # Switched to 1st list, save 3rd list's state
+        three_NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
+        three_NLIST_CURRENT_IDX=$NLIST_CURRENT_IDX
+        three_NLIST_IS_SEARCH_MODE=$NLIST_IS_SEARCH_MODE
+        three_NLIST_SEARCH_BUFFER=$NLIST_SEARCH_BUFFER
+        three_NLIST_TEXT_OFFSET=$NLIST_TEXT_OFFSET
+        three_NLIST_IS_UNIQ_MODE=$NLIST_IS_UNIQ_MODE
+        three_NLIST_IS_F_MODE=$NLIST_IS_F_MODE
+        three_NLIST_GREP_STRING=$NLIST_GREP_STRING
+        three_NLIST_NONSELECTABLE_ELEMENTS=( ${NLIST_NONSELECTABLE_ELEMENTS[@]} )
+        three_NLIST_REMEMBER_STATE=$NLIST_REMEMBER_STATE
+        three_NLIST_ENABLED_EVENTS=( ${NLIST_ENABLED_EVENTS[@]} )
 
-if [ "$#list" -eq 0 ]; then
-    echo "No matching history entries"
-    return 1
-fi
+        # ..and restore 1st list's state
+        NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$one_NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
+        NLIST_CURRENT_IDX=$one_NLIST_CURRENT_IDX
+        NLIST_IS_SEARCH_MODE=$one_NLIST_IS_SEARCH_MODE
+        NLIST_SEARCH_BUFFER=$one_NLIST_SEARCH_BUFFER
+        NLIST_TEXT_OFFSET=$one_NLIST_TEXT_OFFSET
+        NLIST_IS_UNIQ_MODE=$one_NLIST_IS_UNIQ_MODE
+        NLIST_IS_F_MODE=$one_NLIST_IS_F_MODE
+        NLIST_GREP_STRING=$one_NLIST_GREP_STRING
+        NLIST_NONSELECTABLE_ELEMENTS=( ${one_NLIST_NONSELECTABLE_ELEMENTS[@]} )
+        NLIST_REMEMBER_STATE=$one_NLIST_REMEMBER_STATE
+        NLIST_ENABLED_EVENTS=( ${one_NLIST_ENABLED_EVENTS[@]} )
+    elif [ "$1" = "1" ]; then
+        # Switched to 2nd list, save 1st list's state
+        one_NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
+        one_NLIST_CURRENT_IDX=$NLIST_CURRENT_IDX
+        one_NLIST_IS_SEARCH_MODE=$NLIST_IS_SEARCH_MODE
+        one_NLIST_SEARCH_BUFFER=$NLIST_SEARCH_BUFFER
+        one_NLIST_TEXT_OFFSET=$NLIST_TEXT_OFFSET
+        one_NLIST_IS_UNIQ_MODE=$NLIST_IS_UNIQ_MODE
+        one_NLIST_IS_F_MODE=$NLIST_IS_F_MODE
+        one_NLIST_GREP_STRING=$NLIST_GREP_STRING
+        one_NLIST_NONSELECTABLE_ELEMENTS=( ${NLIST_NONSELECTABLE_ELEMENTS[@]} )
+        one_NLIST_REMEMBER_STATE=$NLIST_REMEMBER_STATE
+        one_NLIST_ENABLED_EVENTS=( ${NLIST_ENABLED_EVENTS[@]} )
+
+        # ..and restore 2nd list's state
+        NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$two_NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
+        NLIST_CURRENT_IDX=$two_NLIST_CURRENT_IDX
+        NLIST_IS_SEARCH_MODE=$two_NLIST_IS_SEARCH_MODE
+        NLIST_SEARCH_BUFFER=$two_NLIST_SEARCH_BUFFER
+        NLIST_TEXT_OFFSET=$two_NLIST_TEXT_OFFSET
+        NLIST_IS_UNIQ_MODE=$two_NLIST_IS_UNIQ_MODE
+        NLIST_IS_F_MODE=$two_NLIST_IS_F_MODE
+        NLIST_GREP_STRING=$two_NLIST_GREP_STRING
+        NLIST_NONSELECTABLE_ELEMENTS=( ${two_NLIST_NONSELECTABLE_ELEMENTS[@]} )
+        NLIST_REMEMBER_STATE=$two_NLIST_REMEMBER_STATE
+        NLIST_ENABLED_EVENTS=( ${two_NLIST_ENABLED_EVENTS[@]} )
+    elif [ "$1" = "2" ]; then
+        # Switched to 3rd list, save 2nd list's state
+        two_NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
+        two_NLIST_CURRENT_IDX=$NLIST_CURRENT_IDX
+        two_NLIST_IS_SEARCH_MODE=$NLIST_IS_SEARCH_MODE
+        two_NLIST_SEARCH_BUFFER=$NLIST_SEARCH_BUFFER
+        two_NLIST_TEXT_OFFSET=$NLIST_TEXT_OFFSET
+        two_NLIST_IS_UNIQ_MODE=$NLIST_IS_UNIQ_MODE
+        two_NLIST_IS_F_MODE=$NLIST_IS_F_MODE
+        two_NLIST_GREP_STRING=$NLIST_GREP_STRING
+        two_NLIST_NONSELECTABLE_ELEMENTS=( ${NLIST_NONSELECTABLE_ELEMENTS[@]} )
+        two_NLIST_REMEMBER_STATE=$NLIST_REMEMBER_STATE
+        two_NLIST_ENABLED_EVENTS=( ${NLIST_ENABLED_EVENTS[@]} )
+
+        # ..and restore 3rd list's state
+        NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$three_NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
+        NLIST_CURRENT_IDX=$three_NLIST_CURRENT_IDX
+        NLIST_IS_SEARCH_MODE=$three_NLIST_IS_SEARCH_MODE
+        NLIST_SEARCH_BUFFER=$three_NLIST_SEARCH_BUFFER
+        NLIST_TEXT_OFFSET=$three_NLIST_TEXT_OFFSET
+        NLIST_IS_UNIQ_MODE=$three_NLIST_IS_UNIQ_MODE
+        NLIST_IS_F_MODE=$three_NLIST_IS_F_MODE
+        NLIST_GREP_STRING=$three_NLIST_GREP_STRING
+        NLIST_NONSELECTABLE_ELEMENTS=( ${three_NLIST_NONSELECTABLE_ELEMENTS[@]} )
+        NLIST_REMEMBER_STATE=$three_NLIST_REMEMBER_STATE
+        NLIST_ENABLED_EVENTS=( ${three_NLIST_ENABLED_EVENTS[@]} )
+    fi
+}
+
+local most_frequent_db="$HOME/.config/znt/mostfrequent.db"
+_nhistory_generate_most_frequent() {
+    local title=$'\x1b[00;31m'"Most frequent history words:"$'\x1b[00;00m\0'
+
+    typeset -A uniq
+    for k in "${historywords[@]}"; do
+        uniq[$k]=$(( ${uniq[$k]:-0} + 1 ))
+    done
+    vk=()
+    for k v in ${(kv)uniq}; do
+        vk+="$v"$'\t'"$k"
+    done
+
+    print -rl "$title" "${(On)vk[@]}" > "$most_frequent_db"
+}
+
+# Load configuration
+unset NLIST_COLORING_PATTERN
+[ -f ~/.config/znt/n-list.conf ] && builtin source ~/.config/znt/n-list.conf
+[ -f ~/.config/znt/n-history.conf ] && builtin source ~/.config/znt/n-history.conf
+
+local list
+local selected
+local private_history_db="$HOME/.config/znt/privhist.db"
 
 local NLIST_GREP_STRING="$1"
+# 2 is: init once, then remember
+local NLIST_REMEMBER_STATE=2
+two_NLIST_REMEMBER_STATE=2
+three_NLIST_REMEMBER_STATE=2
+
+# Only Private history has EDIT
+local -a NLIST_ENABLED_EVENTS
+NLIST_ENABLED_EVENTS=( "F1" "HELP" )
+two_NLIST_ENABLED_EVENTS=( "F1" "EDIT" "HELP" )
+three_NLIST_ENABLED_EVENTS=( "F1" "HELP" )
+
+# All view should attempt to replace new lines with \n
 local NLIST_REPLACE_NEWLINES="1"
-n-list "${list[@]}"
+two_NLIST_REPLACE_NEWLINES="1"
+three_NLIST_REPLACE_NEWLINES="1"
+
+# Only second and third view has non-selectable first entry
+local -a NLIST_NONSELECTABLE_ELEMENTS
+NLIST_NONSELECTABLE_ELEMENTS=( )
+two_NLIST_NONSELECTABLE_ELEMENTS=( 1 )
+three_NLIST_NONSELECTABLE_ELEMENTS=( 1 )
+
+while (( 1 )); do
+
+    #
+    # View 1 - history
+    #
+    if [ "$active_view" = "0" ]; then
+        list=( "$history[@]" )
+        list=( "${(@M)list:#(#i)*$NLIST_GREP_STRING*}" )
+
+        if [ "$#list" -eq 0 ]; then
+            echo "No matching history entries"
+            return 1
+        fi
+
+        n-list "${list[@]}"
+
+        # Selection or quit?
+        if [[ "$REPLY" = -(#c0,1)[0-9]## && ("$REPLY" -lt 0 || "$REPLY" -gt 0) ]]; then
+            break
+        fi
+
+        # View change?
+        if [ "$REPLY" = "F1" ]; then
+            # Target view: 2
+            active_view=1
+            _nhistory_switch_lists_states "1"
+        elif [ "$REPLY" = "HELP" ]; then
+            n-help
+        fi
+
+    #
+    # View 3 - most frequent words in history
+    #
+    elif [ "$active_view" = "2" ]; then
+        local -a dbfile
+        dbfile=( $most_frequent_db(Nm+1) )
+
+        # Compute most frequent history words
+        if [[ "${#NHISTORY_WORDS}" -eq "0" || "${#dbfile}" -ne "0" ]]; then
+            # Read the list if it's there
+            local -a list
+            list=()
+            [ -s "$most_frequent_db" ] && list=( ${(f)"$(<$most_frequent_db)"} )
+
+            # Will wait for the data?
+            local message=0
+            if [[ "${#list}" -eq 0 ]]; then
+                message=1
+                _nlist_alternate_screen 1
+                zcurses init
+                zcurses delwin info 2>/dev/null
+                zcurses addwin info "$term_height" "$term_width" 0 0
+                zcurses bg info white/black
+                zcurses string info "Computing most frequent history words..."$'\n'
+                zcurses string info "(This is done once per day, from now on transparently)"$'\n'
+                zcurses refresh info
+                sleep 3
+            fi
+
+            # Start periodic list regeneration?
+            if [[ "${#list}" -eq 0 || "${#dbfile}" -ne "0" ]]; then
+                # Mark the file with current time, to prevent double
+                # regeneration (on quick double change of view)
+                print >> "$most_frequent_db"
+                (_nhistory_generate_most_frequent &) &> /dev/null
+            fi
+
+            # Ensure we got the list, wait for it if needed
+            while [[ "${#list}" -eq 0 ]]; do
+                zcurses string info "."
+                zcurses refresh info
+                LANG=C sleep 0.5
+                [ -s "$most_frequent_db" ] && list=( ${(f)"$(<$most_frequent_db)"} )
+            done
+
+            NHISTORY_WORDS=( "${list[@]}" )
+
+            if [ "$message" -eq "1" ]; then
+                zcurses delwin info 2>/dev/null
+                zcurses refresh
+                zcurses end
+                _nlist_alternate_screen 0
+            fi
+        else
+            # Reuse most frequent history words
+            local -a list
+            list=( "${NHISTORY_WORDS[@]}" )
+        fi
+
+        n-list "${list[@]}"
+
+        if [ "$REPLY" = "F1" ]; then
+            # Target view: 1
+            active_view=0
+            _nhistory_switch_lists_states "0"
+        elif [[ "$REPLY" = -(#c0,1)[0-9]## && "$REPLY" -lt 0 ]]; then
+            break
+        elif [[ "$REPLY" = -(#c0,1)[0-9]## && "$REPLY" -gt 0 ]]; then
+            local word="${reply[REPLY]#(#s) #[0-9]##$'\t'}"
+            one_NLIST_SEARCH_BUFFER="$word"
+            one_NLIST_SEARCH_BUFFER="${one_NLIST_SEARCH_BUFFER## ##}"
+
+            # Target view: 1
+            active_view=0
+            _nhistory_switch_lists_states "0"
+        elif [ "$REPLY" = "HELP" ]; then
+            n-help
+        fi
+
+    #
+    # View 2 - private history
+    #
+    elif [ "$active_view" = "1" ]; then
+        if [ -s "$private_history_db" ]; then
+            local title=$'\x1b[00;32m'"Private history:"$'\x1b[00;00m\0'
+            () { fc -ap -R "$private_history_db"; list=( "$title" ${history[@]} ) }
+        else
+            list=( "Private history - history entries selected via this tool will be put here" )
+        fi
+
+        n-list "${list[@]}"
+
+        # Selection or quit?
+        if [[ "$REPLY" = -(#c0,1)[0-9]## && ("$REPLY" -lt 0 || "$REPLY" -gt 0) ]]; then
+            break
+        fi
+
+        # View change?
+        if [ "$REPLY" = "F1" ]; then
+            # Target view: 3
+            active_view=2
+            _nhistory_switch_lists_states "2"
+        # Edit of the history?
+        elif [ "$REPLY" = "EDIT" ]; then
+            "${EDITOR:-vim}" "$private_history_db"
+        elif [ "$REPLY" = "HELP" ]; then
+            n-help
+        fi
+    fi
+done
 
 if [ "$REPLY" -gt 0 ]; then
     selected="$reply[REPLY]"
@@ -43,7 +339,12 @@ if [ "$REPLY" -gt 0 ]; then
     if [ "${(t)CURSOR}" = "integer-local-special" ]; then
         zle redisplay
         zle kill-buffer
-        zle -U "$selected"
+        LBUFFER+="$selected"
+
+        # Append to private history
+        local newline=$'\n'
+        selected="${selected//$newline/\\$newline}"
+        [ "$active_view" = "0" ] && print -r "$selected" >> "$private_history_db"
     else
         print -zr "$selected"
     fi

+ 2 - 2
plugins/zsh-navigation-tools/n-kill

@@ -13,8 +13,8 @@ zmodload zsh/curses
 local IFS="
 "
 
-[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
-[ -f ~/.config/znt/n-kill.conf ] && . ~/.config/znt/n-kill.conf
+[ -f ~/.config/znt/n-list.conf ] && builtin source ~/.config/znt/n-list.conf
+[ -f ~/.config/znt/n-kill.conf ] && builtin source ~/.config/znt/n-kill.conf
 
 typeset -A signals
 signals=(

+ 106 - 23
plugins/zsh-navigation-tools/n-list

@@ -29,7 +29,7 @@ _nlist_exit() {
     setopt localoptions
     setopt extendedglob
 
-    [[ "$REPLY" = -(#c0,1)[0-9]## ]] || REPLY="-1"
+    [[ "$REPLY" = -(#c0,1)[0-9]## || "$REPLY" = F<-> || "$REPLY" = "EDIT" || "$REPLY" = "HELP" ]] || REPLY="-1"
     zcurses 2>/dev/null delwin inner
     zcurses 2>/dev/null delwin main
     zcurses 2>/dev/null refresh
@@ -167,6 +167,26 @@ integer prev_uniq_mode=0
 integer prev_start_idx=-1
 local MBEGIN MEND MATCH mbegin mend match
 
+# Iteration over predefined keywords
+integer curkeyword nkeywords
+local keywordisfresh="0"
+if [[ "${(t)keywords}" != *array* ]]; then
+    local -a keywords
+    keywords=()
+fi
+curkeyword=0
+nkeywords=${#keywords}
+
+# Iteration over themes
+integer curtheme nthemes
+local themeisfresh="0"
+if [[ "${(t)themes}" != *array* ]]; then
+    local -a themes
+    themes=()
+fi
+curtheme=0
+nthemes=${#themes}
+
 # Ability to remember the list between calls
 if [[ -z "$NLIST_REMEMBER_STATE" || "$NLIST_REMEMBER_STATE" -eq 0 || "$NLIST_REMEMBER_STATE" -eq 2 ]]; then
     NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=1
@@ -175,6 +195,7 @@ if [[ -z "$NLIST_REMEMBER_STATE" || "$NLIST_REMEMBER_STATE" -eq 0 || "$NLIST_REM
     NLIST_SEARCH_BUFFER=""
     NLIST_TEXT_OFFSET=0
     NLIST_IS_UNIQ_MODE=0
+    NLIST_IS_F_MODE=0
 
     # Zero - because it isn't known, unless we
     # confirm that first element is selectable
@@ -207,12 +228,19 @@ zcurses delwin main 2>/dev/null
 zcurses delwin inner 2>/dev/null
 zcurses addwin main "$term_height" "$term_width" 0 0
 zcurses addwin inner "$inner_height" "$inner_width" 1 2
-zcurses bg main white/black
-zcurses bg inner white/black
+# From n-list.conf
+[ "$colorpair" = "" ] && colorpair="white/black"
+[ "$border" = "0" ] || border="1"
+local background="${colorpair#*/}"
+local backuptheme="$colorpair/$bold"
+zcurses bg main "$colorpair"
+zcurses bg inner "$colorpair"
 if [ "$NLIST_IS_SEARCH_MODE" -ne 1 ]; then
     _nlist_cursor_visibility 0
 fi
 
+zcurses refresh
+
 #
 # Listening for input
 #
@@ -237,9 +265,12 @@ while (( 1 )); do
     # Do searching (filtering with string)
     if [ -n "$NLIST_SEARCH_BUFFER" ]; then
         # Compute new list?
-        if [[ "$NLIST_SEARCH_BUFFER" != "$prev_search_buffer" || "$NLIST_IS_UNIQ_MODE" -ne "$prev_uniq_mode" ]]; then
+        if [[ "$NLIST_SEARCH_BUFFER" != "$prev_search_buffer" || "$NLIST_IS_UNIQ_MODE" -ne "$prev_uniq_mode"
+                || "$NLIST_IS_F_MODE" -ne "$prev_f_mode" ]]
+        then
             prev_search_buffer="$NLIST_SEARCH_BUFFER"
             prev_uniq_mode="$NLIST_IS_UNIQ_MODE"
+            prev_f_mode="$NLIST_IS_F_MODE"
             # regenerating list -> regenerating disp_list
             prev_start_idx=-1
 
@@ -251,7 +282,9 @@ while (( 1 )); do
 
             # Remove non-selectable elements
             [ "$#NLIST_NONSELECTABLE_ELEMENTS" -gt 0 ] && for i in "${(nO)NLIST_NONSELECTABLE_ELEMENTS[@]}"; do
-                list[$i]=()
+                if [[ "$i" = <-> ]]; then
+                    list[$i]=()
+                fi
             done
 
             # Remove duplicates
@@ -266,13 +299,22 @@ while (( 1 )); do
             local search_pattern=""
             local colsearch_pattern=""
             if [ -n "$search_buffer" ]; then
-                # Patterns will be *foo*~^*bar* and (foo|bar)
-                search_pattern="${search_buffer// ##/*~^*}"
-                colsearch_pattern="${search_buffer// ##/|}"
-
                 # The repeat will make the matching work on a fresh heap
                 repeat 1; do
-                    list=( "${(@M)list:#(#i)*$~search_pattern*}" )
+                    if [ "$NLIST_IS_F_MODE" -eq "1" ]; then
+                        search_pattern="${search_buffer// ##/*~^(#a1)*}"
+                        colsearch_pattern="${search_buffer// ##/|(#a1)}"
+                        list=( "${(@M)list:#(#ia1)*$~search_pattern*}" )
+                    elif [ "$NLIST_IS_F_MODE" -eq "2" ]; then
+                        search_pattern="${search_buffer// ##/*~^(#a2)*}"
+                        colsearch_pattern="${search_buffer// ##/|(#a2)}"
+                        list=( "${(@M)list:#(#ia2)*$~search_pattern*}" )
+                    else
+                        # Patterns will be *foo*~^*bar* and (foo|bar)
+                        search_pattern="${search_buffer// ##/*~^*}"
+                        colsearch_pattern="${search_buffer// ##/|}"
+                        list=( "${(@M)list:#(#i)*$~search_pattern*}" )
+                    fi
                 done
 
                 last_element="$#list"
@@ -295,7 +337,13 @@ while (( 1 )); do
                 local red=$'\x1b[00;31m' reset=$'\x1b[00;00m'
                 # The repeat will make the matching work on a fresh heap
                 repeat 1; do
-                    disp_list=( "${(@)disp_list//(#mi)($~colsearch_pattern)/$red${MATCH}$reset}" )
+                    if [ "$NLIST_IS_F_MODE" -eq "1" ]; then
+                        disp_list=( "${(@)disp_list//(#mia1)($~colsearch_pattern)/$red${MATCH}$reset}" )
+                    elif [ "$NLIST_IS_F_MODE" -eq "2" ]; then
+                        disp_list=( "${(@)disp_list//(#mia2)($~colsearch_pattern)/$red${MATCH}$reset}" )
+                    else
+                        disp_list=( "${(@)disp_list//(#mi)($~colsearch_pattern)/$red${MATCH}$reset}" )
+                    fi
                 done
             fi
 
@@ -304,6 +352,7 @@ while (( 1 )); do
         fi
 
         # Output colored list
+        zcurses clear inner
         n-list-draw "$(( (NLIST_CURRENT_IDX-1) % page_height + 1 ))" \
             "$page_height" "$page_width" 0 0 "$NLIST_TEXT_OFFSET" inner \
             "$disp_list[@]"
@@ -327,7 +376,9 @@ while (( 1 )); do
             # Remove non-selectable elements only when in uniq mode
             [ "$NLIST_IS_UNIQ_MODE" -eq 1 ] && [ "$#NLIST_NONSELECTABLE_ELEMENTS" -gt 0 ] &&
             for i in "${(nO)NLIST_NONSELECTABLE_ELEMENTS[@]}"; do
-                list[$i]=()
+                if [[ "$i" = <-> ]]; then
+                    list[$i]=()
+                fi
             done
 
             # Remove duplicates when in uniq mode
@@ -355,29 +406,46 @@ while (( 1 )); do
         fi
 
         # Output the list
+        zcurses clear inner
         n-list-draw "$(( (NLIST_CURRENT_IDX-1) % page_height + 1 ))" \
             "$page_height" "$page_width" 0 0 "$NLIST_TEXT_OFFSET" inner \
             "$disp_list[@]"
     fi
 
     local status_msg_strlen
+    local keywordmsg=""
+    if [ "$keywordisfresh" = "1" ]; then
+        keywordmsg="($curkeyword/$nkeywords) "
+        keywordisfresh="0"
+    fi
+
+    local thememsg=""
+    if [ "$themeisfresh" = "1" ]; then
+        local theme="$backuptheme"
+        [ "$curtheme" -gt 0 ] && theme="${themes[curtheme]}"
+        thememsg="($curtheme/$nthemes $theme) "
+        themeisfresh="0"
+    fi
+
+    local _txt2="" _txt3=""
+    [ "$NLIST_IS_UNIQ_MODE" -eq 1 ] && _txt2="[-UNIQ-] "
+    [ "$NLIST_IS_F_MODE" -eq 1 ] && _txt3="[-FIX-] "
+    [ "$NLIST_IS_F_MODE" -eq 2 ] && _txt3="[-FIX2-] "
+
     if [ "$NLIST_IS_SEARCH_MODE" = "1" ]; then
-        local _txt2=""
-        [ "$NLIST_IS_UNIQ_MODE" -eq 1 ] && _txt2="[-UNIQ-] "
-        _nlist_status_msg "${_txt2}Filtering with: ${NLIST_SEARCH_BUFFER// /+}"
+        _nlist_status_msg "${_txt2}${_txt3}${keywordmsg}${thememsg}Filtering with: ${NLIST_SEARCH_BUFFER// /+}"
     elif [[ ${NLIST_NONSELECTABLE_ELEMENTS[(r)$NLIST_CURRENT_IDX]} != $NLIST_CURRENT_IDX ||
             -n "$NLIST_SEARCH_BUFFER" || "$NLIST_IS_UNIQ_MODE" -eq 1 ]]; then
-        local _txt="" _txt2=""
+        local _txt=""
         [ -n "$NLIST_GREP_STRING" ] && _txt=" [$NLIST_GREP_STRING]"
-        [ "$NLIST_IS_UNIQ_MODE" -eq 1 ] && _txt2="[-UNIQ-] "
-        _nlist_status_msg "${_txt2}Current #$NLIST_USER_CURRENT_IDX (of #$NLIST_USER_LAST_ELEMENT entries)$_txt"
+        _nlist_status_msg "${_txt2}${_txt3}${keywordmsg}${thememsg}Current #$NLIST_USER_CURRENT_IDX (of #$NLIST_USER_LAST_ELEMENT entries)$_txt"
     else
-        _nlist_status_msg ""
+        _nlist_status_msg "${keywordmsg}${thememsg}"
     fi
 
-    zcurses border main
+    [ "$border" = "1" ] && zcurses border main
 
-    local top_msg="${(C)ZSH_NAME} $ZSH_VERSION, shell level $SHLVL, $USER"
+    local top_msg=" F1-change view, ${(C)ZSH_NAME} $ZSH_VERSION, shell level $SHLVL "
     zcurses move main 0 $(( term_width / 2 - $#top_msg / 2 ))
     zcurses string main $top_msg
 
@@ -400,7 +468,7 @@ while (( 1 )); do
     n-list-input "$NLIST_CURRENT_IDX" "$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN" \
                     "$page_height" "$page_width" "$last_element" "$NLIST_TEXT_OFFSET" \
                     "$final_key" "$NLIST_IS_SEARCH_MODE" "$NLIST_SEARCH_BUFFER" \
-                    "$NLIST_IS_UNIQ_MODE"
+                    "$NLIST_IS_UNIQ_MODE" "$NLIST_IS_F_MODE"
 
     selection="$reply[1]"
     action="$reply[2]"
@@ -410,8 +478,11 @@ while (( 1 )); do
     NLIST_IS_SEARCH_MODE="$reply[6]"
     NLIST_SEARCH_BUFFER="$reply[7]"
     NLIST_IS_UNIQ_MODE="$reply[8]"
+    NLIST_IS_F_MODE="$reply[9]"
 
-    if [ "$action" = "SELECT" ]; then
+    if [ -z "$action" ]; then
+        continue
+    elif [ "$action" = "SELECT" ]; then
         REPLY="$selection"
         reply=( "$list[@]" )
         break
@@ -422,6 +493,18 @@ while (( 1 )); do
     elif [ "$action" = "REDRAW" ]; then
         zcurses clear main redraw
         zcurses clear inner redraw
+    elif [[ "$action" = F<-> ]]; then
+        REPLY="$action"
+        reply=( "$list[@]" )
+        break
+    elif [[ "$action" = "EDIT" ]]; then
+        REPLY="EDIT"
+        reply=( "$list[@]" )
+        break
+    elif [[ "$action" = "HELP" ]]; then
+        REPLY="HELP"
+        reply=( "$list[@]" )
+        break
     fi
 done
 

+ 8 - 6
plugins/zsh-navigation-tools/n-list-draw

@@ -79,9 +79,9 @@ _nlist_print_with_ansi() {
 
         if (( no_match == 0 )); then
             if (( col >= 30 && col <= 37 )); then
-                zcurses attr "$win" $c[col-29]/black
+                zcurses attr "$win" $c[col-29]/"$background"
             elif [[ "$col" -eq 0 ]]; then
-                zcurses attr "$win" white/black
+                zcurses attr "$win" "$colorpair"
             fi
         fi
     done
@@ -97,17 +97,19 @@ local win="$7"
 shift 7
 integer max_text_len=page_width-x_offset
 
-[ "$bold" = "0" ] && bold="" || bold="+bold"
+[[ "$bold" = "0" || "$bold" = "-bold" ]] && bold="-bold" || bold="+bold"
 [[ "$active_text" = "underline" || "$active_text" = "reverse" ]] || local active_text="reverse"
-# With Linux terminal underline won't work properly
-[ "$TERM" = "linux" ] && active_text="reverse"
+# Linux has ncv 18, screen* has ncv 3 - underline won't work properly
+(( ${terminfo[ncv]:-0} & 2 )) && active_text="reverse"
+# FreeBSD uses TERM=xterm for newcons but doesn't actually support underline
+[[ "$TERM" = "xterm" && -z "$DISPLAY" ]] && active_text="reverse"
 
 integer max_idx=page_height
 integer end_idx=max_idx
 [ "$end_idx" -gt "$#" ] && end_idx="$#"
 integer y=y_offset
 
-zcurses attr "$win" $bold white/black
+zcurses attr "$win" "$bold" "$colorpair"
 
 integer i text_len
 local text

+ 148 - 9
plugins/zsh-navigation-tools/n-list-input

@@ -14,6 +14,52 @@ _nlist_compute_first_to_show_idx() {
     from_what_idx_list_is_shown=0+((current_idx-1)/page_height)*page_height+1
 }
 
+_nlist_update_from_keywords() {
+    keywordisfresh="1"
+    if [ "$nkeywords" -gt 0 ]; then
+        curkeyword=$(( (curkeyword+1) % (nkeywords+1) ))
+        if [ "$curkeyword" -eq "0" ]; then
+            buffer=""
+        else
+            buffer="${keywords[curkeyword]}"
+        fi
+    fi
+}
+
+_nlist_iterate_theme() {
+    themeisfresh="1"
+    if [ "$1" = "1" ]; then
+        curtheme=$(( (curtheme+1) % (nthemes+1) ))
+    else
+        curtheme=curtheme-1
+        [ "$curtheme" -lt 0 ] && curtheme=nthemes
+    fi
+
+    if [ "$nthemes" -gt 0 ]; then
+        local theme=${themes[curtheme]}
+        [ "$curtheme" -eq "0" ] && theme="$backuptheme"
+
+        colorpair="${theme%/*}"
+        bold="${theme##*/}"
+        background="${colorpair#*/}"
+        zcurses bg main "$colorpair"
+        zcurses bg inner "$colorpair"
+    fi
+}
+
+_nlist_rotate_buffer() {
+    setopt localoptions noglob
+
+    local -a words
+    words=( ${(s: :)buffer} )
+    words=( ${words[-1]} ${words[1,-2]} )
+
+    local space=""
+    [ "${buffer[-1]}" = " " ] && space=" "
+
+    buffer="${(j: :)words}$space"
+}
+
 typeset -ga reply
 reply=( -1 '' )
 integer current_idx="$1"
@@ -26,6 +72,7 @@ local key="$7"
 integer search="$8"
 local buffer="$9"
 integer uniq_mode="$10"
+integer f_mode="$11"
 
 #
 # Listening for input
@@ -79,21 +126,36 @@ case "$key" in
             ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]]
         then
             # Save current element in the result variable
-            reply=( $current_idx SELECT )
+            reply=( $current_idx "SELECT" )
+        fi
+        ;;
+    (H|'?')
+        # This event needs to be enabled
+        if [[ "${NLIST_ENABLED_EVENTS[(r)HELP]}" = "HELP" ]]; then
+            reply=( -1 "HELP" )
         fi
         ;;
+    (F1)
+        # This event needs to be enabled
+        if [[ "${NLIST_ENABLED_EVENTS[(r)F1]}" = "F1" ]]; then
+            reply=( -1 "$key" )
+        fi
+        ;;
+    (F4|F5|F6|F7|F8|F9|F10|DC)
+        # ignore; F2, F3 are used below
+        ;;
     (q)
-        reply=( -1 QUIT )
+        reply=( -1 "QUIT" )
         ;;
     (/)
         search=1
         _nlist_cursor_visibility 1
         ;;
     ($'\t')
-        reply=( $current_idx LEAVE )
+        reply=( $current_idx "LEAVE" )
         ;;
     ($'\C-L')
-        reply=( -1 REDRAW )
+        reply=( -1 "REDRAW" )
         ;;
     (\])
         [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] &&
@@ -127,9 +189,41 @@ case "$key" in
     ($'\E')
         buffer=""
         ;;
+    (F3)
+        if [ "$search" = "1" ]; then
+            search=0
+            _nlist_cursor_visibility 0
+        else
+            search=1
+            _nlist_cursor_visibility 1
+        fi
+        ;;
     (o|$'\C-O')
         uniq_mode=1-uniq_mode
         ;;
+    (f|$'\C-F')
+        (( f_mode=(f_mode+1) % 3 ))
+        ;;
+    ($'\x1F'|F2|$'\C-X')
+        search=1
+        _nlist_cursor_visibility 1
+        _nlist_update_from_keywords
+        ;;
+    ($'\C-T')
+        _nlist_iterate_theme 1
+        ;;
+    ($'\C-G')
+        _nlist_iterate_theme 0
+        ;;
+    ($'\C-E'|e)
+        # This event needs to be enabled
+        if [[ "${NLIST_ENABLED_EVENTS[(r)EDIT]}" = "EDIT" ]]; then
+            reply=( -1 "EDIT" )
+        fi
+        ;;
+    ($'\C-A')
+        _nlist_rotate_buffer
+        ;;
     (*)
         ;;
 esac
@@ -138,11 +232,19 @@ else
 
 case "$key" in
     ($'\n'|ENTER)
-        search=0
-        _nlist_cursor_visibility 0
+        if [ "$NLIST_INSTANT_SELECT" = "1" ]; then
+            if [[ "$NLIST_SEARCH_BUFFER" != "" || "$NLIST_IS_UNIQ_MODE" -eq 1 ||
+                ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]]
+            then
+                reply=( $current_idx "SELECT" )
+            fi
+        else
+            search=0
+            _nlist_cursor_visibility 0
+        fi
         ;;
     ($'\C-L')
-        reply=( -1 REDRAW )
+        reply=( -1 "REDRAW" )
         ;;
 
     #
@@ -192,8 +294,14 @@ case "$key" in
     (RIGHT)
         hscroll+=7
         ;;
-    (F1|F2|F3|F4|F5|F6|F7|F8|F9|F10)
-        # ignore
+    (F1)
+        # This event needs to be enabled
+        if [[ "${NLIST_ENABLED_EVENTS[(r)F1]}" = "F1" ]]; then
+            reply=( -1 "$key" )
+        fi
+        ;;
+    (F4|F5|F6|F7|F8|F9|F10|DC)
+        # ignore; F2, F3 are used below
         ;;
 
     #
@@ -214,9 +322,39 @@ case "$key" in
         search=0
         _nlist_cursor_visibility 0
         ;;
+    (F3)
+        if [ "$search" = "1" ]; then
+            search=0
+            _nlist_cursor_visibility 0
+        else
+            search=1
+            _nlist_cursor_visibility 1
+        fi
+        ;;
     ($'\C-O')
         uniq_mode=1-uniq_mode
         ;;
+    ($'\C-F')
+        (( f_mode=(f_mode+1) % 3 ))
+        ;;
+    ($'\x1F'|F2|$'\C-X')
+        _nlist_update_from_keywords
+        ;;
+    ($'\C-T')
+        _nlist_iterate_theme 1
+        ;;
+    ($'\C-G')
+        _nlist_iterate_theme 0
+        ;;
+    ($'\C-E')
+        # This event needs to be enabled
+        if [[ "${NLIST_ENABLED_EVENTS[(r)EDIT]}" = "EDIT" ]]; then
+            reply=( -1 "EDIT" )
+        fi
+        ;;
+    ($'\C-A')
+        _nlist_rotate_buffer
+        ;;
     (*)
         if [[ $#key == 1 && $((#key)) -lt 31 ]]; then
             # ignore all other control keys
@@ -234,5 +372,6 @@ reply[5]="$hscroll"
 reply[6]="$search"
 reply[7]="$buffer"
 reply[8]="$uniq_mode"
+reply[9]="$f_mode"
 
 # vim: set filetype=zsh:

+ 2 - 2
plugins/zsh-navigation-tools/n-options

@@ -14,8 +14,8 @@ local IFS="
 
 unset NLIST_COLORING_PATTERN
 
-[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
-[ -f ~/.config/znt/n-options.conf ] && . ~/.config/znt/n-options.conf
+[ -f ~/.config/znt/n-list.conf ] && builtin source ~/.config/znt/n-list.conf
+[ -f ~/.config/znt/n-options.conf ] && builtin source ~/.config/znt/n-options.conf
 
 # TODO restore options
 unsetopt localoptions

+ 2 - 2
plugins/zsh-navigation-tools/n-panelize

@@ -17,8 +17,8 @@ local IFS="
 
 unset NLIST_COLORING_PATTERN
 
-[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
-[ -f ~/.config/znt/n-panelize.conf ] && . ~/.config/znt/n-panelize.conf
+[ -f ~/.config/znt/n-list.conf ] && builtin source ~/.config/znt/n-list.conf
+[ -f ~/.config/znt/n-panelize.conf ] && builtin source ~/.config/znt/n-panelize.conf
 
 local list
 local selected

+ 8 - 0
plugins/zsh-navigation-tools/znt-history-widget

@@ -4,6 +4,14 @@ local NLIST_START_IN_UNIQ_MODE=1
 
 # Only if current $BUFFER doesn't come from history
 if [ "$HISTCMD" = "$HISTNO" ]; then
+    () {
+        setopt localoptions extendedglob
+        local -a match mbegin mend
+        local MATCH; integer MBEGIN MEND
+
+        [ -n "$BUFFER" ] && BUFFER="${BUFFER%% ##} "
+    }
+
     local NLIST_SET_SEARCH_TO="$BUFFER"
 fi
 

+ 16 - 7
plugins/zsh-navigation-tools/zsh-navigation-tools.plugin.zsh

@@ -15,13 +15,21 @@ if ! test -d "$CONFIG_DIR"; then
     mkdir "$CONFIG_DIR"
 fi
 
+# 9 files
 set n-aliases.conf n-env.conf n-history.conf n-list.conf n-panelize.conf n-cd.conf n-functions.conf n-kill.conf n-options.conf
 
-for i; do
-    if ! test -f "$CONFIG_DIR/$i"; then
-        cp "$REPO_DIR/.config/znt/$i" "$CONFIG_DIR"
-    fi
-done
+# Check for random 2 files if they exist
+# This will shift 0 - 7 elements
+shift $(( RANDOM % 8 ))
+if ! test -f "$CONFIG_DIR/$1" || ! test -f "$CONFIG_DIR/$2"; then
+    # Something changed - examine every file
+    set n-aliases.conf n-env.conf n-history.conf n-list.conf n-panelize.conf n-cd.conf n-functions.conf n-kill.conf n-options.conf
+    for i; do
+        if ! test -f "$CONFIG_DIR/$i"; then
+            cp "$REPO_DIR/.config/znt/$i" "$CONFIG_DIR"
+        fi
+    done
+fi
 
 # Don't leave positional parameters being set
 set --
@@ -30,12 +38,13 @@ set --
 # Load functions
 #
 
-autoload n-aliases n-cd n-env n-functions n-history n-kill n-list n-list-draw n-list-input n-options n-panelize
+autoload n-aliases n-cd n-env n-functions n-history n-kill n-list n-list-draw n-list-input n-options n-panelize n-help
 autoload znt-usetty-wrapper znt-history-widget znt-cd-widget znt-kill-widget
 alias naliases=n-aliases ncd=n-cd nenv=n-env nfunctions=n-functions nhistory=n-history
-alias nkill=n-kill noptions=n-options npanelize=n-panelize
+alias nkill=n-kill noptions=n-options npanelize=n-panelize nhelp=n-help
 
 zle -N znt-history-widget
 bindkey '^R' znt-history-widget
 setopt AUTO_PUSHD HIST_IGNORE_DUPS PUSHD_IGNORE_DUPS
+zstyle ':completion::complete:n-kill::bits' matcher 'r:|=** l:|=*'